Cleanup magiskboot

This commit is contained in:
topjohnwu 2017-04-28 03:15:48 +08:00
parent 76f81ece62
commit 727abbea8f
10 changed files with 129 additions and 485 deletions

View File

@ -4,12 +4,23 @@ include $(CLEAR_VARS)
LOCAL_MODULE := magiskboot LOCAL_MODULE := magiskboot
LOCAL_STATIC_LIBRARIES := libz liblzma liblz4 libbz2 LOCAL_STATIC_LIBRARIES := libz liblzma liblz4 libbz2
LOCAL_C_INCLUDES := \ LOCAL_C_INCLUDES := \
jni/utils \
jni/ndk-compression/zlib/ \ jni/ndk-compression/zlib/ \
jni/ndk-compression/xz/src/liblzma/api/ \ jni/ndk-compression/xz/src/liblzma/api/ \
jni/ndk-compression/lz4/lib/ \ jni/ndk-compression/lz4/lib/ \
jni/ndk-compression/bzip2/ jni/ndk-compression/bzip2/
LOCAL_SRC_FILES := main.c unpack.c repack.c hexpatch.c parseimg.c compress.c utils.c cpio.c sha1.c LOCAL_SRC_FILES := \
main.c \
unpack.c \
repack.c \
hexpatch.c \
parseimg.c \
compress.c \
utils.c \
cpio.c \
sha1.c \
../utils/vector.c
LOCAL_CFLAGS += -DZLIB_CONST LOCAL_CFLAGS += -DZLIB_CONST
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)

View File

@ -556,7 +556,7 @@ void comp_file(const char *method, const char *from, const char *to) {
} else if (strcmp(method, "bzip2") == 0) { } else if (strcmp(method, "bzip2") == 0) {
type = BZIP2; type = BZIP2;
} else { } else {
error(1, "Only support following methods: " SUP_LIST); error(1, "Only support following methods: ");
} }
unsigned char *file; unsigned char *file;
size_t size; size_t size;

View File

@ -1,5 +1,6 @@
#include "magiskboot.h" #include "magiskboot.h"
#include "cpio.h" #include "cpio.h"
#include "vector.h"
static uint32_t x8u(char *hex) { static uint32_t x8u(char *hex) {
uint32_t val, inpos = 8, outpos; uint32_t val, inpos = 8, outpos;
@ -25,13 +26,13 @@ static void cpio_free(cpio_file *f) {
} }
} }
static void cpio_vec_insert(vector *v, cpio_file *n) { static void cpio_vec_insert(struct vector *v, cpio_file *n) {
cpio_file *f, *t; cpio_file *f, *t;
int shift = 0; int shift = 0;
// Insert in alphabet order // Insert in alphabet order
vec_for_each(v, f) { vec_for_each(v, f) {
if (shift) { if (shift) {
vec_entry(v)[_i] = t; vec_entry(v)[_] = t;
t = f; t = f;
continue; continue;
} }
@ -39,11 +40,11 @@ static void cpio_vec_insert(vector *v, cpio_file *n) {
if (strcmp(f->filename, n->filename) == 0) { if (strcmp(f->filename, n->filename) == 0) {
// Replace, then all is done // Replace, then all is done
cpio_free(f); cpio_free(f);
vec_entry(v)[_i] = n; vec_entry(v)[_] = n;
return; return;
} else if (strcmp(f->filename, n->filename) > 0) { } else if (strcmp(f->filename, n->filename) > 0) {
// Insert, then start shifting // Insert, then start shifting
vec_entry(v)[_i] = n; vec_entry(v)[_] = n;
t = f; t = f;
shift = 1; shift = 1;
} }
@ -59,7 +60,7 @@ static int cpio_compare(const void *a, const void *b) {
} }
// Parse cpio file to a vector of cpio_file // Parse cpio file to a vector of cpio_file
static void parse_cpio(const char *filename, vector *v) { static void parse_cpio(const char *filename, struct vector *v) {
printf("Loading cpio: [%s]\n\n", filename); printf("Loading cpio: [%s]\n\n", filename);
int fd = open(filename, O_RDONLY); int fd = open(filename, O_RDONLY);
if (fd < 0) if (fd < 0)
@ -104,7 +105,7 @@ static void parse_cpio(const char *filename, vector *v) {
vec_sort(v, cpio_compare); vec_sort(v, cpio_compare);
} }
static void dump_cpio(const char *filename, vector *v) { static void dump_cpio(const char *filename, struct vector *v) {
printf("\nDump cpio: [%s]\n\n", filename); printf("\nDump cpio: [%s]\n\n", filename);
int fd = open_new(filename); int fd = open_new(filename);
unsigned inode = 300000; unsigned inode = 300000;
@ -143,7 +144,7 @@ static void dump_cpio(const char *filename, vector *v) {
close(fd); close(fd);
} }
static void cpio_vec_destroy(vector *v) { static void cpio_vec_destroy(struct vector *v) {
// Free each cpio_file // Free each cpio_file
cpio_file *f; cpio_file *f;
vec_for_each(v, f) { vec_for_each(v, f) {
@ -152,7 +153,7 @@ static void cpio_vec_destroy(vector *v) {
vec_destroy(v); vec_destroy(v);
} }
static void cpio_rm(int recursive, const char *entry, vector *v) { static void cpio_rm(int recursive, const char *entry, struct vector *v) {
cpio_file *f; cpio_file *f;
vec_for_each(v, f) { vec_for_each(v, f) {
if ((recursive && strncmp(f->filename, entry, strlen(entry)) == 0) if ((recursive && strncmp(f->filename, entry, strlen(entry)) == 0)
@ -166,7 +167,7 @@ static void cpio_rm(int recursive, const char *entry, vector *v) {
} }
} }
static void cpio_mkdir(mode_t mode, const char *entry, vector *v) { static void cpio_mkdir(mode_t mode, const char *entry, struct vector *v) {
cpio_file *f = calloc(sizeof(*f), 1); cpio_file *f = calloc(sizeof(*f), 1);
f->mode = S_IFDIR | mode; f->mode = S_IFDIR | mode;
f->namesize = strlen(entry) + 1; f->namesize = strlen(entry) + 1;
@ -176,7 +177,7 @@ static void cpio_mkdir(mode_t mode, const char *entry, vector *v) {
printf("Create directory [%s] (%04o)\n",entry, mode); printf("Create directory [%s] (%04o)\n",entry, mode);
} }
static void cpio_add(mode_t mode, const char *entry, const char *filename, vector *v) { static void cpio_add(mode_t mode, const char *entry, const char *filename, struct vector *v) {
int fd = open(filename, O_RDONLY); int fd = open(filename, O_RDONLY);
if (fd < 0) if (fd < 0)
error(1, "Cannot open %s", filename); error(1, "Cannot open %s", filename);
@ -194,7 +195,7 @@ static void cpio_add(mode_t mode, const char *entry, const char *filename, vecto
printf("Add entry [%s] (%04o)\n", entry, mode); printf("Add entry [%s] (%04o)\n", entry, mode);
} }
static void cpio_test(vector *v) { static void cpio_test(struct vector *v) {
#define MAGISK_PATCH 0x1 #define MAGISK_PATCH 0x1
#define SUPERSU_PATCH 0x2 #define SUPERSU_PATCH 0x2
int ret = 0; int ret = 0;
@ -221,7 +222,7 @@ static int check_verity_pattern(const char *s) {
return pos; return pos;
} }
static void cpio_dmverity(vector *v) { static void cpio_dmverity(struct vector *v) {
cpio_file *f; cpio_file *f;
size_t read, write; size_t read, write;
int skip; int skip;
@ -243,7 +244,7 @@ static void cpio_dmverity(vector *v) {
} }
} }
static void cpio_forceencrypt(vector *v) { static void cpio_forceencrypt(struct vector *v) {
cpio_file *f; cpio_file *f;
size_t read, write; size_t read, write;
#define ENCRYPT_LIST_SIZE 2 #define ENCRYPT_LIST_SIZE 2
@ -267,7 +268,7 @@ static void cpio_forceencrypt(vector *v) {
} }
} }
static void cpio_extract(const char *entry, const char *filename, vector *v) { static void cpio_extract(const char *entry, const char *filename, struct vector *v) {
cpio_file *f; cpio_file *f;
vec_for_each(v, f) { vec_for_each(v, f) {
if (strcmp(f->filename, entry) == 0 && S_ISREG(f->mode)) { if (strcmp(f->filename, entry) == 0 && S_ISREG(f->mode)) {
@ -283,8 +284,8 @@ static void cpio_extract(const char *entry, const char *filename, vector *v) {
error(1, "Cannot find the file entry [%s]", entry); error(1, "Cannot find the file entry [%s]", entry);
} }
static void cpio_backup(const char *orig, vector *v) { static void cpio_backup(const char *orig, struct vector *v) {
vector o_body, *o = &o_body, bak; struct vector o_body, *o = &o_body, bak;
cpio_file *m, *n, *dir, *rem; cpio_file *m, *n, *dir, *rem;
char chk1[21], chk2[21], buf[PATH_MAX]; char chk1[21], chk2[21], buf[PATH_MAX];
int res, doBak; int res, doBak;
@ -329,14 +330,14 @@ static void cpio_backup(const char *orig, vector *v) {
// Something is missing in new ramdisk, backup! // Something is missing in new ramdisk, backup!
++i; ++i;
doBak = 1; doBak = 1;
printf("Entry [%s] is missing\n", m->filename); printf("Backup missing entry: ");
} else if (res == 0) { } else if (res == 0) {
++i; ++j; ++i; ++j;
if (m->filesize == n->filesize && memcmp(m->data, n->data, m->filesize) == 0) if (m->filesize == n->filesize && memcmp(m->data, n->data, m->filesize) == 0)
continue; continue;
// Not the same! // Not the same!
doBak = 1; doBak = 1;
printf("Entry [%s] missmatch\n", m->filename); printf("Backup mismatch entry: ");
} else { } else {
// Someting new in ramdisk, record in rem // Someting new in ramdisk, record in rem
++j; ++j;
@ -344,13 +345,14 @@ static void cpio_backup(const char *orig, vector *v) {
rem->data = realloc(rem->data, rem->filesize + n->namesize); rem->data = realloc(rem->data, rem->filesize + n->namesize);
memcpy(rem->data + rem->filesize, n->filename, n->namesize); memcpy(rem->data + rem->filesize, n->filename, n->namesize);
rem->filesize += n->namesize; rem->filesize += n->namesize;
printf("Entry [%s] is new\n", n->filename); printf("Record new entry: [%s] -> [.backup/.rmlist]\n", n->filename);
} }
if (doBak) { if (doBak) {
m->namesize += 8; m->namesize += 8;
m->filename = realloc(m->filename, m->namesize); m->filename = realloc(m->filename, m->namesize);
strcpy(buf, m->filename); strcpy(buf, m->filename);
sprintf(m->filename, ".backup/%s", buf); sprintf(m->filename, ".backup/%s", buf);
printf("[%s] -> [%s]\n", buf, m->filename);
vec_push_back(&bak, m); vec_push_back(&bak, m);
// NULL the original entry, so it won't be freed // NULL the original entry, so it won't be freed
vec_entry(o)[i - 1] = NULL; vec_entry(o)[i - 1] = NULL;
@ -376,7 +378,7 @@ static void cpio_backup(const char *orig, vector *v) {
cpio_vec_destroy(o); cpio_vec_destroy(o);
} }
static int cpio_restore(vector *v) { static int cpio_restore(struct vector *v) {
cpio_file *f, *n; cpio_file *f, *n;
int ret = 1; int ret = 1;
vec_for_each(v, f) { vec_for_each(v, f) {
@ -441,7 +443,7 @@ int cpio_commands(const char *command, int argc, char *argv[]) {
cmd = NONE; cmd = NONE;
return 1; return 1;
} }
vector v; struct vector v;
vec_init(&v); vec_init(&v);
parse_cpio(incpio, &v); parse_cpio(incpio, &v);
switch(cmd) { switch(cmd) {

View File

@ -1,151 +0,0 @@
#ifndef _ELF_H_
#define _ELF_H_
#include <stdint.h>
/*
** ELF structure
**
** +-----------------+
** | ELF magic | | 4 bytes
** +------------ +
** | ELF class | | 1 byte
** +------------ +
** | ELF header |
** +-----------------+
** ~
** +-----------------+
** | program header | kernel info
** +-----------------+
** | program header | ramdisk info
** +-----------------+
** | program header | dtb info
** +-----------------+
** | program header | (possible) cmdline info
** +-----------------+
** ~
** +-----------------+
** | section header | cmdline info
** +-----------------+
** ~
** +-----------------+
** | |
** | Data |
** | |
** +-----------------+
*/
typedef uint32_t elf32_addr;
typedef uint16_t elf32_half;
typedef uint32_t elf32_off;
typedef uint32_t elf32_word;
typedef uint64_t elf64_addr;
typedef uint16_t elf64_half;
typedef uint64_t elf64_off;
typedef uint32_t elf64_word;
typedef uint64_t elf64_xword;
#define ELF_MAGIC "\x7f""ELF"
#define ELF_MAGIC_SIZE 4
#define EI_CLASS 4
#define EI_DATA 5
#define EI_VERSION 6
#define EI_OSABI 7
#define EI_PAD 8
#define ELFCLASSNONE 0
#define ELFCLASS32 1
#define ELFCLASS64 2
#define ELFCLASSNUM 3
#define ET_EXEC 2
#define EM_ARM 40
#define EI_NIDENT 16
typedef struct elf32_ehdr {
unsigned char e_ident[EI_NIDENT];
elf32_half e_type;
elf32_half e_machine;
elf32_word e_version;
elf32_addr e_entry; /* Entry point */
elf32_off e_phoff;
elf32_off e_shoff;
elf32_word e_flags;
elf32_half e_ehsize;
elf32_half e_phentsize;
elf32_half e_phnum;
elf32_half e_shentsize;
elf32_half e_shnum;
elf32_half e_shstrndx;
} elf32_ehdr;
typedef struct elf64_ehdr {
unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */
elf64_half e_type;
elf64_half e_machine;
elf64_word e_version;
elf64_addr e_entry; /* Entry point virtual address */
elf64_off e_phoff; /* Program header table file offset */
elf64_off e_shoff; /* Section header table file offset */
elf64_word e_flags;
elf64_half e_ehsize;
elf64_half e_phentsize;
elf64_half e_phnum;
elf64_half e_shentsize;
elf64_half e_shnum;
elf64_half e_shstrndx;
} elf64_ehdr;
typedef struct elf32_phdr {
elf32_word p_type;
elf32_off p_offset;
elf32_addr p_vaddr;
elf32_addr p_paddr;
elf32_word p_filesz;
elf32_word p_memsz;
elf32_word p_flags;
elf32_word p_align;
} elf32_phdr;
typedef struct elf64_phdr {
elf64_word p_type;
elf64_word p_flags;
elf64_off p_offset; /* Segment file offset */
elf64_addr p_vaddr; /* Segment virtual address */
elf64_addr p_paddr; /* Segment physical address */
elf64_xword p_filesz; /* Segment size in file */
elf64_xword p_memsz; /* Segment size in memory */
elf64_xword p_align; /* Segment alignment, file & memory */
} elf64_phdr;
typedef struct elf32_shdr {
elf32_word s_name;
elf32_word s_type;
elf32_word s_flags;
elf32_addr s_addr;
elf32_off s_offset;
elf32_word s_size;
elf32_word s_link;
elf32_word s_info;
elf32_word s_addralign;
elf32_word s_entsize;
} elf32_shdr;
typedef struct elf64_shdr {
elf64_word s_name; /* Section name, index in string tbl */
elf64_word s_type; /* Type of section */
elf64_xword s_flags; /* Miscellaneous section attributes */
elf64_addr s_addr; /* Section virtual addr at execution */
elf64_off s_offset; /* Section file offset */
elf64_xword s_size; /* Size of section in bytes */
elf64_word s_link; /* Index of another section */
elf64_word s_info; /* Additional section information */
elf64_xword s_addralign; /* Section alignment */
elf64_xword s_entsize; /* Entry size if section holds table */
} elf64_shdr;
#endif

View File

@ -17,7 +17,8 @@
#include "sha1.h" #include "sha1.h"
#define CHROMEOS_MAGIC "CHROMEOS" #define CHROMEOS_MAGIC "CHROMEOS"
#define CHROMEOS_MAGIC_SIZE 8 #define ELF32_MAGIC "\x7f""ELF\x01"
#define ELF64_MAGIC "\x7f""ELF\x02"
#define KERNEL_FILE "kernel" #define KERNEL_FILE "kernel"
#define RAMDISK_FILE "ramdisk.cpio" #define RAMDISK_FILE "ramdisk.cpio"
@ -25,11 +26,15 @@
#define DTB_FILE "dtb" #define DTB_FILE "dtb"
#define NEW_BOOT "new-boot.img" #define NEW_BOOT "new-boot.img"
#define str(a) #a
#define xstr(a) str(a)
typedef enum { typedef enum {
UNKNOWN, UNKNOWN,
CHROMEOS, CHROMEOS,
AOSP, AOSP,
ELF, ELF32,
ELF64,
GZIP, GZIP,
LZOP, LZOP,
XZ, XZ,
@ -37,8 +42,7 @@ typedef enum {
BZIP2, BZIP2,
LZ4, LZ4,
LZ4_LEGACY, LZ4_LEGACY,
MTK, MTK
QCDT,
} file_t; } file_t;
typedef enum { typedef enum {
@ -54,38 +58,14 @@ typedef enum {
RESTORE RESTORE
} command_t; } command_t;
#define SUP_LIST "gzip, xz, lzma, bzip2, lz4, lz4_legacy" extern char *SUP_LIST[];
#define SUP_NUM 6 extern char *SUP_EXT_LIST[];
extern file_t SUP_TYPE_LIST[];
// Cannot declare in header, but place a copy here for convenience
// char *SUP_EXT_LIST[SUP_NUM] = { "gz", "xz", "lzma", "bz2", "lz4", "lz4" };
// file_t SUP_TYPE_LIST[SUP_NUM] = { GZIP, XZ, LZMA, BZIP2, LZ4, LZ4_LEGACY };
extern char *SUP_EXT_LIST[SUP_NUM];
extern file_t SUP_TYPE_LIST[SUP_NUM];
// Vector
typedef struct vector {
size_t size;
size_t cap;
void **data;
} vector;
void vec_init(vector *v);
void vec_push_back(vector *v, void *p);
void vec_sort(vector *v, int (*compar)(const void *, const void *));
void vec_destroy(vector *v);
#define vec_size(v) (v)->size
#define vec_cap(v) (v)->cap
#define vec_entry(v) (v)->data
// vec_for_each(vector *v, void *e)
#define vec_for_each(v, e) \
e = (v)->data[0]; \
for (size_t _i = 0; _i < (v)->size; ++_i, e = (v)->data[_i])
// Global variables // Global variables
extern unsigned char *kernel, *ramdisk, *second, *dtb, *extra; extern unsigned char *kernel, *ramdisk, *second, *dtb, *extra;
extern boot_img_hdr hdr; extern boot_img_hdr hdr;
extern file_t boot_type, ramdisk_type, dtb_type; extern file_t ramdisk_type;
extern int mtk_kernel, mtk_ramdisk; extern int mtk_kernel, mtk_ramdisk;
// Main entries // Main entries

View File

@ -5,50 +5,55 @@
*********************/ *********************/
static void usage(char *arg0) { static void usage(char *arg0) {
fprintf(stderr, "%s --unpack <bootimg>\n", arg0); fprintf(stderr,
fprintf(stderr, " Unpack <bootimg> to kernel, ramdisk.cpio, (second), (dtb) into the\n current directory\n"); "%s --unpack <bootimg>\n"
fprintf(stderr, "\n"); " Unpack <bootimg> to kernel, ramdisk.cpio, (second), (dtb) into the\n current directory\n"
"\n"
fprintf(stderr, "%s --repack <origbootimg> [outbootimg]\n", arg0); "%s --repack <origbootimg> [outbootimg]\n"
fprintf(stderr, " Repack kernel, ramdisk.cpio[.ext], second, dtb... from current directory\n"); " Repack kernel, ramdisk.cpio[.ext], second, dtb... from current directory\n"
fprintf(stderr, " to [outbootimg], or new-boot.img if not specified.\n"); " to [outbootimg], or new-boot.img if not specified.\n"
fprintf(stderr, " It will compress ramdisk.cpio with the same method used in <origbootimg>\n"); " It will compress ramdisk.cpio with the same method used in <origbootimg>\n"
fprintf(stderr, " if exists, or attempt to find ramdisk.cpio.[ext], and repack\n"); " if exists, or attempt to find ramdisk.cpio.[ext], and repack\n"
fprintf(stderr, " directly with the compressed ramdisk file\n"); " directly with the compressed ramdisk file\n"
fprintf(stderr, "\n"); "\n"
"%s --hexpatch <file> <hexpattern1> <hexpattern2>\n"
fprintf(stderr, "%s --hexpatch <file> <hexpattern1> <hexpattern2>\n", arg0); " Search <hexpattern1> in <file>, and replace with <hexpattern2>\n"
fprintf(stderr, " Search <hexpattern1> in <file>, and replace with <hexpattern2>\n"); "\n"
fprintf(stderr, "\n"); "%s --cpio-<cmd> <incpio> [flags...] [params...]\n"
" Do cpio related cmds to <incpio> (modifications are done directly)\n Supported commands:\n"
fprintf(stderr, "%s --cpio-<cmd> <incpio> [flags...] [params...]\n", arg0); " --cpio-rm <incpio> [-r] <entry>\n Remove entry from cpio, flag -r to remove recursively\n"
fprintf(stderr, " Do cpio related cmds to <incpio> (modifications are done directly)\n Supported commands:\n"); " --cpio-mkdir <incpio> <mode> <entry>\n Create directory as an <entry>\n"
fprintf(stderr, " --cpio-rm <incpio> [-r] <entry>\n Remove entry from cpio, flag -r to remove recursively\n"); " --cpio-add <incpio> <mode> <entry> <infile>\n Add <infile> as an <entry>; replaces <entry> if already exists\n"
fprintf(stderr, " --cpio-mkdir <incpio> <mode> <entry>\n Create directory as an <entry>\n"); " --cpio-extract <incpio> <entry> <outfile>\n Extract <entry> to <outfile>\n"
fprintf(stderr, " --cpio-add <incpio> <mode> <entry> <infile>\n Add <infile> as an <entry>; replaces <entry> if already exists\n"); " --cpio-test <incpio>\n Return value: 0/not patched 1/Magisk 2/SuperSU\n"
fprintf(stderr, " --cpio-extract <incpio> <entry> <outfile>\n Extract <entry> to <outfile>\n"); " --cpio-patch-dmverity <incpio>\n Remove dm-verity\n"
fprintf(stderr, " --cpio-test <incpio>\n Return value: 0/not patched 1/Magisk 2/SuperSU\n"); " --cpio-patch-forceencrypt <incpio>\n Change forceencrypt flag to encryptable\n"
fprintf(stderr, " --cpio-patch-dmverity <incpio>\n Remove dm-verity\n"); " --cpio-backup <incpio> <origcpio>\n Create ramdisk backups into <incpio> from <origcpio>\n"
fprintf(stderr, " --cpio-patch-forceencrypt <incpio>\n Change forceencrypt flag to encryptable\n"); " --cpio-restore <incpio>\n Restore ramdisk from ramdisk backup within <incpio>\n"
fprintf(stderr, " --cpio-backup <incpio> <origcpio>\n Create ramdisk backups into <incpio> from <origcpio>\n"); "\n"
fprintf(stderr, " --cpio-restore <incpio>\n Restore ramdisk from ramdisk backup within <incpio>\n"); "%s --compress[=method] <infile> [outfile]\n"
fprintf(stderr, "\n"); " Compress <infile> with [method] (default: gzip), optionally to [outfile]\n Supported methods: "
, arg0, arg0, arg0, arg0, arg0);
fprintf(stderr, "%s --compress[=method] <infile> [outfile]\n", arg0); for (int i = 0; SUP_LIST[i]; ++i)
fprintf(stderr, " Compress <infile> with [method] (default: gzip), optionally to [outfile]\n Supported methods: " SUP_LIST "\n"); fprintf(stderr, "%s ", SUP_LIST[i]);
fprintf(stderr, "\n"); fprintf(stderr,
"\n"
fprintf(stderr, "%s --decompress <infile> [outfile]\n", arg0); "\n"
fprintf(stderr, " Detect method and decompress <infile>, optionally to [outfile]\n Supported methods: " SUP_LIST "\n"); "%s --decompress <infile> [outfile]\n"
fprintf(stderr, "\n"); " Detect method and decompress <infile>, optionally to [outfile]\n Supported methods: "
, arg0);
fprintf(stderr, "%s --sha1 <file>\n", arg0); for (int i = 0; SUP_LIST[i]; ++i)
fprintf(stderr, " Print the SHA1 checksum for <file>\n"); fprintf(stderr, "%s ", SUP_LIST[i]);
fprintf(stderr, "\n"); fprintf(stderr,
"\n"
fprintf(stderr, "%s --cleanup\n", arg0); "\n"
fprintf(stderr, " Cleanup the current working directory\n"); "%s --sha1 <file>\n"
fprintf(stderr, "\n"); " Print the SHA1 checksum for <file>\n"
"\n"
"%s --cleanup\n"
" Cleanup the current working directory\n"
"\n"
, arg0, arg0);
exit(1); exit(1);
} }
@ -63,7 +68,7 @@ void error(int rc, const char *msg, ...) {
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
printf("MagiskBoot (by topjohnwu) - Boot Image Modification Tool\n\n"); printf("MagiskBoot v" xstr(MAGISK_VERSION) " (by topjohnwu) - Boot Image Modification Tool\n\n");
if (argc > 1 && strcmp(argv[1], "--cleanup") == 0) { if (argc > 1 && strcmp(argv[1], "--cleanup") == 0) {
cleanup(); cleanup();

View File

@ -1,11 +1,10 @@
#include "bootimg.h" #include "bootimg.h"
#include "elf.h"
#include "magiskboot.h" #include "magiskboot.h"
unsigned char *kernel, *ramdisk, *second, *dtb, *extra; unsigned char *kernel, *ramdisk, *second, *dtb, *extra;
boot_img_hdr hdr; boot_img_hdr hdr;
int mtk_kernel = 0, mtk_ramdisk = 0; int mtk_kernel = 0, mtk_ramdisk = 0;
file_t boot_type, ramdisk_type, dtb_type; file_t ramdisk_type;
static void check_headers() { static void check_headers() {
// Check ramdisk compression type // Check ramdisk compression type
@ -22,174 +21,13 @@ static void check_headers() {
ramdisk_type = check_type(ramdisk + 512); ramdisk_type = check_type(ramdisk + 512);
} }
// Check dtb if ELF boot
if (boot_type == ELF && hdr.dt_size) {
dtb_type = check_type(dtb);
}
// Print info // Print info
print_info(); print_info();
} }
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");
}
static void elf_set(int i, unsigned char *base, size_t size, size_t offset, size_t addr) {
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;
}
}
static void parse_elf(unsigned char *base) {
// Reset boot image header
memset(&hdr, 0, sizeof(hdr));
// Hardcode header magic and pagesize
memcpy(hdr.magic, BOOT_MAGIC, BOOT_MAGIC_SIZE);
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) {
elf_set(i, base, ph32[i].p_filesz, ph32[i].p_offset, ph32[i].p_paddr);
}
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) {
elf_set(i, base, ph64[i].p_filesz, ph64[i].p_offset, ph64[i].p_paddr);
}
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!");
}
check_headers();
}
static void parse_aosp(unsigned char *base, size_t size) { static void parse_aosp(unsigned char *base, size_t size) {
printf("IMG [AOSP]\n"); // printf("IMG [AOSP]\n");
size_t pos = 0; size_t pos = 0;
@ -233,17 +71,17 @@ void parse_img(unsigned char *orig, size_t size) {
for(base = orig, end = orig + size; base < end; base += 256, size -= 256) { for(base = orig, end = orig + size; base < end; base += 256, size -= 256) {
switch (check_type(base)) { switch (check_type(base)) {
case CHROMEOS: case CHROMEOS:
boot_type = CHROMEOS; // The caller should know it's chromeos, as it needs additional signing
close(open_new("chromeos"));
continue; continue;
case AOSP: case ELF32:
// Don't override CHROMEOS exit(2);
if (boot_type != CHROMEOS)
boot_type = AOSP;
parse_aosp(base, size);
return; return;
case ELF: case ELF64:
boot_type = ELF; exit(3);
parse_elf(base); return;
case AOSP:
parse_aosp(base, size);
return; return;
default: default:
continue; continue;

View File

@ -69,7 +69,7 @@ void repack(const char* orig_image, const char* out_image) {
// If we found raw cpio, compress to original format // If we found raw cpio, compress to original format
// Before we start, clean up previous compressed files // Before we start, clean up previous compressed files
for (int i = 0; i < SUP_NUM; ++i) { for (int i = 0; SUP_EXT_LIST[i]; ++i) {
sprintf(name, "%s.%s", RAMDISK_FILE, SUP_EXT_LIST[i]); sprintf(name, "%s.%s", RAMDISK_FILE, SUP_EXT_LIST[i]);
unlink(name); unlink(name);
} }
@ -85,7 +85,7 @@ void repack(const char* orig_image, const char* out_image) {
} }
int found = 0; int found = 0;
for (int i = 0; i < SUP_NUM; ++i) { for (int i = 0; SUP_EXT_LIST[i]; ++i) {
sprintf(name, "%s.%s", RAMDISK_FILE, SUP_EXT_LIST[i]); sprintf(name, "%s.%s", RAMDISK_FILE, SUP_EXT_LIST[i]);
if (access(name, R_OK) == 0) { if (access(name, R_OK) == 0) {
ramdisk_type = SUP_TYPE_LIST[i]; ramdisk_type = SUP_TYPE_LIST[i];

View File

@ -16,11 +16,6 @@ void unpack(const char* image) {
printf("Parsing boot image: [%s]\n\n", image); printf("Parsing boot image: [%s]\n\n", image);
parse_img(orig, size); parse_img(orig, size);
if (boot_type == CHROMEOS) {
// The caller should know it's chromeos, as it needs additional signing
dump(orig, 0, "chromeos");
}
char name[PATH_MAX]; char name[PATH_MAX];
// Dump kernel // Dump kernel
@ -47,17 +42,9 @@ void unpack(const char* image) {
} }
if (hdr.dt_size) { if (hdr.dt_size) {
if (boot_type == ELF && (dtb_type != QCDT && dtb_type != ELF)) {
printf("Non QC dtb found in ELF kernel, recreate kernel\n");
gzip(1, KERNEL_FILE, kernel, hdr.kernel_size);
int kfp = open(KERNEL_FILE, O_WRONLY | O_APPEND);
write(kfp, dtb, hdr.dt_size);
close(kfp);
} else {
// Dump dtb // Dump dtb
dump(dtb, hdr.dt_size, DTB_FILE); dump(dtb, hdr.dt_size, DTB_FILE);
} }
}
munmap(orig, size); munmap(orig, size);
} }

View File

@ -1,8 +1,8 @@
#include "magiskboot.h" #include "magiskboot.h"
#include "elf.h"
char *SUP_EXT_LIST[SUP_NUM] = { "gz", "xz", "lzma", "bz2", "lz4", "lz4" }; char *SUP_LIST[] = { "gzip", "xz", "lzma", "bzip2", "lz4", "lz4_legacy", NULL };
file_t SUP_TYPE_LIST[SUP_NUM] = { GZIP, XZ, LZMA, BZIP2, LZ4, LZ4_LEGACY }; char *SUP_EXT_LIST[] = { "gz", "xz", "lzma", "bz2", "lz4", "lz4", NULL };
file_t SUP_TYPE_LIST[] = { GZIP, XZ, LZMA, BZIP2, LZ4, LZ4_LEGACY, 0 };
void mmap_ro(const char *filename, unsigned char **buf, size_t *size) { void mmap_ro(const char *filename, unsigned char **buf, size_t *size) {
int fd = open(filename, O_RDONLY); int fd = open(filename, O_RDONLY);
@ -25,12 +25,14 @@ void mmap_rw(const char *filename, unsigned char **buf, size_t *size) {
} }
file_t check_type(const unsigned char *buf) { file_t check_type(const unsigned char *buf) {
if (memcmp(buf, CHROMEOS_MAGIC, CHROMEOS_MAGIC_SIZE) == 0) { if (memcmp(buf, CHROMEOS_MAGIC, 8) == 0) {
return CHROMEOS; return CHROMEOS;
} else if (memcmp(buf, BOOT_MAGIC, BOOT_MAGIC_SIZE) == 0) { } else if (memcmp(buf, BOOT_MAGIC, BOOT_MAGIC_SIZE) == 0) {
return AOSP; return AOSP;
} else if (memcmp(buf, ELF_MAGIC, ELF_MAGIC_SIZE) == 0) { } else if (memcmp(buf, ELF32_MAGIC, 5) == 0) {
return ELF; return ELF32;
} else if (memcmp(buf, ELF64_MAGIC, 5) == 0) {
return ELF64;
} else if (memcmp(buf, "\x1f\x8b\x08\x00", 4) == 0) { } else if (memcmp(buf, "\x1f\x8b\x08\x00", 4) == 0) {
return GZIP; return GZIP;
} else if (memcmp(buf, "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a", 9) == 0) { } else if (memcmp(buf, "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a", 9) == 0) {
@ -48,8 +50,6 @@ file_t check_type(const unsigned char *buf) {
return LZ4_LEGACY; return LZ4_LEGACY;
} else if (memcmp(buf, "\x88\x16\x88\x58", 4) == 0) { } else if (memcmp(buf, "\x88\x16\x88\x58", 4) == 0) {
return MTK; return MTK;
} else if (memcmp(buf, "QCDT", 4) == 0) {
return QCDT;
} else { } else {
return UNKNOWN; return UNKNOWN;
} }
@ -147,36 +147,8 @@ void cleanup() {
unlink(SECOND_FILE); unlink(SECOND_FILE);
unlink(DTB_FILE); unlink(DTB_FILE);
unlink(NEW_BOOT); unlink(NEW_BOOT);
for (int i = 0; i < SUP_NUM; ++i) { for (int i = 0; SUP_EXT_LIST[i]; ++i) {
sprintf(name, "%s.%s", RAMDISK_FILE, SUP_EXT_LIST[i]); sprintf(name, "%s.%s", RAMDISK_FILE, SUP_EXT_LIST[i]);
unlink(name); unlink(name);
} }
} }
void vec_init(vector *v) {
vec_size(v) = 0;
vec_cap(v) = 1;
vec_entry(v) = malloc(sizeof(void*));
}
void vec_push_back(vector *v, void *p) {
if (v == NULL) return;
if (vec_size(v) == vec_cap(v)) {
vec_cap(v) *= 2;
vec_entry(v) = realloc(vec_entry(v), sizeof(void*) * vec_cap(v));
}
vec_entry(v)[vec_size(v)] = p;
++vec_size(v);
}
void vec_sort(vector *v, int (*compar)(const void *, const void *)) {
qsort(vec_entry(v), vec_size(v), sizeof(void*), compar);
}
void vec_destroy(vector *v) {
// Will not free each entry!
// Manually free each entry, then call this function
vec_size(v) = 0;
vec_cap(v) = 0;
free(v->data);
}