January 24, 2026

Allwinner H5 chip - Try Johang's SD-image boot setup

Johang provides Debian images for a wide range of ARM based boards. He nicely splits these into a boot and a linux image. This means that just the boot image is all that I need (sort of, see below) I download boot-orange_pi_pc2.bin.gz (465K) and unzip it to get:
-rw-r--r-- 1 tom tom 33554432 Jan 21 17:43 boot-orange_pi_pc2.bin
Indeed, it expands to 32M when unzipped. Note that 32*1024*1024 = 33554432. Most of this is trailing zero pads to the 32M boundary. The idea is that you can use the following command to generate a bootable Debian image.
zcat boot-orange_pi_pc2.bin.gz debian-bookworm-arm64-oor7te.bin.gz > sd-card.img
I am not interested (at this point anyway) at running Debian on this hardware. If I was, these "vanilla" images would be exactly what I would want. So I just use dd as follows:
su
dd if=boot-orange_pi_pc2.bin of=/dev/sdf
Note that "/dev/sdf" is an SD card reader on MY system. Your system may be different and you don't want to target a system disk by mistake!

But saveenv doesn't work

I get this message:
=> saveenv
Saving Environment to FAT... Unable to use mmc 0:2...
Failed (1)
I find this interesting. There are a variety of ways that U-boot can be set up to allow "saveenv" to save environment variables. Here is wants to write them to a file in a FAT partition. And I would have one if I had appended the debian image!

I look at his scheme for building SD cards and find sd-card-images/scripts/build-image with (more or less) the following commands:

IMAGE=debian.img

# Aim for a 4 GB image default but with 5% unpartitioned as a margin, and a minimum of 1 GB
# >>> (0.95 * 4000000000 // 512) * 512
# 3800000000.0
IMAGE_SIZE=${IMAGE_SIZE:-3800000000}

rm -f "${IMAGE}"
fallocate -v -l "${IMAGE_SIZE}" "${IMAGE}" # 3,800,000,000 bytes

parted -s "${IMAGE}" mklabel msdos
parted -s "${IMAGE}" mkpart primary fat32 -- 4MiB 32MiB # 28 MiB (29,360,128 bytes)
parted -s "${IMAGE}" mkpart primary ext2 -- 32MiB -1
parted -s "${IMAGE}" set 2 boot on

# Create empty FAT partition
rm -f vfat.img
fallocate -l 28MiB vfat.img
mkfs.vfat vfat.img

# Leave a friendly note about this partition
echo "The boot process for this SoC does not use this partition." >> PARTITION_INTENTIONALLY_EMPTY.TXT
mcopy -v -i vfat.img PARTITION_INTENTIONALLY_EMPTY.TXT ::

# Copy FAT partition to image
dd if=vfat.img of="${IMAGE}" bs=1K seek=4K conv=notrunc
I can imitate this, with a much smaller image size. If I just add a label (partition table) and a small fat32 image, I will be in business. I have no need for the big ext2 partition.

Try it -- and it does not work!

I do this, and it does not work. I still get:
=> saveenv
Saving Environment to FAT... Unable to use mmc 0:2...
Failed (1)

Strangely enough, when I run "strings" on boot-orange_pi_pc2.bin, the last things I see are:

NO NAME    FAT16
This is not a bootable disk.  Please insert a bootable floppy and
press any key to try again ...
PARTIT~1TXT
!\!\
The boot process for this SoC does not use this partition.
This is as though the boot image has a partition table and a file in a FAT partition near the end of the image. This is a surprise. Whatever it is, U-boot cannot find it and use it for the saveenv command. This is starting to get down to a question of how U-boot deals with partitions, labels, and SD/mmc devices.
I type this command to U-boot:
part list mmc 0

Partition Map for mmc device 0  --   Partition Type: DOS

Part	Start Sector	Num Sectors	UUID		Type
  1		8192      		57344     	db8463ed-01	0c
  2		65536     		7354368   	db8463ed-02	83 Boot

Partition type 0c is a FAT32 partition.
Partition type 83 is a linux partition.

Note also that 8192+57344 = 65536 and 7354368 = 7419904
If these are 512 byte sectors, the device size is 3.8G. The FAT partition size is 28M. All this looks exactly like the setup in the original build-image script.

Tests with only the Johang boot image

I get the same results, as follows:
=> part list mmc 0

Partition Map for mmc device 0  --   Partition Type: DOS

Part	Start Sector	Num Sectors	UUID		Type
  1	8192      	57344     	db8463ed-01	0c
  2	65536     	7354368   	db8463ed-02	83 Boot
=> saveenv
Saving Environment to FAT... Unable to use mmc 0:2...
Failed (1)
It looks like the Johang image (only 32M in size) includes a partition table.
Also U-boot seems to expect a FAT partition at 0:2, which is the linux partition. If we told U-boot to use partition 0:1 it ought to work.

I missed something

