32位i.MX6 Arm板Bootloader开发:设备树启动时如何传递initrd位置?
我正在为32位i.MX6 Arm板编写Bootloader,希望使用设备树和内存中静态存储的initrd文件启动Linux内核。参考U-Boot可知,可使用bootm命令传递内核、设备树及ramdisk参数:
从内存启动应用镜像:
bootm [addr [arg ...]] - 启动存储在内存中的应用镜像并传递参数'arg...';启动Linux内核时,‘arg'可为initrd镜像的地址
我了解Bootloader向内核传递信息有两种方式:传统ATAGS方法和现代设备树方法。通过ATAGS可使用ATAG_INITRD2标签指定ramdisk的内存地址,但使用扁平设备树时不会向内核传递ATAGS(启动日志会显示"No ATAGs?"),且未找到设备树方式下指定ramdisk的方法。
查阅Arm平台Linux内核启动文档,文档指定了以下接口:
- CPU寄存器设置
r0 = 0,
r1 = 上述(3)中获取的机器类型编号。
r2 = 系统RAM中标记列表的物理地址,或系统RAM中设备树块(dtb)的物理地址
该文档提到启动前必须配置initramfs,但未说明设备树启动时的配置方法。请问是否存在替代方案?U-Boot是否会自动将相关信息追加到设备树中,或存在其他告知内核initrd位置的方式?
1. U-Boot会自动修改DTB传递initrd信息
当使用U-Boot的bootm(或针对压缩内核的bootz)命令,按bootm <内核地址> <initrd地址> <DTB地址>的格式传递参数时,U-Boot会自动完成以下操作:
- 解析initrd镜像的大小(U-Boot支持识别标准cpio格式的initrd镜像)
- 在DTB的
chosen节点中添加linux,initrd-start和linux,initrd-end两个属性,分别填入initrd的物理起始地址和结束地址(起始地址+镜像大小) - 内核启动时会自动读取这两个属性,找到内存中的initrd并加载
比如执行U-Boot命令:
bootm 0x10800000 0x11000000 0x12000000
U-Boot会自动更新DTB的chosen节点,最终DTB中会出现类似内容:
chosen { linux,initrd-start = <0x11000000>; linux,initrd-end = <0x11800000>; };
2. 自定义Bootloader时的手动配置方法
如果是自己编写Bootloader而非使用U-Boot,需要手动修改内存中的DTB:
- 找到DTB中的
chosen节点(如果没有则创建该节点) - 添加
linux,initrd-start和linux,initrd-end属性,值为initrd在内存中的物理起始和结束地址 - 确保修改后的DTB结构合法(若有校验和等字段,需同步更新)
示例DTB片段:
chosen { bootargs = "console=ttymxc0,115200 root=/dev/ram rw"; linux,initrd-start = <0x11000000>; linux,initrd-end = <0x11800000>; };
3. 补充:内核启动参数方式(适合存储设备中的initrd)
如果initrd存储在Flash等存储设备上,也可以通过chosen节点的bootargs传递initrd=参数,但对于内存中静态存储的initrd,使用上述地址属性的方式更直接高效。
内容的提问来源于stack exchange,提问作者BakaOsaka

