bootloader 内核启动参数

一:启动参数的传递过程 
启动参数是包装在数据结构里的,在linux kernel启动的时候,bootloader把这个数据结构拷贝到某个地址, 
在改动PC跳向内核接口的同时,通过通用寄存器R2来传递这个地址的值,下面这句话就是uboot跳向linux 
kernel的代码(bootm命令) 
theKernel (0, bd->bi_arch_number, bd->bi_boot_params); 
thekernel其实不是个函数,而是指向内核入口地址的指针,把它强行转化为带三个参数的函数指针,会把三个 
参数保存到通用寄存器中,实现了向kernel传递信息的功能,在这个例子里,会把R0赋值为0,R1赋值为机器号 
R2赋值为启动参数数据结构的首地址 
因此,要向内核传递参数很简单,只要把启动参数封装在linux预定好的数据结构里,拷贝到某个地址(一般 
约定俗成是内存首地址+100dex) 
 
二:启动参数的数据结构 
启动参数可保存在两种数据结构中,param_struct和tag,前者是2.4内核用的,后者是2.6以后的内核更期望用的 
但是,到目前为止,2.6的内核也可以兼容前一种结构,两种数据结构具体定义如下(arm cpu): 
 
struct param_struct { 
    union { 
    struct { 
        unsigned long page_size;        /*  0 */ 
        unsigned long nr_pages;        /*  4 */ 
        unsigned long ramdisk_size;        /*  8 */ 
        unsigned long flags;        /* 12 */ 
#define FLAG_READONLY    1 
#define FLAG_RDLOAD    4 
#define FLAG_RDPROMPT    8 
        unsigned long rootdev;        /* 16 */ 
        unsigned long video_num_cols;    /* 20 */ 
        unsigned long video_num_rows;    /* 24 */ 
        unsigned long video_x;        /* 28 */ 
        unsigned long video_y;        /* 32 */ 
        unsigned long memc_control_reg;    /* 36 */ 
        unsigned char sounddefault;        /* 40 */ 
        unsigned char adfsdrives;        /* 41 */ 
        unsigned char bytes_per_char_h;    /* 42 */ 
        unsigned char bytes_per_char_v;    /* 43 */ 
        unsigned long pages_in_bank[4];    /* 44 */ 
        unsigned long pages_in_vram;    /* 60 */ 
        unsigned long initrd_start;        /* 64 */ 
        unsigned long initrd_size;        /* 68 */ 
        unsigned long rd_start;        /* 72 */ 
        unsigned long system_rev;        /* 76 */ 
        unsigned long system_serial_low;    /* 80 */ 
        unsigned long system_serial_high;    /* 84 */ 
        unsigned long mem_fclk_21285;       /* 88 */ 
    } s; 
    char unused[256]; 
    } u1; 
    union { 
    char paths[8][128]; 
    struct { 
        unsigned long magic; 
        char n[1024 - sizeof(unsigned long)]; 
    } s; 
    } u2; 
    char commandline[COMMAND_LINE_SIZE]; 
};  
param_struct只需要设置cmmandline,u1.s.page_size,u1.s.nr_pages三个域,具体使用可参见下面的例子 
对于tag来说,在实际使用中是一个struct tag组成的列表,在tag->tag_header中,一项是u32 tag(重名,注意类型) 
其值用宏ATAG_CORE,ATAG_MEM,ATAG_CMDLINE,ATAG_NONE等等来表示,此时下面union就会使用与之相关的数据结构 
同时,规定tag列表中第一项必须是ATAG_CORE,最后一项必须是ATAG_NONE,比如在linux代码中,找到启动参数之后 
首先看tag列表中的第一项的tag->hdr.tag是否为ATAG_CORE,如果不是,就会认为启动参数不是tag结构而是param_struct 
结构,然后调用函数来转换.在tag->tag_header中,另一项是u32 size,表示tag的大小,tag组成列表的方式就是 
指针+size,实际使用中用tag_next (params).tag的具体使用见三中的例子 
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; 
        struct tag_acorn    acorn;        //Acorn specific 
    struct tag_omap   omap;     //OMAP specific 
        struct tag_memclk    memclk;   //DC21285 specific 
    } u; 
};  
需要注意的是,这两个数据结构在uboot中和linux中分别有定义,这个定义必须一直才能正常传递参数 
如果实际使用中不一致的话就不能正常传递,可以自行修改

你可能感兴趣的:(数据结构,linux,struct,header,command)