Chinaunix首页 | 论坛 | 博客

OS

  • 博客访问: 2229507
  • 博文数量: 691
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2660
  • 用 户 组: 普通用户
  • 注册时间: 2014-04-05 12:49
个人简介

不浮躁

文章分类

全部博文(691)

文章存档

2019年(1)

2017年(12)

2016年(99)

2015年(207)

2014年(372)

分类: 嵌入式

2015-12-13 11:16:09

Kernel 读取U-boot 传递的相关参数
对于 Linux Kernel , ARM 平台启动时,先执行 arch/arm/kernel/head.S ,此文件
会调用 arch/arm/kernel/head-common.S 中的函数,并最后调用 start_kernel :
......
b start_kernel
......
init/main.c 中的 start_kernel 函数中会调用 setup_arch 函数来处理各种平台相关
的动作,包括了 u-boot 传递过来参数的分析和保存:
start_kernel()
{
......
setup_arch(&command_line);
......
}
其中, setup_arch 函数在 arch/arm/kernel/setup.c 文件中实现,如下:
void __init setup_arch(char **cmdline_p)
{
struct tag *tags = (struct tag *)&init_tags;
struct machine_desc *mdesc;
char *from = default_command_line;
setup_processor();
mdesc = setup_machine(machine_arch_type);
machine_name = mdesc->name;
if (mdesc->soft_reboot)
reboot_setup("s");
if (__atags_pointer)
// 指向各种 tag 起始位置的指针,定义如下:
//unsigned int __atags_pointer __initdata;
// 此指针指向 __initdata 段,各种 tag 的信息保存在这个段中。
tags = phys_to_virt(__atags_pointer);
else if (mdesc->boot_params)
tags = phys_to_virt(mdesc->boot_params);
if (tags->hdr.tag != ATAG_CORE)
convert_to_tag_list(tags);
if (tags->hdr.tag != ATAG_CORE)
tags = (struct tag *)&init_tags;
if (mdesc->fixup)
mdesc->fixup(mdesc, tags, &from, &meminfo);
if (tags->hdr.tag == ATAG_CORE) {
if (meminfo.nr_banks != 0)
squash_mem_tags(tags);
save_atags(tags);
parse_tags(tags);
// 处理各种 tags ,其中包括了 RAM 参数的处理。
// 这个函数处理如下 tags :
__tagtable(ATAG_MEM, parse_tag_mem32);
__tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
__tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
__tagtable(ATAG_SERIAL, parse_tag_serialnr);
__tagtable(ATAG_REVISION, parse_tag_revision);
__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
}
init_mm.start_code = (unsigned long) &_text;
init_mm.end_code = (unsigned long) &_etext;
init_mm.end_data = (unsigned long) &_edata;
init_mm.brk = (unsigned long) &_end;
memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
parse_cmdline(cmdline_p, from); // 处理编译内核时指定的 cmdline 或 u-boot 传
递的 cmdline
paging_init(&meminfo, mdesc);
request_standard_resources(&meminfo, mdesc);
#ifdef CONFIG_SMP
smp_init_cpus();
#endif
cpu_init();
init_arch_irq = mdesc->init_irq;
system_timer = mdesc->timer;
init_machine = mdesc->init_machine;
#ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE)
conswitchp = &vga_con;
#elif defined(CONFIG_DUMMY_CONSOLE)
conswitchp = &dummy_con;
#endif
#endif
early_trap_init();
}
对于处理 RAM 的 tag ,调用了 parse_tag_mem32 函数:
static int __init parse_tag_mem32(const struct tag *tag)
{
......
arm_add_memory(tag->u.mem.start, tag->u.mem.size);
......
}
__tagtable(ATAG_MEM, parse_tag_mem32);
上述的 arm_add_memory 函数定义如下:
static void __init arm_add_memory(unsigned long start, unsigned long size)
{
struct membank *bank;
size -= start & ~PAGE_MASK;
bank = &meminfo.bank[meminfo.nr_banks++];
bank->start = PAGE_ALIGN(start);
bank->size = size & PAGE_MASK;
bank->node = PHYS_TO_NID(start);
}
如上可见, parse_tag_mem32 函数调用 arm_add_memory 函数把 RAM 的 start
和 size 等参数保存到了 meminfo 结构的 meminfo 结构体中。最后,在 setup_arch
中执行下面语句:
paging_init(&meminfo, mdesc);
对有 MMU 的平台上调用 arch/arm/mm/nommu.c 中的 paging_init ,否则调用 ar
ch/arm/mm/mmu.c 中的 paging_init 函数。这里暂不分析 mmu.c 中的 paging_init 函
数。
阅读(1531) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~