November 26, 2025

Orange Pi R1 Plus LTS (RK3328) -- Hack the "forky" U-boot sequence

The "forky" U-boot setup is somewhat different from Buster.

The good new is that "saveenv" just works. No need to to do "mmc dev 1" first, or anything.

Here is the U-boot environment setup:

=> printenv
arch=arm
baudrate=1500000
board=evb_rk3328
board_name=evb_rk3328
boot_targets=mmc1 mmc0 nvme scsi usb pxe dhcp spi
bootcmd=bootflow scan
bootdelay=2
cpu=armv8
cpuid#=55524b553339303237000000000e2207
eth1addr=32:87:c7:a6:0b:fb
ethaddr=32:87:c7:a6:0b:fa
fdt_addr_r=0x01e00000
fdtcontroladdr=3df12570
fdtfile=rockchip/rk3328-orangepi-r1-plus-lts.dtb
fdtoverlay_addr_r=0x01f00000
kernel_addr_r=0x02080000
kernel_comp_addr_r=0x08000000
kernel_comp_size=0x2000000
loadaddr=0x800800
partitions=uuid_disk=${uuid_gpt_disk};name=loader1,start=32K,size=4000K,uuid=${uuid_gpt_loader1};name=loader2,start=8MB,size=4MB,uuid=${uuid_gpt_loader2};name=trust,size=4M,uuid=${uuid_gpt_atf};name=boot,size=112M,bootable,uuid=${uuid_gpt_boot};name=rootfs,size=-,uuid=B921B045-1DF0-41C3-AF44-4C6F280D3FAE;
pxefile_addr_r=0x00600000
ramdisk_addr_r=0x06000000
script_offset_f=0xffe000
script_size_f=0x2000
scriptaddr=0x00500000
serial#=2a73990c9e9d3705
soc=rk3328
stderr=serial@ff130000
stdin=serial@ff130000
stdout=serial@ff130000
vendor=rockchip

Environment size: 1024/32764 bytes

Here is /boot/boot.cmd:

load ${devtype} ${devnum}:${distro_bootpart} ${kernel_addr_r} /boot/vmlinuz-6.17.8+deb14-arm64
load ${devtype} ${devnum}:${distro_bootpart} ${ramdisk_addr_r} /boot/initrd.img-6.17.8+deb14-arm64
setenv ramdisk_size ${filesize}
part uuid ${devtype} ${devnum}:${distro_bootpart} partuuid
setenv bootargs root=PARTUUID=${partuuid} rw rootwait
for fdtpath in /lib/firmware/6.17.8+deb14-arm64/device-tree/${vendor} /lib/firmware/6.17.8+deb14-arm64/device-tree /usr/lib/linux-image-6.17.8+deb14-arm64/${vendor} /usr/lib/linux-image-6.17.8+deb14-arm64 /usr/lib/linux/${vendor} /usr/lib/linux; do
  if test -e ${devtype} ${devnum}:${distro_bootpart} ${fdtpath}/${fdtfile}; then
    load ${devtype} ${devnum}:${distro_bootpart} ${fdt_addr_r} ${fdtpath}/${fdtfile}
    booti ${kernel_addr_r} ${ramdisk_addr_r}:${ramdisk_size} ${fdt_addr_r}
  fi
done
booti ${kernel_addr_r} ${ramdisk_addr_r}:${ramdisk_size} ${fdtcontroladdr}

Interesting links

It looks like this is the culmination of a set of pages on U-boot.

What can we do with boot.scr

It turns out we don't care, so skip below. First of all, we learned something important back with Buster, namely how to generate boot.scr from boot.cmd.
mkimage -C none -A arm -T script -d /boot/boot.cmd /boot/boot.scr
What I read is that boot.scr gets run before bootcmd executes.

Also it may be possible to have a file uEnv.txt that is used to set environment variables prior to running bootcmd. My experiments with this indicate that this feature is not present in the U-boot we are using.

If I type "bootflow scan" at the U-boot prompt, it does boot linux.

We could just replace "boot.scr" with whatever we need to do dhcp, but then what do we do if we want to boot linux? Given that savenv works for this U-boot we can just leave this file alone.

The final solution

We can do this to set up "run linux" to boot linux:

setenv linux bootflow scan
setenv loadaddr 0x02000000
setenv kyu echo Booting Kyu via dhcp/tftp\; dhcp\; go \${loadaddr}
setenv bootcmd run kyu
saveenv
I test this by typing "reset". It workss! I also test "run linux" and it also works.

It looks like we are ready to start running our own code.


Have any comments? Questions? Drop me a line!

Tom's electronics pages / tom@mmto.org