Magisk/jni/bootimgtools/unpack.c

112 lines
2.8 KiB
C
Raw Normal View History

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sendfile.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <assert.h>
#include <string.h>
2016-12-09 08:57:10 +01:00
#include "bootimg.h"
2017-02-24 20:29:12 +01:00
#include "elf.h"
2017-02-24 20:29:12 +01:00
static void dump(unsigned char *buf, size_t size, const char *filename) {
unlink(filename);
int ofd = open(filename, O_WRONLY | O_CREAT, 0644);
2017-02-24 20:29:12 +01:00
if (ofd < 0)
error(1, "Cannot open %s", filename);
if (write(ofd, buf, size) != size)
error(1, "Cannot dump %s", filename);
close(ofd);
}
2017-02-24 20:29:12 +01:00
int unpack(const char* image) {
int fd = open(image, O_RDONLY), ret = 0;
if (fd < 0)
error(1, "Cannot open %s", image);
2017-02-24 20:29:12 +01:00
size_t size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
unsigned char *orig = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
2017-02-24 20:29:12 +01:00
// Parse images
for(base = orig; base < (orig + size); base += 256) {
if (memcmp(base, CHROMEOS_MAGIC, CHROMEOS_MAGIC_SIZE) == 0) {
dump(base, 0, "chromeos");
} else if (memcmp(base, BOOT_MAGIC, BOOT_MAGIC_SIZE) == 0) {
parse_aosp();
break;
} else if (memcmp(base, ELF_MAGIC, ELF_MAGIC_SIZE) == 0) {
parse_elf();
break;
}
}
2017-02-24 20:29:12 +01:00
char name[PATH_MAX], *ext;
2017-02-24 20:29:12 +01:00
// Dump kernel
if (memcmp(kernel, "\x88\x16\x88\x58", 4) == 0) {
printf("MTK header found in kernel\n");
kernel += 512;
hdr.kernel_size -= 512;
}
2017-02-24 20:29:12 +01:00
dump(kernel, hdr.kernel_size, "kernel");
// Dump ramdisk
2017-02-24 20:29:12 +01:00
if (memcmp(ramdisk, "\x88\x16\x88\x58", 4) == 0) {
printf("MTK header found in ramdisk\n");
2017-02-24 20:29:12 +01:00
ramdisk += 512;
hdr.ramdisk_size -= 512;
}
// Compression detection
2017-02-24 20:29:12 +01:00
if (memcmp(ramdisk, "\x1f\x8b\x08\x00", 4) == 0) {
// gzip header
2017-02-24 20:29:12 +01:00
printf("COMPRESSION [gzip]\n");
ext = "gz";
2017-02-24 20:29:12 +01:00
} else if (memcmp(ramdisk, "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a", 9) == 0) {
// lzop header
2017-02-24 20:29:12 +01:00
printf("COMPRESSION [lzop]\n");
ext = "lzo";
2017-02-24 20:29:12 +01:00
} else if (memcmp(ramdisk, "\xfd""7zXZ\x00", 6) == 0) {
// xz header
2017-02-24 20:29:12 +01:00
printf("COMPRESSION [xz]\n");
ext = "xz";
2017-02-24 20:29:12 +01:00
} else if (memcmp(ramdisk, "\x5d\x00\x00", 3) == 0
&& (ramdisk[12] == (unsigned char) '\xff' || ramdisk[12] == (unsigned char) '\x00')) {
// lzma header
2017-02-24 20:29:12 +01:00
printf("COMPRESSION [lzma]\n");
ext = "lzma";
2017-02-24 20:29:12 +01:00
} else if (memcmp(ramdisk, "BZh", 3) == 0) {
// bzip2 header
2017-02-24 20:29:12 +01:00
printf("COMPRESSION [bzip2]\n");
ext = "bz2";
2017-02-24 20:29:12 +01:00
} else if ( ( memcmp(ramdisk, "\x04\x22\x4d\x18", 4) == 0
|| memcmp(ramdisk, "\x03\x21\x4c\x18", 4) == 0)
|| memcmp(ramdisk, "\x02\x21\x4c\x18", 4) == 0) {
// lz4 header
2017-02-24 20:29:12 +01:00
printf("COMPRESSION [lz4]\n");
ext = "lz4";
} else {
2017-02-24 20:29:12 +01:00
error(1, "Unknown ramdisk format!");
}
sprintf(name, "%s.%s", "ramdisk", ext);
2017-02-24 20:29:12 +01:00
dump(ramdisk, hdr.ramdisk_size, name);
if (hdr.second_size) {
// Dump second
2017-02-24 20:29:12 +01:00
dump(second, hdr.second_size, "second");
}
if (hdr.dt_size) {
// Dump dtb
2017-02-24 20:29:12 +01:00
dump(dtb, hdr.dt_size, "dtb");
}
munmap(orig, size);
close(fd);
return ret;
}