Magisk/jni/magiskboot/repack.c

167 lines
3.7 KiB
C
Raw Normal View History

2017-02-27 21:37:47 +00:00
#include "magiskboot.h"
// Global pointer of output
2017-02-24 06:58:44 +00:00
static int ofd, opos;
2017-02-24 19:29:12 +00:00
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(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;
return size;
}
2017-02-24 19:29:12 +00:00
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);
}
opos += size;
}
2017-02-24 19:29:12 +00:00
static void page_align() {
uint32_t pagemask = hdr.page_size - 1L;
if (opos & pagemask) {
2017-02-24 19:29:12 +00:00
opos += hdr.page_size - (opos & pagemask);
}
ftruncate(ofd, opos);
lseek(ofd, 0, SEEK_END);
}
2017-02-27 21:37:47 +00:00
void repack(const char* image) {
// Load original image
int ifd = open(image, O_RDONLY);
2017-02-24 19:29:12 +00:00
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);
2017-02-27 21:37:47 +00:00
// Parse original image
parse_img(orig, isize);
2017-02-27 21:37:47 +00:00
// Create new boot image
ofd = open("new-boot.img", O_RDWR | O_CREAT | O_TRUNC, 0644);
2017-02-27 21:37:47 +00:00
char name[PATH_MAX];
#define EXT_NUM 6
char *ext_list[EXT_NUM] = { "gz", "lzo", "xz", "lzma", "bz2", "lz4" };
2017-02-24 19:29:12 +00:00
// Set all sizes to 0
hdr.kernel_size = 0;
hdr.ramdisk_size = 0;
hdr.second_size = 0;
hdr.dt_size = 0;
2017-02-24 19:29:12 +00:00
// Skip a page for header
ftruncate(ofd, hdr.page_size);
lseek(ofd, 0, SEEK_END);
opos += hdr.page_size;
2017-02-24 19:29:12 +00:00
// Restore kernel
2017-02-27 21:37:47 +00:00
if (mtk_kernel) {
2017-02-24 19:29:12 +00:00
restore_buf(512, kernel);
hdr.kernel_size += 512;
}
2017-02-27 21:37:47 +00:00
hdr.kernel_size += restore(KERNEL_FILE);
2017-02-24 19:29:12 +00:00
page_align();
2017-02-27 21:37:47 +00:00
// Restore ramdisk
if (mtk_ramdisk) {
2017-02-24 19:29:12 +00:00
restore_buf(512, ramdisk);
hdr.ramdisk_size += 512;
}
2017-02-27 21:37:47 +00:00
if (access(RAMDISK_FILE, R_OK) == 0) {
// If we found raw cpio, recompress 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);
switch (ramdisk_type) {
case GZIP:
sprintf(name, "%s.%s", RAMDISK_FILE, "gz");
2017-02-28 16:46:11 +00:00
gzip(1, name, cpio, cpio_size);
2017-02-27 21:37:47 +00:00
break;
case LZOP:
sprintf(name, "%s.%s", RAMDISK_FILE, "lzo");
2017-03-01 20:12:47 +00:00
error(1, "Unsupported format! Please compress manually!");
2017-02-27 21:37:47 +00:00
break;
case XZ:
sprintf(name, "%s.%s", RAMDISK_FILE, "xz");
2017-02-28 16:46:11 +00:00
lzma(1, name, cpio, cpio_size);
2017-02-27 21:37:47 +00:00
break;
case LZMA:
sprintf(name, "%s.%s", RAMDISK_FILE, "lzma");
2017-02-28 16:46:11 +00:00
lzma(2, name, cpio, cpio_size);
2017-02-27 21:37:47 +00:00
break;
case BZIP2:
sprintf(name, "%s.%s", RAMDISK_FILE, "bz2");
2017-03-01 21:23:31 +00:00
bzip2(1, name, cpio, cpio_size);
2017-02-27 21:37:47 +00:00
break;
case LZ4:
sprintf(name, "%s.%s", RAMDISK_FILE, "lz4");
2017-03-01 20:12:47 +00:00
lz4(1, name, cpio, cpio_size);
2017-02-27 21:37:47 +00:00
break;
default:
// Never happens
break;
}
munmap(cpio, cpio_size);
close(rfd);
} else {
2017-02-27 21:37:47 +00:00
// If no raw cpio found, find compressed ones
int found = 0;
for (int i = 0; i < EXT_NUM; ++i) {
sprintf(name, "%s.%s", RAMDISK_FILE, ext_list[i]);
if (access(name, R_OK) == 0) {
found = 1;
break;
}
}
if (!found) {
error(1, "No ramdisk exists!");
}
}
2017-02-27 21:37:47 +00:00
2017-02-24 19:29:12 +00:00
hdr.ramdisk_size += restore(name);
page_align();
2017-02-27 21:37:47 +00:00
// Restore second
if (access(SECOND_FILE, R_OK) == 0) {
hdr.second_size += restore(SECOND_FILE);
2017-02-24 19:29:12 +00:00
page_align();
}
2017-02-27 21:37:47 +00:00
// Restore dtb
if (access(DTB_FILE, R_OK) == 0) {
hdr.dt_size += restore(DTB_FILE);
2017-02-24 19:29:12 +00:00
page_align();
}
// Write header back
lseek(ofd, 0, SEEK_SET);
write(ofd, &hdr, sizeof(hdr));
munmap(orig, isize);
close(ifd);
2017-02-24 19:29:12 +00:00
close(ofd);
2017-02-27 21:37:47 +00:00
if (opos > isize) {
error(2, "Boot partition too small!");
}
}