Many distros are shipping raw kernel images (i.e. vmlinux.efi). Support booting such image by parsing header as per Linux's specification [1].
[1]: https://docs.kernel.org/arch/loongarch/booting.html Signed-off-by: Jiaxun Yang <jiaxun.y...@flygoat.com> --- It is based on my previous booting protocol patch --- hw/loongarch/boot.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ include/hw/loongarch/boot.h | 17 +++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c index 93847b0eaf8e50ce1a990b91267780e6785e1c2f..5bc889c51fafa9c6d37426b9bee9709c12183927 100644 --- a/hw/loongarch/boot.c +++ b/hw/loongarch/boot.c @@ -260,6 +260,43 @@ static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr) return addr & MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS); } +static int64_t get_linux_image_info(struct loongarch_boot_info *info, + uint64_t *kernel_entry, + uint64_t *kernel_low, + uint64_t *kernel_high) +{ + int fd; + struct loongarch_linux_hdr hdr; + int64_t kernel_size = -1; + + fd = open(info->kernel_filename, O_RDONLY | O_BINARY); + if (fd < 0) { + return -1; + } + + if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { + close(fd); + return -1; + } + + if ((le32_to_cpu(hdr.mz_magic) & 0xffff) != MZ_MAGIC || + le32_to_cpu(hdr.linux_pe_magic) != LINUX_PE_MAGIC) { + close(fd); + return -1; + } + + *kernel_entry = le64_to_cpu(hdr.kernel_entry); + /* Early kernel versions may have those fields in virtual address */ + *kernel_entry &= MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS); + *kernel_low = le64_to_cpu(hdr.load_offset); + *kernel_low &= MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS); + kernel_size = le64_to_cpu(hdr.kernel_size); + *kernel_high = *kernel_low + kernel_size; + + close(fd); + return kernel_size; +} + static int64_t load_kernel_info(struct loongarch_boot_info *info) { uint64_t kernel_entry, kernel_low, kernel_high; @@ -270,6 +307,14 @@ static int64_t load_kernel_info(struct loongarch_boot_info *info) &kernel_entry, &kernel_low, &kernel_high, NULL, 0, EM_LOONGARCH, 1, 0); + if (kernel_size < 0) { + kernel_size = get_linux_image_info(info, &kernel_entry, + &kernel_low, &kernel_high); + if (kernel_size >= 0) { + kernel_size = load_image_targphys(info->kernel_filename, + kernel_low, kernel_size); + } + } if (kernel_size < 0) { error_report("could not load kernel '%s': %s", diff --git a/include/hw/loongarch/boot.h b/include/hw/loongarch/boot.h index 96ec15016a314499acf65c6c47e0c4932aa99d01..5e8bd4dd73bbb27abccfa1fa577df52aed15b6a2 100644 --- a/include/hw/loongarch/boot.h +++ b/include/hw/loongarch/boot.h @@ -8,6 +8,23 @@ #ifndef HW_LOONGARCH_BOOT_H #define HW_LOONGARCH_BOOT_H +/* Linux Image Format */ +#define LINUX_PE_MAGIC 0x818223cd +#define MZ_MAGIC 0x5a4d /* "MZ" */ + +struct loongarch_linux_hdr { + uint32_t mz_magic; + uint32_t res0; + uint64_t kernel_entry; + uint64_t kernel_size; + uint64_t load_offset; + uint64_t res1; + uint64_t res2; + uint64_t res3; + uint32_t linux_pe_magic; + uint32_t pe_header_offset; +} QEMU_PACKED; + /* UEFI 2.10 */ #define EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249 #define EFI_2_100_SYSTEM_TABLE_REVISION ((2<<16) | (100)) --- base-commit: c69612063e1844b76ac01e3a781b979548c3585c change-id: 20241222-la-direct-kernel-boot-c598264710e7 Best regards, -- Jiaxun Yang <jiaxun.y...@flygoat.com>