I am now looking at the "build-boot" script. It does this:
build-image tmp.img
build-boot-sunxi BOARD CHIP DEF TUPLE
The sunxi build script calls "build-u_boot", then:
dd if=u-boot/u-boot-sunxi-with-spl.bin of=tmp.img bs=1K seek=8 conv=notrunc
Notice the "notrunc" option here to U-boot. This tells it not to truncate the output file. So this command skips 8K into the prepared image (skipping the label, as well as putting the SPL where it is expected to be). There is 8M for U-boot to get written into. If it goes beyond this (it won't), it will overwrite the FAT partition at the 8M boundary.

I understand this much better now. I could modify the label so there are two FAT partitions. I would then also need to put a FAT filesystem there to allow U-boot to write whatever file saveenv wants to write there.

No doubt there is some build option that tells U-boot what mmc partition to use for saveenv. Looking through the build options I am now using for U-boot I see:

CONFIG_ENV_IS_IN_FAT=y
CONFIG_ENV_FAT_INTERFACE="mmc"
CONFIG_ENV_FAT_DEVICE_AND_PART=":auto"
CONFIG_ENV_FAT_FILE="uboot.env"
CONFIG_ENV_RELOC_GD_ENV_ADDR=y
CONFIG_ENV_MMC_DEVICE_INDEX=0
CONFIG_ENV_MMC_EMMC_HW_PARTITION=0
This makes sense, but does not explain why U-boot is using 0:2.
That bad decision must have been made by the ":auto" thing.
I look in the configs directory and see things like:
CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
If this were set for our build, it would probably work. Maybe look at env/fat.c in the U-boot sources.

Extract the U-boot.bin code from the boot image

Note that the "dd" command has both skip and seek options.
skip=N says to skip N blocks on the input file
seek=N says to skip N blocks on the output file
We use the seek option (along with conv=notruc) when we write sections into the output file.

We want to use the skip option to read a particular section from the input file.

Find a partition setup that makes saveenv work

I have to point out something unfortunate and potentially confusing. Consider the message "Unable to use mmc 0:2" from U-boot. Here we number mmc devices 0,1,2, but we number partitions 1,2,3

We had hoped that just putting to boot image from Johang would work. It does, with the exception of saveenv.
Now that we have the image on an SD card, we can work with it directly:

ls -l /dev/sdf*
brw-rw---- 1 root disk 8, 80 Jan 26 12:06 /dev/sdf
brw-rw---- 1 root disk 8, 81 Jan 26 12:06 /dev/sdf1
brw-rw---- 1 root disk 8, 82 Jan 26 12:06 /dev/sdf2
su
parted -s /dev/sdf print
Model:  Multi-Reader -3 (scsi)
Disk /dev/sdf: 15.9GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number  Start   End     Size    Type     File system  Flags
 1      4194kB  33.6MB  29.4MB  primary  fat16        lba
 2      33.6MB  3799MB  3765MB  primary               boot
The parted "-l" option lists info for every device on the system, which is stupid and annoying. I gave it a device name, and I don't even want it thinking about other devices on my system. It turns out "print" is what I want, as shown above.

At this point, partition 2 is just empty space. What if we put a filesystem there, as the Johang scripts will eventually do:

mkfs.ext4 -d linux /dev/sdf2
This fails with a strange error:
Copying files into the device: populate_fs3: No such file or directory while calling stat
mkfs.ext4: No such file or directory while populating file system
This is apparently due to the "-d linux" option. If we omit that, things are fine. And my desktop detects the new partition with filesystem and is ready to mount it for me. I put this card into my OrangePi, try saveenv, and it still does not work.

Now let's delete that second partition altogether. The game in all this is trial and error trying to figure out what play nice with the ":auto" specification for the FAT partition for ENV information. I should point out that it is HIGH RISK to be using fdisk or parted on a running system. One mistype or misunderstanding and you could mistakenly do something to one of your system drives.

su
parted -s /dev/sdf rm 2
parted -s /dev/sdf print
After this, we put the card back into the OrangePi and reset.
Aha! Now saveenv works!! Very nice.
saveenv
Saving Environment to FAT... OK
When I put the card back into my card reader, my desktop will mount the FAT filesystem and I see:
-rw-r--r--  1 tom  tom  65536 Dec 31  1999 uboot.env
This is almost an ascii file. It is padded at the end with zeros to exactly 64K in size. A hex dump of the file looks like this:
00000000 172d 78a1 6172 6368 3d61 726d 0062 6175    -x arch=arm bau
00000010 6472 6174 653d 3131 3532 3030 0062 6f61   drate=115200 boa
00000020 7264 3d73 756e 7869 0062 6f61 7264 5f6e   rd=sunxi board_n
....
....
00001280 3365 6339 3362 0075 7569 645f 6770 745f   3ec93b uuid_gpt_
00001290 7379 7374 656d 3d62 3932 3162 3034 352d   system=b921b045-
000012a0 3164 6630 2d34 3163 332d 6166 3434 2d34   1df0-41c3-af44-4
000012b0 6336 6632 3830 6433 6661 6500 0000 0000   c6f280d3fae
000012c0 0000 0000 0000 0000 0000 0000 0000 0000
....
....
The first 4 bytes are something special. Then each environment line is terminated with a 00 byte.


Have any comments? Questions? Drop me a line!

Tom's electronics pages / tom@mmto.org