Magisk/jni/magiskboot/parseimg.c

291 lines
6.6 KiB
C
Raw Normal View History

2017-02-24 19:29:12 +00:00
#include "bootimg.h"
#include "elf.h"
2017-02-27 21:37:47 +00:00
#include "magiskboot.h"
2017-02-24 19:29:12 +00:00
2017-03-04 13:16:59 +00:00
unsigned char *kernel, *ramdisk, *second, *dtb;
2017-02-27 21:37:47 +00:00
boot_img_hdr hdr;
int mtk_kernel = 0, mtk_ramdisk = 0;
file_t boot_type, ramdisk_type, dtb_type;
static void check_headers() {
2017-02-24 19:29:12 +00:00
printf("KERNEL [%d] @ 0x%08x\n", hdr.kernel_size, hdr.kernel_addr);
printf("RAMDISK [%d] @ 0x%08x\n", hdr.ramdisk_size, hdr.ramdisk_addr);
printf("SECOND [%d] @ 0x%08x\n", hdr.second_size, hdr.second_addr);
printf("DTB [%d] @ 0x%08x\n", hdr.dt_size, hdr.tags_addr);
printf("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;
a = (os_version >> 14) & 0x7f;
b = (os_version >> 7) & 0x7f;
c = os_version & 0x7f;
printf("OS_VERSION [%d.%d.%d]\n", a, b, c);
y = (os_patch_level >> 4) + 2000;
m = os_patch_level & 0xf;
printf("PATCH_LEVEL [%d-%02d]\n", y, m);
}
printf("NAME [%s]\n", hdr.name);
printf("CMDLINE [%s]\n", hdr.cmdline);
2017-02-27 21:37:47 +00:00
2017-03-02 13:59:37 +00:00
ramdisk_type = check_type(ramdisk);
2017-02-27 21:37:47 +00:00
2017-03-02 13:59:37 +00:00
switch (ramdisk_type) {
case GZIP:
printf("COMPRESSION [%s]\n", "gzip");
break;
case LZOP:
printf("COMPRESSION [%s]\n", "lzop");
break;
case XZ:
printf("COMPRESSION [%s]\n", "xz");
break;
case LZMA:
printf("COMPRESSION [%s]\n", "lzma");
break;
case BZIP2:
printf("COMPRESSION [%s]\n", "bzip2");
break;
case LZ4:
printf("COMPRESSION [%s]\n", "lz4");
break;
default:
error(1, "Unknown ramdisk format!");
2017-02-27 21:37:47 +00:00
}
// Check MTK
2017-03-02 13:59:37 +00:00
if (check_type(kernel) == MTK) {
2017-02-27 21:37:47 +00:00
printf("MTK header found in kernel\n");
mtk_kernel = 1;
}
2017-03-02 13:59:37 +00:00
if (check_type(ramdisk) == MTK) {
2017-02-27 21:37:47 +00:00
printf("MTK header found in ramdisk\n");
2017-02-28 16:50:49 +00:00
mtk_ramdisk = 1;
2017-02-27 21:37:47 +00:00
}
2017-03-02 13:59:37 +00:00
// Check dtb if ELF boot
2017-02-27 21:37:47 +00:00
if (boot_type == ELF && hdr.dt_size) {
2017-03-02 13:59:37 +00:00
dtb_type = check_type(dtb);
2017-02-27 21:37:47 +00:00
}
2017-02-24 19:29:12 +00:00
}
static void elf_header_check(void *elf, int is64) {
size_t e_size, mach, ver, p_size, p_num, s_size, s_num;
size_t r_e_size, r_p_size, r_s_size;
if (is64) {
e_size = ((elf64_ehdr *) elf)->e_ehsize;
mach = ((elf64_ehdr *) elf)->e_machine;
ver = ((elf64_ehdr *) elf)->e_version;
p_size = ((elf64_ehdr *) elf)->e_phentsize;
p_num = ((elf64_ehdr *) elf)->e_phnum;
s_size = ((elf64_ehdr *) elf)->e_shentsize;
s_num = ((elf64_ehdr *) elf)->e_shnum;
r_e_size = sizeof(elf64_ehdr);
r_p_size = sizeof(elf64_phdr);
r_s_size = sizeof(elf64_shdr);
} else {
e_size = ((elf32_ehdr *) elf)->e_ehsize;
mach = ((elf32_ehdr *) elf)->e_machine;
ver = ((elf32_ehdr *) elf)->e_version;
p_size = ((elf32_ehdr *) elf)->e_phentsize;
p_num = ((elf32_ehdr *) elf)->e_phnum;
s_size = ((elf32_ehdr *) elf)->e_shentsize;
s_num = ((elf32_ehdr *) elf)->e_shnum;
r_e_size = sizeof(elf32_ehdr);
r_p_size = sizeof(elf32_phdr);
r_s_size = sizeof(elf32_shdr);
}
if (e_size != r_e_size)
error(1, "Header size not %d", r_e_size);
if (mach != EM_ARM)
error(1, "ELF machine is not ARM");
if (ver != 1)
error(1, "Unknown ELF version");
if (p_size != r_p_size)
error(1, "Program header size not %d", r_p_size);
if (p_num < 2 || p_num > 4)
error(1, "Unexpected number of elements: %d", p_num);
if (s_num && s_size != r_s_size)
error(1, "Section header size not %d", r_s_size);
if (s_num > 1)
error(1, "More than one section header");
}
2017-03-04 13:16:59 +00:00
static void elf_set(int i, unsigned char *base, size_t size, size_t offset, size_t addr) {
2017-02-24 19:29:12 +00:00
if (size <= 4096) {
// Possible cmdline
memset(hdr.cmdline, 0, BOOT_ARGS_SIZE);
strncpy((char *) hdr.cmdline, (char *) (base + offset), BOOT_ARGS_SIZE);
hdr.cmdline[strcspn((char*) hdr.cmdline, "\n")] = '\0';
return;
}
switch(i) {
case 0:
// kernel
kernel = base + offset;
hdr.kernel_size = size;
hdr.kernel_addr = addr;
break;
case 1:
// ramdisk
ramdisk = base + offset;
hdr.ramdisk_size = size;
hdr.ramdisk_addr = addr;
break;
case 2:
// dtb
dtb = base + offset;
hdr.dt_size = size;
hdr.tags_addr = addr;
break;
}
}
2017-03-04 13:16:59 +00:00
static void parse_elf(unsigned char *base) {
2017-02-24 19:29:12 +00:00
// Reset boot image header
memset(&hdr, 0, sizeof(hdr));
2017-02-28 16:15:38 +00:00
// Hardcode header magic and pagesize
memcpy(hdr.magic, BOOT_MAGIC, BOOT_MAGIC_SIZE);
2017-02-24 19:29:12 +00:00
hdr.page_size = 4096;
switch(base[EI_CLASS]) {
case ELFCLASS32: {
elf32_ehdr *elf32;
elf32_phdr *ph32;
elf32_shdr *sh32;
printf("IMAGE [ELF32]\n");
elf32 = (elf32_ehdr *) base;
elf_header_check(elf32, 0);
ph32 = (elf32_phdr *) (base + elf32->e_phoff);
sh32 = (elf32_shdr *) (base + elf32->e_shoff);
for (int i = 0; i < elf32->e_phnum; ++i) {
2017-03-04 13:16:59 +00:00
elf_set(i, base, ph32[i].p_filesz, ph32[i].p_offset, ph32[i].p_paddr);
2017-02-24 19:29:12 +00:00
}
if (elf32->e_shnum) {
// cmdline
memset(hdr.cmdline, 0, BOOT_ARGS_SIZE);
strncpy((char *) hdr.cmdline, (char *) (base + sh32->s_offset + 8), BOOT_ARGS_SIZE);
hdr.cmdline[strcspn((char*) hdr.cmdline, "\n")] = '\0';
}
break;
}
case ELFCLASS64: {
elf64_ehdr *elf64;
elf64_phdr *ph64;
elf64_shdr *sh64;
printf("IMAGE [ELF64]\n");
elf64 = (elf64_ehdr *) base;
elf_header_check(elf64, 1);
ph64 = (elf64_phdr *) (base + elf64->e_phoff);
sh64 = (elf64_shdr *) (base + elf64->e_shoff);
for (int i = 0; i < elf64->e_phnum; ++i) {
2017-03-04 13:16:59 +00:00
elf_set(i, base, ph64[i].p_filesz, ph64[i].p_offset, ph64[i].p_paddr);
2017-02-24 19:29:12 +00:00
}
if (elf64->e_shnum) {
// cmdline
memset(hdr.cmdline, 0, BOOT_ARGS_SIZE);
strncpy((char *) hdr.cmdline, (char *) (base + sh64->s_offset + 8), BOOT_ARGS_SIZE);
hdr.cmdline[strcspn((char*) hdr.cmdline, "\n")] = '\0';
}
break;
}
default:
error(1, "ELF format error!");
}
2017-02-27 21:37:47 +00:00
check_headers();
2017-02-24 19:29:12 +00:00
}
2017-03-04 13:16:59 +00:00
static void parse_aosp(unsigned char *base) {
2017-02-24 19:29:12 +00:00
printf("IMG [AOSP]\n");
2017-03-04 13:16:59 +00:00
size_t pos = 0;
2017-02-24 19:29:12 +00:00
// Read the header
2017-03-04 13:16:59 +00:00
memcpy(&hdr, base, sizeof(hdr));
2017-02-24 19:29:12 +00:00
pos += hdr.page_size;
// Kernel position
2017-03-04 13:16:59 +00:00
kernel = base + pos;
2017-02-24 19:29:12 +00:00
pos += hdr.kernel_size;
2017-03-04 13:16:59 +00:00
mem_align(&pos, hdr.page_size);
2017-02-24 19:29:12 +00:00
// Ramdisk position
2017-03-04 13:16:59 +00:00
ramdisk = base + pos;
2017-02-24 19:29:12 +00:00
pos += hdr.ramdisk_size;
2017-03-04 13:16:59 +00:00
mem_align(&pos, hdr.page_size);
2017-02-24 19:29:12 +00:00
if (hdr.second_size) {
// Second position
2017-03-04 13:16:59 +00:00
second = base + pos;
2017-02-24 19:29:12 +00:00
pos += hdr.second_size;
2017-03-04 13:16:59 +00:00
mem_align(&pos, hdr.page_size);
2017-02-24 19:29:12 +00:00
}
if (hdr.dt_size) {
// dtb position
2017-03-04 13:16:59 +00:00
dtb = base + pos;
2017-02-24 19:29:12 +00:00
pos += hdr.dt_size;
2017-03-04 13:16:59 +00:00
mem_align(&pos, hdr.page_size);
2017-02-24 19:29:12 +00:00
}
2017-02-27 21:37:47 +00:00
check_headers();
}
void parse_img(unsigned char *orig, size_t size) {
2017-03-04 13:16:59 +00:00
unsigned char *base;
2017-02-27 21:37:47 +00:00
for(base = orig; base < (orig + size); base += 256) {
2017-03-02 13:59:37 +00:00
switch (check_type(base)) {
case CHROMEOS:
boot_type = CHROMEOS;
continue;
case AOSP:
// Don't override CHROMEOS
if (boot_type != CHROMEOS)
boot_type = AOSP;
2017-03-04 13:16:59 +00:00
parse_aosp(base);
2017-03-02 13:59:37 +00:00
return;
case ELF:
boot_type = ELF;
2017-03-04 13:16:59 +00:00
parse_elf(base);
2017-03-02 13:59:37 +00:00
return;
default:
continue;
2017-02-27 21:37:47 +00:00
}
}
2017-02-28 16:15:38 +00:00
error(1, "No boot image magic found!");
2017-02-27 21:37:47 +00:00
}