summary refs log tree commit diff stats
path: root/hw/core
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2023-03-07 09:58:43 +0000
committerPeter Maydell <peter.maydell@linaro.org>2023-03-07 09:58:43 +0000
commitc29a2f40cd5d1fdad4632b48343cd968db041a44 (patch)
treeee30a898f0d168bde15112f78430ee7f978ee67c /hw/core
parentc1feaf76833f5b29f887fd64371512731cbf7086 (diff)
parent2ddc45954f97cd1d7ee5cbca0def05e980d1da9f (diff)
downloadfocaccia-qemu-c29a2f40cd5d1fdad4632b48343cd968db041a44.tar.gz
focaccia-qemu-c29a2f40cd5d1fdad4632b48343cd968db041a44.zip
Merge tag 'pull-target-arm-20230306' of https://git.linaro.org/people/pmaydell/qemu-arm into staging
target-arm queue:
 * allwinner-h3: Fix I2C controller model for Sun6i SoCs
 * allwinner-h3: Add missing i2c controllers
 * Expose M-profile system registers to gdbstub
 * Expose pauth information to gdbstub
 * Support direct boot for Linux/arm64 EFI zboot images
 * Fix incorrect stage 2 MMU setup validation

# -----BEGIN PGP SIGNATURE-----
#
# iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmQGB+wZHHBldGVyLm1h
# eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3gdQEACVfgbs77mxbOb6u8yWHKGZ
# tVnQr9KZMv2lmwt5H3ROJPXznchrIIAwdMeRgKnbI+lC5jTq9L+Q8RJch3t/EbAd
# f0VMyiPe3DzCbCrAR9cW6EWzbYnEVo3Ioj4k7qjxK6u1BIKhXz99DLYd1KRdTxnx
# BAYmcl857Uir1q2FrBVMZ/ItCLbk4ejn+YaDIawNue2/s1oGa+we473x9rosCFvp
# L9bzT3R46e0o+Mfkn1OYRmgCmURTalWPpWAxyOUFR9YbrzXleLgAKEB3o3PPcvls
# u26uxztyRMqje1q06VjUzwaLw7zN9XPhmir+NXX7KXp2/x9PZjApOpPtt0kl+6qe
# FbByKfl24O9w/OKewsJw+udCBYdYrRPm6tWv2D71iAwjBUzBJgNGe5VPRdPFtPDn
# uSRO65o34w1nPzRpAheUciZueiabYrVmIgVltFxj0JlrKGfgiYHPLVyU0Uu0K/A7
# F2kUEQIzIcWdo+c8SlvlWOEA2ojVd/KoLVLgndqr40Tk5pbc65TRS08kkVVl4cMT
# jUGscl7Dyxe+yo8+nHdycAJpnKYDllJOh2JbGv3r2FqCy5FMuIqW4hHeuUxwpE+O
# nxm7lzjnaVHSAFHdzhk9x4E4uH/GTcdWzX1EsmpgGqe5oejLJOrCINb+Dj44+Y8h
# 8aGRvE7kxMs11upxc7BcAw==
# =KIMt
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 06 Mar 2023 15:34:04 GMT
# gpg:                using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE
# gpg:                issuer "peter.maydell@linaro.org"
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate]
# gpg:                 aka "Peter Maydell <peter@archaic.org.uk>" [ultimate]
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* tag 'pull-target-arm-20230306' of https://git.linaro.org/people/pmaydell/qemu-arm: (21 commits)
  hw: arm: allwinner-h3: Fix and complete H3 i2c devices
  hw: allwinner-i2c: Fix TWI_CNTR_INT_FLAG on SUN6i SoCs
  hw: arm: Support direct boot for Linux/arm64 EFI zboot images
  target/arm: Rewrite check_s2_mmu_setup
  target/arm: Diagnose incorrect usage of arm_is_secure subroutines
  target/arm: Stub arm_hcr_el2_eff for m-profile
  target/arm: Handle m-profile in arm_is_secure
  target/arm: Implement gdbstub m-profile systemreg and secext
  target/arm: Export arm_v7m_get_sp_ptr
  target/arm: Export arm_v7m_mrs_control
  target/arm: Implement gdbstub pauth extension
  target/arm: Create pauth_ptr_mask
  target/arm: Simplify iteration over bit widths
  target/arm: Add name argument to output_vector_union_type
  target/arm: Fix svep width in arm_gen_dynamic_svereg_xml
  target/arm: Hoist pred_width in arm_gen_dynamic_svereg_xml
  target/arm: Simplify register counting in arm_gen_dynamic_svereg_xml
  target/arm: Split out output_vector_union_type
  target/arm: Move arm_gen_dynamic_svereg_xml to gdbstub64.c
  target/arm: Unexport arm_gen_dynamic_sysreg_xml
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/core')
-rw-r--r--hw/core/loader.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/hw/core/loader.c b/hw/core/loader.c
index 173f8f67f6..cd53235fed 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -857,6 +857,97 @@ ssize_t load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz)
     return bytes;
 }
 
