NVME Boot using VisionFive2 Software v2.11.5

Yeah, me. When I heard about this I immediately rushed to get git head then to build it.
Immediately I found that U-Boot does not enumerate PCI automatically, but I knew it can be scripted to do so before you even get dropped to it’s prompt.

U-Boot runs preboot each time it runs but before bootcmd or shell pops up. All you need is to properly instruct it:

Append pci enum; nvme scan to end of existing preboot contents: echo $preboot to get current contents, then add ; pci enum; nvme scan to the end. For example, I had run chipa_set_uboot;run mmcbootenv in $preboot, I just made it look like run chipa_set_uboot;run mmcbootenv; pci enum; nvme scan. Run saveenv to save changes (they are saved to same QSPI flash space at 0xf0000), and reset / power cycle your VF2. If your NVME is inserted, it will catch up automatically, otherwise there is no any harm if no any present, driver will just silently fail but will not prevent U-Boot from continuing.

Sometimes PCI enumeration gets stuck for about ten seconds, dunno why, it happens rarely and usually successfully.

If you don’t like it, you can remove the change. In worst case you can reflash the entire thing with recovery binary.

HTH

3 Likes

I also made entire thing of booting more convenient by instructing U-Boot to read an extlinux.conf from my NVME boot partition.

  1. Copy existing contents of bootcmd to a backup variable: env set bootcmd_b $bootcmd
  2. Set bootcmd to sysboot nvme 0:1 any ${pxefile_addr_r} /extlinux.conf
  3. Save environ: saveenv
  4. Reset / power cycle

Prepare your {nvme0n1p1}/extlinux.conf with like:

menu title Slackware RISCV boot options
timeout 20
default linux64

label linux64
        kernel /linux64.gz
        fdt /jh7110-visionfive-v2.dtb
        append ro quiet console=ttyS0,115200 earlycon=sbi root=/dev/nvme0n1p2 rootwait stmmac.chain_mode=1
        initrd <optional if you need it>

idk, you might also need a /extlinux/extlinux.conf symlink to /extlinux.conf. Mine board does have it. If you have troubles booting, move file there or make this symlink. Consult U-Boot environment.

This way you can add boot targets, like working one and another with init=/bin/sh for recovery. And you’ll get text menu to choose from, with timeout to default.

1 Like

You can make these changes permanent by editing /etc/default/uboot, eg this is what I have:

#U_BOOT_UPDATE="true"
#U_BOOT_ALTERNATIVES="default recovery"
#U_BOOT_DEFAULT="l0"
#U_BOOT_ENTRIES="all"
#U_BOOT_MENU_LABEL="Debian GNU/Linux"
#U_BOOT_PARAMETERS="ro quiet"
U_BOOT_ROOT="/dev/nvme0n1p4"
U_BOOT_TIMEOUT="200"
#U_BOOT_FDT=""
#U_BOOT_FDT_DIR="/usr/lib/linux-image-"
#U_BOOT_FDT_OVERLAYS=""
#U_BOOT_FDT_OVERLAYS_DIR="/boot/dtbo/"
U_BOOT_PARAMETERS="rw console=tty0 console=ttyS0,115200 earlycon rootwait stmmaceth=chain_mode:1 selinux=0"
U_BOOT_FDT_DIR="/dtbs/"

If you are upgrading kernels via packages (as I do) this helps update-uboot to set the defaults properly when dpkg -i installs the new kernel.

Note that I remove the root= line from the line parameters, U_BOOT_ROOT should be set automagically by DPKG based on the current root partition, but specifying it here makes sure it is correct. If you do not remove it from the default line you will have two root= entries in the extlinux commandline, which works but is ugly/confusing.

1 Like

I run Slarm64/riscv64 and I dont have these :sob: :slight_smile:

bootcmd is now =bootcmd_distro
I’m using bootcmd=distro_bootcmd

with boot_targets=mmc0 nvme0 dhcp
bootcmd_nvme0=devnum=0; run nvme_boot
kernel_comp_addr_r=0x90000000
kernel_comp_size=0x10000000

