Linux 無法訪問 U-Boot 重定位的 FDT(在 highmem 中)
我們在基於 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
所以解決這個問題的方法之一是使用一些額外的環境變數。如果我們查看 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 內,這將是核心可見的低記憶體(至少在今天使用預設核心設置,大小核心低記憶體是可配置的)。
這裡另一個同樣有用的解決方案是簡單地將設備樹和 ramdisk 放入您知道它們將是安全的記憶體中,並使用 fdt_high=0xffffffff 和 initrd_high=0xffffffff 禁用重定位。重定位的主要用途是確保在一般情況下事情是安全的(U-Boot 可以被交給隨機核心和設備樹和 ramdisk 並且根本不知道一切有多大)。在這樣的生產案例中,您可以找出一些始終安全且正確的值,在那裡載入而不是再次移動它們。