请稍侯

Uboot最重要的全局变量gd

8. gd

gd 是一个 gd_t 类型的结构体变量,在 uboot 阶段地址保存在寄存器 r9:

#define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r9")

gd_t 结构体定义在 include/asm-generic/global_data.h

typedef struct global_data {
    bd_t *bd;
    unsigned long flags;
    unsigned int baudrate;
    unsigned long cpu_clk;  /* CPU clock in Hz!     */
    unsigned long bus_clk;
    /* We cannot bracket this with CONFIG_PCI due to mpc5xxx */
    unsigned long pci_clk;
    unsigned long mem_clk;
#if defined(CONFIG_LCD) || defined(CONFIG_VIDEO)
    unsigned long fb_base;  /* Base address of framebuffer mem */
#endif
#if defined(CONFIG_POST) || defined(CONFIG_LOGBUFFER)
    unsigned long post_log_word;  /* Record POST activities */
    unsigned long post_log_res; /* success of POST test */
    unsigned long post_init_f_time;  /* When post_init_f started */
#endif
#ifdef CONFIG_BOARD_TYPES
    unsigned long board_type;
#endif
    unsigned long have_console; /* serial_init() was called */
#ifdef CONFIG_PRE_CONSOLE_BUFFER
    unsigned long precon_buf_idx;   /* Pre-Console buffer index */
#endif
    unsigned long env_addr; /* Address  of Environment struct */
    unsigned long env_valid;    /* Checksum of Environment valid? */
        unsigned long env_valid;    /* Checksum of Environment valid? */

    unsigned long ram_top;  /* Top address of RAM used by U-Boot */

    unsigned long relocaddr;    /* Start address of U-Boot in RAM */
    phys_size_t ram_size;   /* RAM size */
#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
#define MEM_RESERVE_SECURE_SECURED  0x1
#define MEM_RESERVE_SECURE_MAINTAINED   0x2
#define MEM_RESERVE_SECURE_ADDR_MASK    (~0x3)
    /*
     * Secure memory addr
     * This variable needs maintenance if the RAM base is not zero,
     * or if RAM splits into non-consecutive banks. It also has a
     * flag indicating the secure memory is marked as secure by MMU.
     * Flags used: 0x1 secured
     *             0x2 maintained
     */
    phys_addr_t secure_ram;
#endif
    unsigned long mon_len;  /* monitor len */
    unsigned long irq_sp;       /* irq stack pointer */
    unsigned long start_addr_sp;    /* start_addr_stackpointer */
    unsigned long reloc_off;
    struct global_data *new_gd; /* relocated global data */

#ifdef CONFIG_DM
    struct udevice  *dm_root;   /* Root instance for Driver Model */
    struct udevice  *dm_root_f; /* Pre-relocation root instance */
    struct list_head uclass_root;   /* Head of core tree */
#endif
#ifdef CONFIG_TIMER
    struct udevice  *timer; /* Timer instance for Driver Model */
#endif

    const void *fdt_blob;   /* Our device tree, NULL if none */
    void *new_fdt;      /* Relocated FDT */
    unsigned long fdt_size; /* Space reserved for relocated FDT */
    struct jt_funcs *jt;        /* jump table */
    char env_buf[32];   /* buffer for getenv() before reloc. */
#ifdef CONFIG_TRACE
    void        *trace_buff;    /* The trace buffer */
#endif
#if defined(CONFIG_SYS_I2C)
    int     cur_i2c_bus;    /* current used i2c bus */
#endif
#ifdef CONFIG_SYS_I2C_MXC
    void *srdata[10];
#endif
    unsigned long timebase_h;
        unsigned long timebase_l;
#ifdef CONFIG_SYS_MALLOC_F_LEN
    unsigned long malloc_base;  /* base address of early malloc() */
    unsigned long malloc_limit; /* limit address */
    unsigned long malloc_ptr;   /* current address */
#endif
#ifdef CONFIG_PCI
    struct pci_controller *hose;    /* PCI hose for early use */
    phys_addr_t pci_ram_top;    /* top of region accessible to PCI */
#endif
#ifdef CONFIG_PCI_BOOTDELAY
    int pcidelay_done;
#endif
    struct udevice *cur_serial_dev; /* current serial device */
    struct arch_global_data arch;   /* architecture-specific data */
#ifdef CONFIG_CONSOLE_RECORD
    struct membuff console_out; /* console output */
    struct membuff console_in;  /* console input */
#endif
#ifdef CONFIG_DM_VIDEO
    ulong video_top;        /* Top of video frame buffer area */
    ulong video_bottom;     /* Bottom of video frame buffer area */
#endif
} gd_t;

从定义可以看出 gd 实际上包含了 uboot 运行过程中要使用的几乎全部的全局变量。

gd 最开始是在 _main 里初始化的(有些架构是在 board_init_f() 里面初始化的):

ENTRY(_main)
...
/* set up gd here, outside any C code */
mov r9, r0
bl  board_init_f_init_reserve
...
void board_init_f_init_reserve(ulong base)
{
    struct global_data *gd_ptr;
#ifndef _USE_MEMCPY
    int *ptr;
#endif

    /*
     * clear GD entirely and set it up.
     * Use gd_ptr, as gd may not be properly set yet.
     */

    gd_ptr = (struct global_data *)base;
    /* zero the area */
#ifdef _USE_MEMCPY
    memset(gd_ptr, '\0', sizeof(*gd));
#else
    for (ptr = (int *)gd_ptr; ptr < (int *)(gd_ptr + 1); )
        *ptr++ = 0;
#endif
    /* set GD unless architecture did it already */
#if !defined(CONFIG_ARM)
    arch_setup_gd(gd_ptr);
#endif
    /* next alloc will be higher by one GD plus 16-byte alignment */
    base += roundup(sizeof(struct global_data), 16);

    /*
     * record early malloc arena start.
     * Use gd as it is now properly set for all architectures.
     */

#if defined(CONFIG_SYS_MALLOC_F)
    /* go down one 'early malloc arena' */
    gd->malloc_base = base;
    /* next alloc will be higher by one 'early malloc arena' size */
    base += CONFIG_SYS_MALLOC_F_LEN;
#endif
}

并且随着 uboot 初始化外设、准备引导系统的过程不断的初始化自己的各个成员变量,如初始化串口时就对 *cur_serial_dev 进行赋值。