作者:GWD 时间:.8.25
一、汇编部分到第一个C之前准备
1、问:内核的工作
答
2、问:为什么有两个head.S
答:其中一个是自解压代码,运行时先解压内核
3、uboot中将参数写入结构体
4、查找用于查看是否支持指定的CPU与单板
5、在连接脚本中看一下3B这段存的是什么,所有架构初始化的信息都放在这个段中,然后启动后会进行遍历比较
接下来就是要看一下在内核中arch.info.init是什么
注:##是连字符号
找一下这个宏是谁在用,发现是单板在用,可以推测每一个被支持的单板都需要一个MACHINE_START结构体
展开可以看出是在定义一个结构体,但是这个结构体的特殊情况是,加了一个性质,这个性质是段性质,被加入了连接脚本中的“段”。
带入后就是这个结构体
6、建立页表,使内存映射到0x30000000
7、启动mmu
8、在mmu中启动kernel,这是内核中第一个C函数
9、剧透一下启动流程
二、挂接根文件分析
怎么确定挂接到哪个根文件呢?
1、命令行参数中root=XXX,然后_setup这个宏(宏是会自动加载的,不需要调用)调用root_dev_setup函数,保存到saved_root_name字符串中,所有的函数都被内核以若干结构体的类型保存到段中,然后对比字符串查找执行相应的函数;
Setup这个宏有三个参数,替代__setup_param(str, fn, fn, 0),特殊的是被强制加入了段属性,;
2、saved_root_name字符串中的数据会被void __init prepare_namespace(void)函数赋值给root_device_name。
3、mount_root(void)中启动第一个文件系统中的应用
三、Start_kernel函数(第一个C)解析参数、启动根文件系统
这两个函数是处理uboot中传进来的参数的
void __init setup_arch(char **cmdline_p)函数
Boot_params地址0x30000100与uboot中的参数地址是一样的,接下来就是读出参数并且保存了
init_post()用于启动第一个根文件(设备)