diff --git a/native/jni/magiskboot/bootimg.cpp b/native/jni/magiskboot/bootimg.cpp index bd925ef0d..917a807fe 100644 --- a/native/jni/magiskboot/bootimg.cpp +++ b/native/jni/magiskboot/bootimg.cpp @@ -235,64 +235,69 @@ static format_t check_fmt_lg(uint8_t *buf, unsigned sz) { return fmt; } -#define get_block(name) {\ -name = addr + off; \ -off += hdr->name##_size(); \ -off = do_align(off, hdr->page_size()); \ -} - #define CMD_MATCH(s) BUFFER_MATCH(h->cmdline, s) -void boot_img::parse_image(uint8_t *addr, format_t type) { - auto h = reinterpret_cast(addr); +dyn_img_hdr *boot_img::create_hdr(uint8_t *addr, format_t type) { if (type == AOSP_VENDOR) { fprintf(stderr, "VENDOR_BOOT_HDR\n"); + auto h = reinterpret_cast(addr); + hdr_addr = addr; switch (h->header_version) { case 4: - hdr = new dyn_img_vnd_v4(addr); - break; - case 3: + return new dyn_img_vnd_v4(addr); default: - hdr = new dyn_img_vnd_v3(addr); - break; - } - } else if (h->page_size >= 0x02000000) { - fprintf(stderr, "PXA_BOOT_HDR\n"); - hdr = new dyn_img_pxa(addr); - } else { - if (CMD_MATCH(NOOKHD_RL_MAGIC) || - CMD_MATCH(NOOKHD_GL_MAGIC) || - CMD_MATCH(NOOKHD_GR_MAGIC) || - CMD_MATCH(NOOKHD_EB_MAGIC) || - CMD_MATCH(NOOKHD_ER_MAGIC)) { - flags[NOOKHD_FLAG] = true; - fprintf(stderr, "NOOKHD_LOADER\n"); - addr += NOOKHD_PRE_HEADER_SZ; - } else if (memcmp(h->name, ACCLAIM_MAGIC, 10) == 0) { - flags[ACCLAIM_FLAG] = true; - fprintf(stderr, "ACCLAIM_LOADER\n"); - addr += ACCLAIM_PRE_HEADER_SZ; - } - - switch (h->header_version) { - case 1: - hdr = new dyn_img_v1(addr); - break; - case 2: - hdr = new dyn_img_v2(addr); - break; - case 3: - hdr = new dyn_img_v3(addr); - break; - case 4: - hdr = new dyn_img_v4(addr); - break; - default: - hdr = new dyn_img_v0(addr); - break; + return new dyn_img_vnd_v3(addr); } } + auto h = reinterpret_cast(addr); + + if (h->page_size >= 0x02000000) { + fprintf(stderr, "PXA_BOOT_HDR\n"); + hdr_addr = addr; + return new dyn_img_pxa(addr); + } + + if (CMD_MATCH(NOOKHD_RL_MAGIC) || + CMD_MATCH(NOOKHD_GL_MAGIC) || + CMD_MATCH(NOOKHD_GR_MAGIC) || + CMD_MATCH(NOOKHD_EB_MAGIC) || + CMD_MATCH(NOOKHD_ER_MAGIC)) { + flags[NOOKHD_FLAG] = true; + fprintf(stderr, "NOOKHD_LOADER\n"); + addr += NOOKHD_PRE_HEADER_SZ; + } else if (memcmp(h->name, ACCLAIM_MAGIC, 10) == 0) { + flags[ACCLAIM_FLAG] = true; + fprintf(stderr, "ACCLAIM_LOADER\n"); + addr += ACCLAIM_PRE_HEADER_SZ; + } + + // addr could be adjusted + h = reinterpret_cast(addr); + hdr_addr = addr; + + switch (h->header_version) { + case 1: + return new dyn_img_v1(addr); + case 2: + return new dyn_img_v2(addr); + case 3: + return new dyn_img_v3(addr); + case 4: + return new dyn_img_v4(addr); + default: + return new dyn_img_v0(addr); + } +} + +#define get_block(name) \ +name = hdr_addr + off; \ +off += hdr->name##_size(); \ +off = do_align(off, hdr->page_size()); + +void boot_img::parse_image(uint8_t *addr, format_t type) { + hdr = create_hdr(addr, type); + if (char *id = hdr->id()) { for (int i = SHA_DIGEST_SIZE + 4; i < SHA256_DIGEST_SIZE; ++i) { if (id[i]) { @@ -305,7 +310,6 @@ void boot_img::parse_image(uint8_t *addr, format_t type) { hdr->print(); size_t off = hdr->hdr_space(); - hdr_addr = addr; get_block(kernel); get_block(ramdisk); get_block(second); diff --git a/native/jni/magiskboot/bootimg.hpp b/native/jni/magiskboot/bootimg.hpp index 2b9dc4893..1c3d8e429 100644 --- a/native/jni/magiskboot/bootimg.hpp +++ b/native/jni/magiskboot/bootimg.hpp @@ -151,7 +151,15 @@ struct boot_img_hdr_v0_common { struct boot_img_hdr_v0 : public boot_img_hdr_v0_common { uint32_t tags_addr; /* physical addr for kernel tags */ - uint32_t page_size; /* flash page size we assume */ + + // In AOSP headers, this field is used for page size. + // For Samsung PXA headers, the use of this field is unknown; + // however, its value is something unrealistic to be treated as page size. + // We use this fact to determine whether this is an AOSP or PXA header. + union { + uint32_t unknown; + uint32_t page_size; /* flash page size we assume */ + }; // In header v1, this field is used for header version // However, on some devices like Samsung, this field is used to store DTB @@ -374,13 +382,10 @@ struct dyn_img_hdr { protected: union { - // Main header could be either AOSP or PXA boot_img_hdr_v2 *v2_hdr; /* AOSP v2 header */ - boot_img_hdr_v3 *v3_hdr; /* AOSP v3 header */ boot_img_hdr_v4 *v4_hdr; /* AOSP v4 header */ - boot_img_hdr_pxa *hdr_pxa; /* Samsung PXA header */ - boot_img_hdr_vnd_v3 *v3_vnd; /* AOSP vendor v3 header */ boot_img_hdr_vnd_v4 *v4_vnd; /* AOSP vendor v4 header */ + boot_img_hdr_pxa *hdr_pxa; /* Samsung PXA header */ void *raw; /* Raw pointer */ }; dyn_img_hdr(bool b) : is_vendor(b) {} @@ -394,31 +399,33 @@ private: #undef decl_var #undef decl_val -#define __impl_cls(name, hdr) \ -protected: name() = default; \ -public: \ -name(void *ptr) { \ - raw = xmalloc(sizeof(hdr)); \ - memcpy(raw, ptr, sizeof(hdr)); \ -} \ -size_t hdr_size() override { return sizeof(hdr); } \ -dyn_img_hdr *clone() override { \ - auto p = new name(this->raw); \ +#define __impl_cls(name, hdr) \ +protected: name() = default; \ +public: \ +name(void *ptr) { \ + raw = xmalloc(sizeof(hdr)); \ + memcpy(raw, ptr, sizeof(hdr)); \ +} \ +size_t hdr_size() override { \ + return sizeof(hdr); \ +} \ +dyn_img_hdr *clone() override { \ + auto p = new name(raw); \ p->kernel_dt_size = kernel_dt_size; \ - return p; \ + return p; \ }; #define __impl_val(name, hdr_name) \ decltype(std::declval().name()) name() override { return hdr_name->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_hdr_boot : public dyn_img_hdr { protected: dyn_img_hdr_boot() : dyn_img_hdr(false) {} }; +#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_boot { impl_val(kernel_size) impl_val(ramdisk_size) @@ -469,7 +476,7 @@ struct dyn_img_pxa : public dyn_img_common { }; #undef impl_val -#define impl_val(name) __impl_val(name, v3_hdr) +#define impl_val(name) __impl_val(name, v4_hdr) struct dyn_img_v3 : public dyn_img_hdr_boot { impl_cls(v3) @@ -483,15 +490,12 @@ struct dyn_img_v3 : public dyn_img_hdr_boot { // Make API compatible uint32_t &page_size() override { page_sz = 4096; return page_sz; } - char *extra_cmdline() override { return &v3_hdr->cmdline[BOOT_ARGS_SIZE]; } + char *extra_cmdline() override { return &v4_hdr->cmdline[BOOT_ARGS_SIZE]; } private: uint32_t page_sz = 4096; }; -#undef impl_val -#define impl_val(name) __impl_val(name, v4_hdr) - struct dyn_img_v4 : public dyn_img_v3 { impl_cls(v4) }; @@ -502,7 +506,7 @@ protected: }; #undef impl_val -#define impl_val(name) __impl_val(name, v3_vnd) +#define impl_val(name) __impl_val(name, v4_vnd) struct dyn_img_vnd_v3 : public dyn_img_hdr_vendor { impl_cls(vnd_v3) @@ -518,12 +522,9 @@ struct dyn_img_vnd_v3 : public dyn_img_hdr_vendor { size_t hdr_space() override { auto sz = page_size(); return do_align(hdr_size(), sz); } // Make API compatible - char *extra_cmdline() override { return &v3_vnd->cmdline[BOOT_ARGS_SIZE]; } + char *extra_cmdline() override { return &v4_vnd->cmdline[BOOT_ARGS_SIZE]; } }; -#undef impl_val -#define impl_val(name) __impl_val(name, v4_vnd) - struct dyn_img_vnd_v4 : public dyn_img_vnd_v3 { impl_cls(vnd_v4) }; @@ -616,4 +617,5 @@ struct boot_img { ~boot_img(); void parse_image(uint8_t *addr, format_t type); + dyn_img_hdr *create_hdr(uint8_t *addr, format_t type); };