diff --git a/native/jni/magiskboot/bootimg.cpp b/native/jni/magiskboot/bootimg.cpp index e38e04c6a..b66536ef8 100644 --- a/native/jni/magiskboot/bootimg.cpp +++ b/native/jni/magiskboot/bootimg.cpp @@ -269,11 +269,35 @@ void boot_img::print_hdr() { fprintf(stderr, "]\n"); } -int unpack(const char *image) { +int unpack(const char *image, bool hdr) { boot_img boot {}; int ret = boot.parse_file(image); int fd; + if (hdr) { + FILE *fp = xfopen(HEADER_FILE, "w"); + fprintf(fp, "pagesize=%u\n", boot.hdr.page_size()); + fprintf(fp, "name=%s\n", boot.hdr.name()); + fprintf(fp, "cmdline=%.512s%.1024s\n", boot.hdr.cmdline(), boot.hdr.extra_cmdline()); + uint32_t ver = boot.hdr.os_version(); + if (ver) { + int a, b, c, y, m = 0; + int version, patch_level; + version = ver >> 11; + patch_level = ver & 0x7ff; + + a = (version >> 14) & 0x7f; + b = (version >> 7) & 0x7f; + c = version & 0x7f; + fprintf(fp, "os_version=%d.%d.%d\n", a, b, c); + + y = (patch_level >> 4) + 2000; + m = patch_level & 0xf; + fprintf(fp, "patch_level=%d-%02d\n", y, m); + } + fclose(fp); + } + // Dump kernel if (COMPRESSED(boot.k_fmt)) { fd = creat(KERNEL_FILE, 0644); @@ -338,6 +362,40 @@ void repack(const char* orig_image, const char* out_image) { restore_buf(fd, boot.map_addr, ACCLAIM_PRE_HEADER_SZ); } + // header + if (access(HEADER_FILE, R_OK) == 0) { + int os_version = 0; + parse_prop_file(HEADER_FILE, [&](string_view key, string_view value) -> bool { + if (key == "page_size") { + boot.hdr.page_size() = parse_int(value); + } else if (key == "name") { + memset(boot.hdr.name(), 0, 16); + memcpy(boot.hdr.name(), value.data(), value.length() + 1); + } else if (key == "cmdline") { + memset(boot.hdr.cmdline(), 0, 512); + memset(boot.hdr.extra_cmdline(), 0, 1024); + if (value.length() > 512) { + memcpy(boot.hdr.cmdline(), value.data(), 512); + memcpy(boot.hdr.extra_cmdline(), &value[512], value.length() - 511); + } else { + memcpy(boot.hdr.cmdline(), value.data(), value.length() + 1); + } + } else if (key == "os_version") { + int a, b, c; + sscanf(value.data(), "%d.%d.%d", &a, &b, &c); + os_version |= ((a << 14) | (b << 7) | c) << 11; + } else if (key == "patch_level") { + int y, m; + sscanf(value.data(), "%d-%d", &y, &m); + y -= 2000; + os_version |= (y << 4) | m; + } + return true; + }); + if (os_version) + boot.hdr.os_version() = os_version; + } + // Skip a page for header header_off = lseek(fd, 0, SEEK_CUR); write_zero(fd, boot.hdr.page_size()); diff --git a/native/jni/magiskboot/magiskboot.h b/native/jni/magiskboot/magiskboot.h index b14ea00d0..3b5ffee9b 100644 --- a/native/jni/magiskboot/magiskboot.h +++ b/native/jni/magiskboot/magiskboot.h @@ -2,6 +2,7 @@ #include +#define HEADER_FILE "header" #define KERNEL_FILE "kernel" #define RAMDISK_FILE "ramdisk.cpio" #define SECOND_FILE "second" @@ -11,7 +12,7 @@ #define NEW_BOOT "new-boot.img" // Main entries -int unpack(const char *image); +int unpack(const char *image, bool hdr = false); void repack(const char* orig_image, const char* out_image); void hexpatch(const char *image, const char *from, const char *to); int cpio_commands(int argc, char *argv[]); diff --git a/native/jni/magiskboot/main.cpp b/native/jni/magiskboot/main.cpp index b517b1eea..679065595 100644 --- a/native/jni/magiskboot/main.cpp +++ b/native/jni/magiskboot/main.cpp @@ -18,9 +18,11 @@ static void usage(char *arg0) { "Usage: %s [args...]\n" "\n" "Supported actions:\n" - " unpack \n" - " Unpack to, if available, kernel, ramdisk.cpio, \n" + " unpack [-h] \n" + " Unpack to, if available, kernel, ramdisk.cpio,\n" " second, dtb, extra, and recovery_dtbo into current directory.\n" + " If '-h' is provided, it will dump header info to 'header',\n" + " which will be parsed when repacking.\n" " Return values:\n" " 0:valid 1:error 2:chromeos 3:ELF32 4:ELF64\n" "\n" @@ -116,6 +118,7 @@ int main(int argc, char *argv[]) { if (strcmp(argv[1], "cleanup") == 0) { fprintf(stderr, "Cleaning up...\n"); + unlink(HEADER_FILE); unlink(KERNEL_FILE); unlink(RAMDISK_FILE); unlink(SECOND_FILE); @@ -133,7 +136,13 @@ int main(int argc, char *argv[]) { printf("\n"); munmap(buf, size); } else if (argc > 2 && strcmp(argv[1], "unpack") == 0) { - return unpack(argv[2]); + if (strcmp(argv[2], "-h") == 0) { + if (argc == 3) + usage(argv[0]); + return unpack(argv[3], true); + } else { + return unpack(argv[2]); + } } else if (argc > 2 && strcmp(argv[1], "repack") == 0) { repack(argv[2], argv[3] ? argv[3] : NEW_BOOT); } else if (argc > 2 && strcmp(argv[1], "decompress") == 0) {