From 6b41653a328b817d9d64f44b20e62286fc213c10 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Tue, 12 Sep 2017 22:09:10 +0800 Subject: [PATCH] Add kernel decompression and appended dtb support --- jni/magiskboot/bootimg.c | 251 +++++++++++++++++++----------------- jni/magiskboot/bootimg.h | 40 ++++-- jni/magiskboot/magiskboot.h | 2 +- 3 files changed, 161 insertions(+), 132 deletions(-) diff --git a/jni/magiskboot/bootimg.c b/jni/magiskboot/bootimg.c index 0f11b132b..198f0e97b 100644 --- a/jni/magiskboot/bootimg.c +++ b/jni/magiskboot/bootimg.c @@ -1,11 +1,6 @@ #include "bootimg.h" #include "magiskboot.h" -static void *kernel, *ramdisk, *second, *dtb, *extra; -static boot_img_hdr hdr; -static int mtk_kernel = 0, mtk_ramdisk = 0; -static file_t ramdisk_type; - static void dump(void *buf, size_t size, const char *filename) { int fd = open_new(filename); xwrite(fd, buf, size); @@ -25,17 +20,17 @@ static void restore_buf(int fd, const void *buf, size_t size) { xwrite(fd, buf, size); } -static void print_info() { - fprintf(stderr, "KERNEL [%d] @ 0x%08x\n", hdr.kernel_size, hdr.kernel_addr); - fprintf(stderr, "RAMDISK [%d] @ 0x%08x\n", hdr.ramdisk_size, hdr.ramdisk_addr); - fprintf(stderr, "SECOND [%d] @ 0x%08x\n", hdr.second_size, hdr.second_addr); - fprintf(stderr, "DTB [%d] @ 0x%08x\n", hdr.dt_size, hdr.tags_addr); - fprintf(stderr, "PAGESIZE [%d]\n", hdr.page_size); - if (hdr.os_version != 0) { +static void print_hdr(const boot_img_hdr *hdr) { + fprintf(stderr, "KERNEL [%d] @ 0x%08x\n", hdr->kernel_size, hdr->kernel_addr); + fprintf(stderr, "RAMDISK [%d] @ 0x%08x\n", hdr->ramdisk_size, hdr->ramdisk_addr); + fprintf(stderr, "SECOND [%d] @ 0x%08x\n", hdr->second_size, hdr->second_addr); + fprintf(stderr, "DTB [%d] @ 0x%08x\n", hdr->dt_size, hdr->tags_addr); + fprintf(stderr, "PAGESIZE [%d]\n", hdr->page_size); + if (hdr->os_version != 0) { int a,b,c,y,m = 0; int os_version, os_patch_level; - os_version = hdr.os_version >> 11; - os_patch_level = hdr.os_version & 0x7ff; + os_version = hdr->os_version >> 11; + os_patch_level = hdr->os_version & 0x7ff; a = (os_version >> 14) & 0x7f; b = (os_version >> 7) & 0x7f; @@ -46,20 +41,16 @@ static void print_info() { m = os_patch_level & 0xf; fprintf(stderr, "PATCH_LEVEL [%d-%02d]\n", y, m); } - fprintf(stderr, "NAME [%s]\n", hdr.name); - fprintf(stderr, "CMDLINE [%s]\n", hdr.cmdline); - - char cmp[16]; - - get_type_name(ramdisk_type, cmp); - fprintf(stderr, "RAMDISK_COMP [%s]\n", cmp); + fprintf(stderr, "NAME [%s]\n", hdr->name); + fprintf(stderr, "CMDLINE [%s]\n", hdr->cmdline); fprintf(stderr, "\n"); } -int parse_img(void *orig, size_t size) { +int parse_img(void *orig, size_t size, boot_img *boot) { void *base, *end; size_t pos = 0; int ret = 0; + memset(boot, 0, sizeof(*boot)); for(base = orig, end = orig + size; base < end; base += 256, size -= 256) { switch (check_type(base)) { case CHROMEOS: @@ -72,53 +63,75 @@ int parse_img(void *orig, size_t size) { exit(4); case AOSP: // Read the header - memcpy(&hdr, base, sizeof(hdr)); - pos += hdr.page_size; + memcpy(&boot->hdr, base, sizeof(boot->hdr)); + pos += boot->hdr.page_size; - // Kernel position - kernel = base + pos; - pos += hdr.kernel_size; - mem_align(&pos, hdr.page_size); + print_hdr(&boot->hdr); - // Ramdisk position - ramdisk = base + pos; - pos += hdr.ramdisk_size; - mem_align(&pos, hdr.page_size); + boot->kernel = base + pos; + pos += boot->hdr.kernel_size; + mem_align(&pos, boot->hdr.page_size); - if (hdr.second_size) { - // Second position - second = base + pos; - pos += hdr.second_size; - mem_align(&pos, hdr.page_size); + boot->ramdisk = base + pos; + pos += boot->hdr.ramdisk_size; + mem_align(&pos, boot->hdr.page_size); + + if (boot->hdr.second_size) { + boot->second = base + pos; + pos += boot->hdr.second_size; + mem_align(&pos, boot->hdr.page_size); } - if (hdr.dt_size) { - // dtb position - dtb = base + pos; - pos += hdr.dt_size; - mem_align(&pos, hdr.page_size); + if (boot->hdr.dt_size) { + boot->dtb = base + pos; + pos += boot->hdr.dt_size; + mem_align(&pos, boot->hdr.page_size); } if (pos < size) { - extra = base + pos; + boot->extra = base + pos; } - // Check ramdisk compression type - ramdisk_type = check_type(ramdisk); + // Linear search in kernel for DTB + for (int i = 0; i < boot->hdr.kernel_size; ++i) { + if (memcmp(boot->kernel + i, DTB_MAGIC, 4) == 0) { + boot->flags |= APPEND_DTB; + boot->dtb = boot->kernel + i; + boot->hdr.dt_size = boot->hdr.kernel_size - i; + boot->hdr.kernel_size = i; + fprintf(stderr, "APPEND_DTB [%d]\n", boot->hdr.dt_size); + } + } + + boot->ramdisk_type = check_type(boot->ramdisk); + boot->kernel_type = check_type(boot->kernel); // Check MTK - if (check_type(kernel) == MTK) { - fprintf(stderr, "MTK header found in kernel\n"); - mtk_kernel = 1; + if (boot->kernel_type == MTK) { + fprintf(stderr, "MTK_KERNEL_HDR [512]\n"); + boot->flags |= MTK_KERNEL; + memcpy(&boot->mtk_kernel_hdr, boot->kernel, sizeof(mtk_hdr)); + boot->kernel += 512; + boot->hdr.kernel_size -= 512; + boot->kernel_type = check_type(boot->kernel); } - if (ramdisk_type == MTK) { - fprintf(stderr, "MTK header found in ramdisk\n"); - mtk_ramdisk = 1; - ramdisk_type = check_type(ramdisk + 512); + if (boot->ramdisk_type == MTK) { + fprintf(stderr, "MTK_RAMDISK_HDR [512]\n"); + boot->flags |= MTK_RAMDISK; + memcpy(&boot->mtk_ramdisk_hdr, boot->ramdisk, sizeof(mtk_hdr)); + boot->ramdisk += 512; + boot->hdr.ramdisk_size -= 512; + boot->ramdisk_type = check_type(boot->ramdisk + 512); } - // Print info - print_info(); + char fmt[16]; + + get_type_name(boot->kernel_type, fmt); + fprintf(stderr, "KERNEL_FMT [%s]\n", fmt); + get_type_name(boot->ramdisk_type, fmt); + fprintf(stderr, "RAMDISK_FMT [%s]\n", fmt); + fprintf(stderr, "\n"); + return ret; default: continue; @@ -131,39 +144,40 @@ void unpack(const char* image) { size_t size; void *orig; mmap_ro(image, &orig, &size); + int fd; + boot_img boot; // Parse image fprintf(stderr, "Parsing boot image: [%s]\n\n", image); - int ret = parse_img(orig, size); + int ret = parse_img(orig, size, &boot); // Dump kernel - if (mtk_kernel) { - kernel += 512; - hdr.kernel_size -= 512; + if (boot.kernel_type == UNKNOWN) { + dump(boot.kernel, boot.hdr.kernel_size, KERNEL_FILE); + } else { + fd = open_new(KERNEL_FILE); + decomp(boot.kernel_type, fd, boot.kernel, boot.hdr.kernel_size); + close(fd); } - dump(kernel, hdr.kernel_size, KERNEL_FILE); // Dump ramdisk - if (mtk_ramdisk) { - ramdisk += 512; - hdr.ramdisk_size -= 512; - } - int fd = open_new(RAMDISK_FILE); - if (decomp(ramdisk_type, fd, ramdisk, hdr.ramdisk_size) < 0) { - // Dump the compressed ramdisk - dump(ramdisk, hdr.ramdisk_size, RAMDISK_FILE ".raw"); + if (boot.ramdisk_type == UNKNOWN) { + dump(boot.ramdisk, boot.hdr.ramdisk_size, RAMDISK_FILE ".raw"); LOGE(1, "Unknown ramdisk format! Dumped to %s\n", RAMDISK_FILE ".raw"); + } else { + fd = open_new(RAMDISK_FILE); + decomp(boot.ramdisk_type, fd, boot.ramdisk, boot.hdr.ramdisk_size); + close(fd); } - close(fd); - if (hdr.second_size) { + if (boot.hdr.second_size) { // Dump second - dump(second, hdr.second_size, SECOND_FILE); + dump(boot.second, boot.hdr.second_size, SECOND_FILE); } - if (hdr.dt_size) { + if (boot.hdr.dt_size) { // Dump dtb - dump(dtb, hdr.dt_size, DTB_FILE); + dump(boot.dtb, boot.hdr.dt_size, DTB_FILE); } munmap(orig, size); @@ -173,9 +187,9 @@ void unpack(const char* image) { void repack(const char* orig_image, const char* out_image) { size_t size; void *orig; + boot_img boot; // There are possible two MTK headers - mtk_hdr mtk_kernel_hdr, mtk_ramdisk_hdr; size_t mtk_kernel_off, mtk_ramdisk_off; // Load original image @@ -183,51 +197,47 @@ void repack(const char* orig_image, const char* out_image) { // Parse original image fprintf(stderr, "Parsing boot image: [%s]\n\n", orig_image); - parse_img(orig, size); + parse_img(orig, size, &boot); fprintf(stderr, "Repack to boot image: [%s]\n\n", out_image); // Create new image int fd = open_new(out_image); - // Set all sizes to 0 - hdr.kernel_size = 0; - hdr.ramdisk_size = 0; - hdr.second_size = 0; - hdr.dt_size = 0; - // Skip a page for header - write_zero(fd, hdr.page_size); + write_zero(fd, boot.hdr.page_size); - if (mtk_kernel) { + if (boot.flags & MTK_KERNEL) { + // Record position and skip MTK header mtk_kernel_off = lseek(fd, 0, SEEK_CUR); - // Skip header write_zero(fd, 512); - memcpy(&mtk_kernel_hdr, kernel, sizeof(mtk_kernel_hdr)); } - hdr.kernel_size = restore(KERNEL_FILE, fd); - file_align(fd, hdr.page_size, 1); + if (boot.kernel_type == UNKNOWN) { + boot.hdr.kernel_size = restore(KERNEL_FILE, fd); + } else { + size_t raw_size; + void *kernel_raw; + mmap_ro(KERNEL_FILE, &kernel_raw, &raw_size); + boot.hdr.kernel_size = comp(boot.kernel_type, fd, kernel_raw, raw_size); + munmap(kernel_raw, raw_size); + } + if (boot.flags & APPEND_DTB) { + boot.hdr.kernel_size += restore(DTB_FILE, fd); + boot.hdr.dt_size = 0; + } + file_align(fd, boot.hdr.page_size, 1); - if (mtk_ramdisk) { + if (boot.flags & MTK_RAMDISK) { + // Record position and skip MTK header mtk_ramdisk_off = lseek(fd, 0, SEEK_CUR); - // Skip header write_zero(fd, 512); - memcpy(&mtk_ramdisk_hdr, ramdisk, sizeof(mtk_ramdisk_hdr)); } if (access(RAMDISK_FILE, R_OK) == 0) { // If we found raw cpio, compress to original format size_t cpio_size; void *cpio; mmap_ro(RAMDISK_FILE, &cpio, &cpio_size); - - long long ramdisk_size = comp(ramdisk_type, fd, cpio, cpio_size); - - if (ramdisk_size < 0) { - LOGE(1, "Unsupported ramdisk format!\n"); - } else { - hdr.ramdisk_size = ramdisk_size; - } - + boot.hdr.ramdisk_size = comp(boot.ramdisk_type, fd, cpio, cpio_size); munmap(cpio, cpio_size); } else { // Find compressed ramdisk @@ -242,49 +252,50 @@ void repack(const char* orig_image, const char* out_image) { } if (!found) LOGE(1, "No ramdisk exists!\n"); - hdr.ramdisk_size = restore(name, fd); + boot.hdr.ramdisk_size = restore(name, fd); } - file_align(fd, hdr.page_size, 1); + file_align(fd, boot.hdr.page_size, 1); // Restore second - if (access(SECOND_FILE, R_OK) == 0) { - hdr.second_size = restore(SECOND_FILE, fd); - file_align(fd, hdr.page_size, 1); + if (boot.hdr.second_size && access(SECOND_FILE, R_OK) == 0) { + boot.hdr.second_size = restore(SECOND_FILE, fd); + file_align(fd, boot.hdr.page_size, 1); } // Restore dtb - if (access(DTB_FILE, R_OK) == 0) { - hdr.dt_size = restore(DTB_FILE, fd); - file_align(fd, hdr.page_size, 1); + if (boot.hdr.dt_size && access(DTB_FILE, R_OK) == 0) { + printf("Here\n"); + boot.hdr.dt_size = restore(DTB_FILE, fd); + file_align(fd, boot.hdr.page_size, 1); } // Check extra info, currently only for LG Bump and Samsung SEANDROIDENFORCE - if (extra) { - if (memcmp(extra, "SEANDROIDENFORCE", 16) == 0 || - memcmp(extra, LG_BUMP_MAGIC, 16) == 0 ) { - restore_buf(fd, extra, 16); + if (boot.extra) { + if (memcmp(boot.extra, "SEANDROIDENFORCE", 16) == 0 || + memcmp(boot.extra, LG_BUMP_MAGIC, 16) == 0 ) { + restore_buf(fd, boot.extra, 16); } } // Write MTK headers back - if (mtk_kernel) { + if (boot.flags & MTK_KERNEL) { lseek(fd, mtk_kernel_off, SEEK_SET); - mtk_kernel_hdr.size = hdr.kernel_size; - hdr.kernel_size += 512; - restore_buf(fd, &mtk_kernel_hdr, sizeof(mtk_kernel_hdr)); + boot.mtk_kernel_hdr.size = boot.hdr.kernel_size; + boot.hdr.kernel_size += 512; + restore_buf(fd, &boot.mtk_kernel_hdr, sizeof(mtk_hdr)); } - if (mtk_ramdisk) { + if (boot.flags & MTK_RAMDISK) { lseek(fd, mtk_ramdisk_off, SEEK_SET); - mtk_ramdisk_hdr.size = hdr.ramdisk_size; - hdr.ramdisk_size += 512; - restore_buf(fd, &mtk_ramdisk_hdr, sizeof(mtk_ramdisk_hdr)); + boot.mtk_ramdisk_hdr.size = boot.hdr.ramdisk_size; + boot.hdr.ramdisk_size += 512; + restore_buf(fd, &boot.mtk_ramdisk_hdr, sizeof(mtk_hdr)); } // Main header lseek(fd, 0, SEEK_SET); - restore_buf(fd, &hdr, sizeof(hdr)); + restore_buf(fd, &boot.hdr, sizeof(boot.hdr)); // Print new image info - print_info(); + print_hdr(&boot.hdr); munmap(orig, size); close(fd); diff --git a/jni/magiskboot/bootimg.h b/jni/magiskboot/bootimg.h index 94c45d8ea..15f1c6fba 100644 --- a/jni/magiskboot/bootimg.h +++ b/jni/magiskboot/bootimg.h @@ -2,20 +2,21 @@ ** ** Copyright 2007, The Android Open Source Project ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at ** -** http://www.apache.org/licenses/LICENSE-2.0 +** http://www.apache.org/licenses/LICENSE-2.0 ** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and ** limitations under the License. */ #include +#include "magic.h" #ifndef _BOOT_IMAGE_H_ #define _BOOT_IMAGE_H_ @@ -64,12 +65,12 @@ struct boot_img_hdr } __attribute__((packed)); /* -** +-----------------+ +** +-----------------+ ** | boot header | 1 page ** +-----------------+ -** | kernel | n pages +** | kernel | n pages ** +-----------------+ -** | ramdisk | m pages +** | ramdisk | m pages ** +-----------------+ ** | second stage | o pages ** +-----------------+ @@ -99,4 +100,21 @@ typedef struct mtk_hdr { uint8_t name[32]; /* The type of the header */ } mtk_hdr; +// Flags +#define MTK_KERNEL 0x1 +#define MTK_RAMDISK 0x2 +#define APPEND_DTB 0x4 + +typedef struct boot_img { + boot_img_hdr hdr; + void *kernel; + void *ramdisk; + void *second; + void *dtb; + void *extra; + int flags; + file_t kernel_type, ramdisk_type; + mtk_hdr mtk_kernel_hdr, mtk_ramdisk_hdr; +} boot_img; + #endif diff --git a/jni/magiskboot/magiskboot.h b/jni/magiskboot/magiskboot.h index b0dae65f4..7bafdbd30 100644 --- a/jni/magiskboot/magiskboot.h +++ b/jni/magiskboot/magiskboot.h @@ -35,7 +35,7 @@ extern file_t SUP_TYPE_LIST[]; void unpack(const char *image); void repack(const char* orig_image, const char* out_image); void hexpatch(const char *image, const char *from, const char *to); -int parse_img(void *orig, size_t size); +int parse_img(void *orig, size_t size, boot_img *boot); int cpio_commands(const char *command, int argc, char *argv[]); void comp_file(const char *method, const char *from, const char *to); void decomp_file(char *from, const char *to);