Boot

Linux 無法訪問 U-Boot 重定位的 FDT(在 highmem 中)

  • January 26, 2016

我們在基於 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 並且根本不知道一切有多大)。在這樣的生產案例中,您可以找出一些始終安全且正確的值,在那裡載入而不是再次移動它們。

引用自:https://unix.stackexchange.com/questions/257508