Ejemplo n.º 1
0
/*
 * This function is shared between the create and update subcommands.
 * The difference between the two subcommands is that when the FIP file
 * is created, the parsing of an existing FIP is skipped.  This results
 * in update_fip() creating the new FIP file from scratch because the
 * internal image table is not populated.
 */
static void update_fip(void)
{
    toc_entry_t *toc_entry;
    image_t *image;

    /* Add or replace images in the FIP file. */
    for (toc_entry = toc_entries;
            toc_entry->cmdline_name != NULL;
            toc_entry++) {
        if (toc_entry->action != DO_PACK)
            continue;

        image = read_image_from_file(toc_entry, toc_entry->action_arg);
        if (toc_entry->image != NULL) {
            if (verbose)
                log_dbgx("Replacing image %s.bin with %s",
                         toc_entry->cmdline_name,
                         toc_entry->action_arg);
            replace_image(toc_entry->image, image);
        } else {
            if (verbose)
                log_dbgx("Adding image %s",
                         toc_entry->action_arg);
            add_image(image);
        }
        /* Link backpointer from lookup entry. */
        toc_entry->image = image;

        free(toc_entry->action_arg);
        toc_entry->action_arg = NULL;
    }
}
Ejemplo n.º 2
0
/*
 * This function is shared between the create and update subcommands.
 * The difference between the two subcommands is that when the FIP file
 * is created, the parsing of an existing FIP is skipped.  This results
 * in update_fip() creating the new FIP file from scratch because the
 * internal image table is not populated.
 */
static void update_fip(void)
{
	image_desc_t *desc;

	/* Add or replace images in the FIP file. */
	for (desc = image_desc_head; desc != NULL; desc = desc->next) {
		image_t *image;

		if (desc->action != DO_PACK)
			continue;

		image = read_image_from_file(&desc->uuid,
		    desc->action_arg);
		if (desc->image != NULL) {
			if (verbose) {
				log_dbgx("Replacing %s with %s",
				    desc->cmdline_name,
				    desc->action_arg);
			}
			free(desc->image);
			desc->image = image;
		} else {
			if (verbose)
				log_dbgx("Adding image %s",
				    desc->action_arg);
			desc->image = image;
		}
	}
}
Ejemplo n.º 3
0
/*
 * This function is shared between the create and update subcommands.
 * The difference between the two subcommands is that when the FIP file
 * is created, the parsing of an existing FIP is skipped.  This results
 * in update_fip() creating the new FIP file from scratch because the
 * internal image table is not populated.
 */
static void update_fip(void)
{
    toc_entry_t *toc_entry;
    image_t *new_image, *old_image;

    /* Add or replace images in the FIP file. */
    for (toc_entry = toc_entries;
            toc_entry->cmdline_name != NULL;
            toc_entry++) {
        if (toc_entry->action != DO_PACK)
            continue;

        new_image = read_image_from_file(&toc_entry->uuid,
                                         toc_entry->action_arg);
        old_image = lookup_image_from_uuid(&toc_entry->uuid);
        if (old_image != NULL) {
            if (verbose)
                log_dbgx("Replacing image %s.bin with %s",
                         toc_entry->cmdline_name,
                         toc_entry->action_arg);
            replace_image(old_image, new_image);
        } else {
            if (verbose)
                log_dbgx("Adding image %s",
                         toc_entry->action_arg);
            add_image(new_image);
        }

        free(toc_entry->action_arg);
        toc_entry->action_arg = NULL;
    }
}
Ejemplo n.º 4
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)
        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;
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
0
static int pack_images(char *filename, uint64_t toc_flags)
{
    FILE *fp;
    image_t *image;
    fip_toc_header_t *toc_header;
    fip_toc_entry_t *toc_entry;
    char *buf;
    uint64_t entry_offset, buf_size, payload_size;
    int i;

    /* Calculate total payload size and allocate scratch buffer. */
    payload_size = 0;
    for (i = 0; i < nr_images; i++)
        payload_size += images[i]->size;

    buf_size = sizeof(fip_toc_header_t) +
               sizeof(fip_toc_entry_t) * (nr_images + 1);
    buf = calloc(1, buf_size);
    if (buf == NULL)
        log_err("calloc");

    /* Build up header and ToC entries from the image table. */
    toc_header = (fip_toc_header_t *)buf;
    toc_header->name = TOC_HEADER_NAME;
    toc_header->serial_number = TOC_HEADER_SERIAL_NUMBER;
    toc_header->flags = toc_flags;

    toc_entry = (fip_toc_entry_t *)(toc_header + 1);

    entry_offset = buf_size;
    for (i = 0; i < nr_images; i++) {
        image = images[i];
        memcpy(&toc_entry->uuid, &image->uuid, sizeof(uuid_t));
        toc_entry->offset_address = entry_offset;
        toc_entry->size = image->size;
        toc_entry->flags = 0;
        entry_offset += toc_entry->size;
        toc_entry++;
    }

    /* Append a null uuid entry to mark the end of ToC entries. */
    memcpy(&toc_entry->uuid, &uuid_null, sizeof(uuid_t));
    toc_entry->offset_address = entry_offset;
    toc_entry->size = 0;
    toc_entry->flags = 0;

    /* Generate the FIP file. */
    fp = fopen(filename, "w");
    if (fp == NULL)
        log_err("fopen %s", filename);

    if (verbose)
        log_dbgx("Metadata size: %zu bytes", buf_size);

    if (fwrite(buf, 1, buf_size, fp) != buf_size)
        log_errx("Failed to write image to %s", filename);
    free(buf);

    if (verbose)
        log_dbgx("Payload size: %zu bytes", payload_size);

    for (i = 0; i < nr_images; i++) {
        image = images[i];
        if (fwrite(image->buffer, 1, image->size, fp) != image->size)
            log_errx("Failed to write image to %s", filename);
    }

    fclose(fp);
    return 0;
}
Ejemplo n.º 10
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;
}
Ejemplo n.º 11
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;
}
Ejemplo n.º 12
0
static int pack_images(const char *filename, uint64_t toc_flags, unsigned long align)
{
	FILE *fp;
	image_desc_t *desc;
	fip_toc_header_t *toc_header;
	fip_toc_entry_t *toc_entry;
	char *buf;
	uint64_t entry_offset, buf_size, payload_size = 0;
	size_t nr_images = 0;

	for (desc = image_desc_head; desc != NULL; desc = desc->next)
		if (desc->image != NULL)
			nr_images++;

	buf_size = sizeof(fip_toc_header_t) +
	    sizeof(fip_toc_entry_t) * (nr_images + 1);
	buf = calloc(1, buf_size);
	if (buf == NULL)
		log_err("calloc");

	/* Build up header and ToC entries from the image table. */
	toc_header = (fip_toc_header_t *)buf;
	toc_header->name = TOC_HEADER_NAME;
	toc_header->serial_number = TOC_HEADER_SERIAL_NUMBER;
	toc_header->flags = toc_flags;

	toc_entry = (fip_toc_entry_t *)(toc_header + 1);

	entry_offset = buf_size;
	for (desc = image_desc_head; desc != NULL; desc = desc->next) {
		image_t *image = desc->image;

		if (image == NULL)
			continue;
		payload_size += image->toc_e.size;
		entry_offset = (entry_offset + align - 1) & ~(align - 1);
		image->toc_e.offset_address = entry_offset;
		*toc_entry++ = image->toc_e;
		entry_offset += image->toc_e.size;
	}

	/* Append a null uuid entry to mark the end of ToC entries. */
	memset(toc_entry, 0, sizeof(*toc_entry));
	toc_entry->offset_address = entry_offset;

	/* Generate the FIP file. */
	fp = fopen(filename, "wb");
	if (fp == NULL)
		log_err("fopen %s", filename);

	if (verbose)
		log_dbgx("Metadata size: %zu bytes", buf_size);

	xfwrite(buf, buf_size, fp, filename);
	free(buf);

	if (verbose)
		log_dbgx("Payload size: %zu bytes", payload_size);

	for (desc = image_desc_head; desc != NULL; desc = desc->next) {
		image_t *image = desc->image;

		if (image == NULL)
			continue;
		if (fseek(fp, image->toc_e.offset_address, SEEK_SET))
			log_errx("Failed to set file position");

		xfwrite(image->buffer, image->toc_e.size, fp, filename);
	}

	fclose(fp);
	return 0;
}