mkimage: Support adding device tree files to a FIT
authorSimon Glass <sjg@chromium.org>
Tue, 23 Feb 2016 05:55:52 +0000 (22:55 -0700)
committerTom Rini <trini@konsulko.com>
Mon, 14 Mar 2016 23:18:29 +0000 (19:18 -0400)
To make the auto-FIT feature useful we need to be able to provide a list of
device tree files on the command line for mkimage to add into the FIT. Add
support for this feature.

So far there is no support for hashing or verified boot using this method.
For those cases, a .its file must still be provided.

Signed-off-by: Simon Glass <sjg@chromium.org>
doc/mkimage.1
tools/fit_image.c
tools/imagetool.h
tools/mkimage.c

index 146c114d9d6a3a7aaf37cbf13fb5076d8928ff86..036b095c1b6022e15758daa4b0c1847e495eb658 100644 (file)
@@ -96,6 +96,10 @@ Set XIP (execute in place) flag.
 .P
 .B Create FIT image:
 
+.TP
+.BI "\-b
+Specifies that the following arguments are device tree binary files (.dtb).
+
 .TP
 .BI "\-c [" "comment" "]"
 Specifies a comment to be added when signing. This is typically a useful
@@ -191,6 +195,15 @@ is required.
 .br
 .B -c """Kernel 4.4 image for production devices""" -d vmlinuz kernel.itb
 .fi
+.P
+Create a FIT image containing a kernel and some device tree files, using
+automatic mode. No .its file is required.
+.nf
+.B mkimage -f auto -A arm -O linux -T kernel -C none -a 43e00000 -e 0 \\\\
+.br
+.B -c """Kernel 4.4 image for production devices""" -d vmlinuz \\\\
+.B -b /path/to/rk3288-firefly.dtb /path/to/rk3288-jerry.dtb kernel.itb
+.fi
 
 .SH HOMEPAGE
 http://www.denx.de/wiki/U-Boot/WebHome
index ed101f1d31dac9154a0db61887b09f7eb998d968..765ff31e672abe7939e32c27aed856bcce5f404c 100644 (file)
@@ -77,6 +77,7 @@ err_keydest:
  */
 static int fit_calc_size(struct image_tool_params *params)
 {
+       struct content_info *cont;
        int size, total_size;
 
        size = imagetool_get_filesize(params, params->datafile);
@@ -84,8 +85,14 @@ static int fit_calc_size(struct image_tool_params *params)
                return -1;
 
        total_size = size;
+       for (cont = params->content_head; cont; cont = cont->next) {
+               size = imagetool_get_filesize(params, cont->fname);
+               if (size < 0)
+                       return -1;
 
-       /* TODO(sjg@chromium.org): Add in the size of any other files */
+               /* Add space for properties */
+               total_size += size + 300;
+       }
 
        /* Add plenty of space for headers, properties, nodes, etc. */
        total_size += 4096;
@@ -141,15 +148,40 @@ static int fdt_property_strf(void *fdt, const char *name, const char *fmt, ...)
        return fdt_property_string(fdt, name, str);
 }
 
