Yesterday I picked up the Banana Pi BPI-F3 I ordered 2 weeks ago. It is joining the small army of RISC-V devices I already own:

  • Espressif ESP32-C3 (20x)
  • Espressif ESP32-C6 (20x)
  • SiFive HiFive Unmatched
  • StarFive VisionFive 2

After giving the Armbian Noble image a quick try and being unimpressed, I decided to try installing Gentoo on it. I'll be documenting the process here. The first step: compile U-Boot.

The documentation contains links to the source code of OpenSBI, U-Boot and the Linux kernel. Looking at those links, I continue to be unimpressed: the repositories aren't proper forks of the upstream projects and have monster commits without any useful info in the commit messages. Upstreaming this is going to be challenging.

As I could not find any board-specific documentation to build U-Boot, I followed the instructions of one of my other RISC-V boards. To be able to build U-Boot, you first need to build OpenSBI. The files for the SpacemiT K1 are in the platform/generic directory, so the following command should be used to build OpenSBI:

make PLATFORM=generic

This immediately fails due to missing includes for the K1Pro. I reported a Github issue for this. Fortunately it was easy to fix.

make PLATFORM=generic menuconfig

In menuconfig, under Platform Options, disable Spacemit K1pro support, enable Spacemit K1x support and Spacemit K1x board evb, save and run make again. When the build is done, export the full path to build/platform/generic/firmware/fw_dynamic.bin in the OpenSBI dir as OPENSBI and change to the U-Boot source directory. To build, U-Boot, run the following commands:

make k1_defconfig
make

U-Boot built without issues from the first try. Yay! Now to figure out where to write the SPL and U-Boot images to the eMMC. During the U-Boot build I noticed the following files being generated:

bootinfo_emmc.bin  bootinfo_sd.bin  bootinfo_spinand.bin  bootinfo_spinor.bin

Looking at the files with hexdump, it seems the bootinfo_sd.bin file contents are in the Armbian image at offset 0. The BPI-F3 boot rom appears to look for it in the eMMC boot partitions, so we need to write it there. Without it, we see the following error when powering up the board without SD card:

ERROR:   emmc: invalid bootinfo magic code:0x0
ERROR:   invalid bootinfo image.

Write the bootinfo_emmc.bin file to the eMMC boot0 partition:

echo 0 > /sys/block/mmcblk2boot0/force_ro
dd if=bootinfo_emmc.bin of=/dev/mmcblk2boot0

This is also instructed in the Getting Started guide. In the same guide, we also find the offset where to write the SPL:

dd if=FSBL.bin of=/dev/mmcblk2boot0 bs=512 seek=1

After these steps SPL seems to load from eMMC. Remove the SD card and reset the board.

U-Boot SPL 2022.10spacemit-g2aa062b05 (May 19 2024 - 21:51:49 +0300)
lpddr4_silicon_init consume 11ms
BPI: partition=2 part_name[uboot]
BPI: p=1 info.name=[uboot] info.start[800]
BPI:hdr read sector 800, count=1
mmc_load_image_raw_sector: mmc block read error
spl: partition error
BPI: partition=1 part_name[opensbi]
BPI: p=1 info.name=[opensbi] info.start[500]
BPI:hdr read sector 500, count=1
mmc_load_image_raw_sector: mmc block read error
spl: partition error
SPL: Unsupported Boot Device!
SPL: failed to boot from all boot devices
### ERROR ### Please RESET the board ###

Now we have to figure out where to put U-Boot. The Bianbu image has U-Boot in a partition named uboot. Create a 2MiB partition on mmcblk2 with name "uboot", write the U-Boot image to it and reboot.

dd if=u-boot.itb of=/dev/mmcblk2p1
sync
reboot

And we have SPL and U-Boot built from source booting from the eMMC!

sys: 0x2
try sd...
bm:3
ERROR:   CMD8
ERROR:   sd f! l:76
bm:0
j...

U-Boot SPL 2022.10spacemit-g2aa062b05 (May 19 2024 - 21:51:49 +0300)
lpddr4_silicon_init consume 11ms
BPI: partition=2 part_name[uboot]
BPI: p=1 info.name=[uboot] info.start[800]
BPI:hdr read sector 800, count=1
Boot from fit configuration k1-x_deb1
## Checking hash(es) for config conf_2 ... OK
## Checking hash(es) for Image uboot ... crc32+ OK
## Checking hash(es) for Image fdt_2 ... crc32+ OK
BPI: partition=1 part_name[opensbi]
BPI: p=1 info.name=[uboot] info.start[800]
BPI: p=2 info.name=[opensbi] info.start[500]
BPI:hdr read sector 500, count=1
mmc_load_image_raw_sector: mmc block read error
BPI2: info.name=[uboot] info.start[800]
BPI:hdr read sector 800, count=1
Boot from fit configuration k1-x_deb1
## Checking hash(es) for config conf_2 ... OK
## Checking hash(es) for Image uboot ... crc32+ OK
## Checking hash(es) for Image fdt_2 ... crc32+ OK


U-Boot 2022.10spacemit-g2aa062b05 (May 19 2024 - 21:51:49 +0300)

CPU:   rv64imafdcvsu_zicsr_zifencei_zicbom_zihintpause_zba_zbb_zbc_zbs_svpbmt_sstc_sscofpmf
Model: spacemit k1-x deb1 board
DRAM:  DDR size = 4096 MB
DDR size = 4096 MB
DDR size = 4096 MB
4 GiB
[RESET]probe start 

[RESET]probe finish 

DCDC_REG1@dcdc1: ; enabling
DCDC_REG2@dcdc2: ; enabling
DCDC_REG3@dcdc3: ; enabling
DCDC_REG4@dcdc4: ; enabling
DCDC_REG5@dcdc5: ; enabling
DCDC_REG6@dcdc6: ; enabling
LDO_REG1@ldo1: ; enabling
LDO_REG2@ldo2: ; enabling
LDO_REG3@ldo3: ; enabling
LDO_REG4@ldo4: ; enabling
LDO_REG5@ldo5: ; enabling
LDO_REG6@ldo6: ; enabling
LDO_REG7@ldo7: ; enabling
LDO_REG8@ldo8: ; enabling
LDO_REG9@ldo9: ; enabling
LDO_REG10@ldo10: ; enabling
LDO_REG11@ldo11: ; enabling
SWITCH_REG1@switch1: ; enabling
DDR size = 4096 MB
Core:  399 devices, 27 uclasses, devicetree: board
MMC:   [RESET]spacemit_reset_set assert=0, id=71 

[RESET]spacemit_reset_set assert=0, id=72 

sdh@d4280000: probe done.
[RESET]spacemit_reset_set assert=0, id=71 

[RESET]spacemit_reset_set assert=0, id=83 

sdh@d4281000: probe done.
sdh@d4280000: 0, sdh@d4281000: 2
Loading Environment from MMC... sdh@d4281000: 74 clk wait timeout(100)
*** Warning - bad CRC, using default environment

pcie_dw_k1x_probe, 662
[RESET]spacemit_reset_set assert=0, id=90 

Now init Rterm...
pcie prot id = 1, porta_init_done = 0
Now waiting portA resister tuning done...
porta redonly_reg2: 00005d47
pcie_rcal = 0x00005d47
pcie port id = 1, lane num = 2
Now int init_puphy...
waiting pll lock...
Now finish init_puphy....
pcie_dw_k1x pcie@ca400000: Unable to get phy0pcie_dw_k1x pcie@ca400000: Unable to get phy1PCIE-0: Link down
Cannot find partition: bootfs
Failed to get partition index for bootfs
initialize_console_log_buffer
Have allocated memory for console log buffer
In:    serial
Out:   serial
Err:   serial
ddr_freq_change: ddr frequency change from level 0 to 6
Change DDR data rate to 2400MT/s
[RESET]spacemit_reset_set assert=0, id=38 

Default to 100kHz
EEPROM: TlvInfo v1 len=32
valid ethaddr: fe:fe:fe:3d:87:d5
Serial number is valid.
Cannot find TLV data: product_name
Cannot find TLV data: manufacture_date
Cannot find TLV data: manufacturer
Cannot find TLV data: device_version
Cannot find TLV data: sdk_version
sdh@d4280000: 74 clk wait timeout(100)
MMC: no card present
mmc_init: -123, time 5
BPI: :_load_env_from_blk
BPI: cmd:load mmc 2:1 0x20000000 env_k1-x.txt
Can't set block device
Net:   [RESET]spacemit_reset_set assert=0, id=92 

RGMII interface
eth0: ethernet@cac80000
Autoboot in 0 seconds, press <Space> to stop
Try to boot from MMC2 ...
setexpr - set environment variable as the result of eval expression

Usage:
setexpr [.b, .w, .l, .s] name [*]value1 <op> [*]value2
    - set environment variable 'name' to the result of the evaluated
      expression specified by <op>.  <op> can be &, |, ^, +, -, *, /, %
      (for strings only + is supported)
      size argument is only meaningful if value1 and/or value2 are
      memory addresses (*)
setexpr[.b, .w, .l] name [*]value
    - load a value into a variable
setexpr name gsub r s [t]
    - For each substring matching the regular expression <r> in the
      string <t>, substitute the string <s>.  The result is
      assigned to <name>.  If <t> is not supplied, use the old
      value of <name>
setexpr name sub r s [t]
    - Just like gsub(), but replace only the first matching substring
product_name: k1-x_deb1
falling to default dtb: /k1-x_deb1.dtb
select /k1-x_deb1.dtb to load
Loading kernel...
Can't set block device
Loading dtb...
Can't set block device
load dtb from bootfs fail, use built-in dtb
Loading ramdisk ...
Can't set block device
load ramdisk from bootfs fail, use built-in ramdisk
## Loading kernel from FIT Image at 10000000 ...
   Using 'conf-default' configuration
   Verifying Hash Integrity ... OK
   Trying 'kernel' kernel subimage
     Description:  Linux 6.1.15
     Type:         Kernel Image
     Compression:  gzip compressed
     Data Start:   0x100000bc
     Data Size:    13082784 Bytes = 12.5 MiB
     Architecture: RISC-V
     OS:           Linux
     Load Address: 0x01400000
     Entry Point:  0x01400000
     Hash algo:    crc32
     Hash value:   ae8da93b
   Verifying Hash Integrity ... crc32 error!
Bad hash value for 'hash' hash node in 'kernel' image node
Bad Data Hash
ERROR: can't get kernel image!
########### boot kernel failed by default config, check your boot config #############
run autoboot
=>