blob: c6869f95632b7fc9ac93cb5a19ff7dc349572609 [file] [log] [blame]
Harry Liebelf58ad362014-01-10 18:00:33 +00001/*
2 * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of ARM nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific
16 * prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <errno.h>
32#include <getopt.h> /* getopt_long() is a GNU extention */
33#include <stdbool.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <sys/stat.h>
38#include "fip_create.h"
39#include "firmware_image_package.h"
40
Sandrine Bailleux29e54422014-03-19 13:09:54 +000041/* Values returned by getopt() as part of the command line parsing */
42#define OPT_TOC_ENTRY 0
43#define OPT_DUMP 1
Sandrine Bailleux8c60fee2014-03-19 13:21:42 +000044#define OPT_HELP 2
Sandrine Bailleux29e54422014-03-19 13:09:54 +000045
Dan Handleye2712bc2014-04-10 15:37:22 +010046file_info_t files[MAX_FILES];
Harry Liebelf58ad362014-01-10 18:00:33 +000047unsigned file_info_count = 0;
48uuid_t uuid_null = {0};
49
50/*
51 * TODO: Add ability to specify and flag different file types.
52 * Add flags to the toc_entry?
53 * const char* format_type_str[] = { "RAW", "ELF", "PIC" };
54 */
55
Harry Liebeleed7a5b2014-05-01 14:09:16 +010056/* The images used depends on the platform. */
Dan Handleye2712bc2014-04-10 15:37:22 +010057static entry_lookup_list_t toc_entry_lookup_list[] = {
Harry Liebelf58ad362014-01-10 18:00:33 +000058 { "Trusted Boot Firmware BL2", UUID_TRUSTED_BOOT_FIRMWARE_BL2,
59 "bl2", NULL, FLAG_FILENAME },
60 { "SCP Firmware BL3-0", UUID_SCP_FIRMWARE_BL30,
61 "bl30", NULL, FLAG_FILENAME},
62 { "EL3 Runtime Firmware BL3-1", UUID_EL3_RUNTIME_FIRMWARE_BL31,
63 "bl31", NULL, FLAG_FILENAME},
64 { "Secure Payload BL3-2 (Trusted OS)", UUID_SECURE_PAYLOAD_BL32,
65 "bl32", NULL, FLAG_FILENAME},
66 { "Non-Trusted Firmware BL3-3", UUID_NON_TRUSTED_FIRMWARE_BL33,
67 "bl33", NULL, FLAG_FILENAME},
Juan Castillo379954c2014-11-04 17:36:40 +000068 /* Key Certificates */
69 { "Root Of Trust key certificate", UUID_ROT_KEY_CERT,
70 "rot-cert", NULL, FLAG_FILENAME },
71 { "Trusted key certificate", UUID_TRUSTED_KEY_CERT,
72 "trusted-key-cert", NULL, FLAG_FILENAME},
73 { "SCP Firmware BL3-0 key certificate", UUID_SCP_FIRMWARE_BL30_KEY_CERT,
74 "bl30-key-cert", NULL, FLAG_FILENAME},
75 { "EL3 Runtime Firmware BL3-1 key certificate", UUID_EL3_RUNTIME_FIRMWARE_BL31_KEY_CERT,
76 "bl31-key-cert", NULL, FLAG_FILENAME},
77 { "Secure Payload BL3-2 (Trusted OS) key certificate", UUID_SECURE_PAYLOAD_BL32_KEY_CERT,
78 "bl32-key-cert", NULL, FLAG_FILENAME},
79 { "Non-Trusted Firmware BL3-3 key certificate", UUID_NON_TRUSTED_FIRMWARE_BL33_KEY_CERT,
80 "bl33-key-cert", NULL, FLAG_FILENAME},
81 /* Content certificates */
82 { "Trusted Boot Firmware BL2 certificate", UUID_TRUSTED_BOOT_FIRMWARE_BL2_CERT,
83 "bl2-cert", NULL, FLAG_FILENAME },
84 { "SCP Firmware BL3-0 certificate", UUID_SCP_FIRMWARE_BL30_CERT,
85 "bl30-cert", NULL, FLAG_FILENAME},
86 { "EL3 Runtime Firmware BL3-1 certificate", UUID_EL3_RUNTIME_FIRMWARE_BL31_CERT,
87 "bl31-cert", NULL, FLAG_FILENAME},
88 { "Secure Payload BL3-2 (Trusted OS) certificate", UUID_SECURE_PAYLOAD_BL32_CERT,
89 "bl32-cert", NULL, FLAG_FILENAME},
90 { "Non-Trusted Firmware BL3-3 certificate", UUID_NON_TRUSTED_FIRMWARE_BL33_CERT,
91 "bl33-cert", NULL, FLAG_FILENAME},
Harry Liebelf58ad362014-01-10 18:00:33 +000092 { NULL, {0}, 0 }
93};
94
95
96/* Return 0 for equal uuids */
97static inline int compare_uuids(const uuid_t *uuid1, const uuid_t *uuid2)
98{
99 return memcmp(uuid1, uuid2, sizeof(uuid_t));
100}
101
102
103static inline void copy_uuid(uuid_t *to_uuid, const uuid_t *from_uuid)
104{
105 memcpy(to_uuid, from_uuid, sizeof(uuid_t));
106}
107
108
109static void print_usage(void)
110{
Dan Handleye2712bc2014-04-10 15:37:22 +0100111 entry_lookup_list_t *entry = toc_entry_lookup_list;
Harry Liebelf58ad362014-01-10 18:00:33 +0000112
Sandrine Bailleux8c60fee2014-03-19 13:21:42 +0000113 printf("Usage: fip_create [options] FIP_FILENAME\n\n");
Harry Liebelf58ad362014-01-10 18:00:33 +0000114 printf("\tThis tool is used to create a Firmware Image Package.\n\n");
Sandrine Bailleux8c60fee2014-03-19 13:21:42 +0000115 printf("Options:\n");
116 printf("\t--help: Print this help message and exit\n");
117 printf("\t--dump: Print contents of FIP\n\n");
Harry Liebelf58ad362014-01-10 18:00:33 +0000118 printf("\tComponents that can be added/updated:\n");
119 for (; entry->command_line_name != NULL; entry++) {
Sandrine Bailleux8c60fee2014-03-19 13:21:42 +0000120 printf("\t--%s%s\t\t%s",
121 entry->command_line_name,
122 (entry->flags & FLAG_FILENAME) ? " FILENAME" : "",
123 entry->name);
124 printf("\n");
Harry Liebelf58ad362014-01-10 18:00:33 +0000125 }
126}
127
128
Dan Handleye2712bc2014-04-10 15:37:22 +0100129static entry_lookup_list_t *get_entry_lookup_from_uuid(const uuid_t *uuid)
Harry Liebelf58ad362014-01-10 18:00:33 +0000130{
131 unsigned int lookup_index = 0;
132
133 while (toc_entry_lookup_list[lookup_index].command_line_name != NULL) {
134 if (compare_uuids(&toc_entry_lookup_list[lookup_index].name_uuid,
135 uuid) == 0) {
136 return &toc_entry_lookup_list[lookup_index];
137 }
138 lookup_index++;
139 }
140 return NULL;
141}
142
143
Dan Handleye2712bc2014-04-10 15:37:22 +0100144static file_info_t *find_file_info_from_uuid(const uuid_t *uuid)
Harry Liebelf58ad362014-01-10 18:00:33 +0000145{
146 int index;
147
148 for (index = 0; index < file_info_count; index++) {
149 if (compare_uuids(&files[index].name_uuid, uuid) == 0) {
150 return &files[index];
151 }
152 }
153 return NULL;
154}
155
156
Dan Handleye2712bc2014-04-10 15:37:22 +0100157static int add_file_info_entry(entry_lookup_list_t *lookup_entry, char *filename)
Harry Liebelf58ad362014-01-10 18:00:33 +0000158{
Dan Handleye2712bc2014-04-10 15:37:22 +0100159 file_info_t *file_info_entry;
Harry Liebelf58ad362014-01-10 18:00:33 +0000160 int error;
161 struct stat file_status;
162 bool is_new_entry = false;
163
164 /* Check if the file already exists in the array */
165 file_info_entry = find_file_info_from_uuid(&lookup_entry->name_uuid);
166 if (file_info_entry == NULL) {
167 /* The file does not exist in the current list; take the next
168 * one available in the file_info list. 'file_info_count' is
169 * incremented in case of successful update at the end of the
170 * function.
171 */
172 file_info_entry = &files[file_info_count];
173 is_new_entry = true;
174
175 /* Copy the uuid for the new entry */
176 copy_uuid(&file_info_entry->name_uuid,
177 &lookup_entry->name_uuid);
178 }
179
180 /* Get the file information for entry */
181 error = stat(filename, &file_status);
182 if (error != 0) {
183 printf("Error: Cannot get information for file \"%s\": %s\n",
184 filename, strerror(errno));
185 return errno;
186 }
187 file_info_entry->filename = filename;
188 file_info_entry->size = (unsigned int)file_status.st_size;
189 file_info_entry->entry = lookup_entry;
190
191 /* Increment the file_info counter on success if it is new file entry */
192 if (is_new_entry) {
193 file_info_count++;
194
195 /* Ensure we do not overflow */
196 if (file_info_count > MAX_FILES) {
197 printf("ERROR: Too many files in Package\n");
198 return 1;
199 }
200 }
201
202 return 0;
203}
204
205
206static int write_memory_to_file(const uint8_t *start, const char *filename,
207 unsigned int size)
208{
209 FILE *stream;
210 unsigned int bytes_written;
211
212 /* Write the packed file out to the filesystem */
213 stream = fopen(filename, "r+");
214 if (stream == NULL) {
215 stream = fopen(filename, "w");
216 if (stream == NULL) {
217 printf("Error: Cannot create output file \"%s\": %s\n",
218 filename, strerror(errno));
219 return errno;
220 } else {
221 printf("Creating \"%s\"\n", filename);
222 }
223 } else {
224 printf("Updating \"%s\"\n", filename);
225 }
226
227 bytes_written = fwrite(start, sizeof(uint8_t), size, stream);
228 fclose(stream);
229
230 if (bytes_written != size) {
231 printf("Error: Incorrect write for file \"%s\": Size=%u,"
232 "Written=%u bytes.\n", filename, size, bytes_written);
233 return EIO;
234 }
235
236 return 0;
237}
238
239
Dan Handleye2712bc2014-04-10 15:37:22 +0100240static int read_file_to_memory(void *memory, const file_info_t *info)
Harry Liebelf58ad362014-01-10 18:00:33 +0000241{
242 FILE *stream;
243 unsigned int bytes_read;
244
245 /* If the file_info is defined by its filename we need to load it */
246 if (info->filename) {
247 /* Read image from filesystem */
248 stream = fopen(info->filename, "r");
249 if (stream == NULL) {
250 printf("Error: Cannot open file \"%s\": %s\n",
251 info->filename, strerror(errno));
252 return errno;
253 }
254
255 bytes_read = (unsigned int)fread(memory, sizeof(uint8_t),
256 info->size, stream);
257 fclose(stream);
258 if (bytes_read != info->size) {
259 printf("Error: Incomplete read for file \"%s\":"
260 "Size=%u, Read=%u bytes.\n", info->filename,
261 info->size, bytes_read);
262 return EIO;
263 }
264 } else {
265 if (info->image_buffer == NULL) {
266 printf("ERROR: info->image_buffer = NULL\n");
267 return EIO;
268 }
269 /* Copy the file_info buffer (extracted from the existing
270 * image package) into the new buffer.
271 */
272 memcpy(memory, info->image_buffer, info->size);
273 }
274
275 return 0;
276}
277
278
279/* Create the image package file */
280static int pack_images(const char *fip_filename)
281{
282 int status;
283 uint8_t *fip_base_address;
284 void *entry_address;
Dan Handleye2712bc2014-04-10 15:37:22 +0100285 fip_toc_header_t *toc_header;
286 fip_toc_entry_t *toc_entry;
Harry Liebelf58ad362014-01-10 18:00:33 +0000287 unsigned int entry_index;
288 unsigned int toc_size;
289 unsigned int fip_size;
290 unsigned int entry_offset_address;
291 unsigned int payload_size = 0;
292
293 /* Validate filename */
294 if ((fip_filename == NULL) || (strcmp(fip_filename, "") == 0)) {
295 return EINVAL;
296 }
297
298 /* Payload size calculation */
299 for (entry_index = 0; entry_index < file_info_count; entry_index++) {
300 payload_size += files[entry_index].size;
301 }
302
303 /* Allocate memory for entire package, including the final null entry */
Dan Handleye2712bc2014-04-10 15:37:22 +0100304 toc_size = (sizeof(fip_toc_header_t) +
305 (sizeof(fip_toc_entry_t) * (file_info_count + 1)));
Harry Liebelf58ad362014-01-10 18:00:33 +0000306 fip_size = toc_size + payload_size;
307 fip_base_address = malloc(fip_size);
308 if (fip_base_address == NULL) {
309 printf("Error: Can't allocate enough memory to create package."
310 "Process aborted.\n");
311 return ENOMEM;
312 }
313 memset(fip_base_address, 0, fip_size);
314
315 /* Create ToC Header */
Dan Handleye2712bc2014-04-10 15:37:22 +0100316 toc_header = (fip_toc_header_t *)fip_base_address;
Harry Liebelf58ad362014-01-10 18:00:33 +0000317 toc_header->name = TOC_HEADER_NAME;
318 toc_header->serial_number = TOC_HEADER_SERIAL_NUMBER;
319 toc_header->flags = 0;
320
Dan Handleye2712bc2014-04-10 15:37:22 +0100321 toc_entry = (fip_toc_entry_t *)(fip_base_address +
322 sizeof(fip_toc_header_t));
Harry Liebelf58ad362014-01-10 18:00:33 +0000323
324 /* Calculate the starting address of the first image, right after the
325 * toc header.
326 */
327 entry_offset_address = toc_size;
328 entry_index = 0;
329
330 /* Create the package in memory. */
331 for (entry_index = 0; entry_index < file_info_count; entry_index++) {
332 entry_address = (fip_base_address + entry_offset_address);
333 status = read_file_to_memory(entry_address,
334 &files[entry_index]);
335 if (status != 0) {
336 printf("Error: While reading \"%s\" from filesystem.\n",
337 files[entry_index].filename);
338 return status;
339 }
340
341 copy_uuid(&toc_entry->uuid, &files[entry_index].name_uuid);
342 toc_entry->offset_address = entry_offset_address;
343 toc_entry->size = files[entry_index].size;
344 toc_entry->flags = 0;
345 entry_offset_address += toc_entry->size;
346 toc_entry++;
347 }
348
349 /* Add a null uuid entry to mark the end of toc entries */
350 copy_uuid(&toc_entry->uuid, &uuid_null);
351 toc_entry->offset_address = entry_offset_address;
352 toc_entry->size = 0;
353 toc_entry->flags = 0;
354
355 /* Save the package to file */
356 status = write_memory_to_file(fip_base_address, fip_filename, fip_size);
357 if (status != 0) {
358 printf("Error: Failed while writing package to file \"%s\" "
359 "with status=%d.\n", fip_filename, status);
360 return status;
361 }
362 return 0;
363}
364
365
366static void dump_toc(void)
367{
368 unsigned int index = 0;
369 unsigned int image_offset;
370 unsigned int image_size = 0;
371
Dan Handleye2712bc2014-04-10 15:37:22 +0100372 image_offset = sizeof(fip_toc_header_t) +
373 (sizeof(fip_toc_entry_t) * (file_info_count + 1));
Harry Liebelf58ad362014-01-10 18:00:33 +0000374
375 printf("Firmware Image Package ToC:\n");
376 printf("---------------------------\n");
377 for (index = 0; index < file_info_count; index++) {
378 if (files[index].entry) {
379 printf("- %s: ", files[index].entry->name);
380 } else {
381 printf("- Unknown entry: ");
382 }
383 image_size = files[index].size;
384
385 printf("offset=0x%X, size=0x%X\n", image_offset, image_size);
386 image_offset += image_size;
387
388 if (files[index].filename) {
389 printf(" file: '%s'\n", files[index].filename);
390 }
391 }
392 printf("---------------------------\n");
393}
394
395
396/* Read and load existing package into memory. */
397static int parse_fip(const char *fip_filename)
398{
399 FILE *fip;
400 char *fip_buffer;
401 char *fip_buffer_end;
402 int fip_size, read_fip_size;
Dan Handleye2712bc2014-04-10 15:37:22 +0100403 fip_toc_header_t *toc_header;
404 fip_toc_entry_t *toc_entry;
Harry Liebelf58ad362014-01-10 18:00:33 +0000405 bool found_last_toc_entry = false;
Dan Handleye2712bc2014-04-10 15:37:22 +0100406 file_info_t *file_info_entry;
Harry Liebelf58ad362014-01-10 18:00:33 +0000407 int status = -1;
408 struct stat st;
409
410 fip = fopen(fip_filename, "r");
411 if (fip == NULL) {
412 /* If the fip does not exist just return, it should not be
413 * considered as an error. The package will be created later
414 */
415 status = 0;
416 goto parse_fip_return;
417 }
418
419 if (stat(fip_filename, &st) != 0) {
420 status = errno;
421 goto parse_fip_fclose;
422 } else {
423 fip_size = (int)st.st_size;
424 }
425
426 /* Allocate a buffer to read the package */
427 fip_buffer = (char *)malloc(fip_size);
428 if (fip_buffer == NULL) {
429 printf("ERROR: Cannot allocate %d bytes.\n", fip_size);
430 status = errno;
431 goto parse_fip_fclose;
432 }
433 fip_buffer_end = fip_buffer + fip_size;
434
435 /* Read the file */
436 read_fip_size = fread(fip_buffer, sizeof(char), fip_size, fip);
437 if (read_fip_size != fip_size) {
438 printf("ERROR: Cannot read the FIP.\n");
439 status = EIO;
440 goto parse_fip_free;
441 }
442 fclose(fip);
443 fip = NULL;
444
445 /* The package must at least contain the ToC Header */
Dan Handleye2712bc2014-04-10 15:37:22 +0100446 if (fip_size < sizeof(fip_toc_header_t)) {
Harry Liebelf58ad362014-01-10 18:00:33 +0000447 printf("ERROR: Given FIP is smaller than the ToC header.\n");
448 status = EINVAL;
449 goto parse_fip_free;
450 }
451 /* Set the ToC Header at the base of the buffer */
Dan Handleye2712bc2014-04-10 15:37:22 +0100452 toc_header = (fip_toc_header_t *)fip_buffer;
Harry Liebelf58ad362014-01-10 18:00:33 +0000453 /* The first toc entry should be just after the ToC header */
Dan Handleye2712bc2014-04-10 15:37:22 +0100454 toc_entry = (fip_toc_entry_t *)(toc_header + 1);
Harry Liebelf58ad362014-01-10 18:00:33 +0000455
456 /* While the ToC entry is contained into the buffer */
457 int cnt = 0;
Dan Handleye2712bc2014-04-10 15:37:22 +0100458 while (((char *)toc_entry + sizeof(fip_toc_entry_t)) < fip_buffer_end) {
Harry Liebelf58ad362014-01-10 18:00:33 +0000459 cnt++;
460 /* Check if the ToC Entry is the last one */
461 if (compare_uuids(&toc_entry->uuid, &uuid_null) == 0) {
462 found_last_toc_entry = true;
463 status = 0;
464 break;
465 }
466
467 /* Add the entry into file_info */
468
469 /* Get the new entry in the array and clear it */
470 file_info_entry = &files[file_info_count++];
Dan Handleye2712bc2014-04-10 15:37:22 +0100471 memset(file_info_entry, 0, sizeof(file_info_t));
Harry Liebelf58ad362014-01-10 18:00:33 +0000472
473 /* Copy the info from the ToC entry */
474 copy_uuid(&file_info_entry->name_uuid, &toc_entry->uuid);
475 file_info_entry->image_buffer = fip_buffer +
476 toc_entry->offset_address;
477 file_info_entry->size = toc_entry->size;
478
479 /* Check if there is a corresponding entry in lookup table */
480 file_info_entry->entry =
481 get_entry_lookup_from_uuid(&toc_entry->uuid);
482
483 /* Go to the next ToC entry */
484 toc_entry++;
485 }
486
487 if (!found_last_toc_entry) {
488 printf("ERROR: Given FIP does not have an end ToC entry.\n");
489 status = EINVAL;
490 goto parse_fip_free;
491 } else {
492 /* All is well, we should not free any of the loaded images */
493 goto parse_fip_fclose;
494 }
495
496 parse_fip_free:
497 if (fip_buffer != NULL) {
498 free(fip_buffer);
499 fip_buffer = NULL;
500 }
501
502 parse_fip_fclose:
503 if (fip != NULL) {
504 fclose(fip);
505 }
506
507 parse_fip_return:
508 return status;
509}
510
511
512/* Parse all command-line options and return the FIP name if present. */
513static char *get_filename(int argc, char **argv, struct option *options)
514{
515 int c;
516 char *filename = NULL;
517
518 /* Reset option pointer so we parse all args. starts at 1.
519 * The filename is the only argument that does not have an option flag.
520 */
521 optind = 1;
522 while (1) {
523 c = getopt_long(argc, argv, "", options, NULL);
524 if (c == -1)
525 break;
526
527 if (c == '?') {
528 /* Failed to parse an option. Fail. */
529 return NULL;
530 }
531 }
532
533 /* Only one argument left then it is the filename.
534 * We dont expect any other options
535 */
Sandrine Bailleuxfce7a7d2014-03-19 13:39:52 +0000536 if (optind + 1 == argc)
Harry Liebelf58ad362014-01-10 18:00:33 +0000537 filename = argv[optind];
Harry Liebelf58ad362014-01-10 18:00:33 +0000538
539 return filename;
540}
541
542
543/* Work through command-line options */
544static int parse_cmdline(int argc, char **argv, struct option *options,
545 int *do_pack)
546{
547 int c;
548 int status = 0;
549 int option_index = 0;
Dan Handleye2712bc2014-04-10 15:37:22 +0100550 entry_lookup_list_t *lookup_entry;
Harry Liebelf58ad362014-01-10 18:00:33 +0000551 int do_dump = 0;
552
553 /* restart parse to process all options. starts at 1. */
554 optind = 1;
555 while (1) {
556 c = getopt_long(argc, argv, "", options, &option_index);
557 if (c == -1)
558 break;
559
560 switch (c) {
Sandrine Bailleux29e54422014-03-19 13:09:54 +0000561 case OPT_TOC_ENTRY:
Harry Liebelf58ad362014-01-10 18:00:33 +0000562 if (optarg) {
563 /* Does the option expect a filename. */
564 lookup_entry = &toc_entry_lookup_list[option_index];
565 if (lookup_entry->flags & FLAG_FILENAME) {
566 status = add_file_info_entry(lookup_entry, optarg);
567 if (status != 0) {
568 printf("Failed to process %s\n",
569 options[option_index].name);
Kévin Petit90983a52014-12-08 13:23:09 +0000570 return status;
Harry Liebelf58ad362014-01-10 18:00:33 +0000571 } else {
572 /* Update package */
573 *do_pack = 1;
574 }
575 }
576 }
577 break;
Sandrine Bailleux29e54422014-03-19 13:09:54 +0000578
579 case OPT_DUMP:
580 do_dump = 1;
581 continue;
582
Sandrine Bailleux8c60fee2014-03-19 13:21:42 +0000583 case OPT_HELP:
584 print_usage();
585 exit(0);
586
Harry Liebelf58ad362014-01-10 18:00:33 +0000587 default:
588 /* Unrecognised options are caught in get_filename() */
589 break;
590 }
591 }
592
593
594 /* Do not dump toc if we have an error as it could hide the error */
595 if ((status == 0) && (do_dump)) {
596 dump_toc();
597 }
598
599 return status;
600
601}
602
603int main(int argc, char **argv)
604{
605 int i;
606 int status;
607 char *fip_filename;
608 int do_pack = 0;
609
610 /* Clear file list table. */
611 memset(files, 0, sizeof(files));
612
613 /* Initialise for getopt_long().
614 * Use image table as defined at top of file to get options.
Sandrine Bailleux8c60fee2014-03-19 13:21:42 +0000615 * Add 'dump' option, 'help' option and end marker.
Harry Liebelf58ad362014-01-10 18:00:33 +0000616 */
617 static struct option long_options[(sizeof(toc_entry_lookup_list)/
Dan Handleye2712bc2014-04-10 15:37:22 +0100618 sizeof(entry_lookup_list_t)) + 2];
Harry Liebelf58ad362014-01-10 18:00:33 +0000619
620 for (i = 0;
621 /* -1 because we dont want to process end marker in toc table */
Dan Handleye2712bc2014-04-10 15:37:22 +0100622 i < sizeof(toc_entry_lookup_list)/sizeof(entry_lookup_list_t) - 1;
Harry Liebelf58ad362014-01-10 18:00:33 +0000623 i++) {
624 long_options[i].name = toc_entry_lookup_list[i].command_line_name;
625 /* The only flag defined at the moment is for a FILENAME */
626 long_options[i].has_arg = toc_entry_lookup_list[i].flags ? 1 : 0;
627 long_options[i].flag = 0;
Sandrine Bailleux29e54422014-03-19 13:09:54 +0000628 long_options[i].val = OPT_TOC_ENTRY;
Harry Liebelf58ad362014-01-10 18:00:33 +0000629 }
630
631 /* Add '--dump' option */
632 long_options[i].name = "dump";
633 long_options[i].has_arg = 0;
634 long_options[i].flag = 0;
Sandrine Bailleux29e54422014-03-19 13:09:54 +0000635 long_options[i].val = OPT_DUMP;
Harry Liebelf58ad362014-01-10 18:00:33 +0000636
Sandrine Bailleux8c60fee2014-03-19 13:21:42 +0000637 /* Add '--help' option */
638 long_options[++i].name = "help";
639 long_options[i].has_arg = 0;
640 long_options[i].flag = 0;
641 long_options[i].val = OPT_HELP;
642
Harry Liebelf58ad362014-01-10 18:00:33 +0000643 /* Zero the last entry (required) */
644 long_options[++i].name = 0;
645 long_options[i].has_arg = 0;
646 long_options[i].flag = 0;
647 long_options[i].val = 0;
648
649#ifdef DEBUG
650 /* Print all supported options */
651 for (i = 0; i < sizeof(long_options)/sizeof(struct option); i++) {
652 printf("long opt (%d) : name = %s\n", i, long_options[i].name);
653 }
654#endif /* DEBUG */
655
656 /* As the package may already exist and is to be updated we need to get
657 * the filename from the arguments and load from it.
658 * NOTE: As this is the first function to look at the program arguments
659 * it causes a failure if bad options were provided.
660 */
661 fip_filename = get_filename(argc, argv, long_options);
Harry Liebelf58ad362014-01-10 18:00:33 +0000662
663 /* Try to open the file and load it into memory */
Sandrine Bailleuxfce7a7d2014-03-19 13:39:52 +0000664 if (fip_filename != NULL) {
665 status = parse_fip(fip_filename);
666 if (status != 0) {
667 return status;
668 }
Harry Liebelf58ad362014-01-10 18:00:33 +0000669 }
670
671 /* Work through provided program arguments and perform actions */
672 status = parse_cmdline(argc, argv, long_options, &do_pack);
673 if (status != 0) {
674 return status;
675 };
676
Sandrine Bailleuxfce7a7d2014-03-19 13:39:52 +0000677 if (fip_filename == NULL) {
678 printf("ERROR: Missing FIP filename\n");
679 print_usage();
680 return 0;
681 }
682
Harry Liebelf58ad362014-01-10 18:00:33 +0000683 /* Processed all command line options. Create/update the package if
684 * required.
685 */
686 if (do_pack) {
687 status = pack_images(fip_filename);
688 if (status != 0) {
689 printf("Failed to create package (status = %d).\n",
690 status);
691 }
692 }
693
694 return status;
695}