int main(int argc, char *argv[]) { int in; int out; int i; int ret; struct sparse_file *s; if (argc < 3) { usage(); exit(-1); } out = open(argv[argc - 1], O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0664); if (out < 0) { fprintf(stderr, "Cannot open output file %s\n", argv[argc - 1]); exit(-1); } for (i = 1; i < argc - 1; i++) { if (strcmp(argv[i], "-") == 0) { in = STDIN_FILENO; } else { in = open(argv[i], O_RDONLY | O_BINARY); if (in < 0) { fprintf(stderr, "Cannot open input file %s\n", argv[i]); exit(-1); } } s = sparse_file_import(in, true, false); if (!s) { fprintf(stderr, "Failed to read sparse file\n"); exit(-1); } lseek(out, SEEK_SET, 0); ret = sparse_file_write(s, out, false, false, false); if (ret < 0) { fprintf(stderr, "Cannot write output file\n"); exit(-1); } sparse_file_destroy(s); close(in); } close(out); exit(0); }
int main(int argc, char* argv[]) { if (argc != 4 || strcmp(argv[2], "-mincrypt") != 0) { printf("Usage: %s <image> -mincrypt <verity_key>\n" " image the image file (raw or sparse image) to be verified\n" " verity_key the verity key in mincrypt format (/verity_key on device)\n", argv[0]); return 2; } // Get the raw image. android::base::unique_fd fd(open(argv[1], O_RDONLY)); if (!fd) { fprintf(stderr, "failed to open %s: %s\n", argv[1], strerror(errno)); return 1; } struct sparse_file* file = sparse_file_import_auto(fd, false, false); if (file == nullptr) { fprintf(stderr, "failed to read file %s\n", argv[1]); return 1; } TemporaryFile tf; if (sparse_file_write(file, tf.fd, false, false, false) < 0) { fprintf(stderr, "failed to write output file\n"); return 1; } sparse_file_destroy(file); // Verify. fec::io input(tf.path); if (!input) { return 1; } fec_verity_metadata verity; if (!input.get_verity_metadata(verity)) { fprintf(stderr, "failed to get verity metadata\n"); return 1; } int ret = verify_table(argv[3], verity.signature, sizeof(verity.signature), verity.table, verity.table_length); printf("%s\n", ret == 0 ? "VERIFIED" : "FAILED"); return ret; }
int make_f2fs_sparse_fd(int fd, long long len, const char *mountpoint, struct selabel_handle *sehnd) { if (dlopenf2fs() < 0) { return -1; } reset_f2fs_info(); f2fs_init_configuration(&config); len &= ~((__u64)F2FS_BLKSIZE); config.total_sectors = len / config.sector_size; config.start_sector = 0; f2fs_sparse_file = sparse_file_new(F2FS_BLKSIZE, len); f2fs_format_device(); sparse_file_write(f2fs_sparse_file, fd, /*gzip*/0, /*sparse*/1, /*crc*/0); sparse_file_destroy(f2fs_sparse_file); flush_sparse_buffs(); f2fs_sparse_file = NULL; return 0; }
int img2simg_main(int argc, char *argv[]) { int in; int out; int ret; struct sparse_file *s; unsigned int block_size = 4096; off64_t len; if (argc < 3 || argc > 4) { img2simg_usage(); return(-1); } if (argc == 4) { block_size = atoi(argv[3]); } if (block_size < 1024 || block_size % 4 != 0) { img2simg_usage(); return(-1); } if (strcmp(argv[1], "-") == 0) { in = STDIN_FILENO; } else { in = open(argv[1], O_RDONLY | O_BINARY); if (in < 0) { fprintf(stderr, "Cannot open input file %s\n", argv[1]); return(-1); } } if (strcmp(argv[2], "-") == 0) { out = STDOUT_FILENO; } else { out = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0664); if (out < 0) { fprintf(stderr, "Cannot open output file %s\n", argv[2]); return(-1); } } len = lseek64(in, 0, SEEK_END); lseek64(in, 0, SEEK_SET); s = sparse_file_new(block_size, len); if (!s) { fprintf(stderr, "Failed to create sparse file\n"); return(-1); } sparse_file_verbose(s); ret = sparse_file_read(s, in, false, false); if (ret) { fprintf(stderr, "Failed to read file\n"); return(-1); } ret = sparse_file_write(s, out, false, true, false); if (ret) { fprintf(stderr, "Failed to write sparse file\n"); return(-1); } close(in); close(out); return(0); }
/* Write the filesystem image to a file */ void write_ext4_image(int fd, int gz, int sparse, int crc) { sparse_file_write(info.sparse_file, fd, gz, sparse, crc); }
bool handle_command(Socket *client, std::string cmd, std::vector<std::string> args) { const char *trampfile = "/data/misc/fastbootd/mid.bin"; if (cmd == "getvar") { if (args[0] == "max-download-size") { return send_reply(client, "OKAY", "%d", kMaxDownloadSize); } else if (args[0] == "partition-type") { for (size_t i = 0; i < sizeof(part_info) / sizeof(part_info[0]); i++) { if (args[1] == part_info[i].name) { return send_reply(client, "OKAY", part_info[i].type); } } } else if (args[0] == "product") { char property[PROPERTY_VALUE_MAX]; property_get("ro.product.board", property, ""); return send_reply(client, "OKAY", property); } else if (args[0] == "serialno") { char property[PROPERTY_VALUE_MAX]; property_get("ro.serialno", property, ""); return send_reply(client, "OKAY", property); } else if (args[0] == "version-bootloader") { return send_reply(client, "OKAY", "0.1"); } return send_reply(client, "OKAY", ""); } else if (cmd == "download") { uint32_t size = strtol(args[0].c_str(), 0, 16); send_reply(client, "DATA", "%08x", size); int fd = open(trampfile, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fd < 0) { send_reply(client, "FAIL", "fail to create trampoline file to store data!"); return false; } while (size > 0) { char buffer[4096]; ssize_t read = client->Receive(buffer, 8, 0); if (read != 8) { send_reply(client, "FAIL", "fail to receive data!"); close(fd); return false; } size_t length = ExtractMessageLength(buffer); do { read = client->Receive(buffer, std::min(length, sizeof(buffer)), 0); if (read < 0) { close(fd); return false; } write(fd, buffer, read); length -= read; size -= read; } while (length > 0); } close(fd); return send_reply(client, "OKAY", ""); } else if (cmd == "flash") { std::unique_ptr<char, int (*)(const char *)> tmpfile((char *)trampfile, unlink); int fd = open(tmpfile.get(), O_RDONLY); if (fd < 0) { send_reply(client, "FAIL", "please run download command first!"); return false; } const char *devname = NULL; const char *partname = NULL; for (size_t i = 0; i < sizeof(part_info) / sizeof(part_info[0]); i++) { if (args[0] == part_info[i].name) { devname = part_info[i].device; partname = part_info[i].name; break; } } if (devname == NULL) { close(fd); send_reply(client, "FAIL", "partition: %s does not exist!", args[0].c_str()); return false; } if (!strcmp("boot", partname)) { close(fd); return handle_command_flash_boot_partition(client, tmpfile.get(), devname); } int fddev = open(devname, O_WRONLY | O_CREAT, 0600); if (fddev < 0) { close(fd); send_reply(client, "FAIL", "failed to open partition: %s", args[0].c_str()); return false; } struct sparse_file *s = sparse_file_import(fd, true, false); if (!s) { close(fd); close(fddev); send_reply(client, "FAIL", "failed to read sparse file!"); return false; } sparse_file_write(s, fddev, false, false, false); sparse_file_destroy(s); close(fd); close(fddev); sync(); return send_reply(client, "OKAY", ""); } else if (cmd == "erase") { const char *devname = NULL; for (size_t i = 0; i < sizeof(part_info) / sizeof(part_info[0]); i++) { if (args[0] == part_info[i].name) { devname = part_info[i].device; break; } } if (devname == NULL) { send_reply(client, "FAIL", "partition: %s does not exist!", args[0].c_str()); return false; } uint64_t devsize = 0; int fd = open(devname, O_RDONLY); ioctl(fd, BLKGETSIZE64, &devsize); const uint64_t blksize = 64 * 1024; const uint64_t numblk = (devsize + blksize - 1) / blksize; const uint64_t updsize = (numblk / 10) * blksize; for (uint64_t offset = 0; offset < devsize; offset += updsize) { uint64_t realsize = std::min(updsize, devsize - offset); const char *argv[] = { "/system/bin/dd", "if=/dev/zero", android::base::StringPrintf("of=%s", devname).c_str(), android::base::StringPrintf("seek=%lld", offset).c_str(), android::base::StringPrintf("bs=%lld", realsize).c_str(), "count=1", }; int status; android_fork_execvp(sizeof(argv) / sizeof(argv[0]), (char **)argv, &status, true, true); send_reply(client, "INFO", android::base::StringPrintf("erase %s: %3lld/100", devname, (offset + realsize) * 100 / devsize).c_str()); } return send_reply(client, "OKAY", ""); } else if (cmd == "continue") { android::base::WriteStringToFile("5", "/sys/module/bcm2709/parameters/reboot_part"); android_reboot(ANDROID_RB_RESTART, 0, NULL); // while (true) { pause(); } return send_reply(client, "OKAY", ""); } else if (cmd == "reboot" || cmd == "reboot-bootloader") { android::base::WriteStringToFile("0", "/sys/module/bcm2709/parameters/reboot_part"); android_reboot(ANDROID_RB_RESTART, 0, NULL); // while (true) { pause(); } return send_reply(client, "OKAY", ""); } return send_reply(client, "FAIL", "unknown command: %s", cmd.c_str()); }