diff --git a/native/src/boot/bootimg.cpp b/native/src/boot/bootimg.cpp index edb915186..ae0ed3249 100644 --- a/native/src/boot/bootimg.cpp +++ b/native/src/boot/bootimg.cpp @@ -32,7 +32,7 @@ static off_t compress(format_t type, int fd, const void *in, size_t size) { return now - prev; } -static void dump(void *buf, size_t size, const char *filename) { +static void dump(const void *buf, size_t size, const char *filename) { if (size == 0) return; int fd = creat(filename, 0644); @@ -150,7 +150,7 @@ void dyn_img_hdr::load_hdr_file() { boot_img::boot_img(const char *image) : map(image) { fprintf(stderr, "Parsing boot image: [%s]\n", image); - for (uint8_t *addr = map.buf; addr < map.buf + map.sz; ++addr) { + for (const uint8_t *addr = map.buf; addr < map.buf + map.sz; ++addr) { format_t fmt = check_fmt(addr, map.sz); switch (fmt) { case CHROMEOS: @@ -184,15 +184,15 @@ boot_img::~boot_img() { delete hdr; } -static int find_dtb_offset(uint8_t *buf, unsigned sz) { - uint8_t * const end = buf + sz; +static int find_dtb_offset(const uint8_t *buf, unsigned sz) { + const uint8_t * const end = buf + sz; - for (uint8_t *curr = buf; curr < end; curr += sizeof(fdt_header)) { + for (auto curr = buf; curr < end; curr += sizeof(fdt_header)) { curr = static_cast(memmem(curr, end - curr, DTB_MAGIC, sizeof(fdt32_t))); if (curr == nullptr) return -1; - auto fdt_hdr = reinterpret_cast(curr); + auto fdt_hdr = reinterpret_cast(curr); // Check that fdt_header.totalsize does not overflow kernel image size uint32_t totalsize = fdt32_to_cpu(fdt_hdr->totalsize); @@ -205,7 +205,7 @@ static int find_dtb_offset(uint8_t *buf, unsigned sz) { continue; // Check that fdt_node_header.tag of first node is FDT_BEGIN_NODE - auto fdt_node_hdr = reinterpret_cast(curr + off_dt_struct); + auto fdt_node_hdr = reinterpret_cast(curr + off_dt_struct); if (fdt32_to_cpu(fdt_node_hdr->tag) != FDT_BEGIN_NODE) continue; @@ -214,7 +214,7 @@ static int find_dtb_offset(uint8_t *buf, unsigned sz) { return -1; } -static format_t check_fmt_lg(uint8_t *buf, unsigned sz) { +static format_t check_fmt_lg(const uint8_t *buf, unsigned sz) { format_t fmt = check_fmt(buf, sz); if (fmt == LZ4_LEGACY) { // We need to check if it is LZ4_LG @@ -233,10 +233,10 @@ static format_t check_fmt_lg(uint8_t *buf, unsigned sz) { #define CMD_MATCH(s) BUFFER_MATCH(h->cmdline, s) -dyn_img_hdr *boot_img::create_hdr(uint8_t *addr, format_t type) { +dyn_img_hdr *boot_img::create_hdr(const uint8_t *addr, format_t type) { if (type == AOSP_VENDOR) { fprintf(stderr, "VENDOR_BOOT_HDR\n"); - auto h = reinterpret_cast(addr); + auto h = reinterpret_cast(addr); hdr_addr = addr; switch (h->header_version) { case 4: @@ -246,7 +246,7 @@ dyn_img_hdr *boot_img::create_hdr(uint8_t *addr, format_t type) { } } - auto h = reinterpret_cast(addr); + auto h = reinterpret_cast(addr); if (h->page_size >= 0x02000000) { fprintf(stderr, "PXA_BOOT_HDR\n"); @@ -254,6 +254,40 @@ dyn_img_hdr *boot_img::create_hdr(uint8_t *addr, format_t type) { return new dyn_img_pxa(addr); } + auto make_hdr = [](const uint8_t *ptr) -> dyn_img_hdr * { + auto h = reinterpret_cast(ptr); + switch (h->header_version) { + case 1: + return new dyn_img_v1(ptr); + case 2: + return new dyn_img_v2(ptr); + case 3: + return new dyn_img_v3(ptr); + case 4: + return new dyn_img_v4(ptr); + default: + return new dyn_img_v0(ptr); + } + }; + + // For NOOKHD and ACCLAIM, the entire boot image is shifted by a fixed offset. + // For AMONET, only the header is internally shifted by a fixed offset. + + if (BUFFER_CONTAIN(addr, AMONET_MICROLOADER_SZ, AMONET_MICROLOADER_MAGIC) && + BUFFER_MATCH(addr + AMONET_MICROLOADER_SZ, BOOT_MAGIC)) { + flags[AMONET_FLAG] = true; + fprintf(stderr, "AMONET_MICROLOADER\n"); + + // The real header is shifted, copy to temporary buffer + h = reinterpret_cast(addr + AMONET_MICROLOADER_SZ); + auto real_hdr_sz = h->page_size - AMONET_MICROLOADER_SZ; + auto buf = make_unique(h->page_size); + memcpy(buf.get(), h, real_hdr_sz); + + hdr_addr = addr; + return make_hdr(buf.get()); + } + if (CMD_MATCH(NOOKHD_RL_MAGIC) || CMD_MATCH(NOOKHD_GL_MAGIC) || CMD_MATCH(NOOKHD_GR_MAGIC) || @@ -262,36 +296,15 @@ dyn_img_hdr *boot_img::create_hdr(uint8_t *addr, format_t type) { flags[NOOKHD_FLAG] = true; fprintf(stderr, "NOOKHD_LOADER\n"); addr += NOOKHD_PRE_HEADER_SZ; - } else if (memcmp(h->name, ACCLAIM_MAGIC, 10) == 0) { + } else if (BUFFER_MATCH(h->name, ACCLAIM_MAGIC)) { flags[ACCLAIM_FLAG] = true; fprintf(stderr, "ACCLAIM_LOADER\n"); addr += ACCLAIM_PRE_HEADER_SZ; - } else if (str_contains(string_view((const char *) addr, AMONET_MICROLOADER_SZ), AMONET_MICROLOADER_MAGIC) && - string_view((const char *)addr + AMONET_MICROLOADER_SZ, BOOT_MAGIC_SIZE) == BOOT_MAGIC) { - flags[AMONET_FLAG] = true; - fprintf(stderr, "AMONET_MICROLOADER\n"); - uint8_t microloader[AMONET_MICROLOADER_SZ]; - memcpy(microloader, addr, AMONET_MICROLOADER_SZ); - memcpy(addr, addr + AMONET_MICROLOADER_SZ, AMONET_MICROLOADER_SZ); - memcpy(addr + AMONET_MICROLOADER_SZ, microloader, AMONET_MICROLOADER_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); - } + return make_hdr(addr); } #define get_block(name) \ @@ -306,7 +319,7 @@ if (hdr->name##_size()) { \ off += blk_sz; \ } -void boot_img::parse_image(uint8_t *addr, format_t type) { +void boot_img::parse_image(const uint8_t *addr, format_t type) { hdr = create_hdr(addr, type); if (char *id = hdr->id()) { @@ -345,7 +358,7 @@ void boot_img::parse_image(uint8_t *addr, format_t type) { if (k_fmt == MTK) { fprintf(stderr, "MTK_KERNEL_HDR\n"); flags[MTK_KERNEL] = true; - k_hdr = reinterpret_cast(kernel); + k_hdr = reinterpret_cast(kernel); fprintf(stderr, "%-*s [%u]\n", PADDING, "SIZE", k_hdr->size); fprintf(stderr, "%-*s [%s]\n", PADDING, "NAME", k_hdr->name); kernel += sizeof(mtk_hdr); @@ -353,7 +366,7 @@ void boot_img::parse_image(uint8_t *addr, format_t type) { k_fmt = check_fmt_lg(kernel, hdr->kernel_size()); } if (k_fmt == ZIMAGE) { - z_hdr = reinterpret_cast(kernel); + z_hdr = reinterpret_cast(kernel); if (void *gzip_offset = memmem(kernel, hdr->kernel_size(), GZIP1_MAGIC "\x08\x00", 4)) { fprintf(stderr, "ZIMAGE_KERNEL\n"); z_info.hdr_sz = (uint8_t *) gzip_offset - kernel; @@ -397,7 +410,7 @@ void boot_img::parse_image(uint8_t *addr, format_t type) { if (r_fmt == MTK) { fprintf(stderr, "MTK_RAMDISK_HDR\n"); flags[MTK_RAMDISK] = true; - r_hdr = reinterpret_cast(ramdisk); + r_hdr = reinterpret_cast(ramdisk); fprintf(stderr, "%-*s [%u]\n", PADDING, "SIZE", r_hdr->size); fprintf(stderr, "%-*s [%s]\n", PADDING, "NAME", r_hdr->name); ramdisk += sizeof(mtk_hdr); @@ -432,15 +445,15 @@ void boot_img::parse_image(uint8_t *addr, format_t type) { } // Find AVB footer - void *footer = tail + tail_size - sizeof(AvbFooter); + const void *footer = tail + tail_size - sizeof(AvbFooter); if (BUFFER_MATCH(footer, AVB_FOOTER_MAGIC)) { - avb_footer = reinterpret_cast(footer); + avb_footer = reinterpret_cast(footer); // Double check if meta header exists - void *meta = hdr_addr + __builtin_bswap64(avb_footer->vbmeta_offset); + const void *meta = hdr_addr + __builtin_bswap64(avb_footer->vbmeta_offset); if (BUFFER_MATCH(meta, AVB_MAGIC)) { fprintf(stderr, "VBMETA\n"); flags[AVB_FLAG] = true; - vbmeta = reinterpret_cast(meta); + vbmeta = reinterpret_cast(meta); } } } @@ -771,7 +784,12 @@ void repack(const char *src_img, const char *out_img, bool skip_comp) { hdr->print(); // Copy main header - memcpy(out.buf + off.header, hdr->raw_hdr(), hdr->hdr_size()); + if (boot.flags[AMONET_FLAG]) { + auto real_hdr_sz = std::min(hdr->hdr_space() - AMONET_MICROLOADER_SZ, hdr->hdr_size()); + memcpy(out.buf + off.header + AMONET_MICROLOADER_SZ, hdr->raw_hdr(), real_hdr_sz); + } else { + memcpy(out.buf + off.header, hdr->raw_hdr(), hdr->hdr_size()); + } if (boot.flags[AVB_FLAG]) { // Copy and patch AVB structures @@ -796,9 +814,4 @@ void repack(const char *src_img, const char *out_img, bool skip_comp) { auto b_hdr = reinterpret_cast(out.buf); b_hdr->size = off.total - sizeof(blob_hdr); } - - if (boot.flags[AMONET_FLAG]) { - memcpy(out.buf + off.header + AMONET_MICROLOADER_SZ, out.buf + off.header, AMONET_MICROLOADER_SZ); - memcpy(out.buf + off.header, boot.hdr_addr + AMONET_MICROLOADER_SZ, AMONET_MICROLOADER_SZ); - } } diff --git a/native/src/boot/bootimg.hpp b/native/src/boot/bootimg.hpp index ad2e8a791..b815b6cde 100644 --- a/native/src/boot/bootimg.hpp +++ b/native/src/boot/bootimg.hpp @@ -407,7 +407,7 @@ private: #define __impl_cls(name, hdr) \ protected: name() = default; \ public: \ -name(void *ptr) { \ +name(const void *ptr) { \ raw = malloc(sizeof(hdr)); \ memcpy(raw, ptr, sizeof(hdr)); \ } \ @@ -577,13 +577,13 @@ struct boot_img { format_t r_fmt = UNKNOWN; format_t e_fmt = UNKNOWN; - /*************************************************** - * Following pointers points within the mmap region - ***************************************************/ + /************************************************************* + * Following pointers points within the read-only mmap region + *************************************************************/ // MTK headers - mtk_hdr *k_hdr; - mtk_hdr *r_hdr; + const mtk_hdr *k_hdr; + const mtk_hdr *r_hdr; // The pointers/values after parse_image // +---------------+ @@ -593,40 +593,40 @@ struct boot_img { // +---------------+ // | z_info.tail | z_info.tail_sz // +---------------+ - zimage_hdr *z_hdr; + const zimage_hdr *z_hdr; struct { uint32_t hdr_sz; uint32_t tail_sz = 0; - uint8_t *tail = nullptr; + const uint8_t *tail = nullptr; } z_info; // Pointer to dtb that is embedded in kernel - uint8_t *kernel_dtb; + const uint8_t *kernel_dtb; // Pointer to end of image - uint8_t *tail; + const uint8_t *tail; size_t tail_size = 0; // AVB structs - AvbFooter *avb_footer; - AvbVBMetaImageHeader *vbmeta; + const AvbFooter *avb_footer; + const AvbVBMetaImageHeader *vbmeta; // Pointers to blocks defined in header - uint8_t *hdr_addr; - uint8_t *kernel; - uint8_t *ramdisk; - uint8_t *second; - uint8_t *extra; - uint8_t *recovery_dtbo; - uint8_t *dtb; + const uint8_t *hdr_addr; + const uint8_t *kernel; + const uint8_t *ramdisk; + const uint8_t *second; + const uint8_t *extra; + const uint8_t *recovery_dtbo; + const uint8_t *dtb; // Pointer to blocks defined in header, but we do not care - uint8_t *ignore; + const uint8_t *ignore; size_t ignore_size = 0; boot_img(const char *); ~boot_img(); - void parse_image(uint8_t *addr, format_t type); - dyn_img_hdr *create_hdr(uint8_t *addr, format_t type); + void parse_image(const uint8_t *addr, format_t type); + dyn_img_hdr *create_hdr(const uint8_t *addr, format_t type); }; diff --git a/native/src/boot/format.hpp b/native/src/boot/format.hpp index 9dbb313c9..79dac8fec 100644 --- a/native/src/boot/format.hpp +++ b/native/src/boot/format.hpp @@ -31,6 +31,7 @@ typedef enum { #define COMPRESSED_ANY(fmt) ((fmt) >= GZIP && (fmt) <= LZOP) #define BUFFER_MATCH(buf, s) (memcmp(buf, s, sizeof(s) - 1) == 0) +#define BUFFER_CONTAIN(buf, sz, s) (memmem(buf, sz, s, sizeof(s) - 1) != nullptr) #define BOOT_MAGIC "ANDROID!" #define VENDOR_BOOT_MAGIC "VNDRBOOT" @@ -57,8 +58,8 @@ typedef enum { #define NOOKHD_PRE_HEADER_SZ 1048576 #define ACCLAIM_MAGIC "BauwksBoot" #define ACCLAIM_PRE_HEADER_SZ 262144 -#define AMONET_MICROLOADER_SZ 1024 #define AMONET_MICROLOADER_MAGIC "microloader" +#define AMONET_MICROLOADER_SZ 1024 #define AVB_FOOTER_MAGIC "AVBf" #define AVB_MAGIC "AVB0" #define ZIMAGE_MAGIC "\x18\x28\x6f\x01"