and it now works for nvme or mmc
I haven’t got an emmc to test if it can alternatively work

the environment variables are stacking up with a whole lot of patches (cruft)

1 Like

Unfortunately mmcbootenv doesn’t load uEnv.txt for nvme
much of the scripting is built around mmc

a lot of changes are required to use ${devtype} instead of mmc

in a number of places ${partnum} is hardcoded to 3
locking the u-boot to only boot a distro from partition 3

flash firmware should be more adaptable to different booting requirements

1 Like

I’ve independently gone through much of the same exercise today as coltree did, modifying and/or duplicating the mmc-specific boot commands to make them suitable for use with nvme. I agree, a big cleanup of the boot scripts/commands would be very welcome - it’s clear that there’s a lot of “initial development and bringup” logic in there, and not as much generality as would be useful.

Ne’er the less, after a few hours of hacking, I’ve gotten my board so that it can boot directly from QSPI into NVME, with no mmc access at all being required (my SD card is now sitting happily in the storage box).

This took a bit of experimental hackery, since the released versions of the U-Boot payload for QSPI don’t have PCIe/NVMe support yet. I ended up extracting the versions of the SPL and U-Boot from the Wayland .img recently released (used loopback to access the .img file, dd to copy partitions 1 and 2), stripped off some of the redundant zeroes at the ends of each so that spflash didn’t complain about size, and flashed. Amazingly enough, this worked without a single episode of bricking :grin:

So, I now have the Wayland image copied to NVME, its SPL and U-boot copied to QSPI, a bunch of new commands and settings added to the QSPI environment, and it seems to boot NVME reliably every time.

My version of this QSPI stuff won’t auto-boot from MMC at all - if I want to do that again I have to either stop the boot process from the console and “run mmcboot” manually, or flip the boot-device switches so that the ROM loads the SPL and U-Boot from the MMC.

5 Likes

in the preboot stage, identify the boot order
then in bootcmd boot from first bootable partition found
proposed change pseudo code-

boot_targets=sd emmc nvme
preboot=for target in boot_targets;
do initialise target device; set envs ${devtype}, ${devnum};
find first boot partition; setenv ${devpart};
load and import environment variables; exit;
done
(exits preboot after loading first uEnv, etc in boot order)
leaves ${devtype} ${devnum} ${devpart} ready for bootcmd
bootcmd=load … ; boot … ;
(or fall through to)
initialise dhcp; boot dhcp

1 Like

I can now boot from sd, emmc or nvme with a few small changes
not the major changes I feel are needed for a universal u-boot.
it now fails when booting SD sdcard.img from Releases · starfive-tech/VisionFive2 · GitHub
they have forked it…

2 Likes

I have had no luck booting the Starfive Debian ‘69’ image off my NVMe SSD yet by following the instructions in the first post. It starts to boot but it kernel panics before it loads Xorg or gets to the login screen.

I have updated my VF2 to the latest official u-boot and firmware, expanded the root partition to fill the SSD and I’ve adjusted the fstab and extlinux.conf files to use nvme0n1p3 for the root partition instead of the SD card.

Here’s a boot log of me ‘manually’ entering (copy/pasting) the above suggested U-boot commands via a serial connection followed by the kernel panic which seems to be HDMI firmware related?

I can successfully boot the Debian 69 image off SD card fine and I can also access my NVMe disk under Debian 69 when booted from SD card fine but I want to boot Debian directly from NVMe with no SD card boot partition.

This log is from when my VF2 was attached to a 1080p HDMI display that I have tested and know works under Debian 69 when it is booted from a SD card.

you can’t boot old images with a new u-boot and visa versa
get the new Debian image or Armbian, etc
the info is all up there somewhere
get the uboot prompt and good hunting
have to modify a couple of uboot scripts

2 Likes

I would like to try your method and I think others would also. Could you possibly present a step by step method for a learner with limited experience but eager to learn. Thanks much!

1 Like

Almost there!

