Zrozumieć ślad pamięci U-Boot

Nie rozumiem co się dzieje w pamięci RAM podczas ładowania U-Boot. Pracuję nad zestawem ewaluacyjnym Xilinx Zynq ZC702 i próbuję załadować na niego jądro Linuksa za pomocą U-Boot. Więc użyłem narzędzia Xilinx Vivado i SDK do wygenerowania rozruchu.plik bin zapisywany na karcie SD krok po kroku:

  • Utwórz projekt sprzętowy za pomocą Vivado,
  • generowanie strumienia bitów FSBL i FPGA przy użyciu SDK,
  • utworzyć obraz rozruchowy zawierający FSBL + bitstream + U-Boot (pobrałem Źródła U-Boot z repozytorium Xilinx Git).

Krótko mówiąc, wykonałem wszystkie kroki opisane w Xilinx User Guide.

Ale teraz, przed załadowaniem jądra, chciałem zrozumieć, co się dzieje, ale nie mogę. zgodnie z dokumentacją, U-Boot, jeśli załadowany z Flasha, kopiuje się do pamięci RAM i wykonuje się stamtąd, ale gdzie?

Szukałem w sieci i znalazłem, że adres, na którym sam U-Boot wyodrębnia jest zdefiniowany w include / configs/Zynq-common.h by CONFIG_SYS_TEXT_BASE, które wydają się być 0x400_0000.

Ale na innej stronie widziałem, że możemy wydrukować adres relokacji w trybie debugowania, więc zmodyfikowałem plik common / board_r. c i nadpisałem funkcję " initr_announce ", aby wydrukować pole " gd->relocaddr ". Tym razem okazuje się, że U-Boot używa adresu offsetowego 0x3FF3_7000.

Kiedy używam polecenia U-Boot " md " do sprawdzenia w pamięci widzę, że używane są dwa offsety i widzę coś w rodzaju magicznej liczby " be00_00ea "w obu miejscach:

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> 
Po co U-Bootowi te dwa offsety ? A jaki jest prawdziwy ślad pamięci U-Boota ? A ogólniej, gdzie mogę umieścić moje jądro, aby mieć pewność, że nie nadpisze czegoś ?
Author: Sam Protsenko, 2016-02-11

1 answers

Relokacja U-Boota na architekturze ARM

Oto cała sekwencja dwuetapowego procesu rozruchowego:]}
  1. ROM-kod odczytuje SPL (z pliku MLO na karcie SD) na adres CONFIG_SPL_TEXT_BASE. Adres ten jest zwykle w pamięci SRAM, która nie musi być inicjalizowana, aby była funkcjonalna (w przeciwieństwie do pamięci RAM). ROM-code przeskakuje na kod SPL.
  2. SPL konfiguruje RAM, następnie odczytuje u-boot (z pliku u-boot.img na karcie SD) na adres CONFIG_SYS_TEXT_BASE RAM (który zwykle znajduje się na początku RAM) i uruchamia it
  3. U-boot przenosi się na adres gd->relocaddr RAM (który zwykle znajduje się na końcu RAM) i przeskakuje na przeniesiony kod
  4. teraz jesteśmy gotowi do uruchomienia jądra

Do rozruchu jednostopniowego nie masz SPL, zwykle używany jest tylko plik u-boot.bin. W takim przypadku masz tylko kroki 3 i 4.

Istnieją dwa przypadki dotyczące relokacji (opisane w doc / README.arm-relocation):

  1. CONFIG_SYS_TEXT_BASE != gd->relocaddr: Przeprowadzka zostanie wykonana
  2. CONFIG_SYS_TEXT_BASE == gd->relocaddr: przeniesienie nie będzie wykonywane

W Twoim przypadku widzisz, że przeprowadzka została wykonana(jako CONFIG_SYS_TEXT_BASE != gd->relocaddr).

Więc, odpowiadając na twoje pytanie:
Po co U-Bootowi te dwa offsety ?
W 1999 roku, w wyniku przeprowadzonego przez u-Boota projektu, w 1999 roku, został przeniesiony do u-boot ARM.]}

...możemy zmierzyć rzeczywisty rozmiar pamięci obecnej na płycie, a następnie przenieść U-Boot na sam koniec pamięci RAM, pozostawiając prawie cały RAM użyteczny jako jeden duży obszar przylegający do "aplikacji", takich jak ładowanie jądra Linuksa, ramdisk, itp.

Rzeczywiście, jeśli spojrzysz na kod, zobaczysz, że gd->relocaddr jest końcem pamięci RAM minus rozmiar kodu monitora (U-Boot):

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

Można również wykonać dodatkową rezerwację pamięci. Na przykład na mojej platformie (ti DRA7XX EVM) widzę kolejne funkcje, które będą wywoływane:

setup_dest_addr()
reserve_round_4k()
reserve_mmu()
reserve_uboot()

Rzeczywista Relokacja odbywa się zaraz po board_init_f() sprawdzam.

Arch / arm / lib / crt0.S :

bl board_init_f
...
b relocate_code

Arch / arm / lib / relocate.S :

ENTRY(relocate_code)

Teraz łatwo jest odpowiedzieć na następne pytanie:

Jaki jest rzeczywisty ślad pamięci U-Boota ?

Przed relokacją U-Boot rezyduje w CONFIG_SYS_TEXT_BASE. Po relokacji U-Boot przebywa w gs->relocaddr.

Odnośnie Twojego ostatniego pytania:

Gdzie mogę umieścić moje jądro, aby mieć pewność, że nie nadpisze coś?

Ponieważ U-Boot został przeniesiony na koniec pamięci RAM, możesz teoretycznie użyć dowolnego adresu RAM, aby umieścić jądro. Ale spójrz na definicję CONFIG_EXTRA_ENV_SETTINGS w 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" \

Stamtąd widać, że należy załadować jądro do ${kernel_load_address}, czyli 0x2080000:

"kernel_load_address=0x2080000\0" \

Zobacz resztę tej definicji dla innych stałych.

Komenda Bdinfo

Możesz znaleźć bdinfo polecenie przydatne: adres relokacji wraz z innymi przydatnymi informacjami można znaleźć używając polecenia bdinfo z powłoki U-Boot. Na przykład dla DRA7XX EVM:

=> bdinfo

DRAM bank   = 0x00000000
-> start    = 0x80000000
-> size     = 0x60000000
TLB addr    = 0xDFFF0000
relocaddr   = 0xDFF5D000
reloc off   = 0x5F75D000
irq_sp      = 0xDEF3CEE0
sp start    = 0xDEF3CED0

Stąd widać, że:

  • RAM zaczyna się od 0x80000000
  • rozmiar pamięci RAM to 0x60000000
  • ... więc koniec RAM (gd->ram_top) jest 0x80000000 + 0x60000000 = 0xE0000000
  • adres relokacji to 0xDFF5D000
  • zarezerwowana pamięć dla relokacji to 0xE0000000 - 0xDFF5D000 = 652 KB
  • rozmiar monitora (U-Boot) to około TLB addr - relocaddr = 0xDFFF0000 - 0xDFF5D000 = 588 KB

Zobacz też:

[1] u-boot: Relokacja

[2] Na czym polega SPL (secondary program loader)

[3] commit, który dodaje obsługę relokacji ARM do u-boot

 13
Author: Sam Protsenko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-01 10:57:33