[lkrn] Add basic support for the RISC-V Linux kernel image format

The RISC-V and AArch64 bare-metal kernel images share a common header
format, and require essentially the same execution environment: loaded
close to the start of RAM, entered with paging disabled, and passed a
pointer to a flattened device tree that describes the hardware and any
boot arguments.

Implement basic support for executing bare-metal RISC-V and AArch64
kernel images.  The (trivial) AArch64-specific code path is untested
since we do not yet have the ability to build for any bare-metal
AArch64 platforms.  Constructing and passing an initramfs image is not
yet supported.

Rename the IMAGE_BZIMAGE build configuration option to IMAGE_LKRN,
since "bzImage" is specific to x86.  To retain backwards compatibility
with existing local build configurations, we leave IMAGE_BZIMAGE as
the enabled option in config/default/pcbios.h and treat IMAGE_LKRN as
a synonym for IMAGE_BZIMAGE when building for x86 BIOS.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2025-05-20 00:26:08 +01:00
parent d0c35b6823
commit ecac4a34c7
10 changed files with 460 additions and 1 deletions

17
src/include/bits/lkrn.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef _BITS_LKRN_H
#define _BITS_LKRN_H
/** @file
*
* Dummy architecture-specific Linux kernel image invocation
*
* This file is included only if the architecture does not provide its
* own version of this file.
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define LKRN_MAGIC_ARCH 0
#endif /* _BITS_LKRN_H */

View File

@@ -328,6 +328,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define ERRFILE_zlib ( ERRFILE_IMAGE | 0x000b0000 )
#define ERRFILE_gzip ( ERRFILE_IMAGE | 0x000c0000 )
#define ERRFILE_efi_siglist ( ERRFILE_IMAGE | 0x000d0000 )
#define ERRFILE_lkrn ( ERRFILE_IMAGE | 0x000e0000 )
#define ERRFILE_asn1 ( ERRFILE_OTHER | 0x00000000 )
#define ERRFILE_chap ( ERRFILE_OTHER | 0x00010000 )

69
src/include/ipxe/lkrn.h Normal file
View File

@@ -0,0 +1,69 @@
#ifndef _IPXE_LKRN_H
#define _IPXE_LKRN_H
/** @file
*
* Linux kernel images
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
/** Kernel image header */
struct lkrn_header {
/** Executable code */
uint32_t code[2];
/** Image load offset */
uint64_t text_offset;
/** Image size */
uint64_t image_size;
/** Flags */
uint64_t flags;
/** Reserved */
uint8_t reserved_a[24];
/** Magic */
uint32_t magic;
/** Reserved */
uint8_t reserved_b[4];
} __attribute__ (( packed ));
/** Kernel magic value */
#define LKRN_MAGIC( a, b, c, d ) \
( ( (a) << 0 ) | ( (b) << 8 ) | ( (c) << 16 ) | ( (d) << 24 ) )
/** Kernel magic value for AArch64 */
#define LKRN_MAGIC_AARCH64 LKRN_MAGIC ( 'A', 'R', 'M', 0x64 )
/** Kernel magic value for RISC-V */
#define LKRN_MAGIC_RISCV LKRN_MAGIC ( 'R', 'S', 'C', 0x05 )
/** Kernel image context */
struct lkrn_context {
/** Load offset */
size_t offset;
/** File size */
size_t filesz;
/** Memory size */
size_t memsz;
/** Start of RAM */
physaddr_t ram;
/** Entry point */
physaddr_t entry;
/** Device tree */
physaddr_t fdt;
};
#include <bits/lkrn.h>
/**
* Jump to kernel entry point
*
* @v entry Kernel entry point
* @v fdt Device tree
*/
void lkrn_jump ( physaddr_t entry, physaddr_t fdt );
#endif /* _IPXE_LKRN_H */