diff --git a/jni/Android.mk b/jni/Android.mk index e78514d40..afd1549c7 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -5,8 +5,3 @@ include jni/magiskhide/Android.mk include jni/resetprop/Android.mk include jni/sepolicy-inject/Android.mk include jni/su/Android.mk - -# Libraries -include jni/selinux/libsepol/Android.mk -include jni/selinux/libselinux/Android.mk -include jni/ndk-compression/xz/src/liblzma/Android.mk diff --git a/jni/magiskboot/Android.mk b/jni/magiskboot/Android.mk index a8f38a47f..7e9e44037 100644 --- a/jni/magiskboot/Android.mk +++ b/jni/magiskboot/Android.mk @@ -2,8 +2,14 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := magiskboot -LOCAL_STATIC_LIBRARIES := liblzma -LOCAL_C_INCLUDES := jni/ndk-compression/xz/src/liblzma/api/ +LOCAL_STATIC_LIBRARIES := liblzma liblz4 +LOCAL_C_INCLUDES := \ + jni/ndk-compression/xz/src/liblzma/api/ \ + jni/ndk-compression/lz4/lib/ + LOCAL_SRC_FILES := main.c unpack.c repack.c hexpatch.c parseimg.c compress.c LOCAL_LDLIBS += -lz include $(BUILD_EXECUTABLE) + +include jni/ndk-compression/xz/src/liblzma/Android.mk +include jni/ndk-compression/lz4/lib/Android.mk diff --git a/jni/magiskboot/compress.c b/jni/magiskboot/compress.c index c7c6b503b..3a8df422d 100644 --- a/jni/magiskboot/compress.c +++ b/jni/magiskboot/compress.c @@ -1,18 +1,40 @@ #include #include +#include #include "magiskboot.h" -// Mode: 0 = decode gz; 1 = encode gz +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 unsigned char *buf, const size_t size, const char *filename) { + if (write(fd, buf, size) != size) + error(1, "Error in writing %s", filename); +} + +static void report(const int mode, const char* filename) { + switch(mode) { + case 0: + printf("Decompressing to %s\n", filename); + break; + default: + printf("Compressing to %s\n", filename); + break; + } +} + +// Mode: 0 = decode; 1 = encode void gzip(int mode, const char* filename, unsigned char* buf, size_t size) { - size_t ret, flush, have, pos = 0; + size_t ret = 0, flush, have, pos = 0; z_stream strm; unsigned char out[CHUNK]; - int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); - - if (fd < 0) - error(1, "Unable to create %s", filename); + report(mode, filename); + int fd = open_new(filename); strm.zalloc = Z_NULL; strm.zfree = Z_NULL; @@ -30,19 +52,18 @@ void gzip(int mode, const char* filename, unsigned char* buf, size_t size) { } if (ret != Z_OK) - error(1, "Unable to init zlib"); + error(1, "Unable to init zlib stream"); do { strm.next_in = buf + pos; if (pos + CHUNK >= size) { strm.avail_in = size - pos; - pos = size; flush = Z_FINISH; } else { strm.avail_in = CHUNK; - pos += CHUNK; flush = Z_NO_FLUSH; } + pos += strm.avail_in; do { strm.avail_out = CHUNK; @@ -59,8 +80,7 @@ void gzip(int mode, const char* filename, unsigned char* buf, size_t size) { error(1, "Error when running gzip"); have = CHUNK - strm.avail_out; - if (write(fd, out, have) != have) - error(1, "Error when writing %s", filename); + write_file(fd, out, have, filename); } while (strm.avail_out == 0); @@ -81,16 +101,14 @@ 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) { size_t have, pos = 0; - lzma_ret ret; + lzma_ret ret = 0; lzma_stream strm = LZMA_STREAM_INIT; lzma_options_lzma opt; - lzma_action action = LZMA_RUN; + lzma_action action; unsigned char out[BUFSIZ]; - int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); - - if (fd < 0) - error(1, "Unable to create %s", filename); + report(mode, filename); + int fd = open_new(filename); // Initialize preset lzma_lzma_preset(&opt, LZMA_PRESET_DEFAULT); @@ -115,26 +133,25 @@ void lzma(int mode, const char* filename, unsigned char* buf, size_t size) { if (ret != LZMA_OK) - error(1, "Unable to init lzma"); + error(1, "Unable to init lzma stream"); do { strm.next_in = buf + pos; if (pos + BUFSIZ >= size) { strm.avail_in = size - pos; - pos = size; action = LZMA_FINISH; } else { strm.avail_in = BUFSIZ; - pos += BUFSIZ; + action = LZMA_RUN; } + pos += strm.avail_in; do { strm.avail_out = BUFSIZ; strm.next_out = out; ret = lzma_code(&strm, action); have = BUFSIZ - strm.avail_out; - if (write(fd, out, have) != have) - error(1, "Error in writing %s", filename); + write_file(fd, out, have, filename); } while (strm.avail_out == 0 && ret == LZMA_OK); if (ret != LZMA_OK && ret != LZMA_STREAM_END) @@ -144,3 +161,114 @@ void lzma(int mode, const char* filename, unsigned char* buf, size_t size) { lzma_end(&strm); } + +// Mode: 0 = decode; 1 = encode +void lz4(int mode, const char* filename, unsigned char* buf, size_t size) { + LZ4F_decompressionContext_t dctx; + LZ4F_compressionContext_t cctx; + LZ4F_frameInfo_t info; + + size_t outCapacity, avail_in, ret = 0, pos = 0; + size_t have, read; + unsigned char *out = NULL; + + report(mode, filename); + int fd = open_new(filename); + + // Initialize context + switch(mode) { + case 0: + ret = LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION); + break; + case 1: + ret = LZ4F_createCompressionContext(&cctx, LZ4F_VERSION); + break; + default: + error(1, "Unsupported lz4 mode!"); + } + + if (LZ4F_isError(ret)) + error(1, "Context creation error: %s\n", LZ4F_getErrorName(ret)); + + // Allocate out buffer + switch(mode) { + case 0: + // Read header + read = CHUNK; + ret = LZ4F_getFrameInfo(dctx, &info, buf, &read); + if (LZ4F_isError(ret)) + error(1, "LZ4F_getFrameInfo error: %s\n", LZ4F_getErrorName(ret)); + switch (info.blockSizeID) { + case LZ4F_default: + case LZ4F_max64KB: outCapacity = 1 << 16; break; + case LZ4F_max256KB: outCapacity = 1 << 18; break; + case LZ4F_max1MB: outCapacity = 1 << 20; break; + case LZ4F_max4MB: outCapacity = 1 << 22; break; + default: + error(1, "Impossible unless more block sizes are allowed\n"); + } + pos += read; + break; + case 1: + outCapacity = LZ4F_compressBound(CHUNK, NULL) + LZ4_HEADER_SIZE + LZ4_FOOTER_SIZE; + break; + } + + out = malloc(outCapacity); + if (!out) + error(1, "LZ4 malloc error!"); + + // Write header + if (mode == 1) { + have = ret = LZ4F_compressBegin(cctx, out, size, NULL); + if (LZ4F_isError(ret)) + error(1, "Failed to start compression: error %s\n", LZ4F_getErrorName(ret)); + write_file(fd, out, have, filename); + } + + do { + if (pos + CHUNK >= size) { + avail_in = size - pos; + } else { + avail_in = CHUNK; + } + + do { + switch(mode) { + case 0: + have = outCapacity, read = avail_in; + ret = LZ4F_decompress(dctx, out, &have, buf + pos, &read, NULL); + break; + case 1: + read = avail_in; + have = ret = LZ4F_compressUpdate(cctx, out, outCapacity, buf + pos, avail_in, NULL); + break; + } + if (LZ4F_isError(ret)) + error(1, "LZ4 coding error: %s\n", LZ4F_getErrorName(ret)); + + write_file(fd, out, have, filename); + // Update status + pos += read; + avail_in -= read; + } while(avail_in != 0 && ret != 0); + + } while(pos < size && ret != 0); + + switch(mode) { + case 0: + LZ4F_freeDecompressionContext(dctx); + break; + case 1: + have = ret = LZ4F_compressEnd(cctx, out, outCapacity, NULL); + if (LZ4F_isError(ret)) + error(1, "Failed to end compression: error %s\n", LZ4F_getErrorName(ret)); + + write_file(fd, out, have, filename); + + LZ4F_freeCompressionContext(cctx); + break; + } + + free(out); +} diff --git a/jni/magiskboot/magiskboot.h b/jni/magiskboot/magiskboot.h index d0ac0a71f..01fa5ff56 100644 --- a/jni/magiskboot/magiskboot.h +++ b/jni/magiskboot/magiskboot.h @@ -1,5 +1,5 @@ -#ifndef _ARCHIVE_H_ -#define _ARCHIVE_H_ +#ifndef _MAGISKBOOT_H_ +#define _MAGISKBOOT_H_ #include #include @@ -18,6 +18,9 @@ #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 @@ -51,12 +54,11 @@ void unpack(const char *image); void repack(const char *image); void hexpatch(char *image, char *from, char *to); void error(int rc, const char *msg, ...); - -// Parse image void parse_img(unsigned char *orig, size_t size); // 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); #endif diff --git a/jni/magiskboot/repack.c b/jni/magiskboot/repack.c index 2e26e7863..5dfda473b 100644 --- a/jni/magiskboot/repack.c +++ b/jni/magiskboot/repack.c @@ -98,6 +98,7 @@ void repack(const char* image) { break; case LZOP: sprintf(name, "%s.%s", RAMDISK_FILE, "lzo"); + error(1, "Unsupported format! Please compress manually!"); break; case XZ: sprintf(name, "%s.%s", RAMDISK_FILE, "xz"); @@ -109,16 +110,17 @@ void repack(const char* image) { break; case BZIP2: sprintf(name, "%s.%s", RAMDISK_FILE, "bz2"); + error(1, "Unsupported format! Please compress manually!"); break; case LZ4: sprintf(name, "%s.%s", RAMDISK_FILE, "lz4"); + lz4(1, name, cpio, cpio_size); break; default: // Never happens break; } - printf("Re-compressed %s to %s\n", RAMDISK_FILE, name); munmap(cpio, cpio_size); close(rfd); } else { diff --git a/jni/magiskboot/unpack.c b/jni/magiskboot/unpack.c index ef9749da2..0f304a4ea 100644 --- a/jni/magiskboot/unpack.c +++ b/jni/magiskboot/unpack.c @@ -48,6 +48,7 @@ void unpack(const char* image) { break; case LZOP: sprintf(name, "%s.%s", RAMDISK_FILE, "lzo"); + printf("Unsupported format! Please decompress manually!\n"); break; case XZ: sprintf(name, "%s.%s", RAMDISK_FILE, "xz"); @@ -59,9 +60,11 @@ void unpack(const char* image) { break; case BZIP2: sprintf(name, "%s.%s", RAMDISK_FILE, "bz2"); + printf("Unsupported format! Please decompress manually!\n"); break; case LZ4: sprintf(name, "%s.%s", RAMDISK_FILE, "lz4"); + lz4(0, RAMDISK_FILE, ramdisk, hdr.ramdisk_size); break; default: // Never happens diff --git a/jni/ndk-compression b/jni/ndk-compression index 7cfa31b27..602750457 160000 --- a/jni/ndk-compression +++ b/jni/ndk-compression @@ -1 +1 @@ -Subproject commit 7cfa31b27065249b4d35cd1c7ceef4c2453b48b8 +Subproject commit 602750457f2383f9a726eb12d2907f4ed282be91 diff --git a/jni/sepolicy-inject b/jni/sepolicy-inject index 2fe4d9706..9f35fa0fa 160000 --- a/jni/sepolicy-inject +++ b/jni/sepolicy-inject @@ -1 +1 @@ -Subproject commit 2fe4d9706148d19c4ff2dce9119f40ae0641925a +Subproject commit 9f35fa0fa3f9b52c2b6b31253bade848019d7ab2 diff --git a/jni/su b/jni/su index 12cc7b788..addbe81c8 160000 --- a/jni/su +++ b/jni/su @@ -1 +1 @@ -Subproject commit 12cc7b7885c67b17340b4637b67e190148927a7e +Subproject commit addbe81c82e178952e9560d6ba027b1dbe8b840c