From 5aced279d6ca5b64a4b74f399426a59f8a81347a Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Wed, 29 Mar 2017 04:09:59 +0800 Subject: [PATCH] Add legacy lz4 mode support --- jni/magiskboot/compress.c | 92 +++++++++++++++++++++++++++++++++++++ jni/magiskboot/magiskboot.h | 22 ++++----- jni/magiskboot/main.c | 2 +- jni/magiskboot/utils.c | 13 ++++-- 4 files changed, 109 insertions(+), 20 deletions(-) diff --git a/jni/magiskboot/compress.c b/jni/magiskboot/compress.c index ea85d43e0..b2f7aa66a 100644 --- a/jni/magiskboot/compress.c +++ b/jni/magiskboot/compress.c @@ -1,10 +1,20 @@ #include #include +#include #include #include #include "magiskboot.h" +#define windowBits 15 +#define ZLIB_GZIP 16 +#define memLevel 8 +#define CHUNK 0x40000 + +#define LZ4_HEADER_SIZE 19 +#define LZ4_FOOTER_SIZE 4 +#define LZ4_LEGACY_BLOCKSIZE 0x800000 + 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); @@ -154,6 +164,7 @@ void lzma(int mode, const char* filename, const unsigned char* buf, size_t size) } while (pos < size); lzma_end(&strm); + close(fd); } // Mode: 0 = decode; 1 = encode @@ -265,6 +276,7 @@ void lz4(int mode, const char* filename, const unsigned char* buf, size_t size) } free(out); + close(fd); } // Mode: 0 = decode; 1 = encode @@ -335,6 +347,75 @@ void bzip2(int mode, const char* filename, const unsigned char* buf, size_t size close(fd); } +// Mode: 0 = decode; 1 = encode +void lz4_legacy(int mode, const char* filename, const unsigned char* buf, size_t size) { + size_t pos = 0; + int have; + char *out; + unsigned block_size, insize; + unsigned char block_size_le[4]; + + + report(mode, filename); + int fd = open_new(filename); + + switch(mode) { + case 0: + out = malloc(LZ4_LEGACY_BLOCKSIZE); + // Skip magic + pos += 4; + break; + case 1: + out = malloc(LZ4_COMPRESSBOUND(LZ4_LEGACY_BLOCKSIZE)); + // Write magic + write_file(fd, "\x02\x21\x4c\x18", 4, filename); + break; + default: + error(1, "Unsupported lz4_legacy mode!"); + } + + if (!out) + error(1, "lz4_legacy malloc error"); + + do { + switch(mode) { + case 0: + block_size = buf[pos]; + block_size += (buf[pos + 1]<<8); + block_size += (buf[pos + 2]<<16); + block_size += ((unsigned)buf[pos + 3])<<24; + pos += 4; + if (block_size > LZ4_COMPRESSBOUND(LZ4_LEGACY_BLOCKSIZE)) + error(1, "lz4_legacy block size too large!"); + have = LZ4_decompress_safe((const char*) (buf + pos), out, block_size, LZ4_LEGACY_BLOCKSIZE); + if (have < 0) + error(1, "Cannot decode lz4_legacy block"); + pos += block_size; + break; + case 1: + if (pos + LZ4_LEGACY_BLOCKSIZE >= size) + insize = size - pos; + else + insize = LZ4_LEGACY_BLOCKSIZE; + have = LZ4_compress_default((const char*) (buf + pos), out, insize, LZ4_COMPRESSBOUND(LZ4_LEGACY_BLOCKSIZE)); + if (have == 0) + error(1, "lz4_legacy compression error"); + pos += insize; + block_size_le[0] = (unsigned char)have; + block_size_le[1] = (unsigned char)(have >> 8); + block_size_le[2] = (unsigned char)(have >> 16); + block_size_le[3] = (unsigned char)(have >> 24); + write_file(fd, block_size_le, 4, filename); + break; + } + // Write main data + write_file(fd, out, have, filename); + } while(pos < size); + + free(out); + close(fd); +} + int decomp(file_t type, const char *to, const unsigned char *from, size_t size) { switch (type) { case GZIP: @@ -352,6 +433,9 @@ int decomp(file_t type, const char *to, const unsigned char *from, size_t size) case LZ4: lz4(0, to, from, size); break; + case LZ4_LEGACY: + lz4_legacy(0, to, from, size); + break; default: // Unsupported return 1; @@ -391,6 +475,11 @@ int comp(file_t type, const char *to, const unsigned char *from, size_t size) { sprintf(name, "%s.%s", to, "lz4"); lz4(1, name, from, size); break; + case LZ4_LEGACY: + if (strcmp(ext, ".lz4") != 0) + sprintf(name, "%s.%s", to, "lz4"); + lz4_legacy(1, name, from, size); + break; default: // Unsupported return 1; @@ -427,6 +516,7 @@ void decomp_file(char *from, const char *to) { if (strcmp(ext, ".bz2") != 0) ok = 0; break; + case LZ4_LEGACY: case LZ4: if (strcmp(ext, ".lz4") != 0) ok = 0; @@ -461,6 +551,8 @@ void comp_file(const char *method, const char *from, const char *to) { type = LZMA; } else if (strcmp(method, "lz4") == 0) { type = LZ4; + } else if (strcmp(method, "lz4_legacy") == 0) { + type = LZ4_LEGACY; } else if (strcmp(method, "bzip2") == 0) { type = BZIP2; } else { diff --git a/jni/magiskboot/magiskboot.h b/jni/magiskboot/magiskboot.h index c58378ccb..3cca95ad2 100644 --- a/jni/magiskboot/magiskboot.h +++ b/jni/magiskboot/magiskboot.h @@ -16,14 +16,6 @@ #include "bootimg.h" #include "sha1.h" -#define windowBits 15 -#define ZLIB_GZIP 16 -#define memLevel 8 -#define CHUNK 0x40000 - -#define LZ4_HEADER_SIZE 19 -#define LZ4_FOOTER_SIZE 4 - #define CHROMEOS_MAGIC "CHROMEOS" #define CHROMEOS_MAGIC_SIZE 8 @@ -33,9 +25,6 @@ #define DTB_FILE "dtb" #define NEW_BOOT "new-boot.img" -#define SUP_LIST "gzip, xz, lzma, lz4, bzip2" -#define SUP_NUM 5 - typedef enum { UNKNOWN, CHROMEOS, @@ -47,6 +36,7 @@ typedef enum { LZMA, BZIP2, LZ4, + LZ4_LEGACY, MTK, QCDT, } file_t; @@ -64,11 +54,14 @@ typedef enum { RESTORE } command_t; +#define SUP_LIST "gzip, xz, lzma, bzip2, lz4, lz4_legacy" +#define SUP_NUM 6 + +// 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]; -// 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 }; // Vector typedef struct vector { @@ -109,6 +102,7 @@ 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); +void lz4_legacy(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); void comp_file(const char *method, const char *from, const char *to); int decomp(file_t type, const char *to, const unsigned char *from, size_t size); diff --git a/jni/magiskboot/main.c b/jni/magiskboot/main.c index 1938766d7..24ecc086d 100644 --- a/jni/magiskboot/main.c +++ b/jni/magiskboot/main.c @@ -35,7 +35,7 @@ static void usage(char *arg0) { fprintf(stderr, "\n"); fprintf(stderr, "%s --compress[=method] [outfile]\n", arg0); - fprintf(stderr, " Compress with [method](default: gzip), optionally to [outfile]\n Supported methods: " SUP_LIST "\n"); + fprintf(stderr, " Compress with [method] (default: gzip), optionally to [outfile]\n Supported methods: " SUP_LIST "\n"); fprintf(stderr, "\n"); fprintf(stderr, "%s --decompress [outfile]\n", arg0); diff --git a/jni/magiskboot/utils.c b/jni/magiskboot/utils.c index 18c48ea3e..a06511843 100644 --- a/jni/magiskboot/utils.c +++ b/jni/magiskboot/utils.c @@ -1,8 +1,8 @@ #include "magiskboot.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 }; +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 }; void mmap_ro(const char *filename, unsigned char **buf, size_t *size) { int fd = open(filename, O_RDONLY); @@ -42,10 +42,10 @@ file_t check_type(const unsigned char *buf) { 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) { + } else if (memcmp(buf, "\x04\x22\x4d\x18", 4) == 0) { return LZ4; + } else if (memcmp(buf, "\x02\x21\x4c\x18", 4) == 0) { + return LZ4_LEGACY; } else if (memcmp(buf, "\x88\x16\x88\x58", 4) == 0) { return MTK; } else if (memcmp(buf, "QCDT", 4) == 0) { @@ -129,6 +129,9 @@ void print_info() { case LZ4: printf("COMPRESSION [%s]\n", "lz4"); break; + case LZ4_LEGACY: + printf("COMPRESSION [%s]\n", "lz4_legacy"); + break; default: fprintf(stderr, "Unknown ramdisk format!\n"); }