1. 程式人生 > >uboot核心引數的傳遞與核心解析uboot傳遞的核心引數

uboot核心引數的傳遞與核心解析uboot傳遞的核心引數

一、核心引數的傳遞
uboot將核心引數存放在記憶體的某一地址上,bi_boot_params存放uboot傳給kernel 核心引數的首地址.
int board_init (void)
{
gd->bd->bi_arch_number = MACH_TYPE_GODBOX;//cpu id號 
gd->bd->bi_boot_params = CFG_BOOT_PARAMS;//指定核心引數存放的起始地址#define CFG_BOOT_PARAMS                 (MEM_BASE_DDR + 0x0100)
gd->flags = 0;
}


bi_boot_params 指向tagged list的首地址,向tagged list中新增 tag,最後呼叫theKernel (0, machid, bd->bi_boot_params),向核心傳遞核心引數首地址,並啟動核心。theKernel的三個引數將會被賦值給R0 = 0, R1=machid, R2 = bd->bi_boot_params。所以uboot向kernel傳遞引數的起始地址,起始是通過R2暫存器來傳遞。
do_bootm_linux
{
->bd_t *bd = gd->bd;
->setup_start_tag (bd);//設定tag_core tagged, 起始tagged
->setup_memory_tags (bd);//設定tag_mem32 tagged, 記憶體標記,mem引數
->setup_commandline_tag (bd, commandline);//設定cmdline tagged, 命令列標記 cmdline引數
。。。。設定一系列標記 //
->setup_end_tag (bd);//設定結束tagged
->theKernel (0, machid, bd->bi_boot_params);//啟動linux核心
}


//設定起始的tag_core標記
static struct tag *params;
static void setup_start_tag (bd_t *bd)
{
params = (struct tag *) bd->bi_boot_params;


params->hdr.tag = ATAG_CORE;//tag標示
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);
}
//設定 mem32 tag
static void setup_memory_tags (bd_t *bd)
{
int i;


for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
params->hdr.tag = ATAG_MEM;
params->hdr.size = tag_size (tag_mem32);


params->u.mem.start = bd->bi_dram[i].start;
params->u.mem.size = bd->bi_dram[i].size;


params = tag_next (params);
}
}


static void setup_end_tag (bd_t *bd)
{
params->hdr.tag = ATAG_NONE;
params->hdr.size = 0;
}


核心引數使用標記列表的方式來傳遞啟動引數
struct tag_header {
u32 size; //tag大小
u32 tag; //tag標示
};


struct tag {
struct tag_header hdr;
union {
struct tag_corecore;
struct tag_mem32mem;
struct tag_videotextvideotext;
struct tag_ramdiskramdisk;
struct tag_initrdinitrd;
struct tag_serialnrserialnr;
struct tag_revisionrevision;
struct tag_videolfbvideolfb;
struct tag_cmdlinecmdline;


/*
* Acorn specific
*/
struct tag_acornacorn;


/*
* DC21285 specific
*/
struct tag_memclkmemclk;
} u;
};


//幾個全域性結構體
typedefstructglobal_data {
bd_t*bd;/*information about board*/
unsigned long flags;
unsigned long baudrate;
unsigned long have_console;/* serial_init() was called */
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
#ifdef CONFIG_FSL_ESDHC
unsigned long sdhc_clk;
#endif
void**jt;/* jump table */
} gd_t;


typedef struct bd_info {
    intbi_baudrate;/* serial console baudrate */
    unsigned longbi_ip_addr;/* IP Address */
    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];
} bd_t;




二、核心解析uboot傳遞的引數
Linux kernel通過獲取R2暫存器的值來獲取uboot傳遞引數的基地址,並呼叫parse_tags分析解析引數。


arm\arm\kernel\head-common.S中,將__atags_pointer作為R6的引用,並將R2賦值給了R6,
[email protected]
r6


strr2, [r6] @ Save atags pointer



在start_kernel->setup_arch中解析


if (__atags_pointer)//檢測是否bootloader是否傳遞引數
tags = phys_to_virt(__atags_pointer);


//解析各種__tagtable
parse_tags(tags);

static void __init parse_tags(const struct tag *t)
{
for (; t->hdr.size; t = tag_next(t))
if (!parse_tag(t))
printk(KERN_WARNING
"Ignoring unrecognised tag 0x%08x\n",
t->hdr.tag);
}

static int __init parse_tag(const struct tag *tag)
{
extern struct tagtable __tagtable_begin, __tagtable_end;
struct tagtable *t;


for (t = &__tagtable_begin; t < &__tagtable_end; t++)
if (tag->hdr.tag == t->tag) {
t->parse(tag);//呼叫tagtable中的parse函式
break;
}


return t < &__tagtable_end;
}


定義了各種tagtable,並給其賦值,將其存放到.taglist.init段中
__tagtable(ATAG_CORE, parse_tag_core);
__tagtable(ATAG_MEM, parse_tag_mem32);
__tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);

.....


struct tagtable {
__u32 tag;
int (*parse)(const struct tag *);
};


#define __tag               __used __attribute__((__section__(".taglist.init")))
#define __tagtable(tag, fn) static struct tagtable __tagtable_##fn __tag = { tag, fn }


tagtable(ATAG_MEM, parse_tag_mem32)
展開後
static struct tagtable __tagtable_parse_tag_mem32 __used __attribute__((__section__(".taglist.init"))) = 

ATAG_MEM, 
parse_tag_mem32 
}


當在parse_tag中呼叫 parse時,相應tagtable中的函式就會被呼叫