我们在基于 ARM 的嵌入式系统上运行 U-Boot 的定制版本,并希望加载带有设备树 blob 的 Linux 4.3。该系统配备 1GB RAM,其中顶部 128MB 保留用于持久存储。我使用 tftp 将内核和 DTB 复制到某些内存位置(内核:0x02000000,DTB:0x02400000),现在我想忽略 initramfs。所以我打电话bootm 0x2000000 - 0x2400000
。
发生的情况是,DTB 被重新定位到可用 U-Boot 内存的最末端,即 0x37b60000(虚拟:0xf7b60000)。 Linux 无法启动,因为它无法访问该地址。这似乎是一个关于highmem/lowmem的问题,我不明白,lowmem以760MB结束(虚拟0xef800000)。 highmem 不是应该在需要时动态映射吗? (CONFIG_HIGHMEM 已设置。)
解决这个问题的干净且正确的方法是什么——使 U-Boot 使用较低的位置(如何?)或更改 Linux 配置以能够访问高内存(如何?)?
注意:使用 fdt_high=0xffffffff(和 initrd_high=0xffffffff)Linux 可以正常启动,因为重定位被抑制。
带调试信息的 U-Boot:
DRAM: Monitor len: 00044358
Ram size: 40000000
Ram top: 40000000
Reserving 131072k for protected RAM at 38000000
TLB table from 37ff0000 to 37ff4000
Reserving 272k for U-Boot at: 37fab000
Reserving 4352k for malloc() at: 37b6b000
Reserving 80 Bytes for Board Info at: 37b6afb0
Reserving 160 Bytes for Global Data at: 37b6af10
RAM Configuration:
Bank #0: 00000000 1 GiB
DRAM: 1 GiB
New Stack Pointer is: 37b6aef0
Relocation Offset is: 33fab000
Relocating to 37fab000, new gd at 37b6af10, sp at 37b6aef0
[…]
* fdt: cmdline image address = 0x02400000
## Checking for 'FDT'/'FDT Image' at 02400000
* fdt: raw FDT blob
## Flattened Device Tree blob at 02400000
Booting using the fdt blob at 0x2400000
of_flat_tree at 0x02400000 size 0x0000493c
Loading Multi-File Image ... OK
## device tree at 02400000 ... 0240493b (len=31036 [0x793C])
Loading Device Tree to 37b60000, end 37b6793b ... OK
答案1
因此,解决此问题的方法之一是使用一些额外的环境变量。如果我们查看 include/configs/ti_armv7_common.h 我们有:
/*
* We setup defaults based on constraints from the Linux kernel, which should
* also be safe elsewhere. We have the default load at 32MB into DDR (for
* the kernel), FDT above 128MB (the maximum location for the end of the
* kernel), and the ramdisk 512KB above that (allowing for hopefully never
* seen large trees). We say all of this must be within the first 256MB
* as that will normally be within the kernel lowmem and thus visible via
* bootm_size and we only run on platforms with 256MB or more of memory.
*/
#define DEFAULT_LINUX_BOOT_ENV \
"loadaddr=0x82000000\0" \
"kernel_addr_r=0x82000000\0" \
"fdtaddr=0x88000000\0" \
"fdt_addr_r=0x88000000\0" \
"rdaddr=0x88080000\0" \
"ramdisk_addr_r=0x88080000\0" \
"scriptaddr=0x80000000\0" \
"pxefile_addr_r=0x80100000\0" \
"bootm_size=0x10000000\0"
因此,对于您所描述的问题,您需要重新使用 bootm_size=0x10000000 来确保我们将设备树保留在前 256MB 内,这将是内核可见的 lowmem (至少使用今天的默认内核设置,大小为内核 lowmem 是可配置的)。
另一个同样有用的解决方案是简单地将设备树和 ramdisk 放入内存中知道他们将是安全的,并使用 fdt_high=0xffffffff 和 initrd_high=0xffffffff 来禁用重定位。重定位的主要用途是确保在一般情况下一切都是安全的(其中 U-Boot 可以被赋予随机内核、设备树和 ramdisk,并且根本不知道所有东西有多大)。在这样的生产情况下,您可以找出一些始终安全且正确的值,将其加载到此处,而无需再次移动它们。