From 0632b146b80c4933e1764326b2b5302620b1136e Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Sun, 25 Oct 2020 06:09:36 -0700 Subject: [PATCH] Add vendor boot image support to magiskboot --- native/jni/magiskboot/bootimg.cpp | 13 ++++-- native/jni/magiskboot/bootimg.hpp | 70 +++++++++++++++++++++++++++---- native/jni/magiskboot/format.cpp | 8 +--- native/jni/magiskboot/format.hpp | 2 + 4 files changed, 74 insertions(+), 19 deletions(-) diff --git a/native/jni/magiskboot/bootimg.cpp b/native/jni/magiskboot/bootimg.cpp index 235ca274e..cf1a93ee7 100644 --- a/native/jni/magiskboot/bootimg.cpp +++ b/native/jni/magiskboot/bootimg.cpp @@ -162,7 +162,8 @@ boot_img::boot_img(const char *image) { mmap_ro(image, map_addr, map_size); fprintf(stderr, "Parsing boot image: [%s]\n", image); for (uint8_t *addr = map_addr; addr < map_addr + map_size; ++addr) { - switch (check_fmt(addr, map_size)) { + format_t fmt = check_fmt(addr, map_size); + switch (fmt) { case CHROMEOS: // chromeos require external signing flags |= CHROMEOS_FLAG; @@ -179,7 +180,8 @@ boot_img::boot_img(const char *image) { addr += sizeof(blob_hdr) - 1; break; case AOSP: - parse_image(addr); + case AOSP_VENDOR: + parse_image(addr, fmt); return; default: break; @@ -242,9 +244,12 @@ off += hdr->name##_size(); \ off = do_align(off, hdr->page_size()); \ } -void boot_img::parse_image(uint8_t *addr) { +void boot_img::parse_image(uint8_t *addr, format_t type) { auto hp = reinterpret_cast(addr); - if (hp->page_size >= 0x02000000) { + if (type == AOSP_VENDOR) { + fprintf(stderr, "VENDOR_BOOT_HDR\n"); + hdr = new dyn_img_vnd_v3(addr); + } else if (hp->page_size >= 0x02000000) { fprintf(stderr, "PXA_BOOT_HDR\n"); hdr = new dyn_img_pxa(addr); } else { diff --git a/native/jni/magiskboot/bootimg.hpp b/native/jni/magiskboot/bootimg.hpp index e1fdd03a7..6b35eb70f 100644 --- a/native/jni/magiskboot/bootimg.hpp +++ b/native/jni/magiskboot/bootimg.hpp @@ -50,6 +50,7 @@ struct blob_hdr { #define BOOT_ID_SIZE 32 #define BOOT_ARGS_SIZE 512 #define BOOT_EXTRA_ARGS_SIZE 1024 +#define VENDOR_BOOT_ARGS_SIZE 2048 /* * +-----------------+ @@ -159,6 +160,21 @@ struct boot_img_hdr_pxa : public boot_img_hdr_common { * n = (ramdisk_size + 4096 - 1) / 4096 * * Note that in version 3 of the boot image header, page size is fixed at 4096 bytes. + * + * The structure of the vendor boot image (introduced with version 3 and + * required to be present when a v3 boot image is used) is as follows: + * + * +---------------------+ + * | vendor boot header | o pages + * +---------------------+ + * | vendor ramdisk | p pages + * +---------------------+ + * | dtb | q pages + * +---------------------+ + * + * o = (2112 + page_size - 1) / page_size + * p = (ramdisk_size + page_size - 1) / page_size + * q = (dtb_size + page_size - 1) / page_size */ struct boot_img_hdr_v3 { @@ -175,6 +191,23 @@ struct boot_img_hdr_v3 { char cmdline[BOOT_ARGS_SIZE + BOOT_EXTRA_ARGS_SIZE]; } __attribute__((packed)); +struct boot_img_hdr_vnd_v3 { + // Must be VENDOR_BOOT_MAGIC. + uint8_t magic[BOOT_MAGIC_SIZE]; + // Version of the vendor boot image header. + uint32_t header_version; + uint32_t page_size; /* flash page size we assume */ + uint32_t kernel_addr; /* physical load addr */ + uint32_t ramdisk_addr; /* physical load addr */ + uint32_t ramdisk_size; /* size in bytes */ + char cmdline[VENDOR_BOOT_ARGS_SIZE]; + uint32_t tags_addr; /* physical addr for kernel tags (if required) */ + char name[BOOT_NAME_SIZE]; /* asciiz product name */ + uint32_t header_size; + uint32_t dtb_size; /* size in bytes for DTB image */ + uint64_t dtb_addr; /* physical load address for DTB image */ +} __attribute__((packed)); + /******************************* * Polymorphic Universal Header *******************************/ @@ -222,6 +255,7 @@ protected: boot_img_hdr_v2 *v2_hdr; /* AOSP v2 header */ boot_img_hdr_v3 *v3_hdr; /* AOSP v3 header */ boot_img_hdr_pxa *hdr_pxa; /* Samsung PXA header */ + boot_img_hdr_vnd_v3 *vnd; /* AOSP vendor v3 header */ void *raw; /* Raw pointer */ }; @@ -243,10 +277,11 @@ name(void *ptr) { \ } \ size_t hdr_size() override { return sizeof(hdr); } -#define impl_cls(ver) __impl_cls(dyn_img_##ver, boot_img_hdr_##ver) +#define __impl_val(name, hdr_name) \ +decltype(std::declval().name()) name() override { return hdr_name->name; } -#define impl_val(name) \ -decltype(std::declval().name()) name() override { return v2_hdr->name; } +#define impl_cls(ver) __impl_cls(dyn_img_##ver, boot_img_hdr_##ver) +#define impl_val(name) __impl_val(name, v2_hdr) struct dyn_img_common : public dyn_img_hdr { impl_val(kernel_size) @@ -284,8 +319,7 @@ struct dyn_img_v2 : public dyn_img_v1 { }; #undef impl_val -#define impl_val(name) \ -decltype(std::declval().name()) name() override { return hdr_pxa->name; } +#define impl_val(name) __impl_val(name, hdr_pxa) struct dyn_img_pxa : public dyn_img_common { impl_cls(pxa) @@ -299,8 +333,7 @@ struct dyn_img_pxa : public dyn_img_common { }; #undef impl_val -#define impl_val(name) \ -decltype(std::declval().name()) name() override { return v3_hdr->name; } +#define impl_val(name) __impl_val(name, v3_hdr) struct dyn_img_v3 : public dyn_img_hdr { impl_cls(v3) @@ -320,7 +353,26 @@ private: uint32_t page_sz; }; +#undef impl_val +#define impl_val(name) __impl_val(name, vnd) + +struct dyn_img_vnd_v3 : public dyn_img_hdr { + impl_cls(vnd_v3) + + impl_val(header_version) + impl_val(page_size) + impl_val(ramdisk_size) + impl_val(cmdline) + impl_val(name) + impl_val(header_size) + impl_val(dtb_size) + + // Make API compatible + char *extra_cmdline() override { return &vnd->cmdline[BOOT_ARGS_SIZE]; } +}; + #undef __impl_cls +#undef __impl_val #undef impl_cls #undef impl_val @@ -363,7 +415,7 @@ struct boot_img { mtk_hdr *k_hdr; mtk_hdr *r_hdr; - // Pointer to dtb that is appended after kernel + // Pointer to dtb that is embedded in kernel uint8_t *kernel_dtb; uint32_t kernel_dt_size = 0; @@ -383,5 +435,5 @@ struct boot_img { boot_img(const char *); ~boot_img(); - void parse_image(uint8_t *addr); + void parse_image(uint8_t *addr, format_t type); }; diff --git a/native/jni/magiskboot/format.cpp b/native/jni/magiskboot/format.cpp index e34b73128..44c56cc00 100644 --- a/native/jni/magiskboot/format.cpp +++ b/native/jni/magiskboot/format.cpp @@ -28,6 +28,8 @@ format_t check_fmt(const void *buf, size_t len) { return CHROMEOS; } else if (MATCH(BOOT_MAGIC)) { return AOSP; + } else if (MATCH(VENDOR_BOOT_MAGIC)) { + return AOSP_VENDOR; } else if (MATCH(GZIP1_MAGIC) || MATCH(GZIP2_MAGIC)) { return GZIP; } else if (MATCH(LZOP_MAGIC)) { @@ -58,10 +60,6 @@ format_t check_fmt(const void *buf, size_t len) { const char *Fmt2Name::operator[](format_t fmt) { switch (fmt) { - case CHROMEOS: - return "chromeos"; - case AOSP: - return "aosp"; case GZIP: return "gzip"; case LZOP: @@ -78,8 +76,6 @@ const char *Fmt2Name::operator[](format_t fmt) { return "lz4_legacy"; case LZ4_LG: return "lz4_lg"; - case MTK: - return "mtk"; case DTB: return "dtb"; default: diff --git a/native/jni/magiskboot/format.hpp b/native/jni/magiskboot/format.hpp index 7b6589878..c35ba7797 100644 --- a/native/jni/magiskboot/format.hpp +++ b/native/jni/magiskboot/format.hpp @@ -8,6 +8,7 @@ typedef enum { /* Boot formats */ CHROMEOS, AOSP, + AOSP_VENDOR, DHTB, BLOB, /* Compression formats */ @@ -29,6 +30,7 @@ typedef enum { #define COMPRESSED_ANY(fmt) ((fmt) >= GZIP && (fmt) <= LZOP) #define BOOT_MAGIC "ANDROID!" +#define VENDOR_BOOT_MAGIC "VNDRBOOT" #define CHROMEOS_MAGIC "CHROMEOS" #define GZIP1_MAGIC "\x1f\x8b" #define GZIP2_MAGIC "\x1f\x9e"