Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
adam.huang
Arm Trusted Firmware
Commits
e8508834
Commit
e8508834
authored
Apr 07, 2016
by
danh-arm
Browse files
Merge pull request #582 from jcastillo-arm/jc/fip_extract
fip_create: add support for image unpacking
parents
91e8ae66
c49a805d
Changes
1
Show whitespace changes
Inline
Side-by-side
tools/fip_create/fip_create.c
View file @
e8508834
/*
/*
* Copyright (c) 2014-201
5
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2014-201
6
, 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:
...
@@ -40,12 +40,19 @@
...
@@ -40,12 +40,19 @@
/* Values returned by getopt() as part of the command line parsing */
/* Values returned by getopt() as part of the command line parsing */
#define OPT_TOC_ENTRY 0
#define OPT_TOC_ENTRY 0
#define OPT_DUMP 1
#define OPT_DUMP 'd'
#define OPT_HELP 2
#define OPT_HELP 'h'
#define OPT_UNPACK 'u'
file_info_t
files
[
MAX_FILES
];
#define OPT_FORCE 'f'
unsigned
file_info_count
=
0
;
#define OPT_STR "dfhu"
uuid_t
uuid_null
=
{
0
};
static
file_info_t
files
[
MAX_FILES
];
static
unsigned
file_info_count
;
static
uuid_t
uuid_null
=
{
0
};
static
int
do_dump
;
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.
...
@@ -118,12 +125,15 @@ static void print_usage(void)
...
@@ -118,12 +125,15 @@ static void print_usage(void)
{
{
entry_lookup_list_t
*
entry
=
toc_entry_lookup_list
;
entry_lookup_list_t
*
entry
=
toc_entry_lookup_list
;
printf
(
"Usage: fip_create [options] FIP_FILENAME
\n\n
"
);
printf
(
"
\n
This tool is used to create a Firmware Image Package.
\n\n
"
);
printf
(
"
\t
This tool is used to create a Firmware Image Package.
\n\n
"
);
printf
(
"Usage:
\n
"
);
printf
(
"
\t
fip_create [options] FIP_FILENAME
\n\n
"
);
printf
(
"Options:
\n
"
);
printf
(
"Options:
\n
"
);
printf
(
"
\t
--help: Print this help message and exit
\n
"
);
printf
(
"
\t
-h,--help: Print this help message and exit
\n
"
);
printf
(
"
\t
--dump: Print contents of FIP
\n\n
"
);
printf
(
"
\t
-d,--dump: Print contents of FIP after update
\n
"
);
printf
(
"
\t
Components that can be added/updated:
\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
"
);
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"
,
entry
->
command_line_name
,
entry
->
command_line_name
,
...
@@ -131,6 +141,7 @@ static void print_usage(void)
...
@@ -131,6 +141,7 @@ static void print_usage(void)
entry
->
name
);
entry
->
name
);
printf
(
"
\n
"
);
printf
(
"
\n
"
);
}
}
printf
(
"
\n
"
);
}
}
...
@@ -371,6 +382,109 @@ static int pack_images(const char *fip_filename)
...
@@ -371,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
;
...
@@ -528,7 +642,7 @@ static char *get_filename(int argc, char **argv, struct option *options)
...
@@ -528,7 +642,7 @@ static char *get_filename(int argc, char **argv, struct option *options)
*/
*/
optind
=
1
;
optind
=
1
;
while
(
1
)
{
while
(
1
)
{
c
=
getopt_long
(
argc
,
argv
,
""
,
options
,
NULL
);
c
=
getopt_long
(
argc
,
argv
,
OPT_STR
,
options
,
NULL
);
if
(
c
==
-
1
)
if
(
c
==
-
1
)
break
;
break
;
...
@@ -549,19 +663,17 @@ static char *get_filename(int argc, char **argv, struct option *options)
...
@@ -549,19 +663,17 @@ static char *get_filename(int argc, char **argv, struct option *options)
/* Work through command-line options */
/* Work through command-line options */
static
int
parse_cmdline
(
int
argc
,
char
**
argv
,
struct
option
*
options
,
static
int
parse_cmdline
(
int
argc
,
char
**
argv
,
struct
option
*
options
)
int
*
do_pack
)
{
{
int
c
;
int
c
;
int
status
=
0
;
int
status
=
0
;
int
option_index
=
0
;
int
option_index
=
0
;
entry_lookup_list_t
*
lookup_entry
;
entry_lookup_list_t
*
lookup_entry
;
int
do_dump
=
0
;
/* restart parse to process all options. starts at 1. */
/* restart parse to process all options. starts at 1. */
optind
=
1
;
optind
=
1
;
while
(
1
)
{
while
(
1
)
{
c
=
getopt_long
(
argc
,
argv
,
""
,
options
,
&
option_index
);
c
=
getopt_long
(
argc
,
argv
,
OPT_STR
,
options
,
&
option_index
);
if
(
c
==
-
1
)
if
(
c
==
-
1
)
break
;
break
;
...
@@ -578,7 +690,7 @@ static int parse_cmdline(int argc, char **argv, struct option *options,
...
@@ -578,7 +690,7 @@ static int parse_cmdline(int argc, char **argv, struct option *options,
return
status
;
return
status
;
}
else
{
}
else
{
/* Update package */
/* Update package */
*
do_pack
=
1
;
do_pack
=
1
;
}
}
}
}
}
}
...
@@ -586,24 +698,26 @@ static int parse_cmdline(int argc, char **argv, struct option *options,
...
@@ -586,24 +698,26 @@ static int parse_cmdline(int argc, char **argv, struct option *options,
case
OPT_DUMP
:
case
OPT_DUMP
:
do_dump
=
1
;
do_dump
=
1
;
continue
;
break
;
case
OPT_HELP
:
case
OPT_HELP
:
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
;
}
}
}
}
/* Do not dump toc if we have an error as it could hide the error */
if
((
status
==
0
)
&&
(
do_dump
))
{
dump_toc
();
}
return
status
;
return
status
;
}
}
...
@@ -613,17 +727,17 @@ int main(int argc, char **argv)
...
@@ -613,17 +727,17 @@ int main(int argc, char **argv)
int
i
;
int
i
;
int
status
;
int
status
;
char
*
fip_filename
;
char
*
fip_filename
;
int
do_pack
=
0
;
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
option
s
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 */
...
@@ -648,6 +762,18 @@ int main(int argc, char **argv)
...
@@ -648,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
;
...
@@ -677,7 +803,7 @@ int main(int argc, char **argv)
...
@@ -677,7 +803,7 @@ int main(int argc, char **argv)
}
}
/* Work through provided program arguments and perform actions */
/* Work through provided program arguments and perform actions */
status
=
parse_cmdline
(
argc
,
argv
,
long_options
,
&
do_pack
);
status
=
parse_cmdline
(
argc
,
argv
,
long_options
);
if
(
status
!=
0
)
{
if
(
status
!=
0
)
{
return
status
;
return
status
;
};
};
...
@@ -688,10 +814,28 @@ int main(int argc, char **argv)
...
@@ -688,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
"
,
...
@@ -699,5 +843,10 @@ int main(int argc, char **argv)
...
@@ -699,5 +843,10 @@ int main(int argc, char **argv)
}
}
}
}
/* Do not dump toc if we have an error as it could hide the error */
if
((
status
==
0
)
&&
(
do_dump
))
{
dump_toc
();
}
return
status
;
return
status
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment