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中的函数就会被调用
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中的函数就会被调用
相关文章推荐
- JavaScript中,window.opener是什么?window.parent和window.opener有啥区别?
- noi 1999 生日蛋糕
- FriedRing(焦圈)--python的开源自动化性能和接口测试框架
- PHP常量PHP_SAPI与函数php_sapi_name()简介,PHP运行环境检测
- 微信开发学习总结
- Java后端WebSocket的Tomcat实现
- java基础—— Collections.sort的两种用法,简单明了 。
- POJ-3660 Cow Contest( 最短路 )
- Dijkstra算法
- 文章标题
- C#中MessageBox用法大全
- svn插件Subclipse
- PHP导出数据到CSV文件函数/方法
- 160706、Java HashMap工作原理及实现
- 删除字符串中出现次数最少的字符
- Qt5中文乱码问题
- Merge Sorted Array
- 【sublime text 开发常用插件】
- 查看编译后的calss文件编译jdk版本
- linux(centos)搭建SVN服务器