UBOOT中param参数的解析

大家都知道U-Boot启动的时候会将启动参数的地址放入R2中,然后再启动内核。我们看看这些参数是如何设置的。
首先看两个重要的数据结构:
第一个是global_data,定义在include/asm-arm/global_data.h文件中:

typedef    struct     global_data {
     bd_t        *bd;
    unsigned long     flags;
    unsigned long     baudrate;
    unsigned long     have_console;    /* serial_init() was called */
    unsigned long     reloc_off;    /* Relocation Offset */
    unsigned long     env_addr;    /* Address of Environment struct */
    unsigned long     env_valid;    /* Checksum of Environment valid? */
    unsigned long     fb_base;    /* base address of frame buffer */
#ifdef CONFIG_VFD
    unsigned char     vfd_type;    /* display type */
#endif
#if 0
    unsigned long     cpu_clk;    /* CPU clock in Hz!         */
    unsigned long     bus_clk;
    unsigned long     ram_size;    /* RAM size */
    unsigned long     reset_status;    /* reset status register at boot */
#endif
    void        **jt;        /* jump table */
} gd_t;

在同一个文件中有如下定义:

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

在需要使用gd指针的时候,只需要加入DECLARE_GLOBAL_DATA_PTR这句话就可以了。可以知道,gd指针始终是放在r8中的。

其中的第一个变量,bd_t结构体,定义于include/asm-arm/u-boot.h中:

 

typedef struct bd_info {
    int             bi_baudrate;    /* serial console baudrate */
    unsigned long     bi_ip_addr;    /* IP Address */
    unsigned char     bi_enetaddr[6]; /* Ethernet adress */
    struct environment_s     *bi_env;
     ulong     bi_arch_number;    /* unique id for this board */
     ulong     bi_boot_params;    /* where this board expects params */
    struct                /* RAM configuration */
    {
     ulong start;
     ulong size;
    }              bi_dram[CONFIG_NR_DRAM_BANKS];
#ifdef CONFIG_HAS_ETH1
    /* second onboard ethernet port */
    unsigned char bi_enet1addr[6];
#endif
} bd_t;

bd_t中的变量bi_boot_params,表示传递给内核的参数的位置。

然后看看gd和bd的初始化,在lib_arm/board.c中:

gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
memset ((void*)gd, 0, sizeof (gd_t));
gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
memset (gd->bd, 0, sizeof (bd_t));

说明这两个结构体在内存中的位置是在uboot的代码在往下的地址处,所以进行操作的时候不要覆盖了这个位置!

在board/up270/up270.c中,有如下初始化:

gd->bd->bi_boot_params = 0xa0000100;

说明参数位置在0xa0000100。

现在,具体看看uboot是如何(按什么格式)把参数放入内存中。

在lib_arm/armlinux.c的do_bootm_linux函数中:

bd_t *bd = gd->bd;
setup_start_tag (bd);

setup_start_tag函数定义于同一个文件中:

static void setup_start_tag (bd_t *bd)
{
     params = (struct tag *) bd->bi_boot_params;

     params->hdr.tag = ATAG_CORE;
     params->hdr.size = tag_size (tag_core);

     params->u.core.flags = 0;
     params->u.core.pagesize = 0;
     params->u.core.rootdev = 0;

     params = tag_next (params);
}

其中用到了一个重要的指针:params,这是一个指向struct tag的指针,在文件的开始处声明,可以被这个文件中的所有函数访问:

static struct tag *params;

struct tag的定义位于include/asm-arm/setup.h中:

struct tag {
    struct tag_header hdr;
    union {
        struct tag_core         core;
        struct tag_mem32     mem;
        struct tag_videotext     videotext;
        struct tag_ramdisk     ramdisk;
        struct tag_initrd     initrd;
        struct tag_serialnr     serialnr;
        struct tag_revision     revision;
        struct tag_videolfb     videolfb;
        struct tag_cmdline     cmdline;

        
/*
         * Acorn specific
         */

        struct tag_acorn     acorn;

        
/*
         * DC21285 specific
         */

        struct tag_memclk     memclk;
    } u;
};

包括teg_header和tag的内容。tag_header定义在同一个文件中,如下:

struct tag_header {
     u32 size;
     u32 tag;
};

tag和tag_header和内核中的结构一模一样。tag_header中的tag字段表示的是这个tag的类型,在内核和Bootloader中通过一些固定的整形常量来表示:

#define ATAG_CORE 0x54410001
#define ATAG_NONE 0x00000000
#define ATAG_CORE 0x54410001
#define ATAG_MEM 0x54410002
#define ATAG_VIDEOTEXT 0x54410003
#define ATAG_RAMDISK 0x54410004
#define ATAG_INITRD 0x54410005
#define ATAG_INITRD2 0x54420005
#define ATAG_SERIAL 0x54410006
#define ATAG_REVISION 0x54410007
#define ATAG_VIDEOLFB 0x54410008
#define ATAG_CMDLINE 0x54410009
#define ATAG_ACORN 0x41000101
#define ATAG_MEMCLK 0x41000402

set_xxx_tags函数给不同的参数赋值,和set_start_tag类似,就不多说了。需要注意的一个是tag_next。这是一个宏:

#define tag_next(t)    ((struct tag *)((u32 *)(t) + (t)->hdr.size))

作用就是让param跳过刚刚设置好的tag,指向下一个tag开始的地方。所以在每个set_xxx_tag函数的最好都调用这个宏。

具体每个tag的定义可以查看相关文件。
这样,就把每个tag放到了从内存0xa0000100开始的地址,然后由内核根据tag_header的tag字段来识别到底是什么参数,然后再解析出来使用。

 

原文地址:blog.chinaunix.net/u1/49742/showart_1860612.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值