+/* The PE/COFF MS-DOS stub magic number */
+#define EFI_PE_MSDOS_MAGIC        "MZ"
+
+/*
+ * The Linux header magic number for a EFI PE/COFF
+ * image targetting an unspecified architecture.
+ */
+#define EFI_PE_LINUX_MAGIC        "\xcd\x23\x82\x81"
+
+/*
+ * Bootable Linux kernel images may be packaged as EFI zboot images, which are
+ * self-decompressing executables when loaded via EFI. The compressed payload
+ * can also be extracted from the image and decompressed by a non-EFI loader.
+ *
+ * The de facto specification for this format is at the following URL:
+ *
+ * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/efi/libstub/zboot-header.S
+ *
+ * This definition is based on Linux upstream commit 29636a5ce87beba.
+ */
+struct linux_efi_zboot_header {
+    uint8_t     msdos_magic[2];         /* PE/COFF 'MZ' magic number */
+    uint8_t     reserved0[2];
+    uint8_t     zimg[4];                /* "zimg" for Linux EFI zboot images */
+    uint32_t    payload_offset;         /* LE offset to compressed payload */
+    uint32_t    payload_size;           /* LE size of the compressed payload */
+    uint8_t     reserved1[8];
+    char        compression_type[32];   /* Compression type, NUL terminated */
+    uint8_t     linux_magic[4];         /* Linux header magic */
+    uint32_t    pe_header_offset;       /* LE offset to the PE header */
+};
+
+/*
+ * Check whether *buffer points to a Linux EFI zboot image in memory.
+ *
+ * If it does, attempt to decompress it to a new buffer, and free the old one.
+ * If any of this fails, return an error to the caller.
+ *
+ * If the image is not a Linux EFI zboot image, do nothing and return success.
+ */
+ssize_t unpack_efi_zboot_image(uint8_t **buffer, int *size)
+{
+    const struct linux_efi_zboot_header *header;
+    uint8_t *data = NULL;
+    int ploff, plsize;
+    ssize_t bytes;
+
+    /* ignore if this is too small to be a EFI zboot image */
+    if (*size < sizeof(*header)) {
+        return 0;
+    }
+
+    header = (struct linux_efi_zboot_header *)*buffer;
+
+    /* ignore if this is not a Linux EFI zboot image */
+    if (memcmp(&header->msdos_magic, EFI_PE_MSDOS_MAGIC, 2) != 0 ||
+        memcmp(&header->zimg, "zimg", 4) != 0 ||
+        memcmp(&header->linux_magic, EFI_PE_LINUX_MAGIC, 4) != 0) {
+        return 0;
+    }
+
+    if (strcmp(header->compression_type, "gzip") != 0) {
+        fprintf(stderr,
+                "unable to handle EFI zboot image with \"%.*s\" compression\n",
+                (int)sizeof(header->compression_type) - 1,
+                header->compression_type);
+        return -1;
+    }
+
+    ploff = ldl_le_p(&header->payload_offset);
+    plsize = ldl_le_p(&header->payload_size);
+
+    if (ploff < 0 || plsize < 0 || ploff + plsize > *size) {
+        fprintf(stderr, "unable to handle corrupt EFI zboot image\n");
+        return -1;
+    }
+
+    data = g_malloc(LOAD_IMAGE_MAX_GUNZIP_BYTES);
+    bytes = gunzip(data, LOAD_IMAGE_MAX_GUNZIP_BYTES, *buffer + ploff, plsize);
+    if (bytes < 0) {
+        fprintf(stderr, "failed to decompress EFI zboot image\n");
+        g_free(data);
+        return -1;
+    }
+
+    g_free(*buffer);
+    *buffer = g_realloc(data, bytes);
+    *size = bytes;
+    return bytes;
+}
+
 /*
  * Functions for reboot-persistent memory regions.
  *  - used for vga bios and option roms.