I’ve been able to successfully boot Debian sid directly from NVME on my VF2 but only by manually entering these commands into uboot.

I am running the official 2.11.5 u-boot and firmware from here:

I have not updated OpenSBI.

I burned this image onto an NVME disk:

and I expanded the root partition to fill the full SSD. I did not adjust the extlinux.conf or the fstab.

I entered the following commands in u-boot:

nvme scan
fatload nvme 0:3 ${kernel_addr_r} vmlinuz-5.15.0-vf2-104+
fatload nvme 0:3 ${ramdisk_addr_r} initrd.img-5.15.0-vf2-104+
fatload nvme 0:3 ${fdt_addr_r} dtb-5.15.0-vf2-104+/starfive/jh7110-visionfive-v2.dtb
setenv bootargs 'root=/dev/nvme0n1p4 rw console=tty0 console=ttyS0,115200 earlycon rootwait'
setenv kernel_comp_addr_r 0x50000000
setenv kernel_comp_size 0x04000000
booti $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r

That booti command boots Debian off the NVME. Note I’ve omitted saveenv because these commands don’t work when saved, only entered manually at the uboot prompt. I’ve already tried defining the relevant env names ($bootfile, $ramdiskfile, $fdtfile), adding nvme0 to $boot_targets etc and a few other things but I’ve not hit the winning combo yet.

I’m hoping that someone who understands u-boot and the VF2 boot process better than me can tell me how to configure uboot to make this Debian sid image boot without manual intervention or adding extra boot partitions/disks. I doubt that a new u-boot or opensbi is required to fix this.

4K HDMI output works under sid and it survives apt upgrade too.

2 Likes

I have now got Debian sid automatically booting from my m.2 SSD.

Note that this is a hacky solution because it uses the booti command to load the kernel and initrd instead of using the u-boot sysboot command to parse the extlinux.conf but its a step in the right direction and proof that direct SSD boot is possible with a current image and the current official u-boot/firmware, 2.11.5.

I did not need to modify the default fstab nor the extlinux.conf included with sid. The only modifaction to the standard sid image was to resize the root btrfs partition to fill the disk using gparted.

You might want to run env default -a -f to reset your current u-boot config before running the following u-boot commands:

setenv boot_targets nvme0
setenv preboot 'run chipa_set_uboot;pci enum;nvme scan'
setenv bootargs 'root=/dev/nvme0n1p4 console=tty1 console=ttyS0,115200  debug rootwait  earlycon=sbi'
setenv kernel_comp_addr_r 0x50000000
setenv kernel_comp_size 0x04000000
setenv bootcmd 'fatload nvme 0:3 ${kernel_addr_r} vmlinuz-5.15.0-vf2-104+; fatload nvme 0:3 ${ramdisk_addr_r} initrd.img-5.15.0-vf2-104+; fatload nvme 0:3 ${fdt_addr_r} dtb-5.15.0-vf2-104+/starfive/jh7110-visionfive-v2.dtb; booti $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r'
saveenv
5 Likes

Now to figure out how to do it properly with the new V3.0.4 firmware.

NVMe UEFI boot still not work by default with V3.0.4 firmware. It boot after messing with U-Boot commands, but I am not sure how to do it right.

What is recommended method to boot from NVMe UEFI? ESP is first partition on NVMe disk. It contains only EFI boot loader and nothing else (no extlinux, no uEnv.txt etc.).

I’ve not tried UEFI booting on VF2 but I can confirm that direct NVMe boot using extlinux.conf works with the latest arch image (cwt13) using the default u-boot settings.

https://forum.rvspace.org/t/arch-linux-image-for-visionfive-2

Not interested in extlinux because not using Linux.

Currently solved with:

env default -a -f
setenv boot_targets "mmc0 nvme0 dhcp"
setenv bootcmd_nvme0 "devnum=0; run nvme_boot"
saveenv
1 Like

That seems like an acceptable workaround to me but it would be nice if it could be avoided with a correctly configured UEFI partition.

1 Like

Can we boot up Ubuntu on NVME with similar approach? Thanks!