文章目录
Booting ARM Linux
本文翻译自Linux内核文档,如有翻译不当,敬请谅解!
以下文字说明与内核的2.4.18-rmk6版本及以上相关。
为了引导ARM Linux,您需要一个引导加载程序,它很小在主内核之前运行的程序。引导加载程序将初始化各种设备,并最终调用Linux内核,将信息传递给内核。本质上,引导加载程序应该(至少)提供以下内容:
- 设置和初始化RAM。
- 初始化一个串口。
- 检测机器类型。
- 设置内核标记列表。
- 加载initramfs。
- 调用kernel image。
设置和初始化RAM
Loader版本 | 特性 |
---|---|
Existing boot loaders | MANDATORY |
New boot loaders | MANDATORY |
引导加载程序应该找到并初始化内核将用于系统中易失性数据存储的所有RAM。它以依赖于机器的方式执行此操作。(它可以使用内部算法自动定位和调整所有RAM的大小,也可以使用机器中RAM的知识,或者引导加载程序设计者认为合适的任何其他方法)。
初始化一个串口
Loader版本 | 特性 |
---|---|
Existing boot loaders | OPTIONAL, RECOMMENDED |
New boot loaders | OPTIONAL, RECOMMENDED |
引导加载程序应该初始化并启用目标上的一个串行端口。这允许内核串行驱动程序自动检测内核控制台应该使用哪个串行端口(通常用于调试目的,或与目标通信)。
另一种方法是,引导加载程序可以通过指定端口的带标记列表和其中描述的串行格式选项将相关的“console=”选项传递给内核:Documentation/admin-guide/kernel-parameters.rst.
检测机器类型
Loader版本 | 特性 |
---|---|
Existing boot loaders | OPTIONAL |
New boot loaders | MANDATORY except for DT-only platforms |
引导加载程序应该通过某种方法检测正在运行的机器类型。无论是硬编码的值,还是查看连接硬件的算法,都超出了本文的范围。引导加载程序最终必须能够向内核提供MACH_TYPE_xxx值。(见linux /arch/arm/tools/mach-types)。这应该传递给寄存器r1中的内核。
对于只使用dt的平台,机器类型将由设备树决定。将机器类型设置为所有类型(~0)。这不是严格必需的,但可以确保它不匹配任何现有类型。
设置启动数据
Loader版本 | 特性 |
---|---|
Existing boot loaders | OPTIONAL, RECOMMENDED |
New boot loaders | MANDATORY |
引导加载程序必须提供带标记的列表或dtb映像,以便将配置数据传递给内核。引导数据的物理地址在寄存器r2中传递给内核。
设置内核标记列表
引导加载程序必须创建并初始化内核标记的列表。一个有效的带标签列表以ATAG_CORE开始,以ATAG_NONE结束。ATAG_CORE标记可能是空的,也可能不是空的。一个空的ATAG_CORE标记的大小字段设置为’2’ (0x00000002)。ATAG_NONE必须将size字段设置为0。
列表中可以放置任意数量的标记。未定义重复标签是对前一个标签所携带的信息进行追加,还是对信息进行整体替换;有些标记表现为前者,有些表现为后者。
引导加载程序必须传递系统内存的最小大小和位置,以及根文件系统的位置。因此,最小标记列表应该是:
+-----------+
base -> | ATAG_CORE | |
+-----------+ |
| ATAG_MEM | | increasing address
+-----------+ |
| ATAG_NONE | |
+-----------+ v
标记的列表应该存储在系统RAM中。
标记的列表必须放在一个内存区域中,并且内核解压器和initrd的’bootp’程序都不会覆盖它。建议放置在RAM的第一个16KiB中。
设置Device Tree
引导加载程序必须将设备树映像(dtb)以64位对齐的地址加载到系统ram中,并使用引导数据对其进行初始化。dtb格式记录在文档/devicetree/boot-out-of.txt中。内核将在dtb物理地址处查找0xd00dfeed的dtb魔法值,以确定是否传递了dtb,而不是带标记的列表。
引导加载程序必须传递系统内存的最小大小和位置,以及根文件系统的位置。dtb必须放在内核解压器不会覆盖它的内存区域中,而保留在内核的低内存映射将覆盖的区域中。
从RAM开始,一个安全的位置刚好位于128MiB边界之上。
加载 initramfs
Loader版本 | 特性 |
---|---|
Existing boot loaders | OPTIONAL |
New boot loaders | OPTIONAL |
如果使用initramfs,那么就像使用dtb一样,它必须被放置在一个内存区域中,内核解压器不会覆盖它,同时也必须放置在内核的低内存映射所覆盖的区域中。
一个安全的位置就在设备树blob的上面,它本身将按照上面的建议从RAM的开始加载到128MiB边界的上面。
调用kernel image
Loader版本 | 特性 |
---|---|
Existing boot loaders | MANDATORY |
New boot loaders | MANDATORY |
调用内核zImage有两个选项。如果zImage存储在flash中,并且链接正确,以便从flash中运行,那么引导加载程序直接调用flash中的zImage是合法的。
zImage也可以放在系统RAM中并在那里调用。内核应该放在RAM的第一个128MiB中。建议将其加载到32MiB以上,以避免在解压缩之前需要重新定位,这将使引导过程稍微快一些。
当启动一个原始(非zimage)内核时,约束更加严格。在这种情况下,内核必须以一个等于TEXT_OFFSET - PAGE_OFFSET的偏移量加载到系统中。
在任何情况下,必须符合下列条件:
-
静默所有具有DMA能力的设备,这样内存就不会被伪造的网络数据包或磁盘数据损坏。这将为您节省许多调试时间。
-
CPU寄存器设置
r0 = 0,
r1 = 在上面(3)中发现的机器类型号。
r2 = 系统RAM中已标记列表的物理地址,或系统RAM中设备树块(dtb)的物理地址
-
CPU模式
必须禁用所有形式的中断(IRQs和FIQs)。
对于不包含ARM虚拟化扩展的cpu,CPU必须处于SVC模式。(Angel存在特殊例外)。
可以在HYP模式下输入支持虚拟化扩展的cpu,以便内核能够充分利用这些扩展。这是此类cpu推荐的引导方法,除非预安装的hypervisor已经在使用虚拟化。
如果内核由于任何原因没有进入HYP模式,那么它必须进入SVC模式。
-
Caches, MMUs
MMU必须关闭。
指令缓存可以打开或关闭。
数据缓存必须关闭。
如果内核是在HYP模式下输入的,除了普通的PL1(特权内核模式)配置外,上述要求也适用于HYP模式配置。此外,必须禁用管理程序中的所有陷阱,并且必须为架构上可能这样做的所有外围设备和CPU资源授予PL1访问权限。除了进入HYP模式之外,系统配置应该是这样的:不支持虚拟化扩展的内核可以在没有额外帮助的情况下正确引导。
引导加载程序应该通过直接跳到内核映像的第一条指令来调用内核映像。
在支持ARM指令集的cpu上,条目必须处于ARM状态,即使对于thumb2内核也是如此。
在只支持Thumb指令集(如Cortex-M类cpu)的cpu上,条目必须处于Thumb状态。