STM32MP157A-DK1 Evaluation (5) STM32MP Linux System Boot Process
[Copy link]
This post was last edited by cruelfox on 2020-4-26 11:53
If the Linux operating system is considered as a program containing many modules, this program (called Linux kernel) can exist as a single file and can be copied like a normal file. However, just like x86 PC Linux, this program (commonly known as vmlinux, vmlinuz, bzImage ... and other file names) cannot be copied to the hard disk to start the computer, and such a file of embedded Linux (commonly used in ARM and MIPS platforms) cannot be written to the Flash memory to run.
On a PC, the boot process of an operating system has several steps. First, the ROM (BIOS, and now UEFI) program will identify the master boot record on the hard disk, read a section of code in the master boot record into RAM and run it. Then this section of code will search for a bootable hard disk partition, read the boot code in the partition to run, and then the boot code in the partition will search for the operating system files... The more complex the system, the more links it has, so only in this way can the design be flexible to cope with changing software and hardware environments.
The most widely used Linux boot program on PC is GRUB, which is mainly used to read Linux from the hard disk into the memory and pass the running parameters. On the ARM platform, U-Boot is usually used to boot Linux. This is an open source software that supports a wide variety of hardware. If the ARM MPU or MCU automatically starts executing code from a certain address after power-on reset, the U-Boot code should be placed there.
However, for STM32MP157, the situation is not so simple. First of all, there is no Flash in this MPU, so U-Boot cannot be burned into it; it does not directly execute by accessing NOR Flash from the off-chip bus. When STM32MP157 is powered on, it executes its own ROM program, which reads the code from other media (such as the SD card currently used) to SRAM, or obtains the code from USB or UART and stores it in SRAM. It can only be executed after it is supervised and verified. Why is it complicated? Because a security mechanism is introduced. For many applications that do not require so-called security, although it can be omitted, it adds difficulty to the transition from MCU to MPU.
Using the diagram on wiki, the Linux system startup steps and runtime environment may be as follows:
The first thing that the ROM program reads from the SD card is the FSBL (first stage bootloader) called TF-A, and U-Boot as the SSBL (second stage bootloader) needs to be loaded by TF-A. Only then does U-Boot read the Linux kernel program. The left column in the above figure represents the "secure" environment. As for OP-TEE, it is a service outside the Linux system and is optional.
As an introduction to MPU, let's ignore the "security" part. It is worth noting that TF-A is executed in the SYSRAM on the STM32MP157 chip, while U-Boot is executed in the DDR SDRAM outside the chip.
TF-A, OP-TEE, U-Boot and Linux (kernel) ST provides source code packages and ST patches. If you want to tinker with them, there is quite a lot to do.
Regarding the Flash (SD card) resource layout of STM32MP157A-DK1, there are 4 configuration files in the official package:
FlashLayout_sdcard_stm32mp157a-dk1-trusted.tsv
FlashLayout_sdcard_stm32mp157a-dk1-basic.tsv
FlashLayout_sdcard_stm32mp157a-dk1-extensible.tsv
FlashLayout_sdcard_stm32mp157a-dk1-optee.tsv
It describes what image files should be written to what location, including the image description of the file system partition.
The files with "trusted" in the file name correspond to the previous picture, and the key points are these lines:
P 0x04 fsbl1 Binary mmc0 0x00004400 tf-a-stm32mp157a-dk1-trusted.stm32
P 0x05 fsbl2 Binary mmc0 0x00044400 tf-a-stm32mp157a-dk1-trusted.stm32
P 0x06 ssbl Binary mmc0 0x00084400 u-boot-stm32mp157a-dk1-trusted.stm32
P 0x21 bootfs System mmc0 0x00284400 st-image-bootfs-openstlinux-weston-stm32mp1.ext4
There are actually two copies of FSBL (different locations, followed by the same file, which I read from the SD card and compared and they are the same), and only one copy of SSBL.
If you don't want "trusted", you can use the basic configuration, which is what I used when I first wrote the card. The file described in it has changed:
P 0x04 fsbl1 Binary mmc0 0x00004400 u-boot-spl.stm32-stm32mp157a-dk1-basic
P 0x05 fsbl2 Binary mmc0 0x00044400 u-boot-spl.stm32-stm32mp157a-dk1-basic
P 0x06 ssbl Binary mmc0 0x00084400 u-boot-stm32mp157a-dk1-basic.img
P 0x21 bootfs System mmc0 0x00284400 st-image-bootfs-openstlinux-weston-stm32mp1.ext4
There is no "trusted" u-boot anymore, it is divided into two parts, and there is an additional u-boot-spl.
Why must it be divided into two steps, FSBL and SSBL? Because the two parts have different operating environments, and FSBL needs to do some initialization work that the ROM bootloader does not do. At least, SDRAM is initialized by FSBL, and U-Boot needs to run in SDRAM.
I tried to clear the contents of the SSBL part of the SD card - writing all 0xFF bytes. This way, the execution will only stop at the FSBL stage. Let's see what the effect is?
Sure enough, it was stuck when trying to read the SSBL.
Enable OpenOCD debugging:
Open On-Chip Debugger
> halt
stm32mp15x.cpu0 rev 5, partnum c07, arch f, variant 0, implementor 41
stm32mp15x.cpu0 cluster 0 core 0 multi core
stm32mp15x.cpu1 rev 5, partnum c07, arch f, variant 0, implementor 41
stm32mp15x.cpu1 cluster 0 core 1 multi core
target halted in Thumb state due to debug-request, current mode: Supervisor
cpsr: 0x800001f3 pc: 0x0000060e
MMU: disabled, D-Cache: disabled, I-Cache: enabled
target halted in ARM state due to debug-request, current mode: Undefined instruction
cpsr: 0x600001db pc: 0x2ffc2540
MMU: disabled, D-Cache: disabled, I-Cache: enabled
发现异常状态:非法指令不能执行。
> reg pc
pc (/32): 0x2FFC2540
> arm disassemble 0x2FFC2540 2
0x2ffc2540 0xeafffffe B 0x2ffc2540
0x2ffc2544 0xea00002a B 0x2ffc25f4
This confirms that the CPU is in the exception handler (infinite loop). According to the value of the LR register, the address where the exception occurred can be known (note that the Cortex-m CPU does not have this feature), so check the LR register:
> reg lr
lr (/32): 0xC0100004
> mdw 0xc0100000 8
0xc0100000: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
It seems that the content that I erased has been read into SDRAM, so it is an illegal instruction.
Unfortunately, this untrusted version of U-Boot does not provide an ELF file for GDB debugging in the ST official package, so there is no debugging information reference, and you can only guess. In this state, let's take a look at the content code in SYSRAM. Push forward a little according to the PC register address:
> arm disassemble 0x2ffc2500 20
0x2ffc2500 0xea00000f B 0x2ffc2544
0x2ffc2504 0xe59ff014 LDR r15, [r15, #0x14]
0x2ffc2508 0xe59ff014 LDR r15, [r15, #0x14]
0x2ffc250c 0xe59ff014 LDR r15, [r15, #0x14]
0x2ffc2510 0xe59ff014 LDR r15, [r15, #0x14]
0x2ffc2514 0xe59ff014 LDR r15, [r15, #0x14]
0x2ffc2518 0xe59ff014 LDR r15, [r15, #0x14]
0x2ffc251c 0xe59ff014 LDR r15, [r15, #0x14]
0x2ffc2520 0x2ffc2540 SVC 0xfc2540
0x2ffc2524 0x2ffc2540 SVC 0xfc2540
0x2ffc2528 0x2ffc2540 SVC 0xfc2540
0x2ffc252c 0x2ffc2540 SVC 0xfc2540
0x2ffc2530 0x2ffc2540 SVC 0xfc2540
0x2ffc2534 0x2ffc2540 SVC 0xfc2540
0x2ffc2538 0x2ffc2540 SVC 0xfc2540
0x2ffc253c 0xdeadbeef CDPLE p14, 0x0a, c11, c13, c15, 0x07
0x2ffc2540 0xeafffffe B 0x2ffc2540
0x2ffc2544 0xea00002a B 0x2ffc25f4
0x2ffc2548 0xe10f0000 MRS r0, CPSR
0x2ffc254c 0xe200101f AND r1, r0, #0x1f
It looks a bit like the interrupt vector table of Cortex-A7. I'll find where this section is in the image file...
The result is at the beginning of the file at offset 0x100
Moreover, if the memory starts at 0x2ffc2400 and is aligned with the file, a large section of the content is also the same (the first 64kB are the same). Therefore, I suspect that the ROM bootloader reads the FSBL to the address 0x2FFC2400 and then starts executing from somewhere.
This paragraph on the st wiki confirms my guess:
2.2Image loading↑
The ROM code loads the image intoSYSRAMinternal memory at address 0x2ffc2400.
2.3FSBL authentication↑
ROM code implements authentication process as described inSTM32MP15 secure boot, Authentication processing chapter.
2.4Jump to FSBL↑
If image authentication is successful, the ROM code stores the address of theboot contextin r0 register and jumps to the FSBL entry point defined inimage header.
Theboot context(seeboot_api_context_tstructure in ) is in the first 512 bytes ofSYSRAM. It contains information on boot process (such as the selected boot device) and pointers to the ROM code services (used for secure boot authentication).
--------------------------------------------------------------------------------------------------------
It seems that after the ROM bootloader loads the FSBL from the SD card into SYSRAM (a total of 256kB), it first verifies it, and if it is legal, it jumps to the entry address it specifies for execution. This entry address, as well as other important descriptive data, is included in the FSBL file header:
Checking the contents of the u-boot-spl.stm32-stm32mp157a-dk1-basic file, we can see that the entry address is 0x2ffc2500, which is the same as what I guessed. So how does the ROM program locate the FSBL in the SD card? The wiki explains it this way:
4.3Boot from SD↑
SD cards contain two versions of FSBL. The ROM code tries to load and launch the first copy. In case of failure, it then try to load the second copy.
The ROM code first looks for a GPT. If it finds it, it locates two FSBLs by looking for the two first GPT entries which name begins with "fsbl". If it cannot find a GPT, the ROM code looks for FSBL1 at offset LBA34 and FSBL2 at offset LBA546.
---------------------------------------------------------------
So, the process is as follows: After the STM32MP157 is powered on, the ROM bootloader program is executed. When the SD card boot conditions are met, the first two partitions called "fsbl" will be found from the SD card partition table (GPT format, not the MBR partition table used in traditional PCs) and their contents will be read. If the GPT partition table cannot be found, it will read from sector address 34. If this FSBL check fails, the second fsbl used for backup (located at sector 546 when there is no GPT) will be tried again.
When FSBL (u-boot-spl.stm32-stm32mp157a-dk1-basic) is executed, it performs some hardware initialization work, then searches for SSBL, which is U-Boot (u-boot-stm32mp157a-dk1-basic.img), and loads it into SDRAM for execution. U-Boot has many functions and can interact with users through the serial terminal. Enter help in the U-Boot command prompt to list all commands:
U-Boot 2018.11-stm32mp-r4 (Nov 14 2018 - 16:10:06 +0000)
CPU: STM32MP157AAC Rev.B
Model: STMicroelectronics STM32MP157A-DK1 Discovery Board
Board: stm32mp1 in basic mode (st,stm32mp157a-dk1)
Board: MB1272 Var1 Rev.C-01
DRAM: 512 MiB
Clocks:
- MPU : 650 MHz
- MCU : 208.878 MHz
- AXI : 266.500 MHz
- PER : 24 MHz
- DDR : 533 MHz
****************************************************
* WARNING 500mA power supply detected *
* Current too low, use a 3A power supply! *
****************************************************
NAND: 0 MiB
MMC: STM32 SDMMC2: 0
Loading Environment from EXT4... OK
In: serial
Out: serial
Err: serial
Net: eth0: ethernet@5800a000
Hit any key to stop autoboot: 0
STM32MP> help
? - alias for 'help'
adc - ADC sub-system
base - print or set address offset
bdinfo - print Board Info structure
blkcache- block cache diagnostics and control
bmp - manipulate BMP image data
bootefi - Boots an EFI payload from memory
bootm - boot application image from memory
bootp - boot image via network using BOOTP/TFTP protocol
bootz - boot Linux zImage image from memory
chpart - change active partition
......
The default configuration (automatic execution) is to obtain the configuration from the SD card and then load the Linux kernel program. The information printed by the terminal can be judged:
Boot over mmc0!
switch to partitions #0, OK
mmc0 is current device
Scanning mmc 0:4...
Found U-Boot script /boot.scr.uimg
1628 bytes read in 1 ms (1.6 MiB/s)
## Executing script at c4100000
Scanning mmc 0:4...
Found /mmc0_stm32mp157a-dk1_extlinux/extlinux.conf
Retrieving file: /mmc0_stm32mp157a-dk1_extlinux/extlinux.conf
235 bytes read in 1 ms (229.5 KiB/s)
Retrieving file: /splash.bmp
46180 bytes read in 5 ms (8.8 MiB/s)
1: stm32mp157a-dk1-sdcard
Enter choice: 1: stm32mp157a-dk1-sdcard
Retrieving file: /uImage
6722112 bytes read in 479 ms (13.4 MiB/s)
append: root=/dev/mmcblk0p6 rootwait rw console=ttySTM0,115200
Retrieving file: /stm32mp157a-dk1.dtb
71751 bytes read in 6 ms (11.4 MiB/s)
## Booting kernel from Legacy Image at c2000000 ...
Image Name: Linux-4.19.94
Created: 2020-01-09 9:19:10 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 6722048 Bytes = 6.4 MiB
Load Address: c2000040
Entry Point: c2000040
Verifying Checksum ... OK
## Flattened Device Tree blob at c4000000
Booting using the fdt blob at 0xc4000000
XIP Kernel Image ... OK
Using Device Tree in place at c4000000, end c4014846
Starting kernel ...
The information output by U-Boot mentions several files, which should be in a partition - most likely in the image file st-image-bootfs-openstlinux-weston-stm32mp1.ext4. Confirm it in the Linux environment:
root@stm32mp1:/# mount | grep mmc
/dev/mmcblk0p6 on / type ext4 (rw,relatime)
/dev/mmcblk0p4 on /boot type ext4 (rw,relatime)
/dev/mmcblk0p7 on /usr/local type ext4 (rw,relatime)
/dev/mmcblk0p5 on /vendor type ext4 (rw,relatime)
root@stm32mp1:/# ls /boot -l
total 7230
-rwxr-xr-x 1 root root 1628 Mar 9 2018 boot.scr.uimg
drwx------ 2 root root 12288 Feb 18 2020 lost+found
drwxr-xr-x 2 root root 1024 Mar 9 2018 mmc0_stm32mp157a-dk1-optee_extlinux
drwxr-xr-x 2 root root 1024 Mar 9 2018 mmc0_stm32mp157a-dk1_extlinux
drwxr-xr-x 2 root root 1024 Mar 9 2018 mmc0_stm32mp157c-dk2-optee_extlinux
drwxr-xr-x 2 root root 1024 Mar 9 2018 mmc0_stm32mp157c-dk2_extlinux
drwxr-xr-x 2 root root 1024 Mar 9 2018 mmc0_stm32mp157c-ed1-optee_extlinux
drwxr-xr-x 2 root root 1024 Mar 9 2018 mmc0_stm32mp157c-ed1_extlinux
drwxr-xr-x 2 root root 1024 Mar 9 2018 mmc0_stm32mp157c-ev1-optee_extlinux
drwxr-xr-x 2 root root 1024 Mar 9 2018 mmc0_stm32mp157c-ev1_extlinux
drwxr-xr-x 2 root root 1024 Mar 9 2018 mmc1_stm32mp157c-ed1-optee_extlinux
drwxr-xr-x 2 root root 1024 Mar 9 2018 mmc1_stm32mp157c-ed1_extlinux
drwxr-xr-x 2 root root 1024 Mar 9 2018 mmc1_stm32mp157c-ev1-optee_extlinux
drwxr-xr-x 2 root root 1024 Mar 9 2018 mmc1_stm32mp157c-ev1_extlinux
drwxr-xr-x 2 root root 1024 Mar 9 2018 nand0_stm32mp157c-ev1_extlinux
drwxr-xr-x 2 root root 1024 Mar 9 2018 nor0-mmc1_stm32mp157c-ev1_extlinux
drwxr-xr-x 2 root root 1024 Mar 9 2018 nor0_stm32mp157c-ev1_extlinux
-rw-r--r-- 1 root root 46180 Mar 9 2018 splash.bmp
-rw-r--r-- 1 root root 71751 Mar 9 2018 stm32mp157a-dk1.dtb
-rw-r--r-- 1 root root 73626 Mar 9 2018 stm32mp157c-dk2-a7-examples.dtb
-rw-r--r-- 1 root root 74162 Mar 9 2018 stm32mp157c-dk2-m4-examples.dtb
-rw-r--r-- 1 root root 73578 Mar 9 2018 stm32mp157c-dk2.dtb
-rw-r--r-- 1 root root 68471 Mar 9 2018 stm32mp157c-ed1.dtb
-rw-r--r-- 1 root root 78340 Mar 9 2018 stm32mp157c-ev1-a7-examples.dtb
-rw-r--r-- 1 root root 78673 Mar 9 2018 stm32mp157c-ev1-m4-examples.dtb
-rw-r--r-- 1 root root 78033 Mar 9 2018 stm32mp157c-ev1.dtb
-rw-r--r-- 1 root root 6722112 Mar 9 2018 uImage
-rwxr-xr-x 1 root root 8192 Jan 1 1970 uboot.env
From the mounted file system, we can see that the .ext4 image file written in the SD card corresponds to four GPT partitions, which are four MMC block devices under Linux.
/dev/mmcblk0p4 |
/boot |
st-image-bootfs-openstlinux-weston-stm32mp1.ext4 |
/dev/mmcblk0p5 |
/vendor |
st-image-vendorfs-openstlinux-weston-stm32mp1.ext4 |
/dev/mmcblk0p6 |
/ |
st-image-weston-openstlinux-weston-stm32mp1.ext4 |
/dev/mmcblk0p7 |
/usr/local |
st-image-userfs-openstlinux-weston-stm32mp1.ext4 |
The specific configuration for loading the Linux kernel is in this configuration file:
root@stm32mp1:/boot# cat mmc0_stm32mp157a-dk1_extlinux/extlinux.conf
# Generic Distro Configuration file generated by OpenEmbedded
MENU BACKGROUND /splash.bmp
TIMEOUT 20
LABEL stm32mp157a-dk1-sdcard
KERNEL /uImage
FDT /stm32mp157a-dk1.dtb
APPEND root=/dev/mmcblk0p6 rootwait rw console=ttySTM0,115200
uImage is the Linux kernel file. Therefore, the /dev/mmcblk0p6 block device is mounted as the root file system by Linux through the command line parameters, and then Linux creates the init process, starts the service and so on.
|