Updating an older board

I’ve got one of the original crowdfunded boards which I’d like to update to current everything, however with the original MTD layout:

  dev:    size   erasesize  name
  mtd0: 00020000 00001000 "spl"
  mtd1: 00300000 00001000 "uboot"
  mtd2: 00100000 00001000 "data"

that’s not going to work. There are various discussions going back a few years but they’re all rather incomplete and the details of what you should do change over time. Can anyone provide some info on what the current recommended MTD partitioning scheme is, and how to get there from here? Specifically, I’m after the bits between mtdpart del /dev/mtd 0 / 1 / 2 and flashcp -v …, because it looks like not just the size has changed but the number and names as well.

Also, if I do that from the current running system can I just reboot back into the installed Linux setup from the new FW or do I need to upgrade the distro as well?

Using the latest system vf2-debin 202510 requires the corresponding version of spl uboot, and they are all in the same download directory.

The safest way to upgrade SPL U-Boot from the original version of VF2 to the latest version is using USB-to-serial.

Thanks! So the bootloader-recovery process really seems intended for bricked devices and is kinda complex, I’ve got a bootable, running system so I was hoping to avoid all that and do it from the CLI. From your screenshot it looks like it’s just a case of getting from the original:

dev:    size   erasesize  name
mtd0: 00020000 00001000 "spl"				// 128kB
mtd1: 00300000 00001000 "uboot"				// 3072kB
mtd2: 00100000 00001000 "data"				// 1024kB

to the new:

dev:    size   erasesize  name
mtd0: 000f0000 00001000 "spl"				// 960kB
mtd1: 00010000 00001000 "uboot-env"			// 64kB
mtd2: 00f00000 00001000 "uboot"				// 15350kB

which should be achievable via the following:

mtdpart del /dev/mtd 0
mtdpart del /dev/mtd 1
mtdpart del /dev/mtd 2
mtdpart add /dev/mtd "spl" 0x0 0xf0000
mtdpart add /dev/mtd "uboot-env" 0xf0000 0x10000
mtdpart add /dev/mtd "uboot" 0x100000 0xf00000
flashcp -v u-boot-spl.bin.normal.out /dev/mtd0
flashcp -v visionfive2_fw_payload.img  /dev/mtd2

Does that seem about right? Then reflash the SD card with the current Linux release and restart.

I haven’t done it this way, so I’m not sure if it’s correct.
I used the method provided by StarFive officially, which is simple and effective. StarFive’s official solution is conservative and safe.:blush:

One problem is that the QSPI Flash partitions are defined in the device tree, so manually editing them (without also updating the device tree binary) will be reset back to what is defined in the dtb on the next boot.

ref: linux/arch/riscv/boot/dts/starfive/jh7110-common.dtsi at 4cecf169f38eb94b40e307f5f870055e4d9d64f1 · starfive-tech/linux · GitHub

EDIT: But of course you can decompile any dtb to dts, edit the source with your preferred editor and recompile the updated source into a new dtb. But if things go pear shaped, you really do need a USB to 3.3v TTL UART (Or you can use the UART on another SBC with three Female to Female 2.54mm GPIO Jumper Wires for GND-GND, RX<-TX, TX->RX).

e.g.

sudo apt install device-tree-compiler

dtc -I dtb -O dts -o devicetree.dts devicetree.dtb

vi devicetree.dts

dtc -I dts -O dtb -o devicetree.dtb devicetree.dts
3 Likes

After a ridiculous amount of effort I’ve now got a slightly more recent system up and running, I didn’t use the firmware-recovery approach because it looks like it only reflashes the firmware but doesn’t repartition the MTD. For anyone else facing this, to move from older FW to the most recent I could get to, grab the latest release that still contains the sdcard image, which is 5.11.3, write it to an SD card, and switch the boot to SDIO. Booting this takes the MTD from:

cat /proc/mtd
dev:    size   erasesize  name
mtd0: 00020000 00001000 "spl"
mtd1: 00300000 00001000 "uboot"
mtd2: 00100000 00001000 "data"

to:

cat /proc/mtd
dev:    size   erasesize  name
mtd0: 00040000 00001000 "spl"
mtd1: 00010000 00001000 "uboot-env"
mtd2: 00300000 00001000 "uboot"
mtd3: 00100000 00001000 "data"

You can now flash the larger SPL into the mtd0 partition, but the mtd2 partition isn’t big enough to contain the latest FW, the sdcard image doesn’t contain the MTD utils, and the full Debian image doesn’t make /dev/mtd available so you can’t mtdpart it. This means you have to flash the 5.11 SPL/FW image and not a more recent one.

The next problem is that with the latest Debian image (202510) booted off the SPI flash networking doesn’t work, you need to boot off SDIO which pretty much defeats all of the above effort getting the FW flashed. And the signing keys included with it seem to have expired despite it only being a few months old which means you can’t update it either.

So after looking at the device tree (incidentally you missed a step, sudo dd if=/sys/firmware/fdt of=devicetree.dtb) it appears that the 202510 image updated the MTD yet again:

cat /proc/mtd
dev:    size   erasesize  name
mtd0: 000f0000 00001000 "spl"
mtd1: 00010000 00001000 "uboot-env"
mtd2: 00f00000 00001000 "uboot"

Does anyone know what it’s doing here? The layout is completely different from what it was before booting 202510 in that there’s now actually room for the FW, but given that the layout is different does that mean during the initial setup it reflashed the MTD to relocate the FW into the new partitions?

Edit: With the resized MTD partitions it’s now possible to flash the 6.0.0 FW, which works fine, and networking is working again as well when booting via that. So it looks like a quicker upgrade path might be:

  1. Flash the 202510 image to SD card.
  2. Switch boot to SDIO and boot the 202510 image off SD, not MTD.
  3. Check that the MTD resizing has occurred and flash the 6.0.0 FW.
  4. Switch boot back to MTD and boot back into the 202510 image.

This would save a lot of intermediate steps if it works.

1 Like

It’s all defined by the Linux device-tree. Dcompiling it reveals:

partitions {
  compatible = "fixed-partitions";
  #address-cells = <0x00000001>;
  #size-cells = <0x00000001>;
  spl@0 {
    reg = <0x00000000 0x000f0000>;
  };
  uboot-env@f0000 {
    reg = <0x000f0000 0x00010000>;
  };
  uboot@100000 {
    reg = <0x00100000 0x00f00000>;
  };
};

There’s no relocation/reflash. It just split the mtd into different partitions by address/size, and that’s it.

The bootloader (u-boot SPL) hardcodes the offset to the uboot-env and u-boot proper in SPI flash, and that’s how the SPL can find u-boot env and u-boot proper to be able to boot. If you flash something using the Linux MTD partition table, and that happens to be inconsistent with the way u-boot SPL’s built, it’ll get totally messed up. Using mtdpart to fix the partition first before flashing is the right thing to do. Or as you said, boot the new Linux image first and flash from there. Starfive did a terrible job keeping the bootloader forward/backward compatible, and it’s easy to make mistakes and brick the board. Be prepared to invoke the recovery bootloader if anything goes wrong.

2 Likes

Maybe I just got really lucky with the step-by-step incremental upgrade path. In any case now that it’s working I’m really not going to touch it again…