[U-Boot] [PATCH 3/4] dumpimage: fit: extract FIT images
Guilherme Maciel Ferreira
guilherme.maciel.ferreira at gmail.com
Thu Jan 15 05:54:42 CET 2015
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 at 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 at 1 {
algo = "md5";
};
};
...
};
...
};
The dumpimage can extract the 'kernel at 1' node through the following command:
$ ./dumpimage -T flat_dt -i kernel.itb -p 0 kernel
Extracted:
Image 0 (kernel at 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 at gmail.com>
---
common/image-fit.c | 30 +++++++++++++-
include/image.h | 1 +
test/image/test-imagetools.sh | 83 ++++++++++++++++++++++++++++++++++++-
tools/fit_image.c | 93 ++++++++++++++++++++++++++++++++++++++++-
4 files changed, 204 insertions(+), 3 deletions(-)
diff --git a/common/image-fit.c b/common/image-fit.c
index 4ffc5aa..aaf3a81 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -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
diff --git a/include/image.h b/include/image.h
index aa748fa..f236fdd 100644
--- a/include/image.h
+++ b/include/image.h
@@ -750,6 +750,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);
diff --git a/test/image/test-imagetools.sh b/test/image/test-imagetools.sh
index 8aaaade..952f975 100755
--- a/test/image/test-imagetools.sh
+++ b/test/image/test-imagetools.sh
@@ -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 at 1 { \
+ description = \"kernel\"; \
+ data = /incbin/(\"${DATAFILE0}\"); \
+ type = \"kernel\"; \
+ arch = \"sandbox\"; \
+ os = \"linux\"; \
+ compression = \"gzip\"; \
+ load = <0x40000>; \
+ entry = <0x8>; \
+ }; \
+ ramdisk at 1 { \
+ description = \"filesystem\"; \
+ data = /incbin/(\"${DATAFILE1}\"); \
+ type = \"ramdisk\"; \
+ arch = \"sandbox\"; \
+ os = \"linux\"; \
+ compression = \"none\"; \
+ load = <0x80000>; \
+ entry = <0x16>; \
+ }; \
+ fdt at 1 { \
+ description = \"device tree\"; \
+ data = /incbin/(\"${DATAFILE2}\"); \
+ type = \"flat_dt\"; \
+ arch = \"sandbox\"; \
+ compression = \"none\"; \
+ }; \
+ }; \
+ configurations { \
+ default = \"conf at 1\"; \
+ conf at 1 { \
+ kernel = \"kernel at 1\"; \
+ fdt = \"fdt at 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
diff --git a/tools/fit_image.c b/tools/fit_image.c
index 5712842..eb2a25e 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -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 */
--
1.7.0.4
More information about the U-Boot
mailing list