Uboot for the RPi4

In the repo we have uboot-raspberrypi. I have never used uboot to boot an image of my own making. I downloaded it and unpacked the files manually and copied them to a normally populated /boot for a RPi4, allowing it to overwrite any existing files. This includes a file called kernel8.img.

I think what is need next, is a zImage kernel. So I downloaded the PKGBUILD and modified it by replacing Image with zImage. However, this fails as there is no make target for zImage. So I then installed the uboot-tools but not sure what to do with them or if they are needed.

For something so popular, I have not found a good how-to on using uboot with the RPI4. Any help out there as to how to proceed?

Edit: It similarly fails for bzImage.

The uboot-raspberrypi package is meant to be used with the mainline linux kernel package.

We don’t use it by default, but we have the option to use it. It takes a bit of settting up still, as it’s not something we have used a lot.

Would you know what I might expect, if I were to install the linux kernel, replacing the linux-rpi4 kernel? Is there enough configured in the generic kernel to successfully boot and find the required devices?

Most things should work. The most noticable thing missing would be v3d (3d acceleration).

That I can live with, but I’ll start with a fresh install on a SD card to be on the safe side.

The point of this exercise is to have a boot time option to select between different kernel command line options. Am I correct in assuming this is possible with the uboot-raspberrypi package? And if so, it is accomplished with the use of a boot.scr file?

I was successful with booting uboot-raspberrypi and the mainline linux kernel on a SD card. However, it seems there is no USB support, so no mouse or keyboard. So far, I have not found a way to get USB support working. I tried making a boot.scr file with usb start, but I do not think it was referenced.

I did find it gets the boot particulars from the file /boot/extlinux/extlinux.conf.

Edit: Ok, I learned that the extlinux.conf file is the first file uboot looks for. So I renamed it and my boot.scr was executed:

Bus xhci_pci: probe failed, error -110
No working controllers found

So I think this means the uboot-raspberrypi package does not support USB on the RPi4.

Edit 2: After trying many things, I copied a newer /boot/bcm2711-rpi-4-b.dtb file from a arm-unstable install, rebooted and bingo, usb keyboard and mouse are working now. Credit to @Darksky in an old thread.

does wifi work?

Yes, wifi is working, but no sound. I have not looked into the sound issue yet. aplay -l shows no devices, yet there are snd kernel modules loaded.

maybe wait kernel-5.14 original supported?

I copied over the kernel, initramfs and /lib/modules from a working rpi4 install with linux-rpi4-mainline 5.12.10-1 and then modified the extlinux.conf file accordingly and it boots… and everything seems to work.

So no sound devices and no v3d are issues to be resolved with the vanilla kernel, at least out of the box.

To recap, a simple way to add a boot menu to the rpi4:

Download the uboot-raspberrypi package:

$ sudo pacman -Sw uboot-raspberrypi

The file will download to the /var/cache/pacman/pkg/ directory.
Create a directory to store the package contents, I suggest:

$ sudo mkdir /opt/uboot-raspberrypi
$ cd /opt/uboot-raspberrypi
$ sudo cp /var/var/pacman/pkg/uboot-raspberrypi*.zst /opt/uboot-raspberrypi/
$ sudo zstd -d uboot-raspberrypi*.zst
$ tar -xf uboot-raspberrypi*.tar
$ cd ./boot
$ sudo cp kernel8.img /boot/u-boot.bin

The file kernel8.img, is the only file we want from this package, but copy and rename it, as above, so it does not conflict with the linux-rpi4* kernel package.

Edit the /boot/config.txt file and change the kernel= line to:

kernel=u-boot.bin

Now create the directory for the menu file:

sudo mkdir /boot/extlinux/

And finally create the menu file:

sudo nano /boot/extlinux/extlinux.conf

As an example:

MENU TITLE Boot Menu

# This corresponds to a label below.
DEFAULT linux-hardware

# Timeout is measured in 1/10 of a second.
# 60 -> 6 seconds.
# Timeout is ignored if only one menu entry.
TIMEOUT 60

