Add split command to magiskboot

Allow splitting image.*-dtb files to kernel and dtb
This commit is contained in:
topjohnwu 2019-12-30 13:04:39 +08:00
parent 46ba726232
commit 78c64d39ec
3 changed files with 53 additions and 22 deletions

View File

@ -282,33 +282,61 @@ void boot_img::parse_image(uint8_t *addr) {
fprintf(stderr, "RAMDISK_FMT [%s]\n", fmt2name[r_fmt]);
}
void boot_img::find_kernel_dtb() {
const int eof = static_cast<int>(hdr->kernel_size());
for (int i = 0; i < eof - (int) sizeof(fdt_header); ++i) {
auto fdt_hdr = reinterpret_cast<fdt_header *>(kernel + i);
static int find_dtb_offset(uint8_t *buf, int sz) {
for (int off = 0; off < sz - (int) sizeof(fdt_header); ++off) {
auto fdt_hdr = reinterpret_cast<fdt_header *>(buf + off);
if (fdt32_to_cpu(fdt_hdr->magic) != FDT_MAGIC)
continue;
// Check that fdt_header.totalsize does not overflow kernel image size
uint32_t totalsize = fdt32_to_cpu(fdt_hdr->totalsize);
if (totalsize + i > eof)
if (totalsize + off > sz)
continue;
// Check that fdt_header.off_dt_struct does not overflow kernel image size
uint32_t off_dt_struct = fdt32_to_cpu(fdt_hdr->off_dt_struct);
if (off_dt_struct + i > eof)
if (off_dt_struct + off > sz)
continue;
// Check that fdt_node_header.tag of first node is FDT_BEGIN_NODE
auto fdt_node_hdr = reinterpret_cast<fdt_node_header *>(kernel + i + off_dt_struct);
auto fdt_node_hdr = reinterpret_cast<fdt_node_header *>(buf + off + off_dt_struct);
if (fdt32_to_cpu(fdt_node_hdr->tag) != FDT_BEGIN_NODE)
continue;
kernel_dtb = kernel + i;
kernel_dt_size = eof - i;
hdr->kernel_size() = i;
return off;
}
return -1;
}
void boot_img::find_kernel_dtb() {
if (int off = find_dtb_offset(kernel, hdr->kernel_size()); off > 0) {
kernel_dtb = kernel + off;
kernel_dt_size = hdr->kernel_size() - off;
hdr->kernel_size() = off;
fprintf(stderr, "KERNEL_DTB [%u]\n", kernel_dt_size);
break;
}
}
int split_image_dtb(const char *filename) {
uint8_t *buf;
size_t sz;
mmap_ro(filename, buf, sz);
run_finally f([=]{ munmap(buf, sz); });
if (int off = find_dtb_offset(buf, sz); off > 0) {
format_t fmt = check_fmt(buf, sz);
if (COMPRESSED(fmt)) {
int fd = creat(KERNEL_FILE, 0644);
decompress(fmt, fd, buf, off);
close(fd);
} else {
dump(buf, off, KERNEL_FILE);
}
dump(buf + off, sz - off, KER_DTB_FILE);
return 0;
} else {
fprintf(stderr, "Cannot find DTB in %s\n", filename);
return 1;
}
}

View File

@ -14,6 +14,7 @@
int unpack(const char *image, bool nodecomp = false, bool hdr = false);
void repack(const char* src_img, const char* out_img, bool nocomp = false);
int split_image_dtb(const char *filename);
int hexpatch(const char *image, const char *from, const char *to);
int cpio_commands(int argc, char *argv[]);
int dtb_commands(int argc, char *argv[]);

View File

@ -84,6 +84,15 @@ Supported actions:
If [OUT] is not specified, it will directly output to <input>
Configure with env variables: KEEPVERITY TWOSTAGEINIT
split <input>
Split image.*-dtb into kernel + kernel_dtb
sha1 <file>
Print the SHA1 checksum for <file>
cleanup
Cleanup the current working directory
compress[=method] <infile> [outfile]
Compress <infile> with [method] (default: gzip), optionally to [outfile]
<infile>/[outfile] can be '-' to be STDIN/STDOUT
@ -102,16 +111,7 @@ Supported actions:
for (auto &it : name2fmt)
fprintf(stderr, "%s ", it.first.data());
fprintf(stderr, R"EOF(
sha1 <file>
Print the SHA1 checksum for <file>
cleanup
Cleanup the current working directory
)EOF");
fprintf(stderr, "\n\n");
exit(1);
}
@ -147,6 +147,8 @@ int main(int argc, char *argv[]) {
printf("%02x", i);
printf("\n");
munmap(buf, size);
} else if (argc > 2 && action == "split") {
return split_image_dtb(argv[2]);
} else if (argc > 2 && action == "unpack") {
int idx = 2;
bool nodecomp = false;