aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimbeer <himbeer@disroot.org>2024-05-14 11:16:29 +0200
committerHimbeer <himbeer@disroot.org>2024-05-14 11:16:29 +0200
commit0223e24edc677c6cbd761b8705d8044f0598db1d (patch)
tree253e745a04e9f86944afa1d3a966a557a5620432
parent6cf1d26dab3cdefeaa221a0e5499f87e0a2cc7eb (diff)
doc: Add setup instructions for U-Boot and OpenSBI (qemu-virt64)
Fixes #13.
-rw-r--r--README.md138
1 files changed, 137 insertions, 1 deletions
diff --git a/README.md b/README.md
index b22c7e4..f34b815 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,143 @@ for limited command-line or server usage.
See the [project page](https://himbeerserver.de/md/srvre/kernel.md)
for more information.
-# Booting
+# Building a bootable image
+
+## Boot flow
+
+This kernel is mainly developed for qemu-virt64 and the Lichee Pi 4A.
+The latter uses the following boot flow:
+
+```
+~ M-mode ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|~ S-mode ~~~
++------+ +------------+ +--------+ +---------+ +--------+
+| brom | --> | U-Boot SPL | --> | U-Boot | --> | OpenSBI | --> | Kernel |
++------+ +------------+ +--------+ +---------+ +--------+
+```
+
+QEMU can be adapted to use this boot flow as well (the default is different).
+
+## Building the kernel
+
+Making a debug build of this kernel is straightforward:
+
+```
+zig build
+```
+
+You can also use any other Zig build mode, e.g. `-Doptimize=ReleaseFast`.
+
+This results in a `zig-out/bin/srvre_kernel.elf` file.
+You may `strip(1)` this file if you want to.
+
+## Building OpenSBI
+
+Required dependencies:
+
+* riscv64-linux-gnu-gcc
+
+Clone the [OpenSBI repository](https://github.com/riscv-software-src/opensbi)
+and run the following command:
+
+```
+make CROSS_COMPILE=riscv64-linux-gnu- PLATFORM=generic FW_DYNAMIC=y -j $(nproc) all
+```
+
+This results in a `build/platform/generic/firmware/fw_dynamic.bin` file.
+You might be able to use precompiled versions of this file from other sources.
+
+**Important:** The default fw_dynamic payload corrupts the device tree.
+You can fix this by padding it with zeroes at the end:
+
+```
+for i in {1..8192}; do echo -e '\x00' >> build/platform/generic/firmware/fw_dynamic.bin; done
+```
+
+## Building U-Boot
+
+The boot flow is not supported by upstream U-Boot.
+There are several T-Head-specific forks that implement it for the Linux kernel,
+but none that support regular ELF binaries.
+Therefore a custom fork of U-Boot is required.
+
+Clone the [U-Boot fork](https://codeberg.org/Himbeer/u-boot)
+and run:
+
+```
+make qemu-riscv64_spl_defconfig
+make -j$(nproc) menuconfig
+```
+
+This will bring up the build configuration tool.
+Set the following options:
+
+* Device Drivers > Serial > Base address of UART (CONFIG_DEBUG_UART_BASE): 0x10000000
+* Device Drivers > Serial > Base address of UART for SPL (CONFIG_SPL_DEBUG_UART_BASE): 0x10000000
+* Device Drivers > Serial > Select which UART will provide the debug UART (CONFIG_DEBUG_UART_NS16550=y): ns16550
+* Device Drivers > Serial > Check if UART is enabled on output (CONFIG_DEBUG_UART_NS16550_CHECK_ENABLED): Yes
+* General Setup > Support for multiprocessor (?): No
+* RISC-V architecture > Symmetric Multi-Processing (CONFIG_SMP): No
+* RISC-V architecture > Symmetric Multi-Processing in SPL (CONFIG_SPL_SMP): No
+* RISC-V architecture > Run Mode (CONFIG_RISCV_MMODE=y): Machine
+* RISC-V architecture > SPL Run Mode (?): Machine
+* SPL configuration options > Support SPL loading and booting of Legacy images (CONFIG_SPL_LOAD_FIT): No
+* SPL configuration options > Show more information when something goes wrong (CONFIG_SPL_SHOW_ERRORS): Yes
+* SPL configuration options > Offset to which the SPL should be padded before appending the SPL payload (CONFIG_SPL_PAD_TO): 0x1200000
+* Boot options > Boot images > Flattened Image Tree (FIT) > Enable SPL loading U-Boot as a FIT (basic fitImage features) (CONFIG_SPL_LOAD_FIT): No
+* Boot options > Boot images > Flattened Image Tree (FIT) > Enable SPL loading U-Boot as a FIT (full fitImage features) (?): No
+* Boot options > bootcmd value (CONFIG_BOOTCOMMAND): "virtio scan; fatload virtio 0 0x8f000000 uImage; bootm 0x8f000000"
+* CONFIG_SPL_OPENSBI=n
+
+Then exit and select 'yes' to save your changes. Next, build the binaries:
+
+```
+make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- -j $(nproc) u-boot-with-spl.bin
+```
+
+## Create multi-file kernel image
+
+Create a legacy U-Boot image:
+
+```
+/path/to/u-boot/tools/mkimage -A riscv -O elf -T multi -C none -a 0x80400000 -e 0x80400000 -n SRVRE -d /path/to/srvre_kernel.elf:/path/to/fw_dynamic.bin:/path/to/devicetree.dtb /path/to/output/uImage
+```
+
+Write this `uImage` file to the first, FAT32 (LBA) partition
+on an MBR partitioned drive. You should now be able to boot QEMU:
+
+```
+qemu-system-riscv64 -M virt -m 2G -display none -serial stdio -bios /path/to/u-boot-with-spl.bin -drive file=/path/to/disk/image,if=virtio,media=disk,format=raw
+```
+
+### Extract QEMU device tree
+
+The default `arch/riscv/dts/qemu-virt64.dtb` tree is an image tree and doesn't help.
+To extract the device tree, create an empty file on the disk image.
+Then boot the VM as explained above but hit a key before it autoboots.
+Run the following command in the U-Boot shell:
+
+```
+env print fdtcontroladdr
+```
+
+Then use the printed value like so (without the angle brackets):
+
+```
+fdt addr 0x<ENV_OUTPUT>
+fdt header
+```
+
+You should now see a `totalsize` value. Take note of the hexadecimal notation
+and save it to disk:
+
+```
+virtio scan
+fatwrite virtio 0 0x<ENV_OUTPUT> <EMPTY_FILE_NAME> <HEX_TOTALSIZE>
+```
+
+You can now `poweroff` and build an image using the commands above.
+
+# Boot protocol
The kernel expects to be loaded in S-mode with the following register values: