#include #include #include "magiskboot.hpp" #include "compress.hpp" using namespace std; static void print_formats() { for (int fmt = GZIP; fmt < LZOP; ++fmt) { fprintf(stderr, "%s ", fmt2name[(format_t) fmt]); } } static void usage(char *arg0) { fprintf(stderr, R"EOF(MagiskBoot - Boot Image Modification Tool Usage: %s [args...] Supported actions: unpack [-n] [-h] Unpack to its individual components, each component to a file with its corresponding file name in the current directory. Supported components: kernel, kernel_dtb, ramdisk.cpio, second, dtb, extra, and recovery_dtbo. By default, each component will be automatically decompressed on-the-fly before writing to the output file. If '-n' is provided, all decompression operations will be skipped; each component will remain untouched, dumped in its original format. If '-h' is provided, the boot image header information will be dumped to the file 'header', which can be used to modify header configurations during repacking. Return values: 0:valid 1:error 2:chromeos repack [-n] [outbootimg] Repack boot image components using files from the current directory to [outbootimg], or 'new-boot.img' if not specified. is the original boot image used to unpack the components. By default, each component will be automatically compressed using its corresponding format detected in . If a component file in the current directory is already compressed, then no addition compression will be performed for that specific component. If '-n' is provided, all compression operations will be skipped. If env variable PATCHVBMETAFLAG is set to true, all disable flags in the boot image's vbmeta header will be set. extract Extract the boot image from payload.bin to . hexpatch Search in , and replace it with cpio [commands...] Do cpio commands to (modifications are done in-place) Each command is a single argument, add quotes for each command. Supported commands: exists ENTRY Return 0 if ENTRY exists, else return 1 rm [-r] ENTRY Remove ENTRY, specify [-r] to remove recursively mkdir MODE ENTRY Create directory ENTRY in permissions MODE ln TARGET ENTRY Create a symlink to TARGET with the name ENTRY mv SOURCE DEST Move SOURCE to DEST add MODE ENTRY INFILE Add INFILE as ENTRY in permissions MODE; replaces ENTRY if exists extract [ENTRY OUT] Extract ENTRY to OUT, or extract all entries to current directory test Test the cpio's status Return value is 0 or bitwise or-ed of following values: 0x1:Magisk 0x2:unsupported 0x4:Sony patch Apply ramdisk patches Configure with env variables: KEEPVERITY KEEPFORCEENCRYPT backup ORIG Create ramdisk backups from ORIG restore Restore ramdisk from ramdisk backup stored within incpio sha1 Print stock boot SHA1 if previously backed up in ramdisk dtb [args...] Do dtb related actions to Supported actions: print [-f] Print all contents of dtb for debugging Specify [-f] to only print fstab nodes patch Search for fstab and remove verity/avb Modifications are done directly to the file in-place Configure with env variables: KEEPVERITY test Test the fstab's status Return values: 0:valid 1:error split Split image.*-dtb into kernel + kernel_dtb sha1 Print the SHA1 checksum for cleanup Cleanup the current working directory compress[=format] [outfile] Compress with [format] to [outfile]. /[outfile] can be '-' to be STDIN/STDOUT. If [format] is not specified, then gzip will be used. If [outfile] is not specified, then will be replaced with another file suffixed with a matching file extension. Supported formats: )EOF", arg0); print_formats(); fprintf(stderr, R"EOF( decompress [outfile] Detect format and decompress to [outfile]. /[outfile] can be '-' to be STDIN/STDOUT. If [outfile] is not specified, then will be replaced with another file removing its archive format file extension. Supported formats: )EOF"); print_formats(); fprintf(stderr, "\n\n"); exit(1); } int main(int argc, char *argv[]) { cmdline_logging(); umask(0); if (argc < 2) usage(argv[0]); // Skip '--' for backwards compatibility string_view action(argv[1]); if (str_starts(action, "--")) action = argv[1] + 2; if (action == "cleanup") { fprintf(stderr, "Cleaning up...\n"); unlink(HEADER_FILE); unlink(KERNEL_FILE); unlink(RAMDISK_FILE); unlink(SECOND_FILE); unlink(KER_DTB_FILE); unlink(EXTRA_FILE); unlink(RECV_DTBO_FILE); unlink(DTB_FILE); } else if (argc > 2 && action == "sha1") { uint8_t sha1[SHA_DIGEST_SIZE]; auto m = mmap_data(argv[2]); SHA_hash(m.buf, m.sz, sha1); for (uint8_t i : sha1) printf("%02x", i); printf("\n"); } else if (argc > 2 && action == "split") { return split_image_dtb(argv[2]); } else if (argc > 2 && action == "unpack") { int idx = 2; bool nodecomp = false; bool hdr = false; for (;;) { if (idx >= argc) usage(argv[0]); if (argv[idx][0] != '-') break; for (char *flag = &argv[idx][1]; *flag; ++flag) { if (*flag == 'n') nodecomp = true; else if (*flag == 'h') hdr = true; else usage(argv[0]); } ++idx; } return unpack(argv[idx], nodecomp, hdr); } else if (argc > 2 && action == "repack") { if (argv[2] == "-n"sv) { if (argc == 3) usage(argv[0]); repack(argv[3], argv[4] ? argv[4] : NEW_BOOT, true); } else { repack(argv[2], argv[3] ? argv[3] : NEW_BOOT); } } else if (argc > 2 && action == "decompress") { decompress(argv[2], argv[3]); } else if (argc > 2 && str_starts(action, "compress")) { compress(action[8] == '=' ? &action[9] : "gzip", argv[2], argv[3]); } else if (argc > 4 && action == "hexpatch") { return hexpatch(argv[2], argv[3], argv[4]); } else if (argc > 2 && action == "cpio"sv) { if (cpio_commands(argc - 2, argv + 2)) usage(argv[0]); } else if (argc > 3 && action == "dtb") { if (dtb_commands(argc - 2, argv + 2)) usage(argv[0]); } else if (argc > 3 && action == "extract") { return rust::extract_boot_from_payload(argv[2], argv[3]) ? 0 : 1; } else { usage(argv[0]); } return 0; }