Separate utility functions

This commit is contained in:
topjohnwu 2017-03-04 21:16:59 +08:00
parent 9f91c8b59d
commit c6d4740b0c
8 changed files with 180 additions and 179 deletions

View File

@ -4,14 +4,16 @@ include $(CLEAR_VARS)
LOCAL_MODULE := magiskboot
LOCAL_STATIC_LIBRARIES := liblzma liblz4 libbz2
LOCAL_C_INCLUDES := \
jni/ndk-compression/zlib/ \
jni/ndk-compression/xz/src/liblzma/api/ \
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
LOCAL_SRC_FILES := main.c unpack.c repack.c hexpatch.c parseimg.c compress.c utils.c cpio.c
LOCAL_LDLIBS += -lz
include $(BUILD_EXECUTABLE)
include jni/ndk-compression/zlib/Android.mk
include jni/ndk-compression/xz/src/liblzma/Android.mk
include jni/ndk-compression/lz4/lib/Android.mk
include jni/ndk-compression/bzip2/Android.mk

View File

@ -5,13 +5,6 @@
#include "magiskboot.h"
static int open_new(const char *filename) {
int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd < 0)
error(1, "Unable to create %s", filename);
return fd;
}
static void write_file(const int fd, const void *buf, const size_t size, const char *filename) {
if (write(fd, buf, size) != size)
error(1, "Error in writing %s", filename);
@ -29,7 +22,7 @@ static void report(const int mode, const char* filename) {
}
// Mode: 0 = decode; 1 = encode
void gzip(int mode, const char* filename, unsigned char* buf, size_t size) {
void gzip(int mode, const char* filename, const unsigned char* buf, size_t size) {
size_t ret = 0, flush, have, pos = 0;
z_stream strm;
unsigned char out[CHUNK];
@ -100,7 +93,7 @@ void gzip(int mode, const char* filename, unsigned char* buf, size_t size) {
// Mode: 0 = decode xz/lzma; 1 = encode xz; 2 = encode lzma
void lzma(int mode, const char* filename, unsigned char* buf, size_t size) {
void lzma(int mode, const char* filename, const unsigned char* buf, size_t size) {
size_t have, pos = 0;
lzma_ret ret = 0;
lzma_stream strm = LZMA_STREAM_INIT;
@ -164,7 +157,7 @@ void lzma(int mode, const char* filename, unsigned char* buf, size_t size) {
}
// Mode: 0 = decode; 1 = encode
void lz4(int mode, const char* filename, unsigned char* buf, size_t size) {
void lz4(int mode, const char* filename, const unsigned char* buf, size_t size) {
LZ4F_decompressionContext_t dctx;
LZ4F_compressionContext_t cctx;
LZ4F_frameInfo_t info;
@ -275,7 +268,7 @@ void lz4(int mode, const char* filename, unsigned char* buf, size_t size) {
}
// Mode: 0 = decode; 1 = encode
void bzip2(int mode, const char* filename, unsigned char* buf, size_t size) {
void bzip2(int mode, const char* filename, const unsigned char* buf, size_t size) {
size_t ret = 0, action, have, pos = 0;
bz_stream strm;
char out[CHUNK];
@ -342,7 +335,7 @@ void bzip2(int mode, const char* filename, unsigned char* buf, size_t size) {
close(fd);
}
int decomp(file_t type, const char *to, unsigned char *from, size_t size) {
int decomp(file_t type, const char *to, const unsigned char *from, size_t size) {
switch (type) {
case GZIP:
gzip(0, to, from, size);
@ -366,7 +359,7 @@ int decomp(file_t type, const char *to, unsigned char *from, size_t size) {
return 0;
}
int comp(file_t type, const char *to, unsigned char *from, size_t size) {
int comp(file_t type, const char *to, const unsigned char *from, size_t size) {
char name[PATH_MAX];
switch (type) {
case GZIP:

View File

@ -14,7 +14,7 @@ static unsigned hex2ascii(char c, char d) {
return high + low;
}
static void hexstr2str(char *hex, unsigned char *str) {
static void hexstr2str(const char *hex, unsigned char *str) {
char buf = 0;
for(int i = 0, length = strlen(hex); i < length; ++i){
if(i % 2){
@ -25,12 +25,11 @@ static void hexstr2str(char *hex, unsigned char *str) {
}
}
void hexpatch(char * image, char *from, char *to) {
int fd = open(image, O_RDWR), patternsize = strlen(from) / 2, patchsize = strlen(to) / 2;
size_t filesize = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
void hexpatch(const char *image, const char *from, const char *to) {
int patternsize = strlen(from) / 2, patchsize = strlen(to) / 2;
size_t filesize;
unsigned char *file, *pattern, *patch;
file = mmap(NULL, filesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
mmap_rw(image, &file, &filesize);
pattern = malloc(patternsize);
patch = malloc(patchsize);
hexstr2str(from, pattern);
@ -46,5 +45,4 @@ void hexpatch(char * image, char *from, char *to) {
munmap(file, filesize);
free(pattern);
free(patch);
close(fd);
}

View File

@ -45,7 +45,7 @@ typedef enum {
} file_t;
// Global variables
extern unsigned char *base, *kernel, *ramdisk, *second, *dtb;
extern unsigned char *kernel, *ramdisk, *second, *dtb;
extern boot_img_hdr hdr;
extern file_t boot_type, ramdisk_type, dtb_type;
extern int mtk_kernel, mtk_ramdisk;
@ -53,17 +53,25 @@ extern int mtk_kernel, mtk_ramdisk;
// Main entries
void unpack(const char *image);
void repack(const char *image);
void hexpatch(char *image, char *from, char *to);
void hexpatch(const char *image, const char *from, const char *to);
void cpio(const char *filename);
void error(int rc, const char *msg, ...);
void parse_img(unsigned char *orig, size_t size);
file_t check_type(unsigned char *buf);
// Compressions
void gzip(int mode, const char* filename, unsigned char* buf, size_t size);
void lzma(int mode, const char* filename, unsigned char* buf, size_t size);
void lz4(int mode, const char* filename, unsigned char* buf, size_t size);
void bzip2(int mode, const char* filename, unsigned char* buf, size_t size);
int comp(file_t type, const char *to, unsigned char *from, size_t size);
int decomp(file_t type, const char *to, unsigned char *from, size_t size);
void gzip(int mode, const char* filename, const unsigned char* buf, size_t size);
void lzma(int mode, const char* filename, const unsigned char* buf, size_t size);
void lz4(int mode, const char* filename, const unsigned char* buf, size_t size);
void bzip2(int mode, const char* filename, const unsigned char* buf, size_t size);
int comp(file_t type, const char *to, const unsigned char *from, size_t size);
int decomp(file_t type, const char *to, const unsigned char *from, size_t size);
// Utils
void mmap_ro(const char *filename, unsigned char **buf, size_t *size);
void mmap_rw(const char *filename, unsigned char **buf, size_t *size);
file_t check_type(const unsigned char *buf);
void mem_align(size_t *pos, size_t align);
void file_align(int fd, size_t align);
int open_new(const char *filename);
#endif

View File

@ -1,49 +1,12 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include "bootimg.h"
#include "elf.h"
#include "magiskboot.h"
unsigned char *base, *kernel, *ramdisk, *second, *dtb;
unsigned char *kernel, *ramdisk, *second, *dtb;
boot_img_hdr hdr;
int mtk_kernel = 0, mtk_ramdisk = 0;
file_t boot_type, ramdisk_type, dtb_type;
file_t check_type(unsigned char *buf) {
if (memcmp(buf, CHROMEOS_MAGIC, CHROMEOS_MAGIC_SIZE) == 0) {
return CHROMEOS;
} else if (memcmp(buf, BOOT_MAGIC, BOOT_MAGIC_SIZE) == 0) {
return AOSP;
} else if (memcmp(buf, ELF_MAGIC, ELF_MAGIC_SIZE) == 0) {
return ELF;
} else if (memcmp(buf, "\x1f\x8b\x08\x00", 4) == 0) {
return GZIP;
} else if (memcmp(buf, "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a", 9) == 0) {
return LZOP;
} else if (memcmp(buf, "\xfd""7zXZ\x00", 6) == 0) {
return XZ;
} else if (memcmp(buf, "\x5d\x00\x00", 3) == 0
&& (buf[12] == (unsigned char) '\xff' || buf[12] == (unsigned char) '\x00')) {
return LZMA;
} else if (memcmp(buf, "BZh", 3) == 0) {
return BZIP2;
} else if ( ( memcmp(buf, "\x04\x22\x4d\x18", 4) == 0
|| memcmp(buf, "\x03\x21\x4c\x18", 4) == 0)
|| memcmp(buf, "\x02\x21\x4c\x18", 4) == 0) {
return LZ4;
} else if (memcmp(buf, "\x88\x16\x88\x58", 4) == 0) {
return MTK;
} else if (memcmp(buf, "QCDT", 4) == 0) {
return QCDT;
} else {
return UNKNOWN;
}
}
static void check_headers() {
printf("KERNEL [%d] @ 0x%08x\n", hdr.kernel_size, hdr.kernel_addr);
printf("RAMDISK [%d] @ 0x%08x\n", hdr.ramdisk_size, hdr.ramdisk_addr);
@ -109,13 +72,6 @@ static void check_headers() {
}
}
static void page_align(unsigned char **pos) {
uint32_t itemsize = *pos - base, pagemask = hdr.page_size - 1L;
if (itemsize & pagemask) {
*pos += hdr.page_size - (itemsize & pagemask);
}
}
static void elf_header_check(void *elf, int is64) {
size_t e_size, mach, ver, p_size, p_num, s_size, s_num;
@ -167,7 +123,7 @@ static void elf_header_check(void *elf, int is64) {
error(1, "More than one section header");
}
static void elf_set(int i, size_t size, size_t offset, size_t addr) {
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);
@ -197,7 +153,7 @@ static void elf_set(int i, size_t size, size_t offset, size_t addr) {
}
}
static void parse_elf() {
static void parse_elf(unsigned char *base) {
// Reset boot image header
memset(&hdr, 0, sizeof(hdr));
@ -224,7 +180,7 @@ static void parse_elf() {
sh32 = (elf32_shdr *) (base + elf32->e_shoff);
for (int i = 0; i < elf32->e_phnum; ++i) {
elf_set(i, ph32[i].p_filesz, ph32[i].p_offset, ph32[i].p_paddr);
elf_set(i, base, ph32[i].p_filesz, ph32[i].p_offset, ph32[i].p_paddr);
}
if (elf32->e_shnum) {
@ -253,7 +209,7 @@ static void parse_elf() {
sh64 = (elf64_shdr *) (base + elf64->e_shoff);
for (int i = 0; i < elf64->e_phnum; ++i) {
elf_set(i, ph64[i].p_filesz, ph64[i].p_offset, ph64[i].p_paddr);
elf_set(i, base, ph64[i].p_filesz, ph64[i].p_offset, ph64[i].p_paddr);
}
if (elf64->e_shnum) {
@ -272,44 +228,45 @@ static void parse_elf() {
check_headers();
}
static void parse_aosp() {
static void parse_aosp(unsigned char *base) {
printf("IMG [AOSP]\n");
unsigned char *pos = base;
size_t pos = 0;
// Read the header
memcpy(&hdr, pos, sizeof(hdr));
memcpy(&hdr, base, sizeof(hdr));
pos += hdr.page_size;
// Kernel position
kernel = pos;
kernel = base + pos;
pos += hdr.kernel_size;
page_align(&pos);
mem_align(&pos, hdr.page_size);
// Ramdisk position
ramdisk = pos;
ramdisk = base + pos;
pos += hdr.ramdisk_size;
page_align(&pos);
mem_align(&pos, hdr.page_size);
if (hdr.second_size) {
// Second position
second = pos;
second = base + pos;
pos += hdr.second_size;
page_align(&pos);
mem_align(&pos, hdr.page_size);
}
if (hdr.dt_size) {
// dtb position
dtb = pos;
dtb = base + pos;
pos += hdr.dt_size;
page_align(&pos);
mem_align(&pos, hdr.page_size);
}
check_headers();
}
void parse_img(unsigned char *orig, size_t size) {
unsigned char *base;
for(base = orig; base < (orig + size); base += 256) {
switch (check_type(base)) {
case CHROMEOS:
@ -319,11 +276,11 @@ void parse_img(unsigned char *orig, size_t size) {
// Don't override CHROMEOS
if (boot_type != CHROMEOS)
boot_type = AOSP;
parse_aosp();
parse_aosp(base);
return;
case ELF:
boot_type = ELF;
parse_elf();
parse_elf(base);
return;
default:
continue;

View File

@ -1,61 +1,41 @@
#include "magiskboot.h"
// Global pointer of output
static int ofd, opos;
static size_t restore(const char *filename, int fd) {
int ifd = open(filename, O_RDONLY);
if (ifd < 0)
error(1, "Cannot open %s\n", filename);
static size_t restore(const char *filename) {
int fd = open(filename, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "Cannot open %s\n", filename);
exit(1);
size_t size = lseek(ifd, 0, SEEK_END);
lseek(ifd, 0, SEEK_SET);
if (sendfile(fd, ifd, NULL, size) != size) {
error(1, "Cannot write %s\n", filename);
}
size_t size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
if (sendfile(ofd, fd, NULL, size) < 0) {
fprintf(stderr, "Cannot write %s\n", filename);
exit(1);
}
close(fd);
opos += size;
close(ifd);
return size;
}
static void restore_buf(size_t size, const void *buf) {
if (write(ofd, buf, size) != size) {
fprintf(stderr, "Cannot dump from input file\n");
exit(1);
static void restore_buf(const void *buf, size_t size, int fd) {
if (write(fd, buf, size) != size) {
error(1, "Cannot dump from input file\n");
}
opos += size;
}
static void page_align() {
uint32_t pagemask = hdr.page_size - 1L;
if (opos & pagemask) {
opos += hdr.page_size - (opos & pagemask);
}
ftruncate(ofd, opos);
lseek(ofd, 0, SEEK_END);
}
void repack(const char* image) {
// Load original image
int ifd = open(image, O_RDONLY);
if (ifd < 0)
error(1, "Cannot open %s", image);
size_t isize = lseek(ifd, 0, SEEK_END);
lseek(ifd, 0, SEEK_SET);
unsigned char *orig = mmap(NULL, isize, PROT_READ, MAP_SHARED, ifd, 0);
// Parse original image
parse_img(orig, isize);
// Create new boot image
ofd = open("new-boot.img", O_RDWR | O_CREAT | O_TRUNC, 0644);
size_t size;
unsigned char *orig;
char name[PATH_MAX];
#define EXT_NUM 6
char *ext_list[EXT_NUM] = { "gz", "lzo", "xz", "lzma", "bz2", "lz4" };
// Load original image
mmap_ro(image, &orig, &size);
// Parse original image
parse_img(orig, size);
// Create new image
int fd = open_new("new-boot.img");
// Set all sizes to 0
hdr.kernel_size = 0;
hdr.ramdisk_size = 0;
@ -63,39 +43,33 @@ void repack(const char* image) {
hdr.dt_size = 0;
// Skip a page for header
ftruncate(ofd, hdr.page_size);
lseek(ofd, 0, SEEK_END);
opos += hdr.page_size;
ftruncate(fd, hdr.page_size);
lseek(fd, 0, SEEK_END);
// Restore kernel
if (mtk_kernel) {
restore_buf(512, kernel);
restore_buf(kernel, 512, fd);
hdr.kernel_size += 512;
}
hdr.kernel_size += restore(KERNEL_FILE);
page_align();
hdr.kernel_size += restore(KERNEL_FILE, fd);
file_align(fd, hdr.page_size);
// Restore ramdisk
if (mtk_ramdisk) {
restore_buf(512, ramdisk);
restore_buf(ramdisk, 512, fd);
hdr.ramdisk_size += 512;
}
if (access(RAMDISK_FILE, R_OK) == 0) {
// If we found raw cpio, compress to original format
int rfd = open(RAMDISK_FILE, O_RDONLY);
if (rfd < 0)
error(1, "Cannot open " RAMDISK_FILE);
size_t cpio_size = lseek(rfd, 0, SEEK_END);
lseek(rfd, 0, SEEK_SET);
unsigned char *cpio = mmap(NULL, cpio_size, PROT_READ, MAP_SHARED, rfd, 0);
size_t cpio_size;
unsigned char *cpio;
mmap_ro(RAMDISK_FILE, &cpio, &cpio_size);
if (comp(ramdisk_type, RAMDISK_FILE, cpio, cpio_size))
error(1, "Unsupported format! Please compress manually!\n");
error(1, "Unsupported format! Please compress manually!");
munmap(cpio, cpio_size);
close(rfd);
}
int found = 0;
@ -109,29 +83,28 @@ void repack(const char* image) {
if (!found)
error(1, "No ramdisk exists!");
hdr.ramdisk_size += restore(name);
page_align();
hdr.ramdisk_size += restore(name, fd);
file_align(fd, hdr.page_size);
// Restore second
if (access(SECOND_FILE, R_OK) == 0) {
hdr.second_size += restore(SECOND_FILE);
page_align();
hdr.second_size += restore(SECOND_FILE, fd);
file_align(fd, hdr.page_size);
}
// Restore dtb
if (access(DTB_FILE, R_OK) == 0) {
hdr.dt_size += restore(DTB_FILE);
page_align();
hdr.dt_size += restore(DTB_FILE, fd);
file_align(fd, hdr.page_size);
}
// Write header back
lseek(ofd, 0, SEEK_SET);
write(ofd, &hdr, sizeof(hdr));
lseek(fd, 0, SEEK_SET);
write(fd, &hdr, sizeof(hdr));
munmap(orig, isize);
close(ifd);
close(ofd);
if (opos > isize) {
munmap(orig, size);
if (lseek(fd, 0, SEEK_CUR) > size) {
error(2, "Boot partition too small!");
}
close(fd);
}

View File

@ -1,29 +1,23 @@
#include "magiskboot.h"
static void dump(unsigned char *buf, size_t size, const char *filename) {
int ofd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (ofd < 0)
error(1, "Cannot open %s", filename);
if (write(ofd, buf, size) != size)
int fd = open_new(filename);
if (write(fd, buf, size) != size)
error(1, "Cannot dump %s", filename);
close(ofd);
close(fd);
}
void unpack(const char* image) {
int fd = open(image, O_RDONLY);
if (fd < 0)
error(1, "Cannot open %s", image);
size_t size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
unsigned char *orig = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
size_t size;
unsigned char *orig;
mmap_ro(image, &orig, &size);
// Parse image
parse_img(orig, size);
if (boot_type == CHROMEOS) {
// The caller should know it's chromeos, as it needs additional signing
dump(base, 0, "chromeos");
dump(orig, 0, "chromeos");
}
char name[PATH_MAX];
@ -74,6 +68,5 @@ void unpack(const char* image) {
}
munmap(orig, size);
close(fd);
}

77
jni/magiskboot/utils.c Normal file
View File

@ -0,0 +1,77 @@
#include "magiskboot.h"
#include "elf.h"
void mmap_ro(const char *filename, unsigned char **buf, size_t *size) {
int fd = open(filename, O_RDONLY);
if (fd < 0)
error(1, "Cannot open %s", filename);
*size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
*buf = mmap(NULL, *size, PROT_READ, MAP_SHARED, fd, 0);
close(fd);
}
void mmap_rw(const char *filename, unsigned char **buf, size_t *size) {
int fd = open(filename, O_RDWR);
if (fd < 0)
error(1, "Cannot open %s", filename);
*size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
*buf = mmap(NULL, *size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
}
file_t check_type(const unsigned char *buf) {
if (memcmp(buf, CHROMEOS_MAGIC, CHROMEOS_MAGIC_SIZE) == 0) {
return CHROMEOS;
} else if (memcmp(buf, BOOT_MAGIC, BOOT_MAGIC_SIZE) == 0) {
return AOSP;
} else if (memcmp(buf, ELF_MAGIC, ELF_MAGIC_SIZE) == 0) {
return ELF;
} else if (memcmp(buf, "\x1f\x8b\x08\x00", 4) == 0) {
return GZIP;
} else if (memcmp(buf, "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a", 9) == 0) {
return LZOP;
} else if (memcmp(buf, "\xfd""7zXZ\x00", 6) == 0) {
return XZ;
} else if (memcmp(buf, "\x5d\x00\x00", 3) == 0
&& (buf[12] == (unsigned char) '\xff' || buf[12] == (unsigned char) '\x00')) {
return LZMA;
} else if (memcmp(buf, "BZh", 3) == 0) {
return BZIP2;
} else if ( ( memcmp(buf, "\x04\x22\x4d\x18", 4) == 0
|| memcmp(buf, "\x03\x21\x4c\x18", 4) == 0)
|| memcmp(buf, "\x02\x21\x4c\x18", 4) == 0) {
return LZ4;
} else if (memcmp(buf, "\x88\x16\x88\x58", 4) == 0) {
return MTK;
} else if (memcmp(buf, "QCDT", 4) == 0) {
return QCDT;
} else {
return UNKNOWN;
}
}
void mem_align(size_t *pos, size_t align) {
size_t mask = align - 1;
if (*pos & mask) {
*pos += align - (*pos & mask);
}
}
void file_align(int fd, size_t align) {
size_t pos = lseek(fd, 0, SEEK_CUR);
size_t mask = align - 1;
if (pos & mask) {
pos += align - (pos & mask);
ftruncate(fd, pos);
lseek(fd, 0, SEEK_END);
}
}
int open_new(const char *filename) {
int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd < 0)
error(1, "Unable to create %s", filename);
return fd;
}