Add kernel decompression and appended dtb support

This commit is contained in:
topjohnwu 2017-09-12 22:09:10 +08:00
parent 59c1125e72
commit 6b41653a32
3 changed files with 161 additions and 132 deletions

View File

@ -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);

View File

@ -16,6 +16,7 @@
*/
#include <stdint.h>
#include "magic.h"
#ifndef _BOOT_IMAGE_H_
#define _BOOT_IMAGE_H_
@ -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

View File

@ -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);