为了启动ARM Linux,需要一个boot loader。boot loader提供下述工作:
初始化RAM
初始化serial port
检测machine type
设置kernel tagged list
加载initramfs
call the kernel image
初始化RAM是强制的,因为内核运行在RAM上。
初始化serial port是可选的,初始化serial port可使kernel的早期启动阶段具有输出调试信息的能力。
检测machine type,现存的boot loader是可选的,新的boot loader,对于非DT-only,则是强制的。boot loader将MACH_TYPE_xxx通过r1寄存器传递给内核。见linux/arch/arm/tools/mach-types。
对于DT-only平台,machine type是由device tree决定的。
boot loader必须提供tagged list或者dtb image给内核。boot data的地址通过寄存器r2传递给内核。
kernel tagged list
一个合法的tagged list以ATAG_CORE开始,以ATAG_NONE结束。boot loader至少应该传递系统内核的大小、位置以及文件系统的位置给内核。
tagged list必须放在内核解压器和initrd bootp程序不会覆盖的地方,推荐的地方是RAM的第一个16KiB处。
the device tree
boot loader应该将device tree image (dtb)放在64位对齐的地址。dtb的格式可参考文档2。
内核将检查dtb物理地址处的内容是否为dtb magic value 0xd00dfeed,来确定是dtb还是tagged list。
同理,dtb也要放在一个合适的位置,防止和覆盖,安全的地址是RAM的128MiB之后。
这个是可选的,initramfs的唯一目的是挂载一个ram rootfs。
有两种方法调用kernel zImage。如果zImage存在flash上,且链接正确,可以在flash上运行,这样就可以直接在flash上call the zImage。zImage也可以被拷贝到系统RAM,从那里运行。
当启动一个raw (非zImage)内核时,约束更严。内核必须加载到地址TEXT_OFFSET - PAGE_OFFSET。
同时下列条件需要满足:
- 静默所有的DMA设备。
- CPU寄存器
r0 = 0
r1 = machine type
r2 = tagged list地址或者dtb地址
- CPU mode
禁止所有的中断,不包括ARM virtualization extentions的CPU必须处于SVC模式。
- Caches, MMUs
MMU必须关闭,指令Cache可以打开或关闭,数据cache必须关闭。
- boot loader直接跳到内核镜像的第一条指令执行。
支持ARM指令的CPU,必须处于ARM状态。即使是Thumb-2内核。
只支持Thumb指令的CPU,如Cortex-M系列,必须处于Thumb状态。
参考文档
[1] Russell King. https://www.kernel.org/doc/Documentation/arm/Booting
[2] https://www.kernel.org/doc/Documentation/devicetree/booting-without-of.txt
[3] http://www.linuxfromscratch.org/blfs/view/svn/postlfs/initramfs.html