diff --git a/Makefile b/Makefile index e9a07840e..001e94b8c 100644 --- a/Makefile +++ b/Makefile @@ -350,6 +350,10 @@ ifeq (${ENABLE_PSCI_STAT},1) ENABLE_PMF := 1 endif +ifneq (${FIP_ALIGN},0) +FIP_ARGS += --align ${FIP_ALIGN} +endif + ################################################################################ # Auxiliary tools (fiptool, cert_create, etc) ################################################################################ diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index fc39819d7..0b93dfcac 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -89,6 +89,9 @@ ENABLE_RUNTIME_INSTRUMENTATION := 0 # Build flag to treat usage of deprecated platform and framework APIs as error. ERROR_DEPRECATED := 0 +# Byte alignment that each component in FIP is aligned to +FIP_ALIGN := 0 + # Default FIP file name FIP_NAME := fip.bin diff --git a/tools/fiptool/fiptool.c b/tools/fiptool/fiptool.c index 6288cbfd4..865aeae1d 100644 --- a/tools/fiptool/fiptool.c +++ b/tools/fiptool/fiptool.c @@ -50,6 +50,7 @@ #define OPT_TOC_ENTRY 0 #define OPT_PLAT_TOC_FLAGS 1 +#define OPT_ALIGN 2 static image_desc_t *lookup_image_desc_from_uuid(const uuid_t *uuid); static image_t *lookup_image_from_uuid(const uuid_t *uuid); @@ -591,7 +592,7 @@ static void info_usage(void) exit(1); } -static int pack_images(const char *filename, uint64_t toc_flags) +static int pack_images(const char *filename, uint64_t toc_flags, unsigned long align) { FILE *fp; image_t *image; @@ -617,6 +618,7 @@ static int pack_images(const char *filename, uint64_t toc_flags) entry_offset = buf_size; for (image = image_head; image != NULL; image = image->next) { 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; @@ -640,8 +642,12 @@ static int pack_images(const char *filename, uint64_t toc_flags) if (verbose) log_dbgx("Payload size: %zu bytes", payload_size); - for (image = image_head; image != NULL; image = image->next) + for (image = image_head; image != NULL; image = image->next) { + 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; @@ -697,6 +703,24 @@ static void parse_plat_toc_flags(const char *arg, unsigned long long *toc_flags) *toc_flags |= flags << 32; } +static int is_power_of_2(unsigned long x) +{ + return x && !(x & (x - 1)); +} + +static unsigned long get_image_align(char *arg) +{ + char *endptr; + unsigned long align; + + errno = 0; + align = strtoul(arg, &endptr, 10); + if (*endptr != '\0' || !is_power_of_2(align) || errno != 0) + log_errx("Invalid alignment: %s", arg); + + return align; +} + static void parse_blob_opt(char *arg, uuid_t *uuid, char *filename, size_t len) { char *p; @@ -717,6 +741,7 @@ static int create_cmd(int argc, char *argv[]) struct option *opts = NULL; size_t nr_opts = 0; unsigned long long toc_flags = 0; + unsigned long align = 1; if (argc < 2) create_usage(); @@ -724,6 +749,7 @@ static int create_cmd(int argc, char *argv[]) opts = fill_common_opts(opts, &nr_opts, required_argument); opts = add_opt(opts, &nr_opts, "plat-toc-flags", required_argument, OPT_PLAT_TOC_FLAGS); + 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, NULL, 0, 0); @@ -745,6 +771,9 @@ static int create_cmd(int argc, char *argv[]) case OPT_PLAT_TOC_FLAGS: parse_plat_toc_flags(optarg, &toc_flags); break; + case OPT_ALIGN: + align = get_image_align(optarg); + break; case 'b': { char name[_UUID_STR_LEN + 1]; char filename[PATH_MAX] = { 0 }; @@ -780,7 +809,7 @@ static int create_cmd(int argc, char *argv[]) update_fip(); - pack_images(argv[0], toc_flags); + pack_images(argv[0], toc_flags, align); free_images(); return 0; } @@ -792,6 +821,7 @@ static void create_usage(void) printf("fiptool create [opts] FIP_FILENAME\n"); printf("\n"); printf("Options:\n"); + printf(" --align \t\tEach image is aligned to (default: 1).\n"); printf(" --blob uuid=...,file=...\tAdd an image with the given UUID " "pointed to by file.\n"); printf(" --plat-toc-flags \t16-bit platform specific flag field " @@ -811,12 +841,14 @@ static int update_cmd(int argc, char *argv[]) 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, @@ -864,6 +896,9 @@ static int update_cmd(int argc, char *argv[]) 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; @@ -890,7 +925,7 @@ static int update_cmd(int argc, char *argv[]) update_fip(); - pack_images(outfile, toc_flags); + pack_images(outfile, toc_flags, align); free_images(); return 0; } @@ -902,6 +937,7 @@ static void update_usage(void) printf("fiptool update [opts] FIP_FILENAME\n"); printf("\n"); printf("Options:\n"); + printf(" --align \t\tEach image is aligned to (default: 1).\n"); printf(" --blob uuid=...,file=...\tAdd or update an image " "with the given UUID pointed to by file.\n"); printf(" --out FIP_FILENAME\t\tSet an alternative output FIP file.\n"); @@ -1062,12 +1098,14 @@ static int remove_cmd(int argc, char *argv[]) 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'); @@ -1088,6 +1126,9 @@ static int remove_cmd(int argc, char *argv[]) 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 }; @@ -1152,7 +1193,7 @@ static int remove_cmd(int argc, char *argv[]) } } - pack_images(outfile, toc_header.flags); + pack_images(outfile, toc_header.flags, align); free_images(); return 0; } @@ -1164,6 +1205,7 @@ static void remove_usage(void) printf("fiptool remove [opts] FIP_FILENAME\n"); printf("\n"); printf("Options:\n"); + printf(" --align \tEach image is aligned to (default: 1).\n"); printf(" --blob uuid=...\tRemove an image with the given UUID.\n"); printf(" --force\t\tIf the output FIP file already exists, use --force to " "overwrite it.\n");