Add compress, decompress, cleanup command

This commit is contained in:
topjohnwu 2017-03-05 01:50:36 +08:00
parent 65dc99744e
commit a4ce9f6f05
7 changed files with 212 additions and 86 deletions

View File

@ -359,6 +359,7 @@ int decomp(file_t type, const char *to, const unsigned char *from, size_t size)
return 0; return 0;
} }
// Output will be to.ext
int comp(file_t type, const char *to, const 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]; char name[PATH_MAX];
switch (type) { switch (type) {
@ -388,3 +389,75 @@ int comp(file_t type, const char *to, const unsigned char *from, size_t size) {
} }
return 0; return 0;
} }
void decomp_file(char *from) {
int ok = 1;
unsigned char *file;
size_t size;
mmap_ro(from, &file, &size);
file_t type = check_type(file);
char *ext;
ext = strrchr(from, '.');
if (ext == NULL)
error(1, "Bad filename extention");
// File type and extension should match
switch (type) {
case GZIP:
if (strcmp(ext, ".gz") != 0)
ok = 0;
break;
case XZ:
if (strcmp(ext, ".xz") != 0)
ok = 0;
break;
case LZMA:
if (strcmp(ext, ".lzma") != 0)
ok = 0;
break;
case BZIP2:
if (strcmp(ext, ".bz2") != 0)
ok = 0;
break;
case LZ4:
if (strcmp(ext, ".lz4") != 0)
ok = 0;
break;
default:
error(1, "Provided file \'%s\' is not a supported archive format", from);
}
if (ok) {
// If all match, strip out the suffix
*ext = '\0';
decomp(type, from, file, size);
*ext = '.';
unlink(from);
} else {
error(1, "Bad filename extention \'%s\'", ext);
}
munmap(file, size);
}
void comp_file(const char *method, const char *from) {
file_t type;
if (strcmp(method, "gzip") == 0) {
type = GZIP;
} else if (strcmp(method, "xz") == 0) {
type = XZ;
} else if (strcmp(method, "lzma") == 0) {
type = LZMA;
} else if (strcmp(method, "lz4") == 0) {
type = LZ4;
} else if (strcmp(method, "bzip2") == 0) {
type = BZIP2;
} else {
error(1, "Only support following methods: " SUP_LIST);
}
unsigned char *file;
size_t size;
mmap_ro(from, &file, &size);
comp(type, from, file, size);
munmap(file, size);
unlink(from);
}

View File

@ -28,6 +28,10 @@
#define RAMDISK_FILE "ramdisk.cpio" #define RAMDISK_FILE "ramdisk.cpio"
#define SECOND_FILE "second" #define SECOND_FILE "second"
#define DTB_FILE "dtb" #define DTB_FILE "dtb"
#define NEW_BOOT "new-boot.img"
#define SUP_LIST "gzip, xz, lzma, lz4, bzip2"
#define SUP_NUM 5
typedef enum { typedef enum {
UNKNOWN, UNKNOWN,
@ -44,6 +48,12 @@ typedef enum {
QCDT, QCDT,
} file_t; } file_t;
extern char *SUP_EXT_LIST[SUP_NUM];
extern file_t SUP_TYPE_LIST[SUP_NUM];
// Cannot declare in header, but place a copy here for convenience
// char *SUP_EXT_LIST[SUP_NUM] = { "gz", "xz", "lzma", "bz2", "lz4" };
// file_t SUP_TYPE_LIST[SUP_NUM] = { GZIP, XZ, LZMA, BZIP2, LZ4 };
// Global variables // Global variables
extern unsigned char *kernel, *ramdisk, *second, *dtb; extern unsigned char *kernel, *ramdisk, *second, *dtb;
extern boot_img_hdr hdr; extern boot_img_hdr hdr;
@ -57,6 +67,7 @@ void hexpatch(const char *image, const char *from, const char *to);
void cpio(const char *filename); void cpio(const char *filename);
void error(int rc, const char *msg, ...); void error(int rc, const char *msg, ...);
void parse_img(unsigned char *orig, size_t size); void parse_img(unsigned char *orig, size_t size);
void cleanup();
// Compressions // Compressions
void gzip(int mode, const char* filename, const unsigned char* buf, size_t size); void gzip(int mode, const char* filename, const unsigned char* buf, size_t size);
@ -64,7 +75,9 @@ 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 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); 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 comp(file_t type, const char *to, const unsigned char *from, size_t size);
void comp_file(const char *method, const char *from);
int decomp(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);
void decomp_file(char *from);
// Utils // Utils
void mmap_ro(const char *filename, unsigned char **buf, size_t *size); void mmap_ro(const char *filename, unsigned char **buf, size_t *size);
@ -73,5 +86,6 @@ file_t check_type(const unsigned char *buf);
void mem_align(size_t *pos, size_t align); void mem_align(size_t *pos, size_t align);
void file_align(int fd, size_t align); void file_align(int fd, size_t align);
int open_new(const char *filename); int open_new(const char *filename);
void print_info();
#endif #endif

