Buildroot and STM32MP257F-DK
How to build and flash an image onto the STM32MP257F-DK board using Buildroot, plus an analysis of the generated image structure
The STM32MP257F-DK board ships with a preinstalled OpenSTLinux system based on Yocto. But what if we want to build our own, lighter image? The answer: Buildroot — a tool for building complete Linux systems for embedded devices.
In this article I will show how to build and flash an image onto the STM32MP257F-DK board using Buildroot with an external tree from Bootlin.
What is Buildroot?
Buildroot is a set of Makefile and Kconfig scripts that automates the process of building a complete Linux system. Compared to Yocto, it is simpler to use and faster to compile, although it offers fewer configuration options.
Bootlin provides an external tree (buildroot-external-st) with ready-made configurations for STMicroelectronics boards, including the STM32MP2 series.
Setting up the environment
We can use a Docker container for compilation, which avoids having to manually configure dependencies on the host. The following repository contains ready-made Docker files to get started quickly:
Cloning the repositories
We start by cloning Buildroot and the external tree from Bootlin:
git clone -b st/2025.02.5 https://github.com/bootlin/buildroot.git
git clone -b st/2025.02.5 https://github.com/bootlin/buildroot-external-st.git
At the time of writing, the latest available branch is st/2025.02.5.
Configuration and building
We enter the Buildroot directory and select the configuration for our board:
cd buildroot
make BR2_EXTERNAL=../buildroot-external-st st_stm32mp257f_dk_defconfig
Then we start the build:
make -j $(nproc)
The process can take anywhere from a dozen minutes to an hour, depending on your computer’s performance and internet connection (sources are downloaded during the build).
Build output
Once the build is complete, the final image can be found at output/images/sdcard.img.gz. This is a compressed SD card image containing all the components needed to boot the system.
Flashing the image to the SD card
Connect the microSD card to your computer and check the device name:
sudo lsblk
Assuming the card shows up as /dev/sdx, flash the image:
cd output/images
gzip -dc sdcard.img.gz | sudo dd of=/dev/sdx bs=1M status=progress
sync
Warning: Make sure you specify the correct device! The dd command will overwrite all data.
Booting the board
- Insert the SD card into the slot on the board
- Set the boot switches to SD mode:
1-0-0-0 - Connect the USB-C cable to the PWR port
- Connect via the serial port:
picocom -b 115200 /dev/ttyACMx
-> A detailed description of how to boot the board can be found here
After booting, log in as root (no password).
What’s next?
My next goal will be to boot a system on the board without using build systems such as Yocto or Buildroot. The OpenSTLinux system built with Yocto is very complex, which is evident from the number of partitions required on the SD card (Flashlayout). The image built with Buildroot, on the other hand, is minimal, which will make reverse engineering the boot process much easier. Since we have already verified that the image works correctly, we can take a closer look at its structure.
Analyzing the image structure
Let’s put the SD card back into the computer and see what structure the generated image has. First, let’s check the recognized partitions using blkid:
sudo blkid /dev/sdb*
/dev/sdb: PTUUID="42104540-b803-4e34-aad8-e499bc40110f" PTTYPE="gpt"
/dev/sdb1: PARTLABEL="fsbla" PARTUUID="b49f6b5a-f5d8-4d6d-aa50-11611113578d"
/dev/sdb2: PARTLABEL="fip" PARTUUID="6c692391-fb50-4c2e-b757-e07287342d44"
/dev/sdb3: PARTLABEL="u-boot-env" PARTUUID="61d25e7c-4ba2-40c3-8301-3a0f90d2604a"
/dev/sdb4: LABEL="rootfs" UUID="2f3910e7-d70f-4ada-9742-f35e3e006568" BLOCK_SIZE="1024" TYPE="ext4" PARTLABEL="rootfs" PARTUUID="b26967be-18fb-40fe-9d9b-ae035fc4a1c5"
We have just four partitions — far fewer than a Yocto image. The card uses a GPT partition table and contains:
fsbla— first stage bootloader (TF-A BL2)fip— Firmware Image Package (FIP) with subsequent boot stagesu-boot-env— U-Boot environment variablesrootfs— root filesystem (ext4)
Using sgdisk we can display the detailed characteristics of the partitions.
sudo sgdisk -p /dev/sdb
Disk /dev/sdb: 31116288 sectors, 14.8 GiB
Model: MassStorageClass
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): 42104540-B803-4E34-AAD8-E499BC40110F
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 213574
Partitions will be aligned on 2-sector boundaries
Total free space is 5 sectors (2.5 KiB)
Number Start (sector) End (sector) Size Code Name
1 34 545 256.0 KiB 8300 fsbla
2 546 8737 4.0 MiB 8300 fip
3 8738 8769 16.0 KiB 8300 u-boot-env
4 8770 213569 100.0 MiB 8300 rootfs
Let’s now look at the contents of each partition, starting with fsbla:
Partition fsbla — first stage bootloader
sudo hexdump -C /dev/sdb1 | head -20
00000000 53 54 4d 32 00 00 00 00 00 00 00 00 00 00 00 00 |STM2............|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
The first four bytes are the magic number: 0x324D5453 (ASCII: “STM2”). This is the STM32 header signature that the ROM code uses to identify a valid FSBLA (First Stage Boot Loader Authenticate) image — in the case of STM32MP2, this is TF-A BL2.
The ROM code in the processor expects a GPT partition table where the first partition is named fsbla (Boot from SD card).
Partition fip — Firmware Image Package
sudo hexdump -C /dev/sdb2 | head -20
00000000 01 00 64 aa 78 56 34 12 00 00 00 00 00 00 00 00 |..d.xV4.........|
00000010 47 d4 08 6d 4c fe 98 46 9b 95 29 50 cb bd 5a 00 |G..mL..F..)P..Z.|
The first four bytes are the FIP (Firmware Image Package) magic number: 0xAA640001. FIP is a container defined by the TF-A (Trusted Firmware-A) project that bundles multiple firmware components into a single file — including BL31, BL32 (OP-TEE), BL33 (U-Boot), and Device Tree files.
Partition u-boot-env — environment variables
The third partition stores U-Boot environment variables. Let’s dump its contents to a file so we can examine it:
sudo dd if=/dev/sdb3 of=uboot-env.bin bs=16K count=1
1+0 records in
1+0 records out
16384 bytes (16 kB, 16 KiB) copied, 0.00305791 s, 5.4 MB/s
hexdump -C uboot-env.bin | head -20
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00002000 55 6d 6e c1 01 61 70 69 5f 61 64 64 72 65 73 73 |Umn..api_address|
00002010 3d 66 38 30 37 36 34 33 30 00 61 72 63 68 3d 61 |=f8076430.arch=a|
00002020 72 6d 00 61 75 74 6f 6c 6f 61 64 3d 30 00 62 61 |rm.autoload=0.ba|
00002030 75 64 72 61 74 65 3d 31 31 35 32 30 30 00 62 6f |udrate=115200.bo|
00002040 61 72 64 3d 73 74 6d 33 32 6d 70 32 00 62 6f 61 |ard=stm32mp2.boa|
The u-boot-env partition has a simple structure: the first 4 bytes are a CRC32 checksum of the data, followed by environment variables stored as key=value strings separated by null bytes (\0). The following command skips the CRC header and extracts the variables in a readable form:
dd if=uboot-env.bin bs=1 skip=4 2>/dev/null | tr '\0' '\n' | grep -v '^$'
arch=arm
autoload=0
baudrate=115200
board=stm32mp2
board_name=stm32mp257f-dk
boot_a_script=load ${devtype} ${devnum}:${distro_bootpart} ${scriptaddr} ${prefix}${script}; source ${scriptaddr}
boot_device=mmc
...
We’ve already learned quite a bit about the board and are now in a good position to dig deeper :).
Summary
Buildroot offers a faster and simpler way to build a custom Linux image for the STM32MP257F-DK compared to Yocto. It is ideal for prototyping and situations where a lightweight, optimized system is needed. As the analysis showed, the generated image has a clear structure — just four partitions, each serving a specific role in the boot process.
Related Posts
STM32MP257F-DK: Unboxing
ST's STM32MP257F-DK development board - a hit or a hit ;)
Embedded Linux Device Emulation — Part 1: Docker & Buildx
Learn how to emulate ARM64 embedded Linux environments using Docker and Buildx for faster development without physical hardware
Embedded Linux from Scratch — Quick & Easy on QEMU
Compile a Linux system and its build tools from scratch
Comments