From f41575d8b047e7bb32dfa619df12634eaecc3feb Mon Sep 17 00:00:00 2001 From: Chaosmaster Date: Sat, 24 Jul 2021 23:04:44 +0200 Subject: [PATCH] Add support for legacy ARM32 zImage --- native/jni/magiskboot/bootimg.cpp | 58 ++++++++++++++++++++++++++++++- native/jni/magiskboot/bootimg.hpp | 19 ++++++++++ native/jni/magiskboot/format.cpp | 4 +++ native/jni/magiskboot/format.hpp | 2 ++ 4 files changed, 82 insertions(+), 1 deletion(-) diff --git a/native/jni/magiskboot/bootimg.cpp b/native/jni/magiskboot/bootimg.cpp index cf5ea79f2..df5fa2723 100644 --- a/native/jni/magiskboot/bootimg.cpp +++ b/native/jni/magiskboot/bootimg.cpp @@ -321,6 +321,44 @@ void boot_img::parse_image(uint8_t *addr, format_t type) { hdr->kernel_size() -= sizeof(mtk_hdr); k_fmt = check_fmt_lg(kernel, hdr->kernel_size()); } + if (k_fmt == ZIMAGE) { + z_hdr = reinterpret_cast(kernel); + uint32_t zimage_hdr_size = 0; + uint32_t end = z_hdr->end_addr; + if (z_hdr->endianess == 0x01020304) { + // Not supported + fprintf(stderr, "%-*s [%s]\n", PADDING, "ZIMAGE_HDR", "big-endian"); + } + else if (z_hdr->endianess == 0x04030201) { + fprintf(stderr, "%-*s [%s]\n", PADDING, "ZIMAGE_HDR", "little-endian"); + uint8_t *gzip_offset = 0; + if ((gzip_offset = (uint8_t *)memmem(kernel, hdr->kernel_size(), GZIP1_MAGIC, 2))) { + zimage_hdr_size = gzip_offset - kernel; + fprintf(stderr, "%-*s [%u]\n", PADDING, "ZIMAGE_HDR_SZ", zimage_hdr_size); + for (uint8_t * end_ptr = kernel + z_hdr->end_addr - 4; end_ptr >= kernel + z_hdr->end_addr - 64; end_ptr -= 4) { + uint32_t tmp_end = *(uint32_t*)end_ptr; + if (z_hdr->end_addr - tmp_end < 0xFF && tmp_end < end) { + end = tmp_end; + } + } + if (end == z_hdr->end_addr) { + LOGW("Could not find end of zImage gzip data\n"); + } + else { + flags[ZIMAGE_KERNEL] = true; + uint32_t gzip_size = end - zimage_hdr_size; + fprintf(stderr, "%-*s [%u]\n", PADDING, "ZIMAGE_GZIP_SZ", gzip_size); + hdr->kernel_size() -= zimage_hdr_size; + z_tail.size = hdr->kernel_size() - gzip_size; + hdr->kernel_size() -= z_tail.size; + kernel += zimage_hdr_size; + z_tail.data = kernel + hdr->kernel_size(); + fprintf(stderr, "%-*s [%u]\n", PADDING, "ZIMAGE_TAIL_SZ", z_tail.size); + k_fmt = check_fmt_lg(kernel, hdr->kernel_size()); + } + } + } + } fprintf(stderr, "%-*s [%s]\n", PADDING, "KERNEL_FMT", fmt2name[k_fmt]); } if (auto size = hdr->ramdisk_size()) { @@ -498,8 +536,12 @@ void repack(const char *src_img, const char *out_img, bool skip_comp) { // Copy MTK headers xwrite(fd, boot.k_hdr, sizeof(mtk_hdr)); } + if (boot.flags[ZIMAGE_KERNEL]) { + // Copy ZIMAGE headers + xwrite(fd, boot.z_hdr, (uint32_t)((uintptr_t)boot.kernel - (uintptr_t)boot.z_hdr)); + } + size_t raw_size; if (access(KERNEL_FILE, R_OK) == 0) { - size_t raw_size; void *raw_buf; mmap_ro(KERNEL_FILE, raw_buf, raw_size); if (!COMPRESSED_ANY(check_fmt(raw_buf, raw_size)) && COMPRESSED(boot.k_fmt)) { @@ -509,6 +551,20 @@ void repack(const char *src_img, const char *out_img, bool skip_comp) { } munmap(raw_buf, raw_size); } + if (boot.flags[ZIMAGE_KERNEL]) { + if (hdr->kernel_size() > boot.hdr->kernel_size()) { + LOGW("Recompressed kernel is %d bytes too large, using original kernel\n", hdr->kernel_size() - boot.hdr->kernel_size()); + lseek(fd, -hdr->kernel_size(), SEEK_CUR); + hdr->kernel_size() = xwrite(fd, boot.z_tail.data - boot.hdr->kernel_size(), boot.hdr->kernel_size()); + } + else { + write_zero(fd, boot.hdr->kernel_size() - hdr->kernel_size() - 4); + xwrite(fd, &raw_size, 4); + hdr->kernel_size() += boot.hdr->kernel_size() - hdr->kernel_size(); + } + hdr->kernel_size() += (uint32_t)((uintptr_t)boot.kernel - (uintptr_t)boot.z_hdr); + hdr->kernel_size() += xwrite(fd, boot.z_tail.data, boot.z_tail.size); + } // kernel dtb if (access(KER_DTB_FILE, R_OK) == 0) diff --git a/native/jni/magiskboot/bootimg.hpp b/native/jni/magiskboot/bootimg.hpp index 3f7b3bfd3..14fbf606e 100644 --- a/native/jni/magiskboot/bootimg.hpp +++ b/native/jni/magiskboot/bootimg.hpp @@ -41,6 +41,20 @@ struct blob_hdr { uint32_t version; /* 0x00000001 */ } __attribute__((packed)); +struct zimage_hdr { + uint8_t head[36]; + uint32_t magic; /* zImage magic */ + uint32_t load_addr; /* absolute load/run zImage address */ + uint32_t end_addr; /* zImage end address */ + uint32_t endianess; /* endianess flag */ + uint8_t code[]; +} __attribute__((packed)); + +struct zimage_tail { + uint8_t *data; + uint32_t size; +} __attribute__((packed)); + /************** * AVB Headers **************/ @@ -446,6 +460,7 @@ enum { NOOKHD_FLAG, ACCLAIM_FLAG, AVB_FLAG, + ZIMAGE_KERNEL, BOOT_FLAGS_MAX }; @@ -473,6 +488,10 @@ struct boot_img { mtk_hdr *k_hdr; mtk_hdr *r_hdr; + // ZIMAGE data + zimage_hdr *z_hdr; + zimage_tail z_tail; + // Pointer to dtb that is embedded in kernel uint8_t *kernel_dtb; diff --git a/native/jni/magiskboot/format.cpp b/native/jni/magiskboot/format.cpp index b6f437914..4a4fc81ad 100644 --- a/native/jni/magiskboot/format.cpp +++ b/native/jni/magiskboot/format.cpp @@ -36,6 +36,8 @@ format_t check_fmt(const void *buf, size_t len) { return DHTB; } else if (CHECKED_MATCH(TEGRABLOB_MAGIC)) { return BLOB; + } else if (len >= 0x28 && memcmp(&((char *)buf)[0x24], ZIMAGE_MAGIC, 4) == 0) { + return ZIMAGE; } else { return UNKNOWN; } @@ -61,6 +63,8 @@ const char *Fmt2Name::operator[](format_t fmt) { return "lz4_lg"; case DTB: return "dtb"; + case ZIMAGE: + return "zimage"; default: return "raw"; } diff --git a/native/jni/magiskboot/format.hpp b/native/jni/magiskboot/format.hpp index d4ac997a2..6ff9828e0 100644 --- a/native/jni/magiskboot/format.hpp +++ b/native/jni/magiskboot/format.hpp @@ -23,6 +23,7 @@ typedef enum { /* Misc */ MTK, DTB, + ZIMAGE, } format_t; #define COMPRESSED(fmt) ((fmt) >= GZIP && (fmt) < LZOP) @@ -57,6 +58,7 @@ typedef enum { #define ACCLAIM_PRE_HEADER_SZ 262144 #define AVB_FOOTER_MAGIC "AVBf" #define AVB_MAGIC "AVB0" +#define ZIMAGE_MAGIC "\x18\x28\x6f\x01" class Fmt2Name { public: