Commit c49a805d authored by Juan Castillo's avatar Juan Castillo
Browse files

fip_create: add support for image unpacking

This patch adds support for image unpacking to the FIP packaging
tool. Command line option '-u,--unpack' may be used to unpack the
contents of an existing FIP file into the working directory. The
tool uses default hardcoded filenames for the unpacked images. If
the files already exist, they can be overwritten by specifying the
option '-f,--force'.

Change-Id: I360b11d9c5403e8c0a7a9cac32c1d90ebb228063
parent 24fee61e
/* /*
* Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
...@@ -42,13 +42,17 @@ ...@@ -42,13 +42,17 @@
#define OPT_TOC_ENTRY 0 #define OPT_TOC_ENTRY 0
#define OPT_DUMP 'd' #define OPT_DUMP 'd'
#define OPT_HELP 'h' #define OPT_HELP 'h'
#define OPT_STR "dh" #define OPT_UNPACK 'u'
#define OPT_FORCE 'f'
#define OPT_STR "dfhu"
static file_info_t files[MAX_FILES]; static file_info_t files[MAX_FILES];
static unsigned file_info_count; static unsigned file_info_count;
static uuid_t uuid_null = {0}; static uuid_t uuid_null = {0};
static int do_dump; static int do_dump;
static int do_pack; static int do_pack;
static int do_unpack;
static int do_force;
/* /*
* TODO: Add ability to specify and flag different file types. * TODO: Add ability to specify and flag different file types.
...@@ -127,6 +131,8 @@ static void print_usage(void) ...@@ -127,6 +131,8 @@ static void print_usage(void)
printf("Options:\n"); printf("Options:\n");
printf("\t-h,--help: Print this help message and exit\n"); printf("\t-h,--help: Print this help message and exit\n");
printf("\t-d,--dump: Print contents of FIP after update\n"); printf("\t-d,--dump: Print contents of FIP after update\n");
printf("\t-u,--unpack: Unpack images from an existing FIP\n");
printf("\t-f,--force: Overwrite existing files when unpacking images\n\n");
printf("Components that can be added/updated:\n"); printf("Components that can be added/updated:\n");
for (; entry->command_line_name != NULL; entry++) { for (; entry->command_line_name != NULL; entry++) {
printf("\t--%s%s\t\t%s", printf("\t--%s%s\t\t%s",
...@@ -376,6 +382,109 @@ static int pack_images(const char *fip_filename) ...@@ -376,6 +382,109 @@ static int pack_images(const char *fip_filename)
} }
/*
* Unpack all images from an existing FIP
*
* Images will be unpacked into the working directory using filenames as
* specified by the corresponding command line option plus the 'bin' extension.
* For example, the image specified by the --soc-fw option will be unpacked as
* 'soc-fw.bin'
*/
static int unpack_images(void)
{
FILE *stream;
size_t bytes_written;
file_info_t *file_info;
char *filename[MAX_FILES];
int status, ret = 0;
unsigned int i, idx, num_img;
struct stat st;
size_t len;
/* Make the output filenames */
for (idx = 0; idx < file_info_count; idx++) {
filename[idx] = NULL;
file_info = &files[idx];
if (file_info->image_buffer == NULL) {
continue;
}
len = strlen(file_info->entry->command_line_name);
filename[idx] = malloc(len + 5); /* ".bin" + '\0' */
if (filename[idx] == NULL) {
printf("ERROR: out of memory\n");
for (i = 0; i < idx; i++) {
free(filename[i]);
}
return ENOMEM;
}
strcpy(filename[idx], file_info->entry->command_line_name);
strcat(filename[idx], ".bin");
}
/* Check if output files already exist in the filesystem. We perform
* this check before any other action, so if any of the files
* exists, nothing is unpacked. If force overwrite is enabled, we skip
* this check */
if (!do_force) {
for (idx = 0; idx < file_info_count; idx++) {
file_info = &files[idx];
if (file_info->image_buffer == NULL) {
continue;
}
status = stat(filename[idx], &st);
if (!status) {
printf("File '%s' exists. Use --force to overwrite.\n",
filename[idx]);
printf("Process aborted.\n");
ret = EEXIST;
goto unpack_images_free;
}
}
}
printf("Unpacking images...\n");
/* Write the images to files */
num_img = 0;
for (idx = 0; idx < file_info_count; idx++) {
file_info = &files[idx];
if (file_info->image_buffer == NULL) {
continue;
}
/* Unpack the image to a file */
stream = fopen(filename[idx], "w");
if (!stream) {
printf("ERROR: cannot open '%s' for writing\n",
filename[idx]);
ret = EIO;
goto unpack_images_free;
}
bytes_written = fwrite(file_info->image_buffer, sizeof(uint8_t),
file_info->size, stream);
fclose(stream);
if (bytes_written != file_info->size) {
printf("ERROR: Incorrect write for file \"%s\": Size=%u,"
"Written=%lu bytes.\n", filename[idx], file_info->size,
bytes_written);
ret = EIO;
goto unpack_images_free;
}
num_img++;
}
printf("Done. %u images unpacked\n", num_img);
unpack_images_free:
for (idx = 0; idx < file_info_count; idx++) {
free(filename[idx]);
}
return ret;
}
static void dump_toc(void) static void dump_toc(void)
{ {
unsigned int index = 0; unsigned int index = 0;
...@@ -595,6 +704,14 @@ static int parse_cmdline(int argc, char **argv, struct option *options) ...@@ -595,6 +704,14 @@ static int parse_cmdline(int argc, char **argv, struct option *options)
print_usage(); print_usage();
exit(0); exit(0);
case OPT_UNPACK:
do_unpack = 1;
break;
case OPT_FORCE:
do_force = 1;
break;
default: default:
/* Unrecognised options are caught in get_filename() */ /* Unrecognised options are caught in get_filename() */
break; break;
...@@ -610,16 +727,17 @@ int main(int argc, char **argv) ...@@ -610,16 +727,17 @@ int main(int argc, char **argv)
int i; int i;
int status; int status;
char *fip_filename; char *fip_filename;
struct stat st;
/* Clear file list table. */ /* Clear file list table. */
memset(files, 0, sizeof(files)); memset(files, 0, sizeof(files));
/* Initialise for getopt_long(). /* Initialise for getopt_long().
* Use image table as defined at top of file to get options. * Use image table as defined at top of file to get options.
* Add 'dump' option, 'help' option and end marker. * Add common options and end marker.
*/ */
static struct option long_options[(sizeof(toc_entry_lookup_list)/ static struct option long_options[(sizeof(toc_entry_lookup_list)/
sizeof(entry_lookup_list_t)) + 2]; sizeof(entry_lookup_list_t)) + 4];
for (i = 0; for (i = 0;
/* -1 because we dont want to process end marker in toc table */ /* -1 because we dont want to process end marker in toc table */
...@@ -644,6 +762,18 @@ int main(int argc, char **argv) ...@@ -644,6 +762,18 @@ int main(int argc, char **argv)
long_options[i].flag = 0; long_options[i].flag = 0;
long_options[i].val = OPT_HELP; long_options[i].val = OPT_HELP;
/* Add '--unpack' option */
long_options[++i].name = "unpack";
long_options[i].has_arg = 0;
long_options[i].flag = 0;
long_options[i].val = OPT_UNPACK;
/* Add '--force' option */
long_options[++i].name = "force";
long_options[i].has_arg = 0;
long_options[i].flag = 0;
long_options[i].val = OPT_FORCE;
/* Zero the last entry (required) */ /* Zero the last entry (required) */
long_options[++i].name = 0; long_options[++i].name = 0;
long_options[i].has_arg = 0; long_options[i].has_arg = 0;
...@@ -684,10 +814,28 @@ int main(int argc, char **argv) ...@@ -684,10 +814,28 @@ int main(int argc, char **argv)
return 0; return 0;
} }
/* Processed all command line options. Create/update the package if /* Unpack images from FIP always takes precedence over packaging. In
* required. * the future, there will be different commands for each action and
*/ * only one will be specified in the command line */
if (do_unpack) {
status = stat(fip_filename, &st);
if (status != 0) {
printf("ERROR: cannot open %s\n", fip_filename);
return status;
}
/* Warning if user has specified images */
if (do_pack) { if (do_pack) {
printf("WARNING: Unpack option specified. Input images "
"will be ignored.\n");
}
status = unpack_images();
if (status != 0) {
printf("ERROR: failed to unpack package (status = %d).\n",
status);
return status;
}
} else if (do_pack) {
/* Create/update FIP */
status = pack_images(fip_filename); status = pack_images(fip_filename);
if (status != 0) { if (status != 0) {
printf("Failed to create package (status = %d).\n", printf("Failed to create package (status = %d).\n",
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment