Понять объем памяти U-Boot
Я не понимаю, что происходит в ОЗУ при загрузке U-Boot. Я работаю над набором оценки Xilinx Zynq ZC702, и я пытаюсь загрузить на него ядро Linux с помощью U-Boot. Поэтому я использовал инструмент Xilinx Vivado и SDK для создания загрузки.bin файл, который записывается на SD-карте шаг за шагом:
- создайте проект HW с помощью Vivado,
- генерировать fsbl и FPGA битовый поток с помощью SDK,
- создайте загрузочный образ, содержащий fsbl + bitstream + U-Boot (я загрузил источники U-Boot из репозитория xilinx Git).
короче говоря, я выполнил все шаги, описанные на Руководство Пользователя Xilinx.
но теперь, перед загрузкой ядра, я хотел понять, что происходит, но я не могу. Согласно документации, U-Boot, если загружается из flash, копирует себя в ОЗУ и выполняет себя оттуда, но где ?
Я искал в интернете, и я нашел, что адрес, где U-Boot извлекает себя определяется в include / configs / zynq-common.h by CONFIG_SYS_TEXT_BASE, которые, как представляется, 0x400_0000.
но на другом веб-сайте я видел, что мы можем распечатать адрес перемещения в режиме отладки, поэтому я изменил файл 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 ? И вообще, где я могу поместить свое ядро, чтобы быть уверенным, что оно ничего не перезапишет ?
1 ответов
перемещение u-boot на архитектуре ARM
вот вся последовательность для двухступенчатого процесса загрузки:
- ROM-код читает SPL (от
MLO
файл на SD-карте) доCONFIG_SPL_TEXT_BASE
адрес. Этот адрес обычно находится в SRAM, который не нужно инициализировать, чтобы быть функциональным (в отличие от ОЗУ). ROM-код переходит в код SPL. - SPL настраивает ОЗУ, затем читает u-boot (от
u-boot.img
файл на SD-карте) доCONFIG_SYS_TEXT_BASE
адрес ОЗУ (который обычно находится в начало ОЗУ) и запустите его - u-boot перемещается в
gd->relocaddr
адрес ОЗУ (который обычно находится в конце ОЗУ) и переходит к перемещенному коду - теперь мы готовы к загрузке ядра
для одноступенчатой загрузки у вас нет SPL, обычно только это. В этом случае у вас есть только шаги 3 и 4.
есть два случая, касающиеся переселения (как описано в doc / README.перемещение руки):
-
CONFIG_SYS_TEXT_BASE != gd->relocaddr
: перемещение будет выполнено -
CONFIG_SYS_TEXT_BASE == gd->relocaddr
: перемещение не будет выполнено
в вашем случае вы видите, что перемещение было выполнено (как CONFIG_SYS_TEXT_BASE != gd->relocaddr
).
Итак, отвечая на ваш вопрос:
зачем U-Boot нужны эти два смещения ?
причина этого перемещения описана в рукоятка u-ботинка задача перемещения:
...мы можем измерить фактический размер памяти, присутствующей на плате, а затем переместить U-Boot в самый конец ОЗУ, оставив почти всю ОЗУ в качестве одной большой смежной области для "приложений", таких как загрузка ядра Linux, ramdisk и т. д.
действительно, если вы посмотрите на код, вы можете увидеть, что gd->relocaddr
это конец ОЗУ минус код монитора (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 / переместить.S:
ENTRY(relocate_code)
теперь легко ответить на ваш следующий вопрос:
каков реальный объем памяти U-Boot ?
перед перемещением U-Boot находится в CONFIG_SYS_TEXT_BASE
. После перемещения U-Boot находится на gs->relocaddr
.
по поводу вашего последнего вопроса:
где я могу поместить свое ядро, чтобы быть уверенным, что оно ничего не перезапишет?
поскольку U-Boot был перемещен в конец ОЗУ, вы теоретически можете использовать любой адрес ОЗУ для размещения ядра. Но взгляните на 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" \
оттуда вы можете видеть, что вы должны загрузить ядро в ${kernel_load_address}
, которая составляет 0x2080000
:
"kernel_load_address=0x2080000" \
см. остальную часть этого определения для других констант.
команда bdinfo
вы можете найти bdinfo
команда полезна: адрес перемещения вместе с другой полезной информацией можно найти с помощью bdinfo
команда из оболочки U-Boot. Например, для 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
- размер ОЗУ составляет
0x60000000
- ...Итак, RAM end (
gd->ram_top
) составляет0x80000000 + 0x60000000 = 0xE0000000
- адрес переезд
0xDFF5D000
- зарезервированная память для перемещения
0xE0000000 - 0xDFF5D000 = 652 KB
- монитор (U-Boot) размер приблизительно
TLB addr - relocaddr = 0xDFFF0000 - 0xDFF5D000 = 588 KB
Читайте также:
[2] что польза СПЛ (загрузчик вторичной программы)
[3] commit, который добавляет поддержку перемещения ARM в u-boot