微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > Arm linux kernel 启动之start_kernel

Arm linux kernel 启动之start_kernel

时间:11-09 来源:互联网 点击:

ype来取得proc_info_list这个结构体。这个过程实际上和我们在head-common.S里面的过程是一样的,不知道这里为什么不直接去读switch_data里面已经保存好的数据反而又查询一遍是为什么?取得proc_info_list以后,将里面的内容一个个赋值给相应的全局变量,然后将CPU的信息打印出来。然后它会从arm寄存器里面获得cache的信息,并将cache的信息打印出来。最后它会调用cpu_proc_init()的函数,这个函数实际上定义在proc-v6.S里面,没有做任何事情。

mdesc = setup_machine(machine_arch_type);

首先这个machine_arch_type定义在生成的./include/asm-arm/mach-types.h里面,这个setup_macine实际上也是和上面的processor类似,都是调用head-common.S里面的函数,根据machine ID来获得Machine的信息,并将Machine name打印出来。

if (mdesc->soft_reboot)

reboot_setup("s");

设置reboot方式,默认是硬启动;

if (__atags_pointer)

tags = phys_to_virt(__atags_pointer);

else if (mdesc->boot_params)

tags = phys_to_virt(mdesc->boot_params);

这里首先判断head-common.S里面定义的__atags_pointer是不是为空,不为空的话说明bootloader设置了初始化参数,将参数的物理地址转化为虚拟地址,这里有一个覆盖,就是说可以在Machine desc里面对初始化参数的物理地址重新定位。

if (tags->hdr.tag != ATAG_CORE)

convert_to_tag_list(tags);

if (tags->hdr.tag != ATAG_CORE)

tags = (struct tag *)&init_tags;

首先判断是不是正确的atag格式,如果是以前老版本的param_struct格式会首先将其转换成tag格式,如果转换以后还是不对,则使用默认的init_tags,这里判断的过程都是根据结构体第一个值是不是ATAG_CORE.

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);

这里首先判断fixup函数指针,这里一般为空,如果不为空就会地用fixup来重新修改memory map,meminfo这个结构体定义在arch/arm/include/asm/setup.h里面,描述了内存块的信息,内存块的个数,每个内存块的起始地址和大小,如果修改了memory map则需要从atag参数里面去掉bootloader传过来的的memory map信息,然后是保存一下atag,这个保存函数在这里实际上是空的,没有做任何操作,最后是对atag参数进行解析。这里要说明一下这里的tags实际上是一个tag的数组或者说队列,里面有多个tag结构体,每一个结构体都是一个header加一个参数,具体的结构我们可以看看setup.h。对ATAG参数的解析全部定义在arch/arm/kernel/setup.c里面,首先在setup.c里面定义了一个类似于这样__tagtable(ATAG_CORE, parse_tag_core)的宏,这个宏实际上是声明了一个放在__tagtable_begin和__tagtable_end段之间结构体,这个结构体定义了这个一个参数类型,和对这个参数类型进行解析的函数。所有的参数解析我们都可以从setup.c里面找到相对应的函数,比如说对boot_commad_line的解析,从config文件得到的default_commad_line就会被ATAG里面获得commad_line给替换掉;再比如ramdisk,就会将ATAG里面的ramdisk的信息赋值给rd_image_start, rd_size等系统的全局变量。

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;

这就就是对init_mm结构体进行赋值,具体不了解这些东西咋用的,但是就是将text和data段给赋值了。

memcpy(boot_command_line, from, COMMAND_LINE_SIZE);

boot_command_line[COMMAND_LINE_SIZE-1] = /0;

parse_cmdline(cmdline_p, from);

这里的boot_command_line来自于与config文件里面的CONFIG_CMDLINE,也有可能被ATAG里面的boot参数给覆盖,获得command_line以后对command_line进行解析。这个解析的过程也是在setup.c里面进行的,它首先查找.early_param.init段里面注册的结构体,通过__early_param将early_param结构体注册到这些段里面,实际这个early_param很简单一个就是类似于"initrd="的字符串,用来与command_line里面的字符进行匹配,如果匹配到了就执行early_param里面的那个函数,并将匹配到的字符作为参数传给函数。举个例子比如说我们现在的commadline里面有一句initrd=0x11000000,然后我们首先在early_param.init段里面搜索时候有没有early_param-> 这里的boot_command_line来自于与config文件里面的CONFIG_CMDLIN

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top