[PATCH] hw/loongarch/boot: Support Linux raw boot image

Jiaxun Yang posted 1 patch 16 hours ago
hw/loongarch/boot.c         | 45 +++++++++++++++++++++++++++++++++++++++++++++
include/hw/loongarch/boot.h | 17 +++++++++++++++++
2 files changed, 62 insertions(+)
[PATCH] hw/loongarch/boot: Support Linux raw boot image
Posted by Jiaxun Yang 16 hours ago
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.yang@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.yang@flygoat.com>