X86的pc启动过程
1、 cpu上电初始化,接着从某个特定的位置取得跳转指令并执行,跳转到BIOS
2、 BIOS被固化在主板上的一个小ROM中,
工作就是上电自检,加载内核引导程序(读取启动设备第一个扇区512个字节的信息),
主引导记录MBR包括446字节的引导程序,64字节的分区表,2个字节的校验位
3、 内核引导程序,
主引导程序扫描分区表,将分区表中的次引导程序加载到内存中执行,次引导程序加载内核映像。
Pc环境中,内核引导程序常用LILO和GRUB,嵌入式环境的话,常用UBOOT
4、 内核
首先执行/boot/head.s 进行硬件基本设置,(开始的时候c运行环境还没有搭建)同时设置基本的运行环境,开始解压内核
调用arch/i386/head.s 的startup_32 函数,进行页表初始化,启用内存分页功能。
调用Init/main.c的start_kernel函数,进入内核初始化。
ATPCS定义了寄存器组中的{R0~R3}作为参数传递和结果返回寄存器,如果参数数目超过四个,则使用堆栈进行传递。我们知道内部寄存器的访问速度是远远大于存储器的,所以要尽量使参数传递在寄存器里面进行,即应尽量把函数的参数控制在四个以下。
Bootloadeer的流程
Bootloader 的stage1(用汇编语言编写,c环境没有搭建好)
硬件初始化(关闭中断,cpu时钟初始化)
准备RAM空间
复制stage2到RAM,(内存运行速度快)
堆栈设置,
跳转到stage2的c入口
Stage2:
初始化本阶段的硬件设备
将内核映像和根文件系统从flash读到RAM中,设置启动参数
调用内核
Uboot 下bootm 执行的文件需要特定的文件头
而go命令不需要
_init宏所修饰的函数所占用的内存在初始化结束后就会释放
Uboot 的启动代码分析(以2440为例)
1、 设置arm的工作模式
start_code:
/*
* set the cpu to SVC32 mode
*/
mrs r0,cpsr //读取程序状态寄存器到通用寄存器r0
bic r0,r0,#0x1f //bic 位清除操作
orr r0,r0,#0xd3 //逻辑或
msr cpsr,r0 //将R0的值写回cpsr,因为我们无法直接操作cpst
2、 关闭看门狗,关闭所有中断
3、 系统时钟初始化
4、 将uboot第二阶段代码定位到RAM中
5、 初始化堆栈
6、 跳转到stage2的c入口
第二阶段
必要的硬件初始化
配置环境变量
等待用户操作