我不了解加载U-Boot时RAM中发生了什么。我正在开发Xilinx Zynq ZC702评估套件,并且正在尝试使用U-Boot在其上加载Linux内核。因此,我使用了Xilinx工具Vivado和SDK来生成一个BOOT.bin文件,该文件逐步写在SD卡上:

  • 使用Vivado,
  • 创建一个硬件项目
  • 使用SDK
  • 生成FSBL和FPGA比特流
  • 创建一个包含FSBL +比特流+ U-Boot的引导镜像(我从xilinx Git存储库下载了U-Boot源代码)。

  • 简而言之,我遵循了Xilinx User Guide上描述的所有步骤。

    但是现在,在加载内核之前,我想了解正在发生的事情,但我不能。根据文档,U-Boot如果从闪存中加载,则会将自身复制到RAM中并从那里执行,但是在哪里呢?

    我在网上搜索后,发现U-Boot自身提取的地址是由 CONFIG_SYS_TEXT_BASE 在include/configs/zynq-common.h中定义的,它看起来是0x400_0000。

    但是在另一个网站上,我看到我们可以在 Debug模式下打印重定位地址,因此我修改了文件common/board_r.c并改写了函数“initr_announce”以打印“gd-> relocaddr”字段。这一次,U-Boot似乎使用了偏移地址0x3FF3_7000。

    当我使用U-Boot命令“md”检查内存时,我看到使用了两个偏移量,并且在两个位置都看到了一种魔术数字“be00_00ea”:
    Xilinx First Stage Boot Loader
    Release 2014.4  Feb  8 2016-14:53:56
    Devcfg driver initialized
    Silicon Version 3.1
    Boot mode is SD
    SD: rc= 0
    SD Init Done
    Flash Base Address: 0xE0100000
    Reboot status register: 0x60400000
    Multiboot Register: 0x0000C000
    Image Start Address: 0x00000000
    Partition Header Offset:0x00000C80
    Partition Count: 3
    Partition Number: 1
    Header Dump
    Image Word Len: 0x000F6EC0
    Data Word Len: 0x000F6EC0
    Partition Word Len:0x000F6EC0
    Load Addr: 0x00000000
    Exec Addr: 0x00000000
    Partition Start: 0x000065D0
    Partition Attr: 0x00000020
    Partition Checksum Offset: 0x00000000
    Section Count: 0x00000001
    Checksum: 0xFFD14B7E
    Bitstream
    In FsblHookBeforeBitstreamDload function
    PCAP:StatusReg = 0x40000A30
    PCAP:device ready
    PCAP:Clear done
    Level Shifter Value = 0xA
    Devcfg Status register = 0x40000A30
    PCAP:Fabric is Initialized done
    PCAP register dump:
    PCAP CTRL 0xF8007000: 0x4C00E07F
    PCAP LOCK 0xF8007004: 0x0000001A
    PCAP CONFIG 0xF8007008: 0x00000508
    PCAP ISR 0xF800700C: 0x0802000B
    PCAP IMR 0xF8007010: 0xFFFFFFFF
    PCAP STATUS 0xF8007014: 0x00000A30
    PCAP DMA SRC ADDR 0xF8007018: 0x00100001
    PCAP DMA DEST ADDR 0xF800701C: 0xFFFFFFFF
    PCAP DMA SRC LEN 0xF8007020: 0x000F6EC0
    PCAP DMA DEST LEN 0xF8007024: 0x000F6EC0
    PCAP ROM SHADOW CTRL 0xF8007028: 0xFFFFFFFF
    PCAP MBOOT 0xF800702C: 0x0000C000
    PCAP SW ID 0xF8007030: 0x00000000
    PCAP UNLOCK 0xF8007034: 0x757BDF0D
    PCAP MCTRL 0xF8007080: 0x30800100
    
    DMA Done !
    
    FPGA Done !
    In FsblHookAfterBitstreamDload function
    Partition Number: 2
    Header Dump
    Image Word Len: 0x0001BA12
    Data Word Len: 0x0001BA12
    Partition Word Len:0x0001BA12
    Load Addr: 0x04000000
    Exec Addr: 0x04000000
    Partition Start: 0x000FD490
    Partition Attr: 0x00000010
    Partition Checksum Offset: 0x00000000
    Section Count: 0x00000001
    Checksum: 0xF7EAFAC8
    Application
    Handoff Address: 0x04000000
    In FsblHookBeforeHandoff function
    SUCCESSFUL_HANDOFF
    FSBL Status = 0x1
    
    
    U-Boot 2015.07 (Feb 11 2016 - 10:24:28 +0100)
    
    Model: Zynq ZC702 Development Board
    I2C:   ready
    DRAM:  ECC disabled 1 GiB
    MMC:   zynq_sdhci: 0
    SF: Detected N25Q128A with page size 256 Bytes, erase size 64 KiB, total 16 MiB
    In:    serial
    Out:   serial
    Err:   serial
    Model: Zynq ZC702 Development Board
    Net:   Gem.e000b000
    Hit any key to stop autoboot:  0
    zynq-uboot> md 0x4000000
    04000000: ea0000be e59ff014 e59ff014 e59ff014    ................
    04000010: e59ff014 e59ff014 e59ff014 e59ff014    ................
    04000020: 04000060 040000c0 04000120 04000180    `....... .......
    04000030: 040001e0 04000240 040002a0 deadbeef    ....@...........
    04000040: 0badc0de e320f000 e320f000 e320f000    ...... ... ... .
    04000050: e320f000 e320f000 e320f000 e320f000    .. ... ... ... .
    04000060: e51fd028 e58de000 e14fe000 e58de004    (.........O.....
    04000070: e3a0d013 e169f00d e1a0e00f e1b0f00e    ......i.........
    04000080: e24dd048 e88d1fff e51f2050 e892000c    H.M.....P ......
    04000090: e28d0048 e28d5034 e1a0100e e885000f    H...4P..........
    040000a0: e1a0000d eb0005dc e320f000 e320f000    .......... ... .
    040000b0: e320f000 e320f000 e320f000 e320f000    .. ... ... ... .
    040000c0: e51fd088 e58de000 e14fe000 e58de004    ..........O.....
    040000d0: e3a0d013 e169f00d e1a0e00f e1b0f00e    ......i.........
    040000e0: e24dd048 e88d1fff e51f20b0 e892000c    H.M...... ......
    040000f0: e28d0048 e28d5034 e1a0100e e885000f    H...4P..........
    zynq-uboot> md 0x3ff37000
    3ff37000: ea0000be e59ff014 e59ff014 e59ff014    ................
    3ff37010: e59ff014 e59ff014 e59ff014 e59ff014    ................
    3ff37020: 3ff37060 3ff370c0 3ff37120 3ff37180    `p.?.p.? q.?.q.?
    3ff37030: 3ff371e0 3ff37240 3ff372a0 deadbeef    .q.?@r.?.r.?....
    3ff37040: 3f312628 e320f000 e320f000 e320f000    (&1?.. ... ... .
    3ff37050: e320f000 e320f000 e320f000 e320f000    .. ... ... ... .
    3ff37060: e51fd028 e58de000 e14fe000 e58de004    (.........O.....
    3ff37070: e3a0d013 e169f00d e1a0e00f e1b0f00e    ......i.........
    3ff37080: e24dd048 e88d1fff e51f2050 e892000c    H.M.....P ......
    3ff37090: e28d0048 e28d5034 e1a0100e e885000f    H...4P..........
    3ff370a0: e1a0000d eb0005dc e320f000 e320f000    .......... ... .
    3ff370b0: e320f000 e320f000 e320f000 e320f000    .. ... ... ... .
    3ff370c0: e51fd088 e58de000 e14fe000 e58de004    ..........O.....
    3ff370d0: e3a0d013 e169f00d e1a0e00f e1b0f00e    ......i.........
    3ff370e0: e24dd048 e88d1fff e51f20b0 e892000c    H.M...... ......
    3ff370f0: e28d0048 e28d5034 e1a0100e e885000f    H...4P..........
    zynq-uboot>
    

    为什么U-Boot需要这两个补偿? U-Boot的实际内存占用量是多少?更一般地说,我可以在哪里放置内核以确保它不会覆盖某些内容?

    最佳答案

    在ARM体系结构上进行u-boot重定位

    这是两阶段引导过程的整个序列:

  • ROM代码将SPL(从SD卡上的MLO文件读取)到CONFIG_SPL_TEXT_BASE地址。此地址通常位于SRAM中,而无需初始化即可使用(相对于RAM)。 ROM代码跳转到SPL代码。
  • SPL配置RAM,然后将u-boot(从SD卡上的u-boot.img文件读取)到CONFIG_SYS_TEXT_BASE RAM地址(通常在RAM的开头)并运行
  • u-boot会将其自身重新定位到gd->relocaddr RAM地址(通常位于RAM的末尾),然后跳转到已重新定位的代码
  • 现在我们准备启动内核

  • 对于单阶段引导,您没有SPL,通常仅使用u-boot.bin文件。在这种情况下,您只有第3步和第4步。

    关于重定位有两种情况(如doc/README.arm-relocation中所述):
  • CONFIG_SYS_TEXT_BASE != gd->relocaddr:将执行重定位
  • CONFIG_SYS_TEXT_BASE == gd->relocaddr:将不执行重定位

  • 在您的情况下,您看到执行了重定位(作为CONFIG_SYS_TEXT_BASE != gd->relocaddr)。

    因此,解决您的问题:



    重定位的原因在u-boot ARM relocation task中进行了描述:



    确实,如果您希望编写代码,则可以看到gd->relocaddr是RAM的结尾减去监视器代码(U-Boot)的大小:

    gd->relocaddr = gd->ram_top;
    ...
    gd->relocaddr -= gd->mon_len;
    

    还可以执行一些额外的内存保留。例如,在我的平台(TI DRA7XX EVM)上,我可以看到称为的下一个函数:
    setup_dest_addr()
    reserve_round_4k()
    reserve_mmu()
    reserve_uboot()
    

    实际的重定位是在board_init_f()调用之后完成的。

    arch/arm/lib/crt0.S :
    bl board_init_f
    ...
    b relocate_code
    

    arch/arm/lib/relocate.S :
    ENTRY(relocate_code)
    

    现在很容易回答您的下一个问题:



    在重定位之前,U-Boot位于CONFIG_SYS_TEXT_BASE。重定位后,U-Boot驻留在gs->relocaddr

    关于您的最后一个问题:



    由于U-Boot已重定位到RAM的末尾,因此从理论上讲,您可以使用任何RAM地址将内核放入其中。但是看看CONFIG_EXTRA_ENV_SETTINGS中的include/configs/zynq-common.h定义:
    "sdboot=if mmcinfo; then " \
            "run uenvboot; " \
            "echo Copying Linux from SD to RAM... && " \
            "load mmc 0 ${kernel_load_address} ${kernel_image} && " \
            "load mmc 0 ${devicetree_load_address} ${devicetree_image} && " \
            "load mmc 0 ${ramdisk_load_address} ${ramdisk_image} && " \
            "bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}; " \
        "fi\0" \
    

    从那里您可以看到应该将内核加载到${kernel_load_address},即0x2080000:
    "kernel_load_address=0x2080000\0" \
    

    有关其他常量,请参见该定义的其余部分。

    bdinfo命令

    您会发现bdinfo命令很有用:可以使用U-Boot shell中的bdinfo命令找到重定位地址以及其他有用的信息。例如,对于DRA7XX EVM:
    => bdinfo
    
    DRAM bank   = 0x00000000
    -> start    = 0x80000000
    -> size     = 0x60000000
    TLB addr    = 0xDFFF0000
    relocaddr   = 0xDFF5D000
    reloc off   = 0x5F75D000
    irq_sp      = 0xDEF3CEE0
    sp start    = 0xDEF3CED0
    

    从这里您可以看到:
  • RAM从0x80000000开始
  • RAM大小为0x60000000
  • ...所以RAM结束(gd->ram_top)是0x80000000 + 0x60000000 = 0xE0000000
  • 的重定位地址是0xDFF5D000
  • 保留的用于重定位的内存是0xE0000000 - 0xDFF5D000 = 652 KB
  • 监视器(U引导)的大小大约为TLB addr - relocaddr = 0xDFFF0000 - 0xDFF5D000 = 588 KB

  • 也可以看看:

    [1] u-boot : Relocation

    [2] what is the use of SPL (secondary program loader)

    [3] commit that adds ARM relocation support to u-boot

    关于linux-kernel - 了解U-Boot内存占用量,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35336940/

    10-11 23:20
    查看更多