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_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;
};


//几个全局结构体
typedef struct global_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中的函数就会被调用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值