LABEL linux-hardware
  MENU LABEL Manjaro ARM with v3d
  MENU DEFAULT
  KERNEL /kernel8.img
  APPEND initrd=/initramfs-linux.img root=LABEL=ROOT_MNJRO nofbturbo rw rootwait console=serial0,115200 console=tty3 selinux=0 smsc95xx.turbo_mode=N dwc_otg.lpm_enable=0 kgdboc=serial0,115200 elevator=noop usbhid.mousepoll=8 snd-bcm2835.enable_compat_alsa=0 audit=0root=PARTUUID=8b919108-02 rw rootwait console=serial0,115200 console=tty3 selinux=0 smsc95xx.turbo_mode=N dwc_otg.lpm_enable=0 kgdboc=serial0,115200 elevator=noop usbhid.mousepoll=8 snd-bcm2835.enable_compat_alsa=0 audit=0

LABEL linux-software
  MENU LABEL Manjaro ARM with llvmpipe
  KERNEL /kernel8.img
  APPEND initrd=/initramfs-linux.img root=LABEL=ROOT_MNJRO rw rootwait console=serial0,115200 console=tty3 selinux=0 smsc95xx.turbo_mode=N dwc_otg.lpm_enable=0 kgdboc=serial0,115200 elevator=noop usbhid.mousepoll=8 snd-bcm2835.enable_compat_alsa=0 audit=0root=PARTUUID=8b919108-02 rw rootwait console=serial0,115200 console=tty3 selinux=0 smsc95xx.turbo_mode=N dwc_otg.lpm_enable=0 kgdboc=serial0,115200 elevator=noop usbhid.mousepoll=8 snd-bcm2835.enable_compat_alsa=0 audit=0

The only difference here is the single kernel parameter nofbturbo that switches between hardware and software rendering on my installation, as posted elsewhere.
Note: This swapping of fbturbo/v3d seems to only work with my network boot setup. Stand alone boot seems to have an issue with vc4-fkms-v3d in the device tree and then using llvmpipe, resulting in missing window decorations with kwin_x11. So I think the better way would be to use a uboot script to build different device trees based on the menu selection. To accomplish this, I plan to use uboot-tools to make such a script… I think, I hope. :slight_smile:

Ok, I have been playing around with uboot with a bit of success but more failure.

But I am stumped and hope those with more insight can help me.

I am trying to use the device tree as it was assembled by start.elf. In config.txt I set the address to some value, I have tried several. But for example, if I set device_tree_address=0x1f0000 and overlay=vc4-kms-v3d-rpi4 and check the header, it seems fine, no errors and I it boots and all is good.

However, I now want to load the overlay via uboot and not via start.elf and config.txt. So I set the same address but remove the overlay from config.txt. If I then check the header, all is good. But when I try to perform a resize with fdt resize 8192 to make space to apply the vc4-kms-v3d-pi4.dtbo, the device tree is no longer valid… I think. Because then the fdt apply fails with FDT_ERR_NOTFOUND. And then subsequently when booting: ERROR: Did not find a cmdline Flattened Device Tree.

I am not loading the base device tree via uboot, I am using the one assembled via start.elf because I think more occurs when start.elf executes than simply loading the base device tree, but I could be mistaken, and please correct me if I am wrong.

Edit: I must be doing something wrong. If I start fresh by loading the base device tree and applying the overlay, same error. More efforting ahead…

my recall, fedora using uboot, check it out.

Yes, I am sure that I can do what SUSE and Fedora do, using uboot to load grub. However, I wanted to be able to decide the device tree configuration at boot time. To be able to construct the device tree before booting.

In my testing last night, I found that I can fdt apply the the disable-wifi overlay but the disable-bt also had an error, but a different one. This one about symbols which I have seen something on. However the vc4 fkms/kms overlays will not apply, I always get a FDT_ERR_NOTFOUND.

There is something going on that I do not know about… I expect the magic is found in start.elf. Or maybe it is something like the troublesome overlays bring in or use another other overlay… like maybe overlay_map.dtbo.

Edit: I just found this link… dang, this may be too far over my head. :frowning:

Anyone have any experience with the dtoverlay/dtoverlay-pre/dtoverlay-post or fdtoverlay userland tools? Maybe I can use them to construct a couple of different device trees, and then pass the desired one to the kernel via uboot or grub?

I have created full device trees and passed them before, and it mostly works… but if I recall properly, I had a problem with the mailbox not being created when passing the device tree. However, I did not use these specific userland tools.

Hmm, or maybe this is what I need to use?

Edit: I may need to rethink how best to accomplish my goal. This link offers more insight into the construction and reconstruction of the device tree.

Edit : more details

Linux 5.14 include:
Refactoring of the BCM2711 DTSI structure for supporting the Raspberry Pi 400

https://www.phoronix.com/scan.php?page=news_item&px=Arm-SoC-DT-Platform-Linux-5.14

:crossed_fingers:

According to http://phb-crystal-ball.org/

the v5.14 kernel predictions: merge window closes on Sunday, 2021-07-11 and release on Sunday, 2021-09-05

I keep hitting dead ends. The latest is the uboot-raspberrypi does not seem to have any support for a menu in a script. Only the extlinux.conf, but it does not offer the required ability. Maybe grub can do it…

It has been educational.

The newest version of uboot-raspberrypi now supports the bootmenu command, thanks to @Strit. A basic example of a u-boot script which works for a ssd:
$ cat /boot/boot.txt

setenv fdt_addr_r 0x3e00000
fdt addr ${fdt_addr_r}
setenv bootargs root=LABEL=MNJRO_ROOT rootfstype=btrfs rw rootwait console=serial0,115200 console=tty1 selinux=0 smsc95xx.turbo_mode=N dwc_otg.lpm_enable=0 kgdboc=serial0,115200 usbhid.mousepoll=8 snd-bcm2835.enable_compat_alsa=0 audit=0
fatload usb 0:1 ${kernel_addr_r} kernel8.img
fatload usb 0:1 ${ramdisk_addr_r} initramfs-linux.img
setenv initrdsize $filesize

setenv bootmenu_0 Boot Manjaro kernel=booti ${kernel_addr_r} ${ramdisk_addr_r}:${initrdsize} ${fdt_addr_r}
setenv bootmenu_1 Reboot board=reset
bootmenu 10

And I have device_tree_address=0x3e00000 set in my config.txt file.

Finally, I have a working menu that modifies the device tree and results in either v3d or llvmpipe rendering, without the need to change config.txt:

$ cat /boot/boot.txt

# mkimage -T script -C none -n 'My Script File' -d boot.txt boot.scr

setenv fdt_addr_r 0x3e00000
fdt addr ${fdt_addr_r}
fdt resize 8192
setenv fdt_ovl_addr_r 0x3f00000

setenv bootargs root=LABEL=MNJRO_ROOT rootfstype=btrfs rw rootwait console=serial0,115200 console=tty1 selinux=0 smsc95xx.turbo_mode=N dwc_otg.lpm_enable=0 kgdboc=serial0,115200 usbhid.mousepoll=8 snd-bcm2835.enable_compat_alsa=0 audit=0
fatload usb 0:1 ${kernel_addr_r} kernel8.img
fatload usb 0:1 ${ramdisk_addr_r} initramfs-linux.img
setenv ramdisk_size ${filesize}

setenv load_disable_v3d fatload usb 0:1 ${fdt_ovl_addr_r} overlays/disable-v3d.dtbo
setenv apply_overlay fdt apply ${fdt_ovl_addr_r}
setenv standard_boot booti ${kernel_addr_r} ${ramdisk_addr_r}:${ramdisk_size} ${fdt_addr_r}

setenv bootmenu_0 Manjaro v3d=run standard_boot
setenv bootmenu_1 Manjaro llvmpipe=run load_disable_v3d apply_overlay standard_boot
setenv bootmenu_2 Reboot=reset
bootmenu 10