From 8e38af800b45c87d12af5c343c351a2bd5ec2730 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 13 May 2025 12:51:53 +0100 Subject: [PATCH] [riscv] Add a .lkrn build target resembling a Linux kernel binary On x86 BIOS, it has been useful to be able to build iPXE to resemble a Linux kernel, so that it can be loaded by programs such as syslinux which already know how to handle Linux kernel binaries. Add an equivalent .lkrn build target for RISC-V SBI, allowing for build targets such as: make bin-riscv64/ipxe.lkrn make bin-riscv64/cgem.lkrn The Linux kernel header format allows us to specify a required length (including uninitialised-data portions) and defines that the image will be loaded at a fixed offset from the start of RAM. We can therefore use known-safe areas of memory (within our own .bss) for the initial temporary page table and stack. Signed-off-by: Michael Brown --- src/arch/riscv/Makefile.sbi | 1 + src/arch/riscv/prefix/libprefix.S | 1 + src/arch/riscv/prefix/lkrnprefix.S | 129 +++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+) create mode 100644 src/arch/riscv/prefix/lkrnprefix.S diff --git a/src/arch/riscv/Makefile.sbi b/src/arch/riscv/Makefile.sbi index a10680eaf..2546366b2 100644 --- a/src/arch/riscv/Makefile.sbi +++ b/src/arch/riscv/Makefile.sbi @@ -14,3 +14,4 @@ LDSCRIPT = arch/riscv/scripts/sbi.lds # Media types # MEDIA += sbi +MEDIA += lkrn diff --git a/src/arch/riscv/prefix/libprefix.S b/src/arch/riscv/prefix/libprefix.S index c5f4961c0..e47bab981 100644 --- a/src/arch/riscv/prefix/libprefix.S +++ b/src/arch/riscv/prefix/libprefix.S @@ -452,6 +452,7 @@ paging_mode_names: * This can be used only once .bss is known to be writable. */ .section ".bss.page_table", "a", @nobits + .globl page_table .balign PAGE_SIZE page_table: .space PAGE_SIZE diff --git a/src/arch/riscv/prefix/lkrnprefix.S b/src/arch/riscv/prefix/lkrnprefix.S new file mode 100644 index 000000000..9493d016c --- /dev/null +++ b/src/arch/riscv/prefix/lkrnprefix.S @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2025 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * You can also choose to distribute this program under the terms of + * the Unmodified Binary Distribution Licence (as given in the file + * COPYING.UBDL), provided that you have satisfied its requirements. + */ + + FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ) + +/** @file + * + * Linux kernel prefix + * + */ + + .section ".note.GNU-stack", "", @progbits + .text + + /* Layout of kernel header */ + .struct 0 +hdr_code0: .space 4 +hdr_code1: .space 4 +hdr_text_offset: .space 8 +hdr_image_size: .space 8 +hdr_flags: .space 8 +hdr_version: .space 4 +hdr_res1: .space 4 +hdr_res2: .space 8 +hdr_magic: .space 8 +hdr_magic2: .space 4 +hdr_res3: .space 4 +hdr_end: + .org 64 + .previous + +/* Header version */ +#define HDR_VERSION( major, minor ) ( ( (major) << 16 ) | (minor) ) +#define HDR_VERSION_0_2 HDR_VERSION ( 0, 2 ) + +/* Header flags */ +#define HDR_FL_BIG_ENDIAN 0x00000001 + +/* Magic numbers */ +#define HDR_MAGIC "RISCV\0\0\0" +#define HDR_MAGIC2 "RSC\x05" + + /* + * Linux kernel header + */ + .section ".prefix", "ax", @progbits + + /* Executable code / MZ header (for EFI-compatible binaries) */ + .org hdr_code0 + j _lkrn_start + + /* Image load offset + * + * Must be set to the size of a single "megapage" (2MB for + * 64-bit, 4MB for 32-bit). + */ + .org hdr_text_offset + .dword _max_align + + /* Image size (including uninitialised-data potions) */ + .org hdr_image_size + .dword _memsz + + /* Flags */ + .org hdr_flags + .dword 0 + + /* Version */ + .org hdr_version + .word HDR_VERSION_0_2 + + /* Magic numbers */ + .org hdr_magic + .ascii HDR_MAGIC + .org hdr_magic2 + .ascii HDR_MAGIC2 + + .org hdr_end + + /* + * Linux kernel entry point + */ + .globl _lkrn_start +_lkrn_start: + /* Identify temporary page table and stack space + * + * Linux expects to be placed at the image load offset from + * the start of RAM. Assume that our loaded image is + * therefore already writable, and that we can therefore use + * the page table and stack within our (not yet zeroed) .bss + * section. + */ + la a2, page_table + la sp, _estack + + /* Install iPXE */ + call install + + /* Call main program */ + call main + + /* We have no return path, since the Linux kernel does not + * define that a valid return address exists. + * + * Attempt a system reset, since there is nothing else we can + * viably do at this point. + */ + j reset_system + .size _lkrn_start, . - _lkrn_start -- 2.47.2