+static void get_basename(char *str, int size, const char *fname)
+{
+       const char *p, *start, *end;
+       int len;
+
+       /*
+        * Use the base name as the 'name' field. So for example:
+        *
+        * "arch/arm/dts/sun7i-a20-bananapro.dtb"
+        * becomes "sun7i-a20-bananapro"
+        */
+       p = strrchr(fname, '/');
+       start = p ? p + 1 : fname;
+       p = strrchr(fname, '.');
+       end = p ? p : fname + strlen(fname);
+       len = end - start;
+       if (len >= size)
+               len = size - 1;
+       memcpy(str, start, len);
+       str[len] = '\0';
+}
+
 /**
  * fit_write_images() - Write out a list of images to the FIT
  *
- * Include the main image (params->datafile).
+ * We always include the main image (params->datafile). If there are device
+ * tree files, we include an fdt@ node for each of those too.
  */
 static int fit_write_images(struct image_tool_params *params, char *fdt)
 {
+       struct content_info *cont;
        const char *typename;
        char str[100];
+       int upto;
        int ret;
 
        fdt_begin_node(fdt, "images");
@@ -176,6 +208,27 @@ static int fit_write_images(struct image_tool_params *params, char *fdt)
                return ret;
        fdt_end_node(fdt);
 
+       /* Now the device tree files if available */
+       upto = 0;
+       for (cont = params->content_head; cont; cont = cont->next) {
+               if (cont->type != IH_TYPE_FLATDT)
+                       continue;
+               snprintf(str, sizeof(str), "%s@%d", FIT_FDT_PROP, ++upto);
+               fdt_begin_node(fdt, str);
+
+               get_basename(str, sizeof(str), cont->fname);
+               fdt_property_string(fdt, "description", str);
+               ret = fdt_property_file(params, fdt, "data", cont->fname);
+               if (ret)
+                       return ret;
+               fdt_property_string(fdt, "type", typename);
+               fdt_property_string(fdt, "arch",
+                                   genimg_get_arch_short_name(params->arch));
+               fdt_property_string(fdt, "compression",
+                                   genimg_get_comp_short_name(IH_COMP_NONE));
+               fdt_end_node(fdt);
+       }
+
        fdt_end_node(fdt);
 
        return 0;
@@ -184,21 +237,48 @@ static int fit_write_images(struct image_tool_params *params, char *fdt)
 /**
  * fit_write_configs() - Write out a list of configurations to the FIT
  *
- * Create a configuration with the main image in it.
+ * If there are device tree files, we include a configuration for each, which
+ * selects the main image (params->datafile) and its corresponding device
+ * tree file.
+ *
+ * Otherwise we just create a configuration with the main image in it.
  */
 static void fit_write_configs(struct image_tool_params *params, char *fdt)
 {
+       struct content_info *cont;
        const char *typename;
        char str[100];
+       int upto;
 
        fdt_begin_node(fdt, "configurations");
        fdt_property_string(fdt, "default", "conf@1");
 
-       fdt_begin_node(fdt, "conf@1");
-       typename = genimg_get_type_short_name(params->fit_image_type);
-       snprintf(str, sizeof(str), "%s@1", typename);
-       fdt_property_string(fdt, typename, str);
-       fdt_end_node(fdt);
+       upto = 0;
+       for (cont = params->content_head; cont; cont = cont->next) {
+               if (cont->type != IH_TYPE_FLATDT)
+                       continue;
+               typename = genimg_get_type_short_name(cont->type);
+               snprintf(str, sizeof(str), "conf@%d", ++upto);
+               fdt_begin_node(fdt, str);
+
+               get_basename(str, sizeof(str), cont->fname);
+               fdt_property_string(fdt, "description", str);
+
+               typename = genimg_get_type_short_name(params->fit_image_type);
+               snprintf(str, sizeof(str), "%s@1", typename);
+               fdt_property_string(fdt, typename, str);
+
+               snprintf(str, sizeof(str), FIT_FDT_PROP "@%d", upto);
+               fdt_property_string(fdt, FIT_FDT_PROP, str);
+               fdt_end_node(fdt);
+       }
+       if (!upto) {
+               fdt_begin_node(fdt, "conf@1");
+               typename = genimg_get_type_short_name(params->fit_image_type);
+               snprintf(str, sizeof(str), "%s@1", typename);
+               fdt_property_string(fdt, typename, str);
+               fdt_end_node(fdt);
+       }
 
        fdt_end_node(fdt);
 }
index 4f426e40a04043581d8acb2b09cdfac4bb6c79a4..3d30fbec5c3b3163a1ae9fc08e380e2a7241d3bd 100644 (file)
 
 #define IH_ARCH_DEFAULT                IH_ARCH_INVALID
 
+/* Information about a file that needs to be placed into the FIT */
+struct content_info {
+       struct content_info *next;
+       int type;               /* File type (IH_TYPE_...) */
+       const char *fname;
+};
+
 /*
  * This structure defines all such variables those are initialized by
  * mkimage and dumpimage main core and need to be referred by image
@@ -63,6 +70,8 @@ struct image_tool_params {
        int orig_file_size;     /* Original size for file before padding */
        bool auto_its;          /* Automatically create the .its file */
        int fit_image_type;     /* Image type to put into the FIT */
+       struct content_info *content_head;      /* List of files to include */
+       struct content_info *content_tail;
 };
 
 /*
index 7add86c13d09074cb6bcb09f446c71fa0b290b4b..22fab1d535e142d76c3c853faa506adbc6a5f92b 100644 (file)
@@ -85,7 +85,8 @@ static void usage(const char *msg)
                "          -x ==> set XIP (execute in place)\n",
                params.cmdname);
        fprintf(stderr,
-               "       %s [-D dtc_options] [-f fit-image.its|-f auto|-F] fit-image\n",
+               "       %s [-D dtc_options] [-f fit-image.its|-f auto|-F] [-b <dtb_list>] fit-image\n"
+               "           <dtb_list> is used with -f auto, and is a space-separated list of .dtb files\n",
                params.cmdname);
        fprintf(stderr,
                "          -D => set all options for device tree compiler\n"
@@ -109,6 +110,24 @@ static void usage(const char *msg)
        exit(EXIT_FAILURE);
 }
 
+static int add_content(int type, const char *fname)
+{
+       struct content_info *cont;
+
+       cont = calloc(1, sizeof(*cont));
+       if (!cont)
+               return -1;
+       cont->type = type;
+       cont->fname = fname;
+       if (params.content_tail)
+               params.content_tail->next = cont;
+       else
+               params.content_head = cont;
+       params.content_tail = cont;
+
+       return 0;
+}
+
 static void process_args(int argc, char **argv)
 {
        char *ptr;
@@ -119,7 +138,7 @@ static void process_args(int argc, char **argv)
 
        expecting = IH_TYPE_COUNT;      /* Unknown */
        while ((opt = getopt(argc, argv,
-                            "-a:A:cC:d:D:e:f:Fk:K:ln:O:rR:sT:vVx")) != -1) {
+                            "-a:A:bcC:d:D:e:f:Fk:K:ln:O:rR:sT:vVx")) != -1) {
                switch (opt) {
                case 'a':
                        params.addr = strtoull(optarg, &ptr, 16);
@@ -134,6 +153,9 @@ static void process_args(int argc, char **argv)
                        if (params.arch < 0)
                                usage("Invalid architecture");
                        break;
+               case 'b':
+                       expecting = IH_TYPE_FLATDT;
+                       break;
                case 'c':
                        params.comment = optarg;
                        break;
@@ -222,6 +244,18 @@ static void process_args(int argc, char **argv)
                        if (expecting == type || optind == argc) {
                                params.imagefile = optarg;
                                expecting = IH_TYPE_INVALID;
+                       } else if (expecting == IH_TYPE_INVALID) {
+                               fprintf(stderr,
+                                       "%s: Unknown content type: use -b before device tree files",
+                                       params.cmdname);
+                               exit(EXIT_FAILURE);
+                       } else {
+                               if (add_content(expecting, optarg)) {
+                                       fprintf(stderr,
+                                               "%s: Out of memory adding content '%s'",
+                                               params.cmdname, optarg);
+                                       exit(EXIT_FAILURE);
+                               }
                        }
                        break;
                default: