January 11, 2022

Orange Pi 4 (Rockchip 3399) make a boot SD card

I set aside my "inter" project and began working on this. Why you might ask. Why indeed?

I have a growing set of questions about the bootrom code, often called the "MASKROM" by the RK3399 community. Attempting to simple dump it out using U-Boot failed, and I can only assume that the secure mode "trust" code has somehow protected it from read access. Maybe, maybe not.

So, I would like to understand the boot process and consider the possibility of replacing one of the early stage boot loaders with my own code, if nothing else to be able to dump the on chip bootrom so I can disassemble and study it.

No documentation seems to exist or be public for the bootrom. I am curious in particular about several things:

Various investigations along the way

Somewhat getting ahead of myself here, but this project sprouted a number of "subprojects" and I had to document them somewhere.

Waylaid by a faulty micro SD card

I tried the experiments below and nothing worked. This had me scratching my head for a day or two, but then I was able to recognize that I had a faulty micro SD card. (Fresh out of the box, and a SanDisk I paid full price for!) So the moral of the story is perhaps to test your SD cards. Use dd to copy a big (multi Gigabyte) file to them, then read it back and verify it, or something of the sort.

How did the bootloader of my eMMC get set up?

I decided to learn what I could by studying the script that generated my eMMC image (nand-sata-install in the Debian distribution). I found that 3 components are written using "dd" as follows:
dd if=idbloader.bin of=$(CARD) seek=64 conv=notrunc
dd if=uboot.img of=$(CARD) seek=16384 conv=notrunc
dd if=trust.bin of=$(CARD) seek=24576 conv=notrunc
These 3 files look like this:
-rw-rw-r-- 1 tom  tom    206844 Jan 11 13:14 idbloader.bin
-rw-rw-r-- 1 tom  tom   4194304 Jan 11 13:14 trust.bin
-rw-rw-r-- 1 tom  tom   4194304 Jan 11 13:14 uboot.img

Just put idbloader onto an SD card

dd if=/dev/zero of=/dev/sdh count=62000
dd if=idbloader.bin of=/dev/sdh seek=64 conv=notrunc
I zero out the partition table and every other part of what was previously a valid debian boot setup. Then I put the card into the socket on the Rockchip board, power up, and voila!

I see continual action and chatter on the serial console.

Put all 3 on the card

I copied these 3 files to my desktop linux machine and wrote them to a good micro SD card. When installed in the board and the board reset, voila! It goes through what looks like the usual sequence and is running U-Boot. Since there is no linux for it to boot, it falls back on trying some kind of DHCP boot, which also goes nowhere.

I can reset the board and then tap on the space bar during boot to get to the U-boot prompt. I get a surprise though when I try to change and save environment variables:

Saving Environment to MMC... Card did not respond to voltage select!
No block device
Failed (1)

mmc list
dwmmc@fe320000: 1 (SD)
sdhci@fe330000: 0

All this is being done on my RK3399 board without emmc, but why is U-boot trying to save the env on emmc?

Well, I did get the U-boot image from the collection that was intended to be written to MMC by the "nand_sata_install" script. Note the output of "mmc list".

Experiment with my working Debian boot SD card

I get exactly the same error when I burn the full debian distro onto an SD card and then try to do a saveenv. I had success when using my board with emmc, which booted from an SD card, but apparently it had saved (and was fetching!?) the U-boot environment from emmc, even for an SD card boot. Who would have dreamed? It is not clear what my options are. Certainly I could rebuild U-boot from source.

It may be possible to patch what I want into the U-boot image. I did this once for another project.

Old notes below here, need revision

XXX - below here not yet revised after getting a good SD card. I need to repeat all my experiments and rewrite all that follows.

Boot Debian from my emmc setup

I have this set now to normally it does tftp boot of whatever experimental code I am running. But I can still interrupt the boot by pounding away on the space bar, and then once I get the U-Boot command prompt, I can have it boot linux by typing:
run distro_bootcmd
This is simple and effective. I use fdisk once I am in to look at partitions on emmc. First I do this:
root@orangepi4:~# fdisk /dev/mmcblk1
Command (m for help): p
Disk /dev/mmcblk1: 14.6 GiB, 15634268160 bytes, 30535680 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xecb86bb3

Device         Boot Start      End  Sectors  Size Id Type
/dev/mmcblk1p1      32768 30230303 30197536 14.4G 83 Linux
This is pretty much as expected with an offset I can recognize from the "nand_sata_install" script. What is interesting is to look at fdisk -l
Disk /dev/mmcblk1boot1: 4 MiB, 4194304 bytes, 8192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

Disk /dev/mmcblk1boot0: 4 MiB, 4194304 bytes, 8192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
It shows these 2 other 4M hardware "boot partitions" that we don't see on an SD card. It would seem that our u-boot scheme just uses the big user partition and ignores these.

Study my bootable SD card

I do this on my desktop linux system using my USB card reader. Looking at it with fdisk, I see:
Disk /dev/sdh: 14.84 GiB, 15931539456 bytes, 31116288 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x5ffdd01d

Device     Boot Start      End  Sectors  Size Id Type
/dev/sdh1       61440 30805119 30743680 14.7G 83 Linux
Using dd and cmp, I confirm that the 3 binary files are on this card at the same offsets that I used, determined from the script that installs onto emmc.

Copy a minimum of my bootable SD card

All this is experimentation mind you. So, I figure (wrongly it turns out) that all the action is in the data in the boot area prior to the filesystem. Given that logic, doing the following ought to yield a bootable SD card.
dd if=$(CARD) of=myboot.img count=61440 (from my bootable Debian card)
dd if=myboot.img of=$(CARD)		(to my scratch card)
This does not boot and run anything. It gives me weird trash on the serial console just like the card I made by writing the 3 binary blobs using dd.

The conclusion from this is that U-Boot needs something (maybe even several things) from the linux filesystem. I hear a lot about this "dtb" file. Could it be reading this from the linux filesystem? It would not be what I would expect (since it would need an emmc/sd driver to do such).

Some possibly related links and sources of information

The dicussion in the "chatter" link above discusses idbloader.img and says: This gives starting points for searches like "rockchip ddr.bin" and "rockchip miniloader.bin"
Have any comments? Questions? Drop me a line!

Tom's electronics pages / tom@mmto.org