Add high compression ramdisk support

This commit is contained in:
topjohnwu 2017-12-06 12:51:16 +08:00
parent 742dc137ed
commit 9f6a27c20d
15 changed files with 231 additions and 138 deletions

View File

@ -76,6 +76,7 @@ LOCAL_SRC_FILES := \
utils/vector.c \ utils/vector.c \
utils/file.c \ utils/file.c \
utils/xwrap.c \ utils/xwrap.c \
utils/cpio.c \
magiskpolicy/api.c \ magiskpolicy/api.c \
magiskpolicy/magiskpolicy.c \ magiskpolicy/magiskpolicy.c \
magiskpolicy/rules.c \ magiskpolicy/rules.c \

View File

@ -44,6 +44,7 @@
#include "utils.h" #include "utils.h"
#include "magiskpolicy.h" #include "magiskpolicy.h"
#include "daemon.h" #include "daemon.h"
#include "cpio.h"
#include "magisk.h" #include "magisk.h"
// #define VLOG(fmt, ...) printf(fmt, __VA_ARGS__) /* Enable to debug */ // #define VLOG(fmt, ...) printf(fmt, __VA_ARGS__) /* Enable to debug */
@ -458,11 +459,36 @@ int main(int argc, char *argv[]) {
mount(dev.path, "/vendor", "ext4", MS_RDONLY, NULL); mount(dev.path, "/vendor", "ext4", MS_RDONLY, NULL);
close(system_root); close(system_root);
} else {
char *ramdisk_xz = NULL;
if (access("/ramdisk-recovery.xz", R_OK) == 0)
ramdisk_xz = "/ramdisk-recovery.xz";
else if (access("/ramdisk.cpio.xz", R_OK) == 0)
ramdisk_xz = "/ramdisk.cpio.xz";
if (ramdisk_xz) {
// High compress mode
void *addr;
size_t size;
mmap_ro(ramdisk_xz, &addr, &size);
int fd = creat("/ramdisk.cpio", 0);
unxz(addr, size, fd);
munmap(addr, size);
close(fd);
struct vector v;
vec_init(&v);
parse_cpio(&v, "/ramdisk.cpio");
excl_list = (char *[]) { "overlay", ".backup", NULL };
frm_rf(root);
chdir("/");
cpio_extract_all(&v);
cpio_vec_destroy(&v);
} else { } else {
// Revert original init binary // Revert original init binary
unlink("/init"); unlink("/init");
link("/.backup/init", "/init"); link("/.backup/init", "/init");
} }
}
// Only patch initramfs if not intended to run in recovery (legacy devices) // Only patch initramfs if not intended to run in recovery (legacy devices)
if (access("/etc/recovery.fstab", F_OK) != 0) { if (access("/etc/recovery.fstab", F_OK) != 0) {

View File

@ -55,8 +55,8 @@ void cpio_extract_all(struct vector *v);
// Magisk specific // Magisk specific
int cpio_test(struct vector *v); int cpio_test(struct vector *v);
void cpio_backup(struct vector *v, const char *orig, const char *sha1); struct vector *cpio_backup(struct vector *v, const char *orig, const char *sha1);
int cpio_restore(struct vector *v); void cpio_restore(struct vector *v);
char *cpio_stocksha1(struct vector *v); char *cpio_stocksha1(struct vector *v);
#endif #endif

View File

@ -117,8 +117,8 @@ int fsetattr(int fd, struct file_attr *a);
void fclone_attr(const int sourcefd, const int targetfd); void fclone_attr(const int sourcefd, const int targetfd);
void clone_attr(const char *source, const char *target); void clone_attr(const char *source, const char *target);
void restorecon(int dirfd, int force); void restorecon(int dirfd, int force);
void mmap_ro(const char *filename, void **buf, size_t *size); int mmap_ro(const char *filename, void **buf, size_t *size);
void mmap_rw(const char *filename, void **buf, size_t *size); int mmap_rw(const char *filename, void **buf, size_t *size);
void full_read(int fd, void **buf, size_t *size); void full_read(int fd, void **buf, size_t *size);
void write_zero(int fd, size_t size); void write_zero(int fd, size_t size);
void mem_align(size_t *pos, size_t align); void mem_align(size_t *pos, size_t align);

View File

@ -8,6 +8,11 @@
#include "utils.h" #include "utils.h"
#include "logging.h" #include "logging.h"
#define INSUF_BLOCK_RET 2
#define CHROMEOS_RET 3
#define ELF32_RET 4
#define ELF64_RET 5
static void dump(void *buf, size_t size, const char *filename) { static void dump(void *buf, size_t size, const char *filename) {
int fd = creat(filename, 0644); int fd = creat(filename, 0644);
xwrite(fd, buf, size); xwrite(fd, buf, size);
@ -53,60 +58,61 @@ static void print_hdr(const boot_img_hdr *hdr) {
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
int parse_img(void *orig, size_t size, boot_img *boot) { int parse_img(const char *image, boot_img *boot) {
void *base, *end;
size_t pos = 0;
int ret = 0;
memset(boot, 0, sizeof(*boot)); memset(boot, 0, sizeof(*boot));
for(base = orig, end = orig + size; base < end; base += 256, size -= 256) { int is_blk = mmap_ro(image, &boot->map_addr, &boot->map_size);
switch (check_type(base)) {
// Parse image
fprintf(stderr, "Parsing boot image: [%s]\n\n", image);
for (size_t pos = 0; pos < boot->map_size; pos += 256) {
switch (check_type(boot->map_addr + pos)) {
case CHROMEOS: case CHROMEOS:
// The caller should know it's chromeos, as it needs additional signing // The caller should know it's chromeos, as it needs additional signing
ret = 2; boot->flags |= CHROMEOS_FLAG;
continue; continue;
case ELF32: case ELF32:
exit(3); exit(ELF32_RET);
case ELF64: case ELF64:
exit(4); exit(ELF64_RET);
case AOSP: case AOSP:
// Read the header // Read the header
memcpy(&boot->hdr, base, sizeof(boot->hdr)); memcpy(&boot->hdr, boot->map_addr + pos, sizeof(boot->hdr));
pos += boot->hdr.page_size; pos += boot->hdr.page_size;
print_hdr(&boot->hdr); print_hdr(&boot->hdr);
boot->kernel = base + pos; boot->kernel = boot->map_addr + pos;
pos += boot->hdr.kernel_size; pos += boot->hdr.kernel_size;
mem_align(&pos, boot->hdr.page_size); mem_align(&pos, boot->hdr.page_size);
boot->ramdisk = base + pos; boot->ramdisk = boot->map_addr + pos;
pos += boot->hdr.ramdisk_size; pos += boot->hdr.ramdisk_size;
mem_align(&pos, boot->hdr.page_size); mem_align(&pos, boot->hdr.page_size);
if (boot->hdr.second_size) { if (boot->hdr.second_size) {
boot->second = base + pos; boot->second = boot->map_addr + pos;
pos += boot->hdr.second_size; pos += boot->hdr.second_size;
mem_align(&pos, boot->hdr.page_size); mem_align(&pos, boot->hdr.page_size);
} }
if (boot->hdr.extra_size) { if (boot->hdr.extra_size) {
boot->extra = base + pos; boot->extra = boot->map_addr + pos;
pos += boot->hdr.extra_size; pos += boot->hdr.extra_size;
mem_align(&pos, boot->hdr.page_size); mem_align(&pos, boot->hdr.page_size);
} }
if (pos < size) { if (pos < boot->map_size) {
boot->tail = base + pos; boot->tail = boot->map_addr + pos;
boot->tail_size = end - base - pos; boot->tail_size = boot->map_size - pos;
} }
// Search for dtb in kernel // Search for dtb in kernel
for (int i = 0; i < boot->hdr.kernel_size; ++i) { for (uint32_t i = 0; i < boot->hdr.kernel_size; ++i) {
if (memcmp(boot->kernel + i, DTB_MAGIC, 4) == 0) { if (memcmp(boot->kernel + i, DTB_MAGIC, 4) == 0) {
boot->dtb = boot->kernel + i; boot->dtb = boot->kernel + i;
boot->dt_size = boot->hdr.kernel_size - i; boot->dt_size = boot->hdr.kernel_size - i;
boot->hdr.kernel_size = i; boot->hdr.kernel_size = i;
fprintf(stderr, "DTB [%d]\n", boot->dt_size); fprintf(stderr, "DTB [%u]\n", boot->dt_size);
} }
} }
@ -139,25 +145,19 @@ int parse_img(void *orig, size_t size, boot_img *boot) {
fprintf(stderr, "RAMDISK_FMT [%s]\n", fmt); fprintf(stderr, "RAMDISK_FMT [%s]\n", fmt);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
return ret; return boot->flags & CHROMEOS_FLAG ? CHROMEOS_RET :
((is_blk && boot->tail_size < 500 * 1024) ? INSUF_BLOCK_RET : 0);
default: default:
continue; continue;
} }
} }
LOGE("No boot image magic found!\n"); LOGE("No boot image magic found!\n");
return 1;
} }
void unpack(const char* image) { void unpack(const char* image) {
size_t size;
void *orig;
mmap_ro(image, &orig, &size);
int fd;
boot_img boot; boot_img boot;
int ret = parse_img(image, &boot);
// Parse image int fd;
fprintf(stderr, "Parsing boot image: [%s]\n\n", image);
int ret = parse_img(orig, size, &boot);
// Dump kernel // Dump kernel
if (COMPRESSED(boot.kernel_type)) { if (COMPRESSED(boot.kernel_type)) {
@ -193,24 +193,18 @@ void unpack(const char* image) {
dump(boot.extra, boot.hdr.extra_size, EXTRA_FILE); dump(boot.extra, boot.hdr.extra_size, EXTRA_FILE);
} }
munmap(orig, size); munmap(boot.map_addr, boot.map_size);
exit(ret); exit(ret);
} }
void repack(const char* orig_image, const char* out_image) { void repack(const char* orig_image, const char* out_image) {
size_t size;
void *orig;
boot_img boot; boot_img boot;
// There are possible two MTK headers // There are possible two MTK headers
size_t mtk_kernel_off, mtk_ramdisk_off; size_t mtk_kernel_off, mtk_ramdisk_off;
// Load original image
mmap_ro(orig_image, &orig, &size);
// Parse original image // Parse original image
fprintf(stderr, "Parsing boot image: [%s]\n\n", orig_image); parse_img(orig_image, &boot);
parse_img(orig, size, &boot);
fprintf(stderr, "Repack to boot image: [%s]\n\n", out_image); fprintf(stderr, "Repack to boot image: [%s]\n\n", out_image);
@ -309,7 +303,6 @@ void repack(const char* orig_image, const char* out_image) {
// Print new image info // Print new image info
print_hdr(&boot.hdr); print_hdr(&boot.hdr);
munmap(orig, size); munmap(boot.map_addr, boot.map_size);
close(fd); close(fd);
} }

View File

@ -103,20 +103,25 @@ typedef struct mtk_hdr {
// Flags // Flags
#define MTK_KERNEL 0x1 #define MTK_KERNEL 0x1
#define MTK_RAMDISK 0x2 #define MTK_RAMDISK 0x2
#define CHROMEOS_FLAG 0x4
typedef struct boot_img { typedef struct boot_img {
size_t map_size;
uint32_t dt_size;
size_t tail_size;
uint8_t flags;
file_t kernel_type, ramdisk_type;
boot_img_hdr hdr; boot_img_hdr hdr;
mtk_hdr mtk_kernel_hdr, mtk_ramdisk_hdr;
void *map_addr;
void *kernel; void *kernel;
void *dtb; void *dtb;
uint32_t dt_size;
void *ramdisk; void *ramdisk;
void *second; void *second;
void *extra; void *extra;
void *tail; void *tail;
uint32_t tail_size;
uint32_t flags;
file_t kernel_type, ramdisk_type;
mtk_hdr mtk_kernel_hdr, mtk_ramdisk_hdr;
} boot_img; } boot_img;
#endif #endif

View File

@ -17,7 +17,7 @@
void unpack(const char *image); void unpack(const char *image);
void repack(const char* orig_image, const char* out_image); void repack(const char* orig_image, const char* out_image);
void hexpatch(const char *image, const char *from, const char *to); void hexpatch(const char *image, const char *from, const char *to);
int parse_img(void *orig, size_t size, boot_img *boot); int parse_img(const char *image, boot_img *boot);
int cpio_commands(const char *cmd, int argc, char *argv[]); int cpio_commands(const char *cmd, int argc, char *argv[]);
void comp_file(const char *method, const char *from, const char *to); void comp_file(const char *method, const char *from, const char *to);
void decomp_file(char *from, const char *to); void decomp_file(char *from, const char *to);

View File

@ -17,16 +17,21 @@ static void usage(char *arg0) {
"Usage: %s <action> [args...]\n" "Usage: %s <action> [args...]\n"
"\n" "\n"
"Supported actions:\n" "Supported actions:\n"
" --parse <bootimg>\n"
" Parse <bootimg> only, do not unpack. Return value: \n"
" 0:OK 1:error 2:insufficient boot partition size\n"
" 3:chromeos 4:ELF32 5:ELF64\n"
"\n"
" --unpack <bootimg>\n" " --unpack <bootimg>\n"
" Unpack <bootimg> to kernel, ramdisk.cpio, (second), (dtb), (extra) into\n" " Unpack <bootimg> to kernel, ramdisk.cpio, (second), (dtb), (extra) into\n"
" the current directory\n" " the current directory. Return value is the same as parse command\n"
"\n" "\n"
" --repack <origbootimg> [outbootimg]\n" " --repack <origbootimg> [outbootimg]\n"
" Repack kernel, ramdisk.cpio[.ext], second, dtb... from current directory\n" " Repack kernel, ramdisk.cpio[.ext], second, dtb... from current directory\n"
" to [outbootimg], or new-boot.img if not specified.\n" " to [outbootimg], or new-boot.img if not specified.\n"
" 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"
" if exists, or attempt to find ramdisk.cpio.[ext], and repack\n" " or attempt to find ramdisk.cpio.[ext], and repack directly with the\n"
" directly with the compressed ramdisk file\n" " compressed ramdisk file\n"
"\n" "\n"
" --hexpatch <file> <hexpattern1> <hexpattern2>\n" " --hexpatch <file> <hexpattern1> <hexpattern2>\n"
" Search <hexpattern1> in <file>, and replace with <hexpattern2>\n" " Search <hexpattern1> in <file>, and replace with <hexpattern2>\n"
@ -40,18 +45,19 @@ static void usage(char *arg0) {
" Create directory as an <entry>\n" " Create directory as an <entry>\n"
" -ln <target> <entry>\n" " -ln <target> <entry>\n"
" Create symlink <entry> to point to <target>\n" " Create symlink <entry> to point to <target>\n"
" -add <mode> <entry> <infile>\n"
" Add <infile> as an <entry>; replaces <entry> if already exists\n"
" -mv <from-entry> <to-entry>\n" " -mv <from-entry> <to-entry>\n"
" Move <from-entry> to <to-entry>\n" " Move <from-entry> to <to-entry>\n"
" -add <mode> <entry> <infile>\n"
" Add <infile> as an <entry>; replaces <entry> if already exists\n"
" -extract [<entry> <outfile>]\n" " -extract [<entry> <outfile>]\n"
" Extract <entry> to <outfile>, or extract all to current directory\n" " Extract <entry> to <outfile>, or extract all to current directory\n"
" -test\n" " -test\n"
" Return value: 0/stock 1/Magisk 2/other (phh, SuperSU, Xposed)\n" " Return value: 0/stock 1/Magisk 2/other (phh, SuperSU, Xposed)\n"
" -patch <KEEPVERITY> <KEEPFORCEENCRYPT>\n" " -patch <KEEPVERITY> <KEEPFORCEENCRYPT>\n"
" Patch cpio for Magisk. KEEP**** are true/false values\n" " Patch cpio for Magisk. KEEP**** are boolean values\n"
" -backup <origcpio> [SHA1]\n" " -backup <origcpio> <HIGH_COMP> [SHA1]\n"
" Create ramdisk backups into <incpio> from <origcpio>\n" " Create ramdisk backups into <incpio> from <origcpio>\n"
" HIGH_COMP is a boolean value, toggles high compression mode\n"
" SHA1 of stock boot image is optional\n" " SHA1 of stock boot image is optional\n"
" -restore\n" " -restore\n"
" Restore ramdisk from ramdisk backup within <incpio>\n" " Restore ramdisk from ramdisk backup within <incpio>\n"
@ -63,6 +69,9 @@ static void usage(char *arg0) {
" Supported commands:\n" " Supported commands:\n"
" -dump\n" " -dump\n"
" Dump all contents from dtb for debugging\n" " Dump all contents from dtb for debugging\n"
" -test\n"
" Check if fstab has verity/avb flags\n"
" Return value: 0/no flags 1/flag exists"
" -patch\n" " -patch\n"
" Search for fstab and remove verity/avb\n" " Search for fstab and remove verity/avb\n"
"\n" "\n"
@ -74,8 +83,7 @@ static void usage(char *arg0) {
for (int i = 0; SUP_LIST[i]; ++i) for (int i = 0; SUP_LIST[i]; ++i)
fprintf(stderr, "%s ", SUP_LIST[i]); fprintf(stderr, "%s ", SUP_LIST[i]);
fprintf(stderr, fprintf(stderr,
"\n" "\n\n"
"\n"
" --decompress <infile> [outfile]\n" " --decompress <infile> [outfile]\n"
" Detect method and decompress <infile>, optionally to [outfile]\n" " Detect method and decompress <infile>, optionally to [outfile]\n"
" <infile>/[outfile] can be '-' to be STDIN/STDOUT\n" " <infile>/[outfile] can be '-' to be STDIN/STDOUT\n"
@ -83,8 +91,7 @@ static void usage(char *arg0) {
for (int i = 0; SUP_LIST[i]; ++i) for (int i = 0; SUP_LIST[i]; ++i)
fprintf(stderr, "%s ", SUP_LIST[i]); fprintf(stderr, "%s ", SUP_LIST[i]);
fprintf(stderr, fprintf(stderr,
"\n" "\n\n"
"\n"
" --sha1 <file>\n" " --sha1 <file>\n"
" Print the SHA1 checksum for <file>\n" " Print the SHA1 checksum for <file>\n"
"\n" "\n"
@ -121,6 +128,9 @@ int main(int argc, char *argv[]) {
printf("%02x", sha1[i]); printf("%02x", sha1[i]);
printf("\n"); printf("\n");
munmap(buf, size); munmap(buf, size);
} else if (argc > 2 && strcmp(argv[1], "--parse") == 0) {
boot_img boot;
exit(parse_img(argv[2], &boot));
} else if (argc > 2 && strcmp(argv[1], "--unpack") == 0) { } else if (argc > 2 && strcmp(argv[1], "--unpack") == 0) {
unpack(argv[2]); unpack(argv[2]);
} else if (argc > 2 && strcmp(argv[1], "--repack") == 0) { } else if (argc > 2 && strcmp(argv[1], "--repack") == 0) {

View File

@ -1,6 +1,9 @@
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <utils.h>
#include <sys/mman.h>
#include <fcntl.h>
#include "magiskboot.h" #include "magiskboot.h"
#include "cpio.h" #include "cpio.h"
@ -70,8 +73,68 @@ void cpio_patch(struct vector *v, int keepverity, int keepforceencrypt) {
} }
} }
static void restore_high_compress(struct vector *v, const char *incpio) {
// Check if the ramdisk is in high compression mode
if (cpio_extract(v, "ramdisk.cpio.xz", incpio) == 0) {
void *addr, *xz;
size_t size;
mmap_ro(incpio, &addr, &size);
xz = xmalloc(size);
memcpy(xz, addr, size);
munmap(addr, size);
int fd = creat(incpio, 0644);
lzma(0, fd, xz, size);
close(fd);
cpio_rm(v, 0, "ramdisk.cpio.xz");
cpio_rm(v, 0, "init");
struct vector vv;
vec_init(&vv);
parse_cpio(&vv, incpio);
cpio_entry *e;
vec_for_each(&vv, e)
vec_push_back(v, e);
vec_destroy(&vv);
}
}
static void enable_high_compress(struct vector *v, struct vector *b, const char *incpio) {
cpio_entry *e, *magiskinit, *init;
// Swap magiskinit with original init
vec_for_each(b, e) {
if (strcmp(e->filename, ".backup/init") == 0) {
free(e->filename);
e->filename = strdup("init");
init = e;
vec_for_each(v, e) {
if (strcmp(e->filename, "init") == 0) {
magiskinit = e;
vec_cur(v) = init;
break;
}
}
vec_cur(b) = NULL;
break;
}
}
dump_cpio(v, incpio);
cpio_vec_destroy(v);
void *addr, *cpio;
size_t size;
mmap_ro(incpio, &addr, &size);
cpio = xmalloc(size);
memcpy(cpio, addr, size);
munmap(addr, size);
int fd = creat(incpio, 0644);
lzma(1, fd, cpio, size);
close(fd);
vec_init(v);
vec_push_back(v, magiskinit);
cpio_add(v, 0, "ramdisk.cpio.xz", incpio);
}
int cpio_commands(const char *command, int argc, char *argv[]) { int cpio_commands(const char *command, int argc, char *argv[]) {
int ret = 0;
char *incpio = argv[0]; char *incpio = argv[0];
++argv; ++argv;
--argc; --argc;
@ -82,12 +145,23 @@ int cpio_commands(const char *command, int argc, char *argv[]) {
if (strcmp(command, "test") == 0) { if (strcmp(command, "test") == 0) {
exit(cpio_test(&v)); exit(cpio_test(&v));
} else if (strcmp(command, "restore") == 0) { } else if (strcmp(command, "restore") == 0) {
ret = cpio_restore(&v); restore_high_compress(&v, incpio);
cpio_restore(&v);
} else if (strcmp(command, "stocksha1") == 0) { } else if (strcmp(command, "stocksha1") == 0) {
printf("%s\n", cpio_stocksha1(&v)); printf("%s\n", cpio_stocksha1(&v));
return 0; return 0;
} else if (argc >= 1 && strcmp(command, "backup") == 0) { } else if (argc >= 2 && strcmp(command, "backup") == 0) {
cpio_backup(&v, argv[0], argc > 1 ? argv[1] : NULL); struct vector *back;
cpio_entry *e;
back = cpio_backup(&v, argv[0], argc > 2 ? argv[2] : NULL);
// Enable high compression mode
if (strcmp(argv[1], "true") == 0)
enable_high_compress(&v, back, incpio);
vec_for_each(back, e)
if (e) vec_push_back(&v, e);
} else if (argc > 0 && strcmp(command, "rm") == 0) { } else if (argc > 0 && strcmp(command, "rm") == 0) {
int recursive = 0; int recursive = 0;
if (argc == 2 && strcmp(argv[0], "-r") == 0) { if (argc == 2 && strcmp(argv[0], "-r") == 0) {
@ -119,5 +193,5 @@ int cpio_commands(const char *command, int argc, char *argv[]) {
dump_cpio(&v, incpio); dump_cpio(&v, incpio);
cpio_vec_destroy(&v); cpio_vec_destroy(&v);
exit(ret); exit(0);
} }

View File

@ -3,10 +3,6 @@
#include "bootimg.h" #include "bootimg.h"
#include "types.h" #include "types.h"
char *SUP_LIST[] = { "gzip", "xz", "lzma", "bzip2", "lz4", "lz4_legacy", NULL };
char *SUP_EXT_LIST[] = { "gz", "xz", "lzma", "bz2", "lz4", "lz4", NULL };
file_t SUP_TYPE_LIST[] = { GZIP, XZ, LZMA, BZIP2, LZ4, LZ4_LEGACY, 0 };
file_t check_type(const void *buf) { file_t check_type(const void *buf) {
if (memcmp(buf, CHROMEOS_MAGIC, 8) == 0) { if (memcmp(buf, CHROMEOS_MAGIC, 8) == 0) {
return CHROMEOS; return CHROMEOS;

View File

@ -33,9 +33,8 @@ typedef enum {
#define DTB_MAGIC "\xd0\x0d\xfe\xed" #define DTB_MAGIC "\xd0\x0d\xfe\xed"
#define LG_BUMP_MAGIC "\x41\xa9\xe4\x67\x74\x4d\x1d\x1b\xa4\x29\xf2\xec\xea\x65\x52\x79" #define LG_BUMP_MAGIC "\x41\xa9\xe4\x67\x74\x4d\x1d\x1b\xa4\x29\xf2\xec\xea\x65\x52\x79"
extern char *SUP_LIST[]; #define SUP_LIST ((char *[]) { "gzip", "xz", "lzma", "bzip2", "lz4", "lz4_legacy", NULL })
extern char *SUP_EXT_LIST[]; #define SUP_EXT_LIST ((char *[]) { "gz", "xz", "lzma", "bz2", "lz4", "lz4", NULL })
extern file_t SUP_TYPE_LIST[];
file_t check_type(const void *buf); file_t check_type(const void *buf);
void get_type_name(file_t type, char *name); void get_type_name(file_t type, char *name);

View File

@ -213,7 +213,6 @@ int cpio_extract(struct vector *v, const char *entry, const char *filename) {
vec_for_each(v, f) { vec_for_each(v, f) {
if (strcmp(f->filename, entry) == 0) { if (strcmp(f->filename, entry) == 0) {
fprintf(stderr, "Extracting [%s] to [%s]\n\n", entry, filename); fprintf(stderr, "Extracting [%s] to [%s]\n\n", entry, filename);
unlink(filename);
if (S_ISREG(f->mode)) { if (S_ISREG(f->mode)) {
int fd = creat(filename, f->mode & 0777); int fd = creat(filename, f->mode & 0777);
xwrite(fd, f->data, f->filesize); xwrite(fd, f->data, f->filesize);
@ -222,6 +221,7 @@ int cpio_extract(struct vector *v, const char *entry, const char *filename) {
} else if (S_ISLNK(f->mode)) { } else if (S_ISLNK(f->mode)) {
char *target = xcalloc(f->filesize + 1, 1); char *target = xcalloc(f->filesize + 1, 1);
memcpy(target, f->data, f->filesize); memcpy(target, f->data, f->filesize);
unlink(filename);
symlink(target, filename); symlink(target, filename);
} }
return 0; return 0;
@ -263,9 +263,8 @@ int cpio_test(struct vector *v) {
vec_for_each(v, f) { vec_for_each(v, f) {
for (int i = 0; OTHER_LIST[i]; ++i) { for (int i = 0; OTHER_LIST[i]; ++i) {
if (strcmp(f->filename, OTHER_LIST[i]) == 0) { if (strcmp(f->filename, OTHER_LIST[i]) == 0) {
ret |= OTHER_PATCH;
// Already find other files, abort // Already find other files, abort
exit(OTHER_PATCH); return OTHER_PATCH;
} }
} }
for (int i = 0; MAGISK_LIST[i]; ++i) { for (int i = 0; MAGISK_LIST[i]; ++i) {
@ -277,34 +276,36 @@ int cpio_test(struct vector *v) {
return ret; return ret;
} }
void cpio_backup(struct vector *v, const char *orig, const char *sha1) { struct vector * cpio_backup(struct vector *v, const char *orig, const char *sha1) {
struct vector o_body, *o = &o_body, bak; struct vector o_body, *o = &o_body, *ret;
cpio_entry *m, *n, *rem, *cksm; cpio_entry *m, *n, *rem, *cksm;
char buf[PATH_MAX]; char buf[PATH_MAX];
int res, doBak; int res, backup;
ret = xcalloc(sizeof(*ret), 1);
vec_init(o); vec_init(o);
vec_init(&bak); vec_init(ret);
m = xcalloc(sizeof(*m), 1); m = xcalloc(sizeof(*m), 1);
m->filename = strdup(".backup"); m->filename = strdup(".backup");
m->mode = S_IFDIR; m->mode = S_IFDIR;
vec_push_back(&bak, m); vec_push_back(ret, m);
m = xcalloc(sizeof(*m), 1); m = xcalloc(sizeof(*m), 1);
m->filename = strdup(".backup/.magisk"); m->filename = strdup(".backup/.magisk");
m->mode = S_IFREG; m->mode = S_IFREG;
vec_push_back(&bak, m); vec_push_back(ret, m);
rem = xcalloc(sizeof(*rem), 1); rem = xcalloc(sizeof(*rem), 1);
rem->filename = strdup(".backup/.rmlist"); rem->filename = strdup(".backup/.rmlist");
rem->mode = S_IFREG; rem->mode = S_IFREG;
vec_push_back(&bak, rem); vec_push_back(ret, rem);
if (sha1) { if (sha1) {
fprintf(stderr, "Save SHA1: [%s] -> [.backup/.sha1]\n", sha1); fprintf(stderr, "Save SHA1: [%s] -> [.backup/.sha1]\n", sha1);
cksm = xcalloc(sizeof(*cksm), 1); cksm = xcalloc(sizeof(*cksm), 1);
vec_push_back(&bak, cksm); vec_push_back(ret, cksm);
cksm->filename = strdup(".backup/.sha1"); cksm->filename = strdup(".backup/.sha1");
cksm->mode = S_IFREG; cksm->mode = S_IFREG;
cksm->data = strdup(sha1); cksm->data = strdup(sha1);
@ -323,7 +324,7 @@ void cpio_backup(struct vector *v, const char *orig, const char *sha1) {
// Start comparing // Start comparing
size_t i = 0, j = 0; size_t i = 0, j = 0;
while(i != vec_size(o) || j != vec_size(v)) { while(i != vec_size(o) || j != vec_size(v)) {
doBak = 0; backup = 0;
if (i != vec_size(o) && j != vec_size(v)) { if (i != vec_size(o) && j != vec_size(v)) {
m = vec_entry(o)[i]; m = vec_entry(o)[i];
n = vec_entry(v)[j]; n = vec_entry(v)[j];
@ -339,14 +340,14 @@ void cpio_backup(struct vector *v, const char *orig, const char *sha1) {
if (res < 0) { if (res < 0) {
// Something is missing in new ramdisk, backup! // Something is missing in new ramdisk, backup!
++i; ++i;
doBak = 1; backup = 1;
fprintf(stderr, "Backup missing entry: "); fprintf(stderr, "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; backup = 1;
fprintf(stderr, "Backup mismatch entry: "); fprintf(stderr, "Backup mismatch entry: ");
} else { } else {
// Someting new in ramdisk, record in rem // Someting new in ramdisk, record in rem
@ -357,35 +358,30 @@ void cpio_backup(struct vector *v, const char *orig, const char *sha1) {
rem->filesize += strlen(n->filename) + 1; rem->filesize += strlen(n->filename) + 1;
fprintf(stderr, "Record new entry: [%s] -> [.backup/.rmlist]\n", n->filename); fprintf(stderr, "Record new entry: [%s] -> [.backup/.rmlist]\n", n->filename);
} }
if (doBak) { if (backup) {
sprintf(buf, ".backup/%s", m->filename); sprintf(buf, ".backup/%s", m->filename);
free(m->filename); free(m->filename);
m->filename = strdup(buf); m->filename = strdup(buf);
fprintf(stderr, "[%s] -> [%s]\n", buf, m->filename); fprintf(stderr, "[%s] -> [%s]\n", buf, m->filename);
vec_push_back(&bak, m); vec_push_back(ret, 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;
} }
} }
// Add the backup files to the original ramdisk
vec_for_each(&bak, m) {
vec_push_back(v, m);
}
if (rem->filesize == 0) if (rem->filesize == 0)
rem->remove = 1; rem->remove = 1;
// Cleanup // Cleanup
cpio_vec_destroy(o); cpio_vec_destroy(o);
return ret;
} }
int cpio_restore(struct vector *v) { void cpio_restore(struct vector *v) {
cpio_entry *f, *n; cpio_entry *f, *n;
int ret = 1;
vec_for_each(v, f) { vec_for_each(v, f) {
if (strstr(f->filename, ".backup") != NULL) { if (strncmp(f->filename, ".backup", 7) == 0) {
ret = 0;
f->remove = 1; f->remove = 1;
if (f->filename[7] == '\0') continue; if (f->filename[7] == '\0') continue;
if (f->filename[8] == '.') { if (f->filename[8] == '.') {
@ -405,12 +401,14 @@ int cpio_restore(struct vector *v) {
cpio_vec_insert(v, n); cpio_vec_insert(v, n);
} }
} }
if (strncmp(f->filename, "overlay", 7) == 0)
f->remove = 1;
} }
// Some known stuff we can remove // Some known stuff we can remove
cpio_rm(v, 0, "sbin/magic_mask.sh"); cpio_rm(v, 0, "sbin/magic_mask.sh");
cpio_rm(v, 0, "init.magisk.rc"); cpio_rm(v, 0, "init.magisk.rc");
cpio_rm(v, 0, "magisk"); cpio_rm(v, 0, "magisk");
return ret; cpio_rm(v, 0, "ramdisk-recovery.xz");
} }
char *cpio_stocksha1(struct vector *v) { char *cpio_stocksha1(struct vector *v) {

View File

@ -357,24 +357,25 @@ void restorecon(int dirfd, int force) {
#endif // SELINUX #endif // SELINUX
static void _mmap(int rw, const char *filename, void **buf, size_t *size) { static int _mmap(int rw, const char *filename, void **buf, size_t *size) {
struct stat st; struct stat st;
stat(filename, &st);
int fd = xopen(filename, rw ? O_RDWR : O_RDONLY); int fd = xopen(filename, rw ? O_RDWR : O_RDONLY);
fstat(fd, &st);
if (S_ISBLK(st.st_mode)) if (S_ISBLK(st.st_mode))
ioctl(fd, BLKGETSIZE64, size); ioctl(fd, BLKGETSIZE64, size);
else else
*size = st.st_size; *size = st.st_size;
*buf = *size > 0 ? xmmap(NULL, *size, PROT_READ | (rw ? PROT_WRITE : 0), MAP_SHARED, fd, 0) : NULL; *buf = *size > 0 ? xmmap(NULL, *size, PROT_READ | (rw ? PROT_WRITE : 0), MAP_SHARED, fd, 0) : NULL;
close(fd); close(fd);
return S_ISBLK(st.st_mode);
} }
void mmap_ro(const char *filename, void **buf, size_t *size) { int mmap_ro(const char *filename, void **buf, size_t *size) {
_mmap(0, filename, buf, size); return _mmap(0, filename, buf, size);
} }
void mmap_rw(const char *filename, void **buf, size_t *size) { int mmap_rw(const char *filename, void **buf, size_t *size) {
_mmap(1, filename, buf, size); return _mmap(1, filename, buf, size);
} }
void full_read(int fd, void **buf, size_t *size) { void full_read(int fd, void **buf, size_t *size) {

View File

@ -64,6 +64,7 @@ BOOTIMAGE="$1"
# Presets # Presets
[ -z $KEEPVERITY ] && KEEPVERITY=false [ -z $KEEPVERITY ] && KEEPVERITY=false
[ -z $KEEPFORCEENCRYPT ] && KEEPFORCEENCRYPT=false [ -z $KEEPFORCEENCRYPT ] && KEEPFORCEENCRYPT=false
[ -z $HIGH_COMP ] && HIGH_COMP=false
chmod -R 755 . chmod -R 755 .
@ -86,14 +87,19 @@ case $? in
abort "! Unable to unpack boot image" abort "! Unable to unpack boot image"
;; ;;
2 ) 2 )
ui_print "! Insufficient boot partition size detected"
ui_print "- Enable high compression mode"
HIGH_COMP=true
;;
3 )
ui_print "- ChromeOS boot image detected" ui_print "- ChromeOS boot image detected"
CHROMEOS=true CHROMEOS=true
;; ;;
3 ) 4 )
ui_print "! Sony ELF32 format detected" ui_print "! Sony ELF32 format detected"
abort "! Please use BootBridge from @AdrianDC to flash Magisk" abort "! Please use BootBridge from @AdrianDC to flash Magisk"
;; ;;
4 ) 5 )
ui_print "! Sony ELF64 format detected" ui_print "! Sony ELF64 format detected"
abort "! Stock kernel cannot be patched, please use a custom kernel" abort "! Stock kernel cannot be patched, please use a custom kernel"
esac esac
@ -118,30 +124,7 @@ case $? in
ui_print "- Magisk patched image detected!" ui_print "- Magisk patched image detected!"
# Find SHA1 of stock boot image # Find SHA1 of stock boot image
[ -z $SHA1 ] && SHA1=`./magiskboot --cpio-stocksha1 ramdisk.cpio 2>/dev/null` [ -z $SHA1 ] && SHA1=`./magiskboot --cpio-stocksha1 ramdisk.cpio 2>/dev/null`
OK=false
./magiskboot --cpio-restore ramdisk.cpio ./magiskboot --cpio-restore ramdisk.cpio
if [ $? -eq 0 ]; then
ui_print "- Ramdisk restored from internal backup"
OK=true
else
# Restore failed
ui_print "! Cannot restore from internal backup"
# If we are root and SHA1 known, we try to find the stock backup
if [ ! -z $SHA1 ]; then
STOCKDUMP=/data/stock_boot_${SHA1}.img.gz
if [ -f $STOCKDUMP ]; then
ui_print "- Stock boot image backup found"
./magiskboot --decompress $STOCKDUMP stock_boot.img
./magiskboot --unpack stock_boot.img
rm -f stock_boot.img
OK=true
fi
fi
fi
if ! $OK; then
ui_print "! Ramdisk restoration incomplete"
ui_print "! Will still try to continue installation"
fi
cp -af ramdisk.cpio ramdisk.cpio.orig cp -af ramdisk.cpio ramdisk.cpio.orig
;; ;;
2 ) # Other patched 2 ) # Other patched
@ -156,14 +139,21 @@ esac
ui_print "- Patching ramdisk" ui_print "- Patching ramdisk"
./magiskboot --cpio-add ramdisk.cpio 750 init magiskinit [ -f /sdcard/ramdisk-recovery.img ] && HIGH_COMP=true
./magiskboot --cpio-patch ramdisk.cpio $KEEPVERITY $KEEPFORCEENCRYPT
# Create ramdisk backups ./magiskboot --cpio-patch ramdisk.cpio $KEEPVERITY $KEEPFORCEENCRYPT
./magiskboot --cpio-backup ramdisk.cpio ramdisk.cpio.orig $SHA1 ./magiskboot --cpio-add ramdisk.cpio 750 init magiskinit
./magiskboot --cpio-backup ramdisk.cpio ramdisk.cpio.orig $HIGH_COMP $SHA1
rm -f ramdisk.cpio.orig rm -f ramdisk.cpio.orig
if [ -f /sdcard/ramdisk-recovery.img ]; then
ui_print "- Adding ramdisk-recovery.img"
./magiskboot --decompress - < /sdcard/ramdisk-recovery.img | ./magiskboot --compress=xz - ramdisk-recovery.xz
./magiskboot --cpio-add ramdisk.cpio 0 ramdisk-recovery.xz ramdisk-recovery.xz
rm ramdisk-recovery.xz
fi
########################################################################################## ##########################################################################################
# Binary patches # Binary patches
########################################################################################## ##########################################################################################

View File

@ -84,7 +84,7 @@ getvar() {
local VARNAME=$1 local VARNAME=$1
local VALUE=$(eval echo \$$VARNAME) local VALUE=$(eval echo \$$VARNAME)
[ ! -z $VALUE ] && return [ ! -z $VALUE ] && return
for DIR in /dev /data /cache /system; do for DIR in /.backup /data /cache /system; do
VALUE=`grep_prop $VARNAME $DIR/.magisk` VALUE=`grep_prop $VARNAME $DIR/.magisk`
[ ! -z $VALUE ] && break; [ ! -z $VALUE ] && break;
done done