boot: fix riscv64/aarch64 boot headers

This commit is contained in:
2025-07-16 16:00:57 +03:00
parent 04afd55f35
commit 223aeef10f
8 changed files with 51 additions and 76 deletions
+26 -38
View File
@@ -3,55 +3,43 @@
Booting Yggdrasil on Raspberry Pi 4B with u-boot:
1. Clone u-boot sources to some directory and checkout some
stable branch. I've used v2024.10.
2. Modify cmd/boot.c by replacing the do_go_exec function:
1. Clone u-boot sources and build with rpi_4_defconfig
/* Allow ports to override the default behavior */
__attribute__((weak))
unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc,
char *const argv[])
{
void *entry_ptr = (void *) entry;
ulong fdt_addr_r = 0;
if (argc >= 2) {
fdt_addr_r = hextoul(argv[1], NULL);
}
void (*func)(ulong) = entry_ptr;
func(fdt_addr_r);
return 0;
}
3. make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 rpi_4_defconfig
4. make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 -j
5. Copy u-boot.bin into your Pi SD-card's boot partition.
**NOTE** I assume you have all the bootloader parts in the boot partition already.
If not, clone raspberry fw repo and copy the following files to the boot partition:
* bootcode.bin
* start4.elf
* all the .dtb files (a bcm2711-rpi-4-b.dtb should be enough though)
6. config.txt:
2. Copy u-boot.bin into the Pi's boot partition and edit the config.txt:
enable_uart=1
arm64_bit=1
kernel=u-boot.bin
7. Compile the OS with `cargo xtask --arch=aarch64 --board=raspi4b --release`
8. Copy the following files into some directory:
* target/aarch64-unknown-raspi4b/release/yggdrasil-kernel
3. Compile the OS with `cargo xtask --arch=aarch64 --board=raspi4b --release`
4. Copy the following files into some directory:
* target/aarch64-unknown-raspi4b/release/kernel.bin
* userspace/target/aarch64-unknown-yggdrasil/release/initrd.tar
9. cd into that directory and start a TFTP server of your choice. I used `uftpd`.
5. cd into that directory and start a TFTP server of your choice. I used `uftpd`.
10. Connect an ethernet and serial to the Pi and run the following commands in u-boot shell:
6. Connect an ethernet and serial to the Pi and run the following commands in u-boot shell:
tftpboot 0x04000000 <YOUR IP>:initrd.tar
tftpboot ${loadaddr} <YOUR IP>:yggdrasil-kernel
load mmc 0:1 ${fdt_addr_r} bcm2711-rpi-4-b.dtb
fdt addr ${fdt_addr_r}
fdt resize
fdt memory 0x0 0x3C000000
fdt chosen 0x04000000 <WHATEVER SIZE WAS PRINTED WHEN RUNNING THE FIRST COMMAND>
bootelf -p
go ${kernel_addr_r} ${fdt_addr_r}
### If using DHCP
$ dhcp
### If not using DHCP
$ env set ipaddr <RASPBERRY-IP-ADDR>
$ env set fdt_addr_r 0x11000000
$ env set initrd_addr_r 0x04000000
$ tftpboot ${initrd_addr_r} <BUILD-MACHINE-IP-ADDR>:initrd.tar
$ tftpboot ${loadaddr} <BUILD-MACHINE-IP-ADDR>:kernel.bin
$ load mmc 0:1 ${fdt_addr_r} bcm2711-rpi-4-b.dtb
$ fdt addr ${fdt_addr_r}
$ fdt resize
$ fdt memory 0x0 0x3C000000
$ booti ${loadaddr} ${initrd_addr_r}:<SIZE-PRINTED-WHEN-LOADING-INITRD> ${fdt_addr_r}
11. Yggdrasil OS should start!
###### Assuming BUILD-MACHINE-IP-ADDR is 13.0.0.1 and RASPBERRY-IP-ADDR is 13.0.0.2, here's
###### a quick command for a development boot
###### (FIXME when initrd gets larger than 64MiB)
env set ipaddr 13.0.0.2; env set fdt_addr_r 0x11000000; env set initrd_addr_r 0x04000000; tftpboot ${initrd_addr_r} 13.0.0.1:initrd.tar; tftpboot ${loadaddr} 13.0.0.1:kernel.bin; load mmc 0:1 ${fdt_addr_r} bcm2711-rpi-4-b.dtb; fdt addr ${fdt_addr_r}; fdt resize; fdt memory 0x0 0x3C000000; booti ${loadaddr} ${initrd_addr_r}:67108864 ${fdt_addr_r}
+19 -15
View File
@@ -1,7 +1,6 @@
Booting Yggdrasil OS on Starfive VisionFive 2 RISC-V board:
* TODO: proper format for initrd image
* TODO: 0x70000000 can be replaced with a builtin var?
Prerequisites:
@@ -13,18 +12,23 @@ Steps:
1. Copy yggdrasil-kernel.bin and initrd.img into some directory and start a TFTP server there
2. Connect to VF2's serial port, ethernet and enter u-boot
3. Run the following commands:
3. Run the following commands in u-boot:
# Get an IP address
dhcp
# [Optional] set some kernel cmdline params
setenv bootargs "debug.serial-level=info"
# Load initrd
tftpboot 0x70000000 <your-ip-address>:initrd.img
# Load kernel
tftpboot ${loadaddr} <your-ip-address>:yggdrasil-kernel.bin
# Load dtb
load mmc 1:3 ${fdt_addr_r} dtbs/...-starfive/starfive/${fdtfile}
fdt resize
# Enter the kernel
booti ${loadaddr} 0x70000000:<initrd-size> ${fdt_addr_r}
### If using DHCP
$ dhcp
### If not using DHCP
$ env set ipaddr <VF2-IP-ADDR>
$ env set initrd_addr_r 0x70000000
### [Optional] set some kernel cmdline params
$ env set bootargs "debug.serial-level=info"
$ tftpboot ${initrd_addr_r} <BUILD-MACHINE-IP-ADDR>:initrd.tar
$ tftpboot ${loadaddr} <BUILD-MACHINE-IP-ADDR>:kernel.bin
$ load mmc 1:3 ${fdt_addr_r} dtbs/...-starfive/starfive/${fdtfile}
$ fdt resize
$ booti ${loadaddr} ${initrd_addr_r}:<initrd-size> ${fdt_addr_r}
###### Assuming BUILD-MACHINE-IP-ADDR is 13.0.0.1 and VF2-IP-ADDR is 13.0.0.2, here's
###### a quick command for a development boot
###### (FIXME when initrd gets larger than 64MiB)
env set ipaddr 13.0.0.2; env set initrd_addr_r 0x70000000; tftpboot ${initrd_addr_r} 13.0.0.1:initrd.tar; tftpboot ${loadaddr} 13.0.0.1:kernel.bin; load mmc 1:3 ${fdt_addr_r} dtbs/...-starfive/starfive/${fdtfile}; fdt resize; booti ${loadaddr} ${initrd_addr_r}:67108864 ${fdt_addr_r}
+2 -1
View File
@@ -1,6 +1,6 @@
ENTRY(__aarch64_entry);
KERNEL_PHYS_BASE = 0x80000;
KERNEL_PHYS_BASE = 0x200000;
KERNEL_VIRT_OFFSET = 0xFFFFFF8000000000;
SECTIONS {
@@ -52,4 +52,5 @@ SECTIONS {
PROVIDE(__bss_size = __bss_end_phys - __bss_start_phys);
PROVIDE(__kernel_end = .);
PROVIDE(__kernel_size = __kernel_end - __kernel_start);
};
+1
View File
@@ -55,4 +55,5 @@ SECTIONS {
PROVIDE(__bss_size = __bss_end_phys - __bss_start_phys);
PROVIDE(__kernel_end = .);
PROVIDE(__kernel_size = __kernel_end - __kernel_start);
};
+1 -1
View File
@@ -37,7 +37,7 @@ const MAPPING_OFFSET: usize = KERNEL_VIRT_OFFSET;
#[cfg(any(feature = "aarch64_board_virt", rust_analyzer))]
const KERNEL_PHYS_BASE: usize = 0x40200000;
#[cfg(any(feature = "aarch64_board_raspi4b", rust_analyzer))]
const KERNEL_PHYS_BASE: usize = 0x80000;
const KERNEL_PHYS_BASE: usize = 0x200000;
// Precomputed mappings
const KERNEL_L1_INDEX: usize = page_index::<L1>(KERNEL_VIRT_OFFSET + KERNEL_PHYS_BASE);
+1 -1
View File
@@ -56,7 +56,7 @@
__aarch64_entry:
ccmp x18, #0, #0xd, pl // "MZ" magic
b __aarch64_real_entry // Jump to real entry
.quad 0 // Image load offset from start of RAM
.quad 0x200000 // Image load offset from start of RAM
.quad __kernel_size // Kernel size
.quad 0 // Kernel flags
.quad 0 // reserved
+1 -1
View File
@@ -23,7 +23,7 @@ __rv64_entry:
j __rv64_real_entry // Jump to real entry (if entered by non-Linux bootloader)
.long 0
.quad 0x200000 // Offset from RAM start
.quad 2000000 // Image size TODO fill this by post-tooling
.quad __kernel_size // Image size
.quad 0 // Kernel flags
.long 0x2 // Header version
.long 0
-19
View File
@@ -289,22 +289,6 @@ fn write_tables<F: Write + Seek>(
Ok(())
}
fn write_image_header<F: Write + Seek>(
file: &mut F,
header: ImageHeader,
image_size: u64,
) -> Result<(), GenError> {
match header {
ImageHeader::Riscv(offset) => {
let size_bytes = image_size.to_le_bytes();
println!("Writing RISC-V image header: image_size={image_size}");
file.seek(SeekFrom::Start(offset + 16))?;
file.write_all(&size_bytes)?;
Ok(())
}
}
}
fn write_symbol_table(
out: impl AsRef<Path>,
table: HashMap<String, usize>,
@@ -332,9 +316,6 @@ fn gentables(image: impl AsRef<Path>, symbol_out: impl AsRef<Path>) -> Result<()
let built = build_tables(&mut file)?;
write_symbol_table(symbol_out, built.symbol_table)?;
if let Some(header) = built.image_header {
write_image_header(&mut file, header, built.image_size)?;
}
if let Some((tables, file_offset)) = built.tables {
write_tables(file, file_offset, tables)?;
}