vp-build/srcpkgs/odroid-c2-uboot/patches/add-fip-create.patch

1017 lines
31 KiB
Diff
Raw Normal View History

From 3a2dd09540d3639671d86145336f400ec07b1a4e Mon Sep 17 00:00:00 2001
From: Brian Kim <brian.kim@hardkernel.com>
Date: Wed, 1 Jun 2016 19:02:51 +0900
Subject: [PATCH] ODROID-C2: Add fip_create build tool source code
Current fip_create is a x86_64 ELF excutable binary file. So, anyone could not
compile the u-boot on another archtectures without x86_64.
This patch adds the fip_create source codes to eliminate the build environment
architecture dependency. fip_create is generated by added source code
after applying this change.
Change-Id: I13e005b3c2502fc55deb08bd0739bf1cde5808aa
Signed-off-by: Brian Kim <brian.kim@hardkernel.com>
---
Makefile | 9 +-
fip/fip_create | Bin 13897 -> 0 bytes
tools/fip_create/Makefile | 62 ++
tools/fip_create/fip_create.c | 677 ++++++++++++++++++++++
tools/fip_create/fip_create.h | 61 ++
tools/fip_create/firmware_image_package.h | 68 +++
tools/fip_create/uuid.h | 61 ++
7 files changed, 937 insertions(+), 1 deletion(-)
delete mode 100755 fip/fip_create
create mode 100644 tools/fip_create/Makefile
create mode 100644 tools/fip_create/fip_create.c
create mode 100644 tools/fip_create/fip_create.h
create mode 100644 tools/fip_create/firmware_image_package.h
create mode 100644 tools/fip_create/uuid.h
diff --git ./Makefile ./Makefile
index 52309dc215..d02fc75ecd 100644
--- ./Makefile
+++ ./Makefile
@@ -861,8 +861,13 @@ FIP_ARGS += --bl32 $(FIP_FOLDER_SOC)/bl32.bin
endif
FIP_ARGS += --bl33 $(FIP_FOLDER_SOC)/bl33.bin
+.PHONY: fip_create
+fip_create:
+ $(Q)$(MAKE) -C $(srctree)/tools/fip_create/
+ $(Q)cp $(srctree)/tools/fip_create/fip_create $(FIP_FOLDER)/
+
.PHONY: fip.bin
-fip.bin: tools prepare u-boot.bin
+fip.bin: tools prepare u-boot.bin fip_create
$(Q)cp u-boot.bin $(FIP_FOLDER_SOC)/bl33.bin
$(Q)$(FIP_FOLDER)/fip_create ${FIP_ARGS} $(FIP_FOLDER_SOC)/fip.bin
$(Q)$(FIP_FOLDER)/fip_create --dump $(FIP_FOLDER_SOC)/fip.bin
@@ -1398,8 +1403,10 @@ distclean: mrproper
@rm -f $(FIP_FOLDER_SOC)/u-boot.bin
@rm -f $(FIP_FOLDER_SOC)/u-boot.bin.* $(FIP_FOLDER_SOC)/*.encrypt
@rm -f $(FIP_FOLDER)/u-boot.bin.* $(FIP_FOLDER)/*.bin $(FIP_FOLDER)/*.encrypt
+ @rm -f $(FIP_FOLDER)/fip_create
@rm -f $(srctree)/fip/aml_encrypt_gxb
@rm -f $(FUSING_FOLDER)/u-boot.bin
+ @$(MAKE) -C $(srctree)/tools/fip_create clean
backup:
F=`basename $(srctree)` ; cd .. ; \
diff --git ./tools/fip_create/Makefile ./tools/fip_create/Makefile
new file mode 100644
index 0000000000..69569a1b2f
--- /dev/null
+++ ./tools/fip_create/Makefile
@@ -0,0 +1,62 @@
+#
+# Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of ARM nor the names of its contributors may be used
+# to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+PROJECT = fip_create
+OBJECTS = fip_create.o
+
+CFLAGS = -Wall -Werror -pedantic -std=c99
+ifeq (${DEBUG},1)
+ CFLAGS += -g -O0 -DDEBUG
+else
+ CFLAGS += -O2
+endif
+
+# Make soft links and include from local directory otherwise wrong headers
+# could get pulled in from firmware tree.
+INCLUDE_PATHS = -I.
+
+CC := gcc
+RM := rm -rf
+
+.PHONY: all clean
+
+all: ${PROJECT}
+
+${PROJECT}: ${OBJECTS} Makefile
+ @echo " LD $@"
+ ${Q}${CC} ${OBJECTS} -o $@
+
+%.o: %.c %.h Makefile
+ @echo " CC $<"
+ ${Q}${CC} -c ${CFLAGS} ${INCLUDE_PATHS} $< -o $@
+
+clean:
+ ${Q}${RM} ${PROJECT}
+ ${Q}${RM} ${OBJECTS}
diff --git ./tools/fip_create/fip_create.c ./tools/fip_create/fip_create.c
new file mode 100644
index 0000000000..92affb9e7a
--- /dev/null
+++ ./tools/fip_create/fip_create.c
@@ -0,0 +1,677 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <getopt.h> /* getopt_long() is a GNU extention */
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include "fip_create.h"
+#include "firmware_image_package.h"
+
+/* Values returned by getopt() as part of the command line parsing */
+#define OPT_TOC_ENTRY 0
+#define OPT_DUMP 1
+#define OPT_HELP 2
+
+file_info_t files[MAX_FILES];
+unsigned file_info_count = 0;
+uuid_t uuid_null = {0};
+
+/*
+ * TODO: Add ability to specify and flag different file types.
+ * Add flags to the toc_entry?
+ * const char* format_type_str[] = { "RAW", "ELF", "PIC" };
+ */
+
+/* The images used depends on the platform. */
+static entry_lookup_list_t toc_entry_lookup_list[] = {
+ { "Trusted Boot Firmware BL2", UUID_TRUSTED_BOOT_FIRMWARE_BL2,
+ "bl2", NULL, FLAG_FILENAME },
+ { "SCP Firmware BL3-0", UUID_SCP_FIRMWARE_BL30,
+ "bl30", NULL, FLAG_FILENAME},
+ { "SCP Firmware BL3-0-1", UUID_SCP_FIRMWARE_BL301,
+ "bl301", NULL, FLAG_FILENAME},
+ { "EL3 Runtime Firmware BL3-1", UUID_EL3_RUNTIME_FIRMWARE_BL31,
+ "bl31", NULL, FLAG_FILENAME},
+ { "Secure Payload BL3-2 (Trusted OS)", UUID_SECURE_PAYLOAD_BL32,
+ "bl32", NULL, FLAG_FILENAME},
+ { "Non-Trusted Firmware BL3-3", UUID_NON_TRUSTED_FIRMWARE_BL33,
+ "bl33", NULL, FLAG_FILENAME},
+ { NULL, {0}, 0 }
+};
+
+
+/* Return 0 for equal uuids */
+static inline int compare_uuids(const uuid_t *uuid1, const uuid_t *uuid2)
+{
+ return memcmp(uuid1, uuid2, sizeof(uuid_t));
+}
+
+
+static inline void copy_uuid(uuid_t *to_uuid, const uuid_t *from_uuid)
+{
+ memcpy(to_uuid, from_uuid, sizeof(uuid_t));
+}
+
+
+static void print_usage(void)
+{
+ entry_lookup_list_t *entry = toc_entry_lookup_list;
+
+ printf("Usage: fip_create [options] FIP_FILENAME\n\n");
+ printf("\tThis tool is used to create a Firmware Image Package.\n\n");
+ printf("Options:\n");
+ printf("\t--help: Print this help message and exit\n");
+ printf("\t--dump: Print contents of FIP\n\n");
+ printf("\tComponents that can be added/updated:\n");
+ for (; entry->command_line_name != NULL; entry++) {
+ printf("\t--%s%s\t\t%s",
+ entry->command_line_name,
+ (entry->flags & FLAG_FILENAME) ? " FILENAME" : "",
+ entry->name);
+ printf("\n");
+ }
+}
+
+
+static entry_lookup_list_t *get_entry_lookup_from_uuid(const uuid_t *uuid)
+{
+ unsigned int lookup_index = 0;
+
+ while (toc_entry_lookup_list[lookup_index].command_line_name != NULL) {
+ if (compare_uuids(&toc_entry_lookup_list[lookup_index].name_uuid,
+ uuid) == 0) {
+ return &toc_entry_lookup_list[lookup_index];
+ }
+ lookup_index++;
+ }
+ return NULL;
+}
+
+
+static file_info_t *find_file_info_from_uuid(const uuid_t *uuid)
+{
+ int index;
+
+ for (index = 0; index < file_info_count; index++) {
+ if (compare_uuids(&files[index].name_uuid, uuid) == 0) {
+ return &files[index];
+ }
+ }
+ return NULL;
+}
+
+
+static int add_file_info_entry(entry_lookup_list_t *lookup_entry, char *filename)
+{
+ file_info_t *file_info_entry;
+ int error;
+ struct stat file_status;
+ bool is_new_entry = false;
+
+ /* Check if the file already exists in the array */
+ file_info_entry = find_file_info_from_uuid(&lookup_entry->name_uuid);
+ if (file_info_entry == NULL) {
+ /* The file does not exist in the current list; take the next
+ * one available in the file_info list. 'file_info_count' is
+ * incremented in case of successful update at the end of the
+ * function.
+ */
+ file_info_entry = &files[file_info_count];
+ is_new_entry = true;
+
+ /* Copy the uuid for the new entry */
+ copy_uuid(&file_info_entry->name_uuid,
+ &lookup_entry->name_uuid);
+ }
+
+ /* Get the file information for entry */
+ error = stat(filename, &file_status);
+ if (error != 0) {
+ printf("Error: Cannot get information for file \"%s\": %s\n",
+ filename, strerror(errno));
+ return errno;
+ }
+ file_info_entry->filename = filename;
+ file_info_entry->size = (unsigned int)file_status.st_size;
+ file_info_entry->align_size = 0x4000 * ((file_info_entry->size / 0x4000) + 1);
+ file_info_entry->entry = lookup_entry;
+
+ /* Increment the file_info counter on success if it is new file entry */
+ if (is_new_entry) {
+ file_info_count++;
+
+ /* Ensure we do not overflow */
+ if (file_info_count > MAX_FILES) {
+ printf("ERROR: Too many files in Package\n");
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+static int write_memory_to_file(const uint8_t *start, const char *filename,
+ unsigned int size)
+{
+ FILE *stream;
+ unsigned int bytes_written;
+
+ /* Write the packed file out to the filesystem */
+ stream = fopen(filename, "r+");
+ if (stream == NULL) {
+ stream = fopen(filename, "w");
+ if (stream == NULL) {
+ printf("Error: Cannot create output file \"%s\": %s\n",
+ filename, strerror(errno));
+ return errno;
+ } else {
+ printf("Creating \"%s\"\n", filename);
+ }
+ } else {
+ printf("Updating \"%s\"\n", filename);
+ }
+
+ bytes_written = fwrite(start, sizeof(uint8_t), size, stream);
+ fclose(stream);
+
+ if (bytes_written != size) {
+ printf("Error: Incorrect write for file \"%s\": Size=%u,"
+ "Written=%u bytes.\n", filename, size, bytes_written);
+ return EIO;
+ }
+
+ return 0;
+}
+
+
+static int read_file_to_memory(void *memory, const file_info_t *info)
+{
+ FILE *stream;
+ unsigned int bytes_read;
+
+ /* If the file_info is defined by its filename we need to load it */
+ if (info->filename) {
+ /* Read image from filesystem */
+ stream = fopen(info->filename, "r");
+ if (stream == NULL) {
+ printf("Error: Cannot open file \"%s\": %s\n",
+ info->filename, strerror(errno));
+ return errno;
+ }
+
+ bytes_read = (unsigned int)fread(memory, sizeof(uint8_t),
+ info->size, stream);
+ fclose(stream);
+ if (bytes_read != info->size) {
+ printf("Error: Incomplete read for file \"%s\":"
+ "Size=%u, Read=%u bytes.\n", info->filename,
+ info->size, bytes_read);
+ return EIO;
+ }
+ } else {
+ if (info->image_buffer == NULL) {
+ printf("ERROR: info->image_buffer = NULL\n");
+ return EIO;
+ }
+ /* Copy the file_info buffer (extracted from the existing
+ * image package) into the new buffer.
+ */
+ memcpy(memory, info->image_buffer, info->size);
+ }
+
+ return 0;
+}
+
+
+/* Create the image package file */
+static int pack_images(const char *fip_filename)
+{
+ int status;
+ uint8_t *fip_base_address;
+ void *entry_address;
+ fip_toc_header_t *toc_header;
+ fip_toc_entry_t *toc_entry;
+ unsigned int entry_index;
+ unsigned int toc_size;
+ unsigned int fip_size;
+ unsigned int entry_offset_address;
+ unsigned int payload_size = 0;
+
+ /* Validate filename */
+ if ((fip_filename == NULL) || (strcmp(fip_filename, "") == 0)) {
+ return EINVAL;
+ }
+
+ /* Payload size calculation */
+ for (entry_index = 0; entry_index < file_info_count; entry_index++) {
+ payload_size += files[entry_index].align_size;
+ }
+
+ /* Allocate memory for entire package, including the final null entry */
+ //toc_size = (sizeof(fip_toc_header_t) +
+ //(sizeof(fip_toc_entry_t) * (file_info_count + 1)));
+ toc_size = 0x4000;
+ fip_size = toc_size + payload_size;
+ fip_base_address = malloc(fip_size);
+ if (fip_base_address == NULL) {
+ printf("Error: Can't allocate enough memory to create package."
+ "Process aborted.\n");
+ return ENOMEM;
+ }
+ memset(fip_base_address, 0, fip_size);
+
+ /* Create ToC Header */
+ toc_header = (fip_toc_header_t *)fip_base_address;
+ toc_header->name = TOC_HEADER_NAME;
+ toc_header->serial_number = TOC_HEADER_SERIAL_NUMBER;
+ toc_header->flags = 0;
+
+ toc_entry = (fip_toc_entry_t *)(fip_base_address +
+ sizeof(fip_toc_header_t));
+
+ /* Calculate the starting address of the first image, right after the
+ * toc header.
+ */
+ entry_offset_address = toc_size;
+ entry_index = 0;
+
+ /* Create the package in memory. */
+ for (entry_index = 0; entry_index < file_info_count; entry_index++) {
+ entry_address = (fip_base_address + entry_offset_address);
+ status = read_file_to_memory(entry_address,
+ &files[entry_index]);
+ if (status != 0) {
+ printf("Error: While reading \"%s\" from filesystem.\n",
+ files[entry_index].filename);
+ return status;
+ }
+
+ copy_uuid(&toc_entry->uuid, &files[entry_index].name_uuid);
+ toc_entry->offset_address = entry_offset_address;
+ toc_entry->size = files[entry_index].size;
+ toc_entry->flags = 0;
+ entry_offset_address += files[entry_index].align_size;
+ toc_entry++;
+ }
+
+ /* Add a null uuid entry to mark the end of toc entries */
+ copy_uuid(&toc_entry->uuid, &uuid_null);
+ toc_entry->offset_address = entry_offset_address;
+ toc_entry->size = 0;
+ toc_entry->flags = 0;
+
+ /* Save the package to file */
+ status = write_memory_to_file(fip_base_address, fip_filename, fip_size);
+ if (status != 0) {
+ printf("Error: Failed while writing package to file \"%s\" "
+ "with status=%d.\n", fip_filename, status);
+ return status;
+ }
+ return 0;
+}
+
+
+static void dump_toc(void)
+{
+ unsigned int index = 0;
+ unsigned int image_offset;
+ unsigned int image_size = 0;
+
+ //image_offset = sizeof(fip_toc_header_t) +
+ //(sizeof(fip_toc_entry_t) * (file_info_count + 1));
+ image_offset = 0x4000;
+
+ printf("Firmware Image Package ToC:\n");
+ printf("---------------------------\n");
+ for (index = 0; index < file_info_count; index++) {
+ if (files[index].entry) {
+ printf("- %s: ", files[index].entry->name);
+ } else {
+ printf("- Unknown entry: ");
+ }
+ image_size = files[index].size;
+
+ printf("offset=0x%X, size=0x%X\n", image_offset, image_size);
+ image_offset += files[index].align_size;
+
+ if (files[index].filename) {
+ printf(" file: '%s'\n", files[index].filename);
+ }
+ }
+ printf("---------------------------\n");
+}
+
+
+/* Read and load existing package into memory. */
+static int parse_fip(const char *fip_filename)
+{
+ FILE *fip;
+ char *fip_buffer;
+ char *fip_buffer_end;
+ int fip_size, read_fip_size;
+ fip_toc_header_t *toc_header;
+ fip_toc_entry_t *toc_entry;
+ bool found_last_toc_entry = false;
+ file_info_t *file_info_entry;
+ int status = -1;
+ struct stat st;
+
+ fip = fopen(fip_filename, "r");
+ if (fip == NULL) {
+ /* If the fip does not exist just return, it should not be
+ * considered as an error. The package will be created later
+ */
+ status = 0;
+ goto parse_fip_return;
+ }
+
+ if (stat(fip_filename, &st) != 0) {
+ status = errno;
+ goto parse_fip_fclose;
+ } else {
+ fip_size = (int)st.st_size;
+ }
+
+ /* Allocate a buffer to read the package */
+ fip_buffer = (char *)malloc(fip_size);
+ if (fip_buffer == NULL) {
+ printf("ERROR: Cannot allocate %d bytes.\n", fip_size);
+ status = errno;
+ goto parse_fip_fclose;
+ }
+ fip_buffer_end = fip_buffer + fip_size;
+
+ /* Read the file */
+ read_fip_size = fread(fip_buffer, sizeof(char), fip_size, fip);
+ if (read_fip_size != fip_size) {
+ printf("ERROR: Cannot read the FIP.\n");
+ status = EIO;
+ goto parse_fip_free;
+ }
+ fclose(fip);
+ fip = NULL;
+
+ /* The package must at least contain the ToC Header */
+ if (fip_size < sizeof(fip_toc_header_t)) {
+ printf("ERROR: Given FIP is smaller than the ToC header.\n");
+ status = EINVAL;
+ goto parse_fip_free;
+ }
+ /* Set the ToC Header at the base of the buffer */
+ toc_header = (fip_toc_header_t *)fip_buffer;
+ /* The first toc entry should be just after the ToC header */
+ toc_entry = (fip_toc_entry_t *)(toc_header + 1);
+
+ /* While the ToC entry is contained into the buffer */
+ int cnt = 0;
+ while (((char *)toc_entry + sizeof(fip_toc_entry_t)) < fip_buffer_end) {
+ cnt++;
+ /* Check if the ToC Entry is the last one */
+ if (compare_uuids(&toc_entry->uuid, &uuid_null) == 0) {
+ found_last_toc_entry = true;
+ status = 0;
+ break;
+ }
+
+ /* Add the entry into file_info */
+
+ /* Get the new entry in the array and clear it */
+ file_info_entry = &files[file_info_count++];
+ memset(file_info_entry, 0, sizeof(file_info_t));
+
+ /* Copy the info from the ToC entry */
+ copy_uuid(&file_info_entry->name_uuid, &toc_entry->uuid);
+ file_info_entry->image_buffer = fip_buffer +
+ toc_entry->offset_address;
+ file_info_entry->size = toc_entry->size;
+ file_info_entry->align_size = 0x4000 * ((toc_entry->size / 0x4000) + 1);
+
+ /* Check if there is a corresponding entry in lookup table */
+ file_info_entry->entry =
+ get_entry_lookup_from_uuid(&toc_entry->uuid);
+
+ /* Go to the next ToC entry */
+ toc_entry++;
+ }
+
+ if (!found_last_toc_entry) {
+ printf("ERROR: Given FIP does not have an end ToC entry.\n");
+ status = EINVAL;
+ goto parse_fip_free;
+ } else {
+ /* All is well, we should not free any of the loaded images */
+ goto parse_fip_fclose;
+ }
+
+ parse_fip_free:
+ if (fip_buffer != NULL) {
+ free(fip_buffer);
+ fip_buffer = NULL;
+ }
+
+ parse_fip_fclose:
+ if (fip != NULL) {
+ fclose(fip);
+ }
+
+ parse_fip_return:
+ return status;
+}
+
+
+/* Parse all command-line options and return the FIP name if present. */
+static char *get_filename(int argc, char **argv, struct option *options)
+{
+ int c;
+ char *filename = NULL;
+
+ /* Reset option pointer so we parse all args. starts at 1.
+ * The filename is the only argument that does not have an option flag.
+ */
+ optind = 1;
+ while (1) {
+ c = getopt_long(argc, argv, "", options, NULL);
+ if (c == -1)
+ break;
+
+ if (c == '?') {
+ /* Failed to parse an option. Fail. */
+ return NULL;
+ }
+ }
+
+ /* Only one argument left then it is the filename.
+ * We dont expect any other options
+ */
+ if (optind + 1 == argc)
+ filename = argv[optind];
+
+ return filename;
+}
+
+
+/* Work through command-line options */
+static int parse_cmdline(int argc, char **argv, struct option *options,
+ int *do_pack)
+{
+ int c;
+ int status = 0;
+ int option_index = 0;
+ entry_lookup_list_t *lookup_entry;
+ int do_dump = 0;
+
+ /* restart parse to process all options. starts at 1. */
+ optind = 1;
+ while (1) {
+ c = getopt_long(argc, argv, "", options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case OPT_TOC_ENTRY:
+ if (optarg) {
+ /* Does the option expect a filename. */
+ lookup_entry = &toc_entry_lookup_list[option_index];
+ if (lookup_entry->flags & FLAG_FILENAME) {
+ status = add_file_info_entry(lookup_entry, optarg);
+ if (status != 0) {
+ printf("Failed to process %s\n",
+ options[option_index].name);
+ break;
+ } else {
+ /* Update package */
+ *do_pack = 1;
+ }
+ }
+ }
+ break;
+
+ case OPT_DUMP:
+ do_dump = 1;
+ continue;
+
+ case OPT_HELP:
+ print_usage();
+ exit(0);
+
+ default:
+ /* Unrecognised options are caught in get_filename() */
+ break;
+ }
+ }
+
+
+ /* Do not dump toc if we have an error as it could hide the error */
+ if ((status == 0) && (do_dump)) {
+ dump_toc();
+ }
+
+ return status;
+
+}
+
+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;
+}
diff --git ./tools/fip_create/fip_create.h ./tools/fip_create/fip_create.h
new file mode 100644
index 0000000000..81e0897f98
--- /dev/null
+++ ./tools/fip_create/fip_create.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FIP_CREATE_H__
+#define __FIP_CREATE_H__
+
+#include <stdint.h>
+#include <uuid.h>
+
+#define MAX_FILES 10
+
+/* TODO: Update this number as required */
+#define TOC_HEADER_SERIAL_NUMBER 0x12345678
+
+#define FLAG_FILENAME (1 << 0)
+
+typedef struct entry_lookup_list {
+ const char *name;
+ uuid_t name_uuid;
+ const char *command_line_name;
+ struct file_info *info;
+ unsigned int flags;
+} entry_lookup_list_t;
+
+typedef struct file_info {
+ uuid_t name_uuid;
+ const char *filename;
+ unsigned int size;
+ unsigned int align_size;
+ void *image_buffer;
+ entry_lookup_list_t *entry;
+} file_info_t;
+
+#endif /* __FIP_CREATE_H__ */
diff --git ./tools/fip_create/firmware_image_package.h ./tools/fip_create/firmware_image_package.h
new file mode 100644
index 0000000000..0a8a67d9ac
--- /dev/null
+++ ./tools/fip_create/firmware_image_package.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FIRMWARE_IMAGE_PACKAGE_H__
+#define __FIRMWARE_IMAGE_PACKAGE_H__
+
+#include <stdint.h>
+#include <uuid.h>
+
+/* This is used as a signature to validate the blob header */
+#define TOC_HEADER_NAME 0xAA640001
+
+
+/* ToC Entry UUIDs */
+#define UUID_TRUSTED_BOOT_FIRMWARE_BL2 \
+ {0x0becf95f, 0x224d, 0x4d3e, 0xa5, 0x44, {0xc3, 0x9d, 0x81, 0xc7, 0x3f, 0x0a} }
+#define UUID_SCP_FIRMWARE_BL30 \
+ {0x3dfd6697, 0xbe89, 0x49e8, 0xae, 0x5d, {0x78, 0xa1, 0x40, 0x60, 0x82, 0x13} }
+#define UUID_SCP_FIRMWARE_BL301 \
+ {0xAABBCCDD, 0xABCD, 0xEFEF, 0xAB, 0xCD, {0x12, 0x34, 0x56, 0x78, 0xAB, 0xCD} }
+#define UUID_EL3_RUNTIME_FIRMWARE_BL31 \
+ {0x6d08d447, 0xfe4c, 0x4698, 0x9b, 0x95, {0x29, 0x50, 0xcb, 0xbd, 0x5a, 0x00} }
+#define UUID_SECURE_PAYLOAD_BL32 \
+ {0x89e1d005, 0xdc53, 0x4713, 0x8d, 0x2b, {0x50, 0x0a, 0x4b, 0x7a, 0x3e, 0x38} }
+#define UUID_NON_TRUSTED_FIRMWARE_BL33 \
+ {0xa7eed0d6, 0xeafc, 0x4bd5, 0x97, 0x82, {0x99, 0x34, 0xf2, 0x34, 0xb6, 0xe4} }
+
+typedef struct fip_toc_header {
+ uint32_t name;
+ uint32_t serial_number;
+ uint64_t flags;
+} fip_toc_header_t;
+
+typedef struct fip_toc_entry {
+ uuid_t uuid;
+ uint64_t offset_address;
+ uint64_t size;
+ uint64_t flags;
+} fip_toc_entry_t;
+
+#endif /* __FIRMWARE_IMAGE_PACKAGE_H__ */
diff --git ./tools/fip_create/uuid.h ./tools/fip_create/uuid.h
new file mode 100644
index 0000000000..5c4767b5b5
--- /dev/null
+++ ./tools/fip_create/uuid.h
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 2002 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Portions copyright (c) 2014, ARM Limited and Contributors.
+ * All rights reserved.
+ */
+
+#ifndef _SYS_UUID_H_
+#define _SYS_UUID_H_
+
+/* Length of a node address (an IEEE 802 address). */
+#define _UUID_NODE_LEN 6
+
+/*
+ * See also:
+ * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt
+ * http://www.opengroup.org/onlinepubs/009629399/apdxa.htm
+ *
+ * A DCE 1.1 compatible source representation of UUIDs.
+ */
+struct uuid {
+ uint32_t time_low;
+ uint16_t time_mid;
+ uint16_t time_hi_and_version;
+ uint8_t clock_seq_hi_and_reserved;
+ uint8_t clock_seq_low;
+ uint8_t node[_UUID_NODE_LEN];
+};
+
+/* XXX namespace pollution? */
+typedef struct uuid uuid_t;
+
+#endif /* _SYS_UUID_H_ */