View File

@ -1,8 +1,3 @@
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "magiskboot.h" #include "magiskboot.h"
/******************** /********************
@ -10,13 +5,23 @@
*********************/ *********************/
static void usage(char *arg0) { static void usage(char *arg0) {
fprintf(stderr, "Boot Image Unpack/Repack Tool\n"); fprintf(stderr, "\n");
fprintf(stderr, "%s --unpack <bootimage>\n", arg0); fprintf(stderr, "%s --unpack <bootimage>\n", arg0);
fprintf(stderr, " Unpack <bootimage> into current directory\n\n"); fprintf(stderr, " Unpack <bootimage> to kernel, ramdisk.cpio, (second), (dtb) into the\n current directory\n\n");
fprintf(stderr, "%s --repack <bootimage>\n", arg0); fprintf(stderr, "%s --repack <bootimage>\n", arg0);
fprintf(stderr, " Repack kernel, dtb, ramdisk... from current directory to new-image.img\n <bootimage> is the image you've just unpacked\n\n"); fprintf(stderr, " Repack kernel, ramdisk.cpio[.ext], second, dtb... from current directory\n");
fprintf(stderr, "%s --hexpatch <bootimage> <hexpattern1> <hexpattern2>\n", arg0); fprintf(stderr, " to new-image.img. <bootimage> is the original boot image you've just unpacked.\n");
fprintf(stderr, " Search <hexpattern1> in <bootimage>, and replace with <hexpattern2>\n\n"); fprintf(stderr, " If file ramdisk.cpio exists, it will auto re-compress with the same method\n");
fprintf(stderr, " used in <bootimage>, or it will attempt to find ramdisk.cpio.[ext], and repack\n");
fprintf(stderr, " directly with the compressed file\n\n");
fprintf(stderr, "%s --hexpatch <file> <hexpattern1> <hexpattern2>\n", arg0);
fprintf(stderr, " Search <hexpattern1> in <file>, and replace with <hexpattern2>\n\n");
fprintf(stderr, "%s --compress[=method] <file>\n", arg0);
fprintf(stderr, " Compress <file> with [method], or gzip if not specified.\n Supported methods: " SUP_LIST "\n\n");
fprintf(stderr, "%s --decompress <file>\n", arg0);
fprintf(stderr, " Auto check file type, and decompress <file> accordingly\n Supported methods: " SUP_LIST "\n\n");
fprintf(stderr, "%s --cleanup\n", arg0);
fprintf(stderr, " Cleanup the current working directory\n\n");
exit(1); exit(1);
} }
@ -30,21 +35,34 @@ void error(int rc, const char *msg, ...) {
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
if (argc < 3) printf("MagiskBoot (by topjohnwu) - Boot Image Modification Tool\n");
usage(argv[0]); if (argc < 3) {
if (strcmp(argv[1], "--cleanup") == 0) {
if (strcmp(argv[1], "--unpack") == 0) { cleanup();
unpack(argv[2]); } else {
} else if (strcmp(argv[1], "--repack") == 0) {
repack(argv[2]);
} else if (strcmp(argv[1], "--hexpatch") == 0) {
if (argc < 5)
usage(argv[0]); usage(argv[0]);
hexpatch(argv[2], argv[3], argv[4]); }
} else { } else {
usage(argv[0]); if (strcmp(argv[1], "--unpack") == 0) {
unpack(argv[2]);
} else if (strcmp(argv[1], "--repack") == 0) {
repack(argv[2]);
} else if (strcmp(argv[1], "--hexpatch") == 0) {
if (argc < 5)
usage(argv[0]);
hexpatch(argv[2], argv[3], argv[4]);
} else if (strcmp(argv[1], "--decompress") == 0) {
decomp_file(argv[2]);
} else if (strstr(argv[1], "--compress") != NULL) {
char *method;
method = strchr(argv[1], '=');
if (method == NULL) method = "gzip";
else method++;
comp_file(method, argv[2]);
} else {
usage(argv[0]);
}
} }
return 0; return 0;
} }

View File

@ -8,54 +8,9 @@ int mtk_kernel = 0, mtk_ramdisk = 0;
file_t boot_type, ramdisk_type, dtb_type; file_t boot_type, ramdisk_type, dtb_type;
static void check_headers() { static void check_headers() {
printf("KERNEL [%d] @ 0x%08x\n", hdr.kernel_size, hdr.kernel_addr); // Check ramdisk compression type
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);
ramdisk_type = check_type(ramdisk); ramdisk_type = check_type(ramdisk);
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!");
}
// Check MTK // Check MTK
if (check_type(kernel) == MTK) { if (check_type(kernel) == MTK) {
printf("MTK header found in kernel\n"); printf("MTK header found in kernel\n");
@ -70,6 +25,9 @@ static void check_headers() {
if (boot_type == ELF && hdr.dt_size) { if (boot_type == ELF && hdr.dt_size) {
dtb_type = check_type(dtb); dtb_type = check_type(dtb);
} }
// Print info
print_info();
} }
static void elf_header_check(void *elf, int is64) { static void elf_header_check(void *elf, int is64) {

View File

@ -24,17 +24,16 @@ void repack(const char* image) {
size_t size; size_t size;
unsigned char *orig; unsigned char *orig;
char name[PATH_MAX]; char name[PATH_MAX];
#define EXT_NUM 6
char *ext_list[EXT_NUM] = { "gz", "lzo", "xz", "lzma", "bz2", "lz4" };
// Load original image // Load original image
mmap_ro(image, &orig, &size); mmap_ro(image, &orig, &size);
// Parse original image // Parse original image
printf("\nParsing boot image: [%s]\n\n", image);
parse_img(orig, size); parse_img(orig, size);
// Create new image // Create new image
int fd = open_new("new-boot.img"); int fd = open_new(NEW_BOOT);
// Set all sizes to 0 // Set all sizes to 0
hdr.kernel_size = 0; hdr.kernel_size = 0;
@ -62,27 +61,34 @@ void repack(const char* image) {
if (access(RAMDISK_FILE, R_OK) == 0) { if (access(RAMDISK_FILE, R_OK) == 0) {
// 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
for (int i = 0; i < SUP_NUM; ++i) {
sprintf(name, "%s.%s", RAMDISK_FILE, SUP_EXT_LIST[i]);
unlink(name);
}
size_t cpio_size; size_t cpio_size;
unsigned char *cpio; unsigned char *cpio;
mmap_ro(RAMDISK_FILE, &cpio, &cpio_size); mmap_ro(RAMDISK_FILE, &cpio, &cpio_size);
if (comp(ramdisk_type, RAMDISK_FILE, cpio, cpio_size)) if (comp(ramdisk_type, RAMDISK_FILE, cpio, cpio_size))
error(1, "Unsupported format! Please compress manually!"); error(1, "Unsupported ramdisk format!");
munmap(cpio, cpio_size); munmap(cpio, cpio_size);
} }
int found = 0; int found = 0;
for (int i = 0; i < EXT_NUM; ++i) { for (int i = 0; i < SUP_NUM; ++i) {
sprintf(name, "%s.%s", RAMDISK_FILE, 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];
found = 1; found = 1;
break; break;
} }
} }
if (!found) if (!found)
error(1, "No ramdisk exists!"); error(1, "No ramdisk exists!");
hdr.ramdisk_size += restore(name, fd); hdr.ramdisk_size += restore(name, fd);
file_align(fd, hdr.page_size); file_align(fd, hdr.page_size);
@ -99,6 +105,8 @@ void repack(const char* image) {
} }
// Write header back // Write header back
printf("\nRepack to boot image: [%s]\n\n", NEW_BOOT);
print_info();
lseek(fd, 0, SEEK_SET); lseek(fd, 0, SEEK_SET);
write(fd, &hdr, sizeof(hdr)); write(fd, &hdr, sizeof(hdr));

View File

@ -13,6 +13,7 @@ void unpack(const char* image) {
mmap_ro(image, &orig, &size); mmap_ro(image, &orig, &size);
// Parse image // Parse image
printf("\nParsing boot image: [%s]\n\n", image);
parse_img(orig, size); parse_img(orig, size);
if (boot_type == CHROMEOS) { if (boot_type == CHROMEOS) {
@ -34,19 +35,10 @@ void unpack(const char* image) {
ramdisk += 512; ramdisk += 512;
hdr.ramdisk_size -= 512; hdr.ramdisk_size -= 512;
} }
if (decomp(ramdisk_type, RAMDISK_FILE, ramdisk, hdr.ramdisk_size)) { if (decomp(ramdisk_type, RAMDISK_FILE, ramdisk, hdr.ramdisk_size)) {
printf("Unsupported format! Please decompress manually!\n");
switch (ramdisk_type) {
case LZOP:
sprintf(name, "%s.%s", RAMDISK_FILE, "lzo");
break;
default:
// Never happens
break;
}
// Dump the compressed ramdisk // Dump the compressed ramdisk
dump(ramdisk, hdr.ramdisk_size, name); dump(ramdisk, hdr.ramdisk_size, RAMDISK_FILE ".unsupport");
error(1, "Unsupported ramdisk format! Dumped to %s", RAMDISK_FILE ".unsupport");
} }
if (hdr.second_size) { if (hdr.second_size) {

View File

@ -1,6 +1,9 @@
#include "magiskboot.h" #include "magiskboot.h"
#include "elf.h" #include "elf.h"
char *SUP_EXT_LIST[SUP_NUM] = { "gz", "xz", "lzma", "bz2", "lz4" };
file_t SUP_TYPE_LIST[SUP_NUM] = { GZIP, XZ, LZMA, BZIP2, LZ4 };
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);
if (fd < 0) if (fd < 0)
@ -75,3 +78,63 @@ int open_new(const char *filename) {
error(1, "Unable to create %s", filename); error(1, "Unable to create %s", filename);
return fd; return fd;
} }
void print_info() {
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);
switch (ramdisk_type) {
case GZIP:
printf("COMPRESSION [%s]\n", "gzip");
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:
fprintf(stderr, "Unknown ramdisk format!\n");
}
}
void cleanup() {
printf("Cleaning up...\n");
char name[PATH_MAX];
unlink(KERNEL_FILE);
unlink(RAMDISK_FILE);
unlink(RAMDISK_FILE ".unsupport");
unlink(SECOND_FILE);
unlink(DTB_FILE);
unlink(NEW_BOOT);
for (int i = 0; i < SUP_NUM; ++i) {
sprintf(name, "%s.%s", RAMDISK_FILE, SUP_EXT_LIST[i]);
unlink(name);
}
}