sh1r4s3@blog /2023/06/02/nezha-d1.html% ./show_motd
Hi there, netlander...

sh1r4s3@blog /2023/06/02/nezha-d1.html%

Allwinner’s Nezha D1 is a SoC based on RISC-V CPU with XuanTie C906 which is a 64-bit RV64GC CPU @ 1 GHz capable to run Linux distributions. The SoC is also has 512 Mb/1 Gb/2 Gb of RAM, Ethernet, WiFi, 256 MB of NAND flash memory and HDMI. The detailed description of the board with schematics could be found here. I have a model with 1 Gb of RAM. On the right side is a few photos of this SoC. This SoC ships with a 32 Gb microSD card with bootloaders and Debian distribution. The default partition table is a bit sophisticated:

1
2
3
4
5
6
7
8
9
Number  Start (sector)    End (sector)  Size       Code  Name
   1           41464           49527   3.9 MiB     0700  boot-resource
   2           49528           50031   252.0 KiB   0700  env
   3           50032           50535   252.0 KiB   0700  env-redund
   4           50536           71199   10.1 MiB    0700  boot
   5           71200           72207   504.0 KiB   0700  dsp0
   6           72208          100431   13.8 MiB    0700  recovery
   7          100432        16877647   8.0 GiB     0700  rootfs
   8        16877648        60456925   20.8 GiB    0700  UDISK

Basically it has Debian 11 on it and a test program for LCD or HDMI /home/sipeed/test_lcd.sh:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/bin/bash

echo "----:$1"

if [ "$1" == "hdmi" ] ; then

cd /sys/kernel/debug/dispdbg ;			
echo disp0 > name; 							
echo switch1 > command; 			
echo 4 10 0 0 0x4 0x101 0 0 0 8 > param; 			
echo 1 > start;					
fi
if [ "$1" == "lcd" ] ; then
cd /sys/kernel/debug/dispdbg ;			
echo disp0 > name; 							
echo switch1 > command; 			
echo 4 10 0 0 0x4 0x101 0 0 0 8 > param; 			
echo 1 > start;					
cd /sys/kernel/debug/dispdbg ;			
echo disp0 > name; 							
echo switch1 > command; 			
echo 1 10 0 0 0x4 0x101 0 0 0 8 > param; 			
echo 1 > start;					

fi
#cat /dev/urandom > /dev/fb0 ;

#echo 1 > /sys/class/disp/disp/attr/colorbar		
#echo 0 > /sys/class/disp/disp/attr/colorbar

exit 0

After I’ve got familiar with the default system I decided to install Arch Linux on it. My partition table is based on the table from this by Cezary Sobczak:

I decided to have a single partition with EXT 4 file system for rootfs and /boot/. The start of this partition is 67 Mb from the beginning, a bit extra than needed. Basically, the first stage bootloader (FSBL) and u-boot were placed in the first 21 Mb. For the FSBL I used OpenSBI and for the U-Boot I used this fork that doesn’t have (at the moment of writing) ported changes related to the Nezha D1 board.

OpenSBI building is straightforward:

1
$ CROSS_COMPILE=riscv64-linux-gnu- make PLATFORM=generic PLATFORM_DEFCONFIG=allwinner LATFORM_RISCV_XLEN=64  -j7

To build U-Boot with OpenSBI I used the following commands:

1
2
3
$ CROSS_COMPILE=riscv64-linux-gnu- make ARCH=riscv nezha_defconfig
$ export OPENSBI=<path to opensbi repo>/build/platform/generic/firmware/fw_dynamic.bin
$ CROSS_COMPILE=riscv64-linux-gnu- make V=1 VERBOSE=1 ARCH=riscv

Now we can write the fused bootloader into microSD card:

1
$ sudo dd if=u-boot-sunxi-with-spl.bin of=/dev/sdX bs=512 seek=16

Once the bootloader is in we can create a rootfs and build a Linux kernel. To set up the rootfs one can use this small article with a few additions:

  1. Pick Arch Linux rootfs ported to rv64gc.

  2. QEMU and binfmt might help with tweaking the system, bootloader, etc on the x86 machine.

A custom Linux kernel is needed because of specific patches needed for peripheral of the board to be able to work. As far as I know, at the moment, the mainline Linux kernel doesn’t have these patches merged in so far. I used the following repo that has the patches for the board. To build it (/mnt is where the microSD is mounted on) and install:

1
2
3
$ CROSS_COMPILE=riscv64-linux-gnu- make V=1 VERBOSE=1 ARCH=riscv nezha_defconfig
$ make VERBOSE=1 ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- INSTALL_HDR_PATH=/mnt/usr headers_install
$ make VERBOSE=1 ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- INSTALL_MOD_PATH=/mnt/ modules_install

And that’s it. Now you should be able to put the microSD in and boot the system up.