static int info_cmd(int argc, char *argv[]) { image_t *image; uint64_t image_offset; uint64_t image_size = 0; fip_toc_header_t toc_header; int i; if (argc != 2) info_usage(); argc--, argv++; parse_fip(argv[0], &toc_header); if (verbose) { log_dbgx("toc_header[name]: 0x%llX", (unsigned long long)toc_header.name); log_dbgx("toc_header[serial_number]: 0x%llX", (unsigned long long)toc_header.serial_number); log_dbgx("toc_header[flags]: 0x%llX", (unsigned long long)toc_header.flags); } image_offset = sizeof(fip_toc_header_t) + (sizeof(fip_toc_entry_t) * (nr_images + 1)); for (i = 0; i < nr_images; i++) { toc_entry_t *toc_entry; image = images[i]; toc_entry = lookup_entry_from_uuid(&image->uuid); if (toc_entry != NULL) printf("%s: ", toc_entry->name); else printf("Unknown entry: "); image_size = image->size; printf("offset=0x%llX, size=0x%llX", (unsigned long long)image_offset, (unsigned long long)image_size); if (toc_entry != NULL) printf(", cmdline=\"--%s\"", toc_entry->cmdline_name); if (verbose) { unsigned char md[SHA256_DIGEST_LENGTH]; SHA256(image->buffer, image_size, md); printf(", sha256="); md_print(md, sizeof(md)); } putchar('\n'); image_offset += image_size; } free_images(); return 0; }
static int info_cmd(int argc, char *argv[]) { image_t *image; uint64_t image_offset; uint64_t image_size = 0; fip_toc_header_t toc_header; int i; if (argc != 2) usage(); argc--, argv++; parse_fip(argv[0], &toc_header); if (verbose) { log_dbgx("toc_header[name]: 0x%llX", (unsigned long long)toc_header.name); log_dbgx("toc_header[serial_number]: 0x%llX", (unsigned long long)toc_header.serial_number); log_dbgx("toc_header[flags]: 0x%llX", (unsigned long long)toc_header.flags); } image_offset = sizeof(fip_toc_header_t) + (sizeof(fip_toc_entry_t) * (nr_images + 1)); for (i = 0; i < nr_images; i++) { image = images[i]; if (image->toc_entry != NULL) printf("%s: ", image->toc_entry->name); else printf("Unknown entry: "); image_size = image->size; printf("offset=0x%llX, size=0x%llX", (unsigned long long)image_offset, (unsigned long long)image_size); if (image->toc_entry != NULL) printf(", cmdline=\"--%s\"\n", image->toc_entry->cmdline_name); else putchar('\n'); image_offset += image_size; } free_images(); return 0; }
static int info_cmd(int argc, char *argv[]) { image_desc_t *desc; fip_toc_header_t toc_header; if (argc != 2) info_usage(); argc--, argv++; parse_fip(argv[0], &toc_header); if (verbose) { log_dbgx("toc_header[name]: 0x%llX", (unsigned long long)toc_header.name); log_dbgx("toc_header[serial_number]: 0x%llX", (unsigned long long)toc_header.serial_number); log_dbgx("toc_header[flags]: 0x%llX", (unsigned long long)toc_header.flags); } for (desc = image_desc_head; desc != NULL; desc = desc->next) { image_t *image = desc->image; if (image == NULL) continue; printf("%s: offset=0x%llX, size=0x%llX, cmdline=\"--%s\"", desc->name, (unsigned long long)image->toc_e.offset_address, (unsigned long long)image->toc_e.size, desc->cmdline_name); #ifndef _MSC_VER /* We don't have SHA256 for Visual Studio. */ if (verbose) { unsigned char md[SHA256_DIGEST_LENGTH]; SHA256(image->buffer, image->toc_e.size, md); printf(", sha256="); md_print(md, sizeof(md)); } #endif putchar('\n'); } return 0; }
int main(int argc, char **argv) { int i; int status; char *fip_filename; int do_pack = 0; /* Clear file list table. */ memset(files, 0, sizeof(files)); /* Initialise for getopt_long(). * Use image table as defined at top of file to get options. * Add 'dump' option, 'help' option and end marker. */ static struct option long_options[(sizeof(toc_entry_lookup_list)/ sizeof(entry_lookup_list_t)) + 2]; for (i = 0; /* -1 because we dont want to process end marker in toc table */ i < sizeof(toc_entry_lookup_list)/sizeof(entry_lookup_list_t) - 1; i++) { long_options[i].name = toc_entry_lookup_list[i].command_line_name; /* The only flag defined at the moment is for a FILENAME */ long_options[i].has_arg = toc_entry_lookup_list[i].flags ? 1 : 0; long_options[i].flag = 0; long_options[i].val = OPT_TOC_ENTRY; } /* Add '--dump' option */ long_options[i].name = "dump"; long_options[i].has_arg = 0; long_options[i].flag = 0; long_options[i].val = OPT_DUMP; /* Add '--help' option */ long_options[++i].name = "help"; long_options[i].has_arg = 0; long_options[i].flag = 0; long_options[i].val = OPT_HELP; /* Zero the last entry (required) */ long_options[++i].name = 0; long_options[i].has_arg = 0; long_options[i].flag = 0; long_options[i].val = 0; #ifdef DEBUG /* Print all supported options */ for (i = 0; i < sizeof(long_options)/sizeof(struct option); i++) { printf("long opt (%d) : name = %s\n", i, long_options[i].name); } #endif /* DEBUG */ /* As the package may already exist and is to be updated we need to get * the filename from the arguments and load from it. * NOTE: As this is the first function to look at the program arguments * it causes a failure if bad options were provided. */ fip_filename = get_filename(argc, argv, long_options); /* Try to open the file and load it into memory */ if (fip_filename != NULL) { status = parse_fip(fip_filename); if (status != 0) { return status; } } /* Work through provided program arguments and perform actions */ status = parse_cmdline(argc, argv, long_options, &do_pack); if (status != 0) { return status; }; if (fip_filename == NULL) { printf("ERROR: Missing FIP filename\n"); print_usage(); return 0; } /* Processed all command line options. Create/update the package if * required. */ if (do_pack) { status = pack_images(fip_filename); if (status != 0) { printf("Failed to create package (status = %d).\n", status); } } return status; }
static int remove_cmd(int argc, char *argv[]) { struct option opts[toc_entries_len + 2]; char outfile[FILENAME_MAX] = { 0 }; fip_toc_header_t toc_header; toc_entry_t *toc_entry; int fflag = 0; int i; if (argc < 2) usage(); i = fill_common_opts(opts, no_argument); add_opt(opts, i, "force", no_argument, 'f'); add_opt(opts, ++i, "out", required_argument, 'o'); add_opt(opts, ++i, NULL, 0, 0); while (1) { int c, opt_index; c = getopt_long(argc, argv, "fo:", opts, &opt_index); if (c == -1) break; switch (c) { case OPT_TOC_ENTRY: toc_entry = &toc_entries[opt_index]; toc_entry->action = DO_REMOVE; break; case 'f': fflag = 1; break; case 'o': snprintf(outfile, sizeof(outfile), "%s", optarg); break; default: usage(); } } argc -= optind; argv += optind; if (argc == 0) usage(); if (outfile[0] != '\0' && access(outfile, F_OK) == 0 && !fflag) log_errx("File %s already exists, use --force to overwrite it", outfile); if (outfile[0] == '\0') snprintf(outfile, sizeof(outfile), "%s", argv[0]); parse_fip(argv[0], &toc_header); for (toc_entry = toc_entries; toc_entry->cmdline_name != NULL; toc_entry++) { if (toc_entry->action != DO_REMOVE) continue; if (toc_entry->image != NULL) { if (verbose) log_dbgx("Removing %s.bin", toc_entry->cmdline_name); remove_image(toc_entry->image); } else { log_warnx("Requested image %s.bin is not in %s", toc_entry->cmdline_name, argv[0]); } } pack_images(outfile, toc_header.flags); free_images(); return 0; }
static int unpack_cmd(int argc, char *argv[]) { struct option opts[toc_entries_len + 3]; char file[FILENAME_MAX], outdir[PATH_MAX] = { 0 }; toc_entry_t *toc_entry; int fflag = 0; int unpack_all = 1; int i; if (argc < 2) usage(); i = fill_common_opts(opts, required_argument); add_opt(opts, i, "force", no_argument, 'f'); add_opt(opts, ++i, "out", required_argument, 'o'); add_opt(opts, ++i, NULL, 0, 0); while (1) { int c, opt_index; c = getopt_long(argc, argv, "fo:", opts, &opt_index); if (c == -1) break; switch (c) { case OPT_TOC_ENTRY: unpack_all = 0; toc_entry = &toc_entries[opt_index]; toc_entry->action = DO_UNPACK; toc_entry->action_arg = strdup(optarg); if (toc_entry->action_arg == NULL) log_err("strdup"); break; case 'f': fflag = 1; break; case 'o': snprintf(outdir, sizeof(outdir), "%s", optarg); break; default: usage(); } } argc -= optind; argv += optind; if (argc == 0) usage(); parse_fip(argv[0], NULL); if (outdir[0] != '\0') if (chdir(outdir) == -1) log_err("chdir %s", outdir); /* Mark all images to be unpacked. */ if (unpack_all) { for (toc_entry = toc_entries; toc_entry->cmdline_name != NULL; toc_entry++) { if (toc_entry->image != NULL) { toc_entry->action = DO_UNPACK; toc_entry->action_arg = NULL; } } } /* Unpack all specified images. */ for (toc_entry = toc_entries; toc_entry->cmdline_name != NULL; toc_entry++) { if (toc_entry->action != DO_UNPACK) continue; /* Build filename. */ if (toc_entry->action_arg == NULL) snprintf(file, sizeof(file), "%s.bin", toc_entry->cmdline_name); else snprintf(file, sizeof(file), "%s", toc_entry->action_arg); if (toc_entry->image == NULL) { log_warnx("Requested image %s is not in %s", file, argv[0]); free(toc_entry->action_arg); toc_entry->action_arg = NULL; continue; } if (access(file, F_OK) != 0 || fflag) { if (verbose) log_dbgx("Unpacking %s", file); write_image_to_file(toc_entry->image, file); } else { log_warnx("File %s already exists, use --force to overwrite it", file); } free(toc_entry->action_arg); toc_entry->action_arg = NULL; } free_images(); return 0; }
static int update_cmd(int argc, char *argv[]) { struct option opts[toc_entries_len + 2]; char outfile[FILENAME_MAX] = { 0 }; fip_toc_header_t toc_header = { 0 }; unsigned long long toc_flags = 0; int pflag = 0; int i; if (argc < 2) usage(); i = fill_common_opts(opts, required_argument); add_opt(opts, i, "out", required_argument, 'o'); add_opt(opts, ++i, "plat-toc-flags", required_argument, OPT_PLAT_TOC_FLAGS); add_opt(opts, ++i, NULL, 0, 0); while (1) { int c, opt_index; c = getopt_long(argc, argv, "o:", opts, &opt_index); if (c == -1) break; switch (c) { case OPT_TOC_ENTRY: { toc_entry_t *toc_entry; toc_entry = &toc_entries[opt_index]; toc_entry->action = DO_PACK; toc_entry->action_arg = strdup(optarg); if (toc_entry->action_arg == NULL) log_err("strdup"); break; } case OPT_PLAT_TOC_FLAGS: { parse_plat_toc_flags(optarg, &toc_flags); pflag = 1; break; } case 'o': snprintf(outfile, sizeof(outfile), "%s", optarg); break; default: usage(); } } argc -= optind; argv += optind; if (argc == 0) usage(); if (outfile[0] == '\0') snprintf(outfile, sizeof(outfile), "%s", argv[0]); if (access(outfile, F_OK) == 0) parse_fip(argv[0], &toc_header); if (pflag) toc_header.flags &= ~(0xffffULL << 32); toc_flags = (toc_header.flags |= toc_flags); update_fip(); pack_images(outfile, toc_flags); free_images(); return 0; }
static int remove_cmd(int argc, char *argv[]) { struct option *opts = NULL; size_t nr_opts = 0; char outfile[PATH_MAX] = { 0 }; fip_toc_header_t toc_header; image_desc_t *desc; unsigned long align = 1; int fflag = 0; if (argc < 2) remove_usage(); opts = fill_common_opts(opts, &nr_opts, no_argument); opts = add_opt(opts, &nr_opts, "align", required_argument, OPT_ALIGN); opts = add_opt(opts, &nr_opts, "blob", required_argument, 'b'); opts = add_opt(opts, &nr_opts, "force", no_argument, 'f'); opts = add_opt(opts, &nr_opts, "out", required_argument, 'o'); opts = add_opt(opts, &nr_opts, NULL, 0, 0); while (1) { int c, opt_index = 0; c = getopt_long(argc, argv, "b:fo:", opts, &opt_index); if (c == -1) break; switch (c) { case OPT_TOC_ENTRY: { image_desc_t *desc; desc = lookup_image_desc_from_opt(opts[opt_index].name); set_image_desc_action(desc, DO_REMOVE, NULL); break; } case OPT_ALIGN: align = get_image_align(optarg); break; case 'b': { char name[_UUID_STR_LEN + 1], filename[PATH_MAX]; uuid_t uuid = { 0 }; image_desc_t *desc; parse_blob_opt(optarg, &uuid, filename, sizeof(filename)); if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0) remove_usage(); desc = lookup_image_desc_from_uuid(&uuid); if (desc == NULL) { uuid_to_str(name, sizeof(name), &uuid); desc = new_image_desc(&uuid, name, "blob"); add_image_desc(desc); } set_image_desc_action(desc, DO_REMOVE, NULL); break; } case 'f': fflag = 1; break; case 'o': snprintf(outfile, sizeof(outfile), "%s", optarg); break; default: remove_usage(); } } argc -= optind; argv += optind; free(opts); if (argc == 0) remove_usage(); if (outfile[0] != '\0' && access(outfile, F_OK) == 0 && !fflag) log_errx("File %s already exists, use --force to overwrite it", outfile); if (outfile[0] == '\0') snprintf(outfile, sizeof(outfile), "%s", argv[0]); parse_fip(argv[0], &toc_header); for (desc = image_desc_head; desc != NULL; desc = desc->next) { if (desc->action != DO_REMOVE) continue; if (desc->image != NULL) { if (verbose) log_dbgx("Removing %s", desc->cmdline_name); free(desc->image); desc->image = NULL; } else { log_warnx("%s does not exist in %s", desc->cmdline_name, argv[0]); } } pack_images(outfile, toc_header.flags, align); return 0; }
static int unpack_cmd(int argc, char *argv[]) { struct option *opts = NULL; size_t nr_opts = 0; char outdir[PATH_MAX] = { 0 }; image_desc_t *desc; int fflag = 0; int unpack_all = 1; if (argc < 2) unpack_usage(); opts = fill_common_opts(opts, &nr_opts, required_argument); opts = add_opt(opts, &nr_opts, "blob", required_argument, 'b'); opts = add_opt(opts, &nr_opts, "force", no_argument, 'f'); opts = add_opt(opts, &nr_opts, "out", required_argument, 'o'); opts = add_opt(opts, &nr_opts, NULL, 0, 0); while (1) { int c, opt_index = 0; c = getopt_long(argc, argv, "b:fo:", opts, &opt_index); if (c == -1) break; switch (c) { case OPT_TOC_ENTRY: { image_desc_t *desc; desc = lookup_image_desc_from_opt(opts[opt_index].name); set_image_desc_action(desc, DO_UNPACK, optarg); unpack_all = 0; break; } case 'b': { char name[_UUID_STR_LEN + 1]; char filename[PATH_MAX] = { 0 }; uuid_t uuid = { 0 }; image_desc_t *desc; parse_blob_opt(optarg, &uuid, filename, sizeof(filename)); if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0 || filename[0] == '\0') unpack_usage(); desc = lookup_image_desc_from_uuid(&uuid); if (desc == NULL) { uuid_to_str(name, sizeof(name), &uuid); desc = new_image_desc(&uuid, name, "blob"); add_image_desc(desc); } set_image_desc_action(desc, DO_UNPACK, filename); unpack_all = 0; break; } case 'f': fflag = 1; break; case 'o': snprintf(outdir, sizeof(outdir), "%s", optarg); break; default: unpack_usage(); } } argc -= optind; argv += optind; free(opts); if (argc == 0) unpack_usage(); parse_fip(argv[0], NULL); if (outdir[0] != '\0') if (chdir(outdir) == -1) log_err("chdir %s", outdir); /* Unpack all specified images. */ for (desc = image_desc_head; desc != NULL; desc = desc->next) { char file[PATH_MAX]; image_t *image = desc->image; if (!unpack_all && desc->action != DO_UNPACK) continue; /* Build filename. */ if (desc->action_arg == NULL) snprintf(file, sizeof(file), "%s.bin", desc->cmdline_name); else snprintf(file, sizeof(file), "%s", desc->action_arg); if (image == NULL) { if (!unpack_all) log_warnx("%s does not exist in %s", file, argv[0]); continue; } if (access(file, F_OK) != 0 || fflag) { if (verbose) log_dbgx("Unpacking %s", file); write_image_to_file(image, file); } else { log_warnx("File %s already exists, use --force to overwrite it", file); } } return 0; }
static int update_cmd(int argc, char *argv[]) { struct option *opts = NULL; size_t nr_opts = 0; char outfile[PATH_MAX] = { 0 }; fip_toc_header_t toc_header = { 0 }; unsigned long long toc_flags = 0; unsigned long align = 1; int pflag = 0; if (argc < 2) update_usage(); opts = fill_common_opts(opts, &nr_opts, required_argument); opts = add_opt(opts, &nr_opts, "align", required_argument, OPT_ALIGN); opts = add_opt(opts, &nr_opts, "blob", required_argument, 'b'); opts = add_opt(opts, &nr_opts, "out", required_argument, 'o'); opts = add_opt(opts, &nr_opts, "plat-toc-flags", required_argument, OPT_PLAT_TOC_FLAGS); opts = add_opt(opts, &nr_opts, NULL, 0, 0); while (1) { int c, opt_index = 0; c = getopt_long(argc, argv, "b:o:", opts, &opt_index); if (c == -1) break; switch (c) { case OPT_TOC_ENTRY: { image_desc_t *desc; desc = lookup_image_desc_from_opt(opts[opt_index].name); set_image_desc_action(desc, DO_PACK, optarg); break; } case OPT_PLAT_TOC_FLAGS: parse_plat_toc_flags(optarg, &toc_flags); pflag = 1; break; case 'b': { char name[_UUID_STR_LEN + 1]; char filename[PATH_MAX] = { 0 }; uuid_t uuid = { 0 }; image_desc_t *desc; parse_blob_opt(optarg, &uuid, filename, sizeof(filename)); if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0 || filename[0] == '\0') update_usage(); desc = lookup_image_desc_from_uuid(&uuid); if (desc == NULL) { uuid_to_str(name, sizeof(name), &uuid); desc = new_image_desc(&uuid, name, "blob"); add_image_desc(desc); } set_image_desc_action(desc, DO_PACK, filename); break; } case OPT_ALIGN: align = get_image_align(optarg); break; case 'o': snprintf(outfile, sizeof(outfile), "%s", optarg); break; default: update_usage(); } } argc -= optind; argv += optind; free(opts); if (argc == 0) update_usage(); if (outfile[0] == '\0') snprintf(outfile, sizeof(outfile), "%s", argv[0]); if (access(argv[0], F_OK) == 0) parse_fip(argv[0], &toc_header); if (pflag) toc_header.flags &= ~(0xffffULL << 32); toc_flags = (toc_header.flags |= toc_flags); update_fip(); pack_images(outfile, toc_flags, align); return 0; }