您的位置:首页 > 其它

uboot内核参数的传递与内核解析uboot传递的内核参数

2016-07-11 12:48 525 查看
一、内核参数的传递

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;

};

//几个全局结构体

typedef structglobal_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 {

    int bi_baudrate;/* serial console baudrate */

    unsigned long bi_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,

.long __atags_pointer@ r6

str r2, [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中的函数就会被调用
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: