dumpimage: fit: extract FIT images
The dumpimage is able to extract components contained in a FIT image: $ ./dumpimage -T flat_dt -i CONTAINER.ITB -p INDEX FILE The CONTAINER.ITB is a regular FIT container file. The INDEX is the poisition of the sub-image to be retrieved, and FILE is the file (path+name) to save the extracted sub-image. For example, given the following kernel.its to build a kernel.itb: /dts-v1/; / { ... images { kernel@1 { description = "Kernel 2.6.32-34"; data = /incbin/("/boot/vmlinuz-2.6.32-34-generic"); type = "kernel"; arch = "ppc"; os = "linux"; compression = "gzip"; load = <00000000>; entry = <00000000>; hash@1 { algo = "md5"; }; }; ... }; ... }; The dumpimage can extract the 'kernel@1' node through the following command: $ ./dumpimage -T flat_dt -i kernel.itb -p 0 kernel Extracted: Image 0 (kernel@1) Description: Kernel 2.6.32-34 Created: Wed Oct 22 15:50:26 2014 Type: Kernel Image Compression: gzip compressed Data Size: 4040128 Bytes = 3945.44 kB = 3.85 MB Architecture: PowerPC OS: Linux Load Address: 0x00000000 Entry Point: 0x00000000 Hash algo: md5 Hash value: 22352ad39bdc03e2e50f9cc28c1c3652 Which results in the file 'kernel' being exactly the same as '/boot/vmlinuz-2.6.32-34-generic'. Signed-off-by: Guilherme Maciel Ferreira <guilherme.maciel.ferreira@gmail.com>
This commit is contained in:
parent
67f946cd18
commit
39931f966a
@ -112,6 +112,33 @@ static void fit_get_debug(const void *fit, int noffset,
|
||||
fdt_strerror(err));
|
||||
}
|
||||
|
||||
/**
|
||||
* fit_get_subimage_count - get component (sub-image) count
|
||||
* @fit: pointer to the FIT format image header
|
||||
* @images_noffset: offset of images node
|
||||
*
|
||||
* returns:
|
||||
* number of image components
|
||||
*/
|
||||
int fit_get_subimage_count(const void *fit, int images_noffset)
|
||||
{
|
||||
int noffset;
|
||||
int ndepth;
|
||||
int count = 0;
|
||||
|
||||
/* Process its subnodes, print out component images details */
|
||||
for (ndepth = 0, count = 0,
|
||||
noffset = fdt_next_node(fit, images_noffset, &ndepth);
|
||||
(noffset >= 0) && (ndepth > 0);
|
||||
noffset = fdt_next_node(fit, noffset, &ndepth)) {
|
||||
if (ndepth == 1) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_FIT_SPL_PRINT)
|
||||
/**
|
||||
* fit_print_contents - prints out the contents of the FIT format image
|
||||
@ -423,7 +450,8 @@ void fit_image_print(const void *fit, int image_noffset, const char *p)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !defined(CONFIG_SPL_BUILD) || defined(CONFIG_FIT_SPL_PRINT) */
|
||||
|
||||
/**
|
||||
* fit_get_desc - get node description property
|
||||
|
@ -751,6 +751,7 @@ int fit_parse_conf(const char *spec, ulong addr_curr,
|
||||
int fit_parse_subimage(const char *spec, ulong addr_curr,
|
||||
ulong *addr, const char **image_name);
|
||||
|
||||
int fit_get_subimage_count(const void *fit, int images_noffset);
|
||||
void fit_print_contents(const void *fit);
|
||||
void fit_image_print(const void *fit, int noffset, const char *p);
|
||||
|
||||
|
@ -16,6 +16,8 @@ BASEDIR=sandbox
|
||||
SRCDIR=${BASEDIR}/boot
|
||||
IMAGE_NAME="v1.0-test"
|
||||
IMAGE_MULTI=linux.img
|
||||
IMAGE_FIT_ITS=linux.its
|
||||
IMAGE_FIT_ITB=linux.itb
|
||||
DATAFILE0=vmlinuz
|
||||
DATAFILE1=initrd.img
|
||||
DATAFILE2=System.map
|
||||
@ -34,7 +36,10 @@ cleanup()
|
||||
for file in ${DATAFILES}; do
|
||||
rm -f ${file} ${SRCDIR}/${file}
|
||||
done
|
||||
rm -f ${IMAGE_MULTI} ${DUMPIMAGE_LIST} ${MKIMAGE_LIST} ${TEST_OUT}
|
||||
rm -f ${IMAGE_MULTI}
|
||||
rm -f ${DUMPIMAGE_LIST}
|
||||
rm -f ${MKIMAGE_LIST}
|
||||
rm -f ${TEST_OUT}
|
||||
rmdir ${SRCDIR}
|
||||
}
|
||||
|
||||
@ -105,6 +110,70 @@ extract_multi_image()
|
||||
echo "done."
|
||||
}
|
||||
|
||||
# Write files into a FIT image
|
||||
create_fit_image()
|
||||
{
|
||||
echo " \
|
||||
/dts-v1/; \
|
||||
/ { \
|
||||
description = \"FIT image\"; \
|
||||
#address-cells = <1>; \
|
||||
\
|
||||
images { \
|
||||
kernel@1 { \
|
||||
description = \"kernel\"; \
|
||||
data = /incbin/(\"${DATAFILE0}\"); \
|
||||
type = \"kernel\"; \
|
||||
arch = \"sandbox\"; \
|
||||
os = \"linux\"; \
|
||||
compression = \"gzip\"; \
|
||||
load = <0x40000>; \
|
||||
entry = <0x8>; \
|
||||
}; \
|
||||
ramdisk@1 { \
|
||||
description = \"filesystem\"; \
|
||||
data = /incbin/(\"${DATAFILE1}\"); \
|
||||
type = \"ramdisk\"; \
|
||||
arch = \"sandbox\"; \
|
||||
os = \"linux\"; \
|
||||
compression = \"none\"; \
|
||||
load = <0x80000>; \
|
||||
entry = <0x16>; \
|
||||
}; \
|
||||
fdt@1 { \
|
||||
description = \"device tree\"; \
|
||||
data = /incbin/(\"${DATAFILE2}\"); \
|
||||
type = \"flat_dt\"; \
|
||||
arch = \"sandbox\"; \
|
||||
compression = \"none\"; \
|
||||
}; \
|
||||
}; \
|
||||
configurations { \
|
||||
default = \"conf@1\"; \
|
||||
conf@1 { \
|
||||
kernel = \"kernel@1\"; \
|
||||
fdt = \"fdt@1\"; \
|
||||
}; \
|
||||
}; \
|
||||
}; \
|
||||
" > ${IMAGE_FIT_ITS}
|
||||
|
||||
echo -e "\nBuilding FIT image..."
|
||||
do_cmd ${MKIMAGE} -f ${IMAGE_FIT_ITS} ${IMAGE_FIT_ITB}
|
||||
echo "done."
|
||||
}
|
||||
|
||||
# Extract files from a FIT image
|
||||
extract_fit_image()
|
||||
{
|
||||
echo -e "\nExtracting FIT image contents..."
|
||||
do_cmd ${DUMPIMAGE} -T flat_dt -i ${IMAGE_FIT_ITB} -p 0 ${DATAFILE0}
|
||||
do_cmd ${DUMPIMAGE} -T flat_dt -i ${IMAGE_FIT_ITB} -p 1 ${DATAFILE1}
|
||||
do_cmd ${DUMPIMAGE} -T flat_dt -i ${IMAGE_FIT_ITB} -p 2 ${DATAFILE2}
|
||||
do_cmd ${DUMPIMAGE} -T flat_dt -i ${IMAGE_FIT_ITB} -p 2 ${DATAFILE2} -o ${TEST_OUT}
|
||||
echo "done."
|
||||
}
|
||||
|
||||
# List the contents of a file
|
||||
# Args:
|
||||
# image filename
|
||||
@ -136,6 +205,18 @@ main()
|
||||
list_image ${IMAGE_MULTI}
|
||||
assert_equal ${DUMPIMAGE_LIST} ${MKIMAGE_LIST}
|
||||
|
||||
# Compress and extract FIT images, compare the result
|
||||
create_fit_image
|
||||
extract_fit_image
|
||||
for file in ${DATAFILES}; do
|
||||
assert_equal ${file} ${SRCDIR}/${file}
|
||||
done
|
||||
assert_equal ${TEST_OUT} ${DATAFILE2}
|
||||
|
||||
# List contents of FIT image and compares output from tools
|
||||
list_image ${IMAGE_FIT_ITB}
|
||||
assert_equal ${DUMPIMAGE_LIST} ${MKIMAGE_LIST}
|
||||
|
||||
# Remove files created
|
||||
cleanup
|
||||
|
||||
|
@ -155,6 +155,97 @@ err_system:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* fit_image_extract - extract a FIT component image
|
||||
* @fit: pointer to the FIT format image header
|
||||
* @image_noffset: offset of the component image node
|
||||
* @file_name: name of the file to store the FIT sub-image
|
||||
*
|
||||
* returns:
|
||||
* zero in case of success or a negative value if fail.
|
||||
*/
|
||||
static int fit_image_extract(
|
||||
const void *fit,
|
||||
int image_noffset,
|
||||
const char *file_name)
|
||||
{
|
||||
const void *file_data;
|
||||
size_t file_size = 0;
|
||||
|
||||
/* get the "data" property of component at offset "image_noffset" */
|
||||
fit_image_get_data(fit, image_noffset, &file_data, &file_size);
|
||||
|
||||
/* save the "file_data" into the file specified by "file_name" */
|
||||
return imagetool_save_subimage(file_name, (ulong) file_data, file_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* fit_extract_contents - retrieve a sub-image component from the FIT image
|
||||
* @ptr: pointer to the FIT format image header
|
||||
* @params: command line parameters
|
||||
*
|
||||
* returns:
|
||||
* zero in case of success or a negative value if fail.
|
||||
*/
|
||||
static int fit_extract_contents(void *ptr, struct image_tool_params *params)
|
||||
{
|
||||
int images_noffset;
|
||||
int noffset;
|
||||
int ndepth;
|
||||
const void *fit = ptr;
|
||||
int count = 0;
|
||||
const char *p;
|
||||
|
||||
/* Indent string is defined in header image.h */
|
||||
p = IMAGE_INDENT_STRING;
|
||||
|
||||
if (!fit_check_format(fit)) {
|
||||
printf("Bad FIT image format\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Find images parent node offset */
|
||||
images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
|
||||
if (images_noffset < 0) {
|
||||
printf("Can't find images parent node '%s' (%s)\n",
|
||||
FIT_IMAGES_PATH, fdt_strerror(images_noffset));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Avoid any overrun */
|
||||
count = fit_get_subimage_count(fit, images_noffset);
|
||||
if ((params->pflag < 0) || (count <= params->pflag)) {
|
||||
printf("No such component at '%d'\n", params->pflag);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Process its subnodes, extract the desired component from image */
|
||||
for (ndepth = 0, count = 0,
|
||||
noffset = fdt_next_node(fit, images_noffset, &ndepth);
|
||||
(noffset >= 0) && (ndepth > 0);
|
||||
noffset = fdt_next_node(fit, noffset, &ndepth)) {
|
||||
if (ndepth == 1) {
|
||||
/*
|
||||
* Direct child node of the images parent node,
|
||||
* i.e. component image node.
|
||||
*/
|
||||
if (params->pflag == count) {
|
||||
printf("Extracted:\n%s Image %u (%s)\n", p,
|
||||
count, fit_get_name(fit, noffset, NULL));
|
||||
|
||||
fit_image_print(fit, noffset, p);
|
||||
|
||||
return fit_image_extract(fit, noffset,
|
||||
params->outfile);
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fit_check_params(struct image_tool_params *params)
|
||||
{
|
||||
return ((params->dflag && (params->fflag || params->lflag)) ||
|
||||
@ -171,7 +262,7 @@ U_BOOT_IMAGE_TYPE(
|
||||
fit_verify_header,
|
||||
fit_print_contents,
|
||||
NULL,
|
||||
NULL,
|
||||
fit_extract_contents,
|
||||
fit_check_image_types,
|
||||
fit_handle_file,
|
||||
NULL /* FIT images use DTB header */
|
||||
|
Loading…
Reference in New Issue
Block a user