一.总体说明
arm中内存的大小及地址是uboot通过参数传给kernel的
二.uboot中内存大小的确定
2.1 参数的位置
在board/sunxi/sun8iw7/sun8iw7.c中
-
int board_init(void)
-
{
-
gd->bd->bi_arch_number = LINUX_MACHINE_ID;
-
gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100); //这儿确定了参数的位置
-
return 0;
-
}
-
include/configs/sun8iw7p1.h
#define CONFIG_SYS_SDRAM_BASE (0x40000000)
#define PHYS_SDRAM_1 CONFIG_SYS_SDRAM_BASE -->所以这个位置是0x40000100
2.2 参数中数据的填充
2.2.1 初始化参数
在arch/arm/lib/bootm.c中L213:do_boota_linux-->setup_start_tag
-
先定义了一个全局变量 --> static struct tag *params;
-
static void setup_start_tag (bd_t *bd)
-
{
-
params = (struct tag *) bd->bi_boot_params; //全局变量params指向参数的内存
-
-
params->hdr.tag = ATAG_CORE;
-
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);
-
}
2.2.2 填充args的参数,以内存为例
在arch/arm/lib/bootm.c中L213:do_boota_linux-->setup_memory_tags
-
static void setup_memory_tags (bd_t *bd)
-
{
-
int i;
-
-
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
-
params->hdr.tag = ATAG_MEM; //类型为ATA_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; //物理内存的大小
-
if(gd->ram_size_mb && (!bd->bi_dram[i].size))
-
params->u.mem.size = gd->ram_size_mb;
-
params = tag_next (params);
-
}
-
}
2.2.3 完整流程
在arch/arm/lib/bootm.c中L213:do_boota_linux-->setup_memory_tags
-
int do_boota_linux (struct fastboot_boot_img_hdr *hdr)
-
{
-
ulong initrd_start, initrd_end;
-
void (*kernel_entry)(int zero, int arch, uint params);
-
bd_t *bd = gd->bd;
-
-
kernel_entry = (void (*)(int, int, uint))(hdr->kernel_addr);
-
-
#ifdef CONFIG_CMDLINE_TAG
-
char *commandline = getenv ("bootargs");
-
#endif
-
-
initrd_start = hdr->ramdisk_addr;
-
initrd_end = initrd_start + hdr->ramdisk_size;
-
#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
-
defined (CONFIG_CMDLINE_TAG) || \
-
defined (CONFIG_INITRD_TAG) || \
-
defined (CONFIG_SERIAL_TAG) || \
-
defined (CONFIG_REVISION_TAG)
-
setup_start_tag (bd); //初始化参数
-
#ifdef CONFIG_SERIAL_TAG
-
setup_serial_tag (¶ms);
-
#endif
-
#ifdef CONFIG_REVISION_TAG
-
setup_revision_tag (¶ms); //填充参数-->vision
-
#endif
-
#ifdef CONFIG_SETUP_MEMORY_TAGS
-
setup_memory_tags (bd); //填充参数-->内存
-
#endif
-
#ifdef CONFIG_CMDLINE_TAG
-
setup_commandline_tag (bd, (char *)hdr->cmdline); //填充参数-->cmdline,这个在内核启动时会打印出来
-
#endif
-
#ifdef CONFIG_INITRD_TAG
-
if (hdr->ramdisk_size)
-
setup_initrd_tag (bd, initrd_start, initrd_end);
-
#endif
-
#if defined (CONFIG_VFD) || defined (CONFIG_LCD)
-
setup_videolfb_tag ((gd_t *) gd);
-
#endif
-
setup_end_tag (bd);
-
#endif
-
-
announce_and_cleanup();
-
-
kernel_entry(0, bd->bi_arch_number, bd->bi_boot_params); //最后启动内核
-
-
return 1;
-
}
注意:原来内核中打印的cmdline并不是全部uboot的参数
三.uboot与kernel的参数传递
3.1
在arch/arm/kernel/setup.c中L1060-->start_kernel-->setup_arch
重点关注meminfo这个结构体
-
void __init setup_arch(char **cmdline_p)
-
{
-
struct machine_desc *mdesc;
-
int i; //add by cong
-
setup_processor();
-
-
mdesc = setup_machine_fdt(__atags_pointer);
-
for(i=0; i<NR_BANKS; i++) //add by cong -->此处打印发现meminfo结构体为空
-
dbmsg("bank[%d]-->[0x%x--0x%x],h=%x", i, meminfo.bank[i].start, meminfo.bank[i].size, meminfo.bank[i].highmem);
-
-
if (!mdesc)
-
mdesc = setup_machine_tags(machine_arch_type); -->所以重点在setup_machine_tags中,这个函数会解析uboot中的参数包括meminfo
-
for(i=0; i<NR_BANKS; i++) //add by cong -->此处打印发现meminfo结构体不为空
-
dbmsg("bank[%d]-->[0x%x--0x%x],h=%x", i, meminfo.bank[i].start, meminfo.bank[i].size, meminfo.bank[i].highmem);
-
-
machine_desc = mdesc;
-
machine_name = mdesc->name;
-
-
setup_dma_zone(mdesc);
-
-
if (mdesc->restart_mode)
-
reboot_setup(&mdesc->restart_mode);
-
-
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;
-
-
/* populate cmd_line too for later use, preserving boot_command_line */
-
strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
-
*cmdline_p = cmd_line;
-
-
parse_early_param();
-
-
sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL);
-
sanity_check_meminfo();
-
arm_memblock_init(&meminfo, mdesc); //将meminfo中的数据放到memblock中
-
-
paging_init(mdesc);
-
request_standard_resources(mdesc);
-
-
if (mdesc->restart)
-
arm_pm_restart = mdesc->restart;
-
-
unflatten_device_tree();
-
-
#ifdef CONFIG_ARCH_SUNXI
-
/* init sys_config script parse */
-
script_init();
-
#endif
-
-
#ifdef CONFIG_SMP
-
if (is_smp()) {
-
if (!mdesc->smp_init || !mdesc->smp_init())
-
smp_set_ops(mdesc->smp);
-
smp_init_cpus();
-
smp_build_mpidr_hash();
-
}
-
#endif
-
reserve_crashkernel();
-
-
tcm_init();
-
-
#ifdef CONFIG_MULTI_IRQ_HANDLER
-
handle_arch_irq = mdesc->handle_irq;
-
#endif
-
-
#ifdef CONFIG_VT
-
#if defined(CONFIG_VGA_CONSOLE)
-
conswitchp = &vga_con;
-
#elif defined(CONFIG_DUMMY_CONSOLE)
-
conswitchp = &dummy_con;
-
#endif
-
#endif
-
-
if (mdesc->init_early)
-
mdesc->init_early();
-
}
3.2 解析参数的过程 在arch/arm/kernel/setup.c中L979
-
static struct machine_desc * __init setup_machine_tags(unsigned int nr)
-
{
-
struct tag *tags = (struct tag *)&init_tags;
-
struct machine_desc *mdesc = NULL, *p;
-
char *from = default_command_line;
-
int i; //cong
-
init_tags.mem.start = PHYS_OFFSET;
-
-
/*
-
* locate machine in the list of supported machines.
-
*/
-
for_each_machine_desc(p)
-
if (nr == p->nr) {
-
printk("Machine: %s\n", p->name);
-
mdesc = p;
-
break;
-
}
-
-
if (!mdesc) {
-
early_print("\nError: unrecognized/unsupported machine ID"
-
" (r1 = 0x%08x).\n\n", nr);
-
dump_machine_table(); /* does not return */
-
}
-
-
if (__atags_pointer)
-
tags = phys_to_virt(__atags_pointer);
-
else if (mdesc->atag_offset)
-
tags = (void *)(PAGE_OFFSET + mdesc->atag_offset);
-
-
#if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
-
/*
-
* If we have the old style parameters, convert them to
-
* a tag list.
-
*/
-
if (tags->hdr.tag != ATAG_CORE)
-
convert_to_tag_list(tags);
-
#endif
-
-
if (tags->hdr.tag != ATAG_CORE) {
-
#if defined(CONFIG_OF)
-
/*
-
* If CONFIG_OF is set, then assume this is a reasonably
-
* modern system that should pass boot parameters
-
*/
-
early_print("Warning: Neither atags nor dtb found\n");
-
#endif
-
tags = (struct tag *)&init_tags;
-
}
-
for(i=0; i<NR_BANKS; i++)
-
dbmsg("bank[%d]-->[0x%x--0x%x],h=%x", i, meminfo.bank[i].start, meminfo.bank[i].size, meminfo.bank[i].highmem);
-
-
if (mdesc->fixup)
-
{
-
dbmsg("fixup=0x%x", mdesc->fixup);
-
mdesc->fixup(tags, &from, &meminfo);
-
}
-
for(i=0; i<NR_BANKS; i++) -->此处打印发现meminfo结构体为空
-
dbmsg("bank[%d]-->[0x%x--0x%x],h=%x", i, meminfo.bank[i].start, meminfo.bank[i].size, meminfo.bank[i].highmem);
-
-
if (tags->hdr.tag == ATAG_CORE) {
-
if (meminfo.nr_banks != 0)
-
squash_mem_tags(tags);
-
save_atags(tags);
-
parse_tags(tags); -->所以重点在parse_tags中
-
}
-
for(i=0; i<NR_BANKS; i++) -->此处打印发现meminfo结构体不为空
-
dbmsg("bank[%d]-->[0x%x--0x%x],h=%x", i, meminfo.bank[i].start, meminfo.bank[i].size, meminfo.bank[i].highmem);
-
-
/* parse_early_param needs a boot_command_line */
-
strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
-
-
return mdesc;
-
}
在arch/arm/kernel/setup.c中L859:setup_machine_tags-->parse_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);
-
}
在arch/arm/kernel/setup.c中L866:
setup_machine_tags-->parse_tags-->parse_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); //对每个参数都调用一次t->parse:例如mem类型会调用parse_tag_mem32
-
break;
-
}
-
-
return t < &__tagtable_end;
-
}
在arch/arm/kernel/setup.c中L776
:setup_machine_tags-->parse_tags-->parse_tag-->parse_tag_mem32
-
static int __init parse_tag_mem32(const struct tag *tag)
-
{
-
dbmsg("tag->start=0x%x, tag->mem.size=0x%x", tag->u.mem.start, tag->u.mem.size);
-
//打印结果tag->u.mem.start=0x40000000, tag->u.mem.size=0x40000000
-
//正好是内存的起始与大小
-
return arm_add_memory(tag->u.mem.start, tag->u.mem.size); //这会将start与size保存在meminfo中
-
}
3.3
从memblock中获取内存大小
在arch/arm/mm/init.c中start_kernel-->mm_init-->mem_init
-
void __init mem_init(void)
-
{
-
....
-
-
/*
-
* Since our memory may not be contiguous, calculate the
-
* real number of pages we have in this system
-
*/
-
printk(KERN_INFO "Memory:");
-
num_physpages = 0;
-
for_each_memblock(memory, reg) {
-
unsigned long pages = memblock_region_memory_end_pfn(reg) - memblock_region_memory_base_pfn(reg);
-
num_physpages += pages;
-
printk(" %ldMB", pages >> (20 - PAGE_SHIFT));
-
}
-
printk(" = %luMB total\n", num_physpages >> (20 - PAGE_SHIFT));
-
-
printk(KERN_NOTICE "Memory: %luk/%luk available, %luk reserved, %luK highmem\n",
-
nr_free_pages() << (PAGE_SHIFT-10),
-
free_pages << (PAGE_SHIFT-10),
-
reserved_pages << (PAGE_SHIFT-10),
-
totalhigh_pages << (PAGE_SHIFT-10));
-
....
-
}
注意这个宏:
-
#define for_each_memblock(memblock_type, region) \
-
for (region = memblock.memblock_type.regions; \ 这儿的memblock不是结构体
-
region < (memblock.memblock_type.regions + memblock.memblock_type.cnt); \
-
region++)
-
//注意:这儿的memblock不是结构体,而是变量名
-
struct memblock memblock __initdata_memblock -->在mm/memblock.c中定义的
阅读(3804) | 评论(0) | 转发(0) |