January 14, 2022

Orange Pi 4 (Rockchip 3399) make a bootable SD card - rksd

My aim was to understand the "idbloader.img" and what kind of header it had. This led me to the tools directory of U-Boot where you can find the standard U-Boot utility "mkimage", but more specifically the "rksd" tool.

I downloaded (via git clone) the latest mainline U-Boot distribution. A file doc/README.rockchip provides a wealth of useful information, including the following brief note:

rksd.c produces an image consisting of 32KB of empty space, a header and u-boot-spl-dtb.bin. The header is defined by 'struct header0_info' although most of the fields are unused by U-Boot. We just need to specify the signature, a flag and the block offset and size of the SPL image.

The header occupies a single block but we pad it out to 4 blocks. The header is encoding using RC4 with the key 7c4e0304550509072d2c7b38170d1711. The SPL image can be encoded too but we don't do that.

The maximum size of u-boot-spl-dtb.bin which the boot ROM will read is 32KB, or 0x40 blocks. This is a severe and annoying limitation. There may be a way around this limitation, since there is plenty of SRAM, but at present the board refuses to boot if this limit is exceeded.

The image produced is padded up to a block boundary (512 bytes). It should be written to the start of an SD card using dd.

Since this image is set to load U-Boot from the SD card at block offset, CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR, dd should be used to write u-boot-dtb.img to the SD card at that offset. See above for instructions.

Also a note from the U-boot mail archives about "idbloader":
The 'idb' means 'ID Block' which is header for Rockchip BootRom, and idbloader including header(2KB)+TPL+SPL, which is able to be understand by the BootRom. So this name is very clear to tell people what it is, eg, the idbloader may come from rockchip binary loader with: header(2KB)+ddr.bin+miniloader.bin.

Build rksd

The first thing to do is to configure U-Boot. There are now quite a number of RK3399 defconfig files in the configs directory. I like the looks of this one (given nothing more than the name of the file):
orangepi-rk3399_defconfig
The first step then is to do this at the root of the U-Boot distribution:
make orangepi-rk3399_defconfig
Then we need to select a compiler. We will assume that U-Boot ought to be compiled to aarch64 (64 bit ARM), so we define:
CROSS_COMPILE=aarch64-linux-gnu-
export CROSS_COMPILE
make
This all goes nicely. I will note that both spl and tpl are generated. I have no idea what "tpl" is, this is entirely a new thing. At the end of the build I get the warning:
WARNING: BL31 file bl31.elf NOT found, resulting binary is non-functional
WARNING: Please read Building section in doc/README.rockchip
This will of course require some investigation, but at this stage I don't really intend to use or run this U-Boot, just learn from it (and get my hands on a running rksd). I see that it compiles tools/rksd.c to a .o file, but no rksd standalone executable is generated. Indeed, rksd.c is trivial boilerplate of some kind. So rksd cannot be run directly, but is an option to mkimage. An invocation like this might be done:
./tools/mkimage -n rk3399 -T rksd -d ./tpl/u-boot-tpl-dtb.bin out
cat ./spl/u-boot-spl-dtb.bin >> out
sudo dd if=out of=/dev/sdc seek=64

What is TPL

Apparently is stands for "tertiary program loader". It seems that the SPL loads the TPL which then loads the final uboot into DDR ram.
Have any comments? Questions? Drop me a line!

Tom's electronics pages / tom@mmto.org