Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.sbin/installboot Add support for additional install step...



details:   https://anonhg.NetBSD.org/src/rev/2f5f3a774cad
branches:  trunk
changeset: 965485:2f5f3a774cad
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Thu Sep 19 01:25:29 2019 +0000

description:
Add support for additional install step directives to enable using
installboot(8) to write u-boot images to SPI NOR and other types of
raw flash devices: input-block-size, input-pad-size, output-size, and
output-block-size.

Add the ability to create aliases for install objects, useful for when
e.g. sdmmc and emmc share the same steps.

Tested on an A20-OLinuXino-LIME2-e16Gs16M by bouyer@.

XXX pullup netbsd-9

diffstat:

 usr.sbin/installboot/evboards.c |  407 +++++++++++++++++++++++++++++++++++----
 usr.sbin/installboot/evboards.h |    6 +-
 2 files changed, 368 insertions(+), 45 deletions(-)

diffs (truncated from 555 to 300 lines):

diff -r c7f67a627078 -r 2f5f3a774cad usr.sbin/installboot/evboards.c
--- a/usr.sbin/installboot/evboards.c   Wed Sep 18 23:43:23 2019 +0000
+++ b/usr.sbin/installboot/evboards.c   Thu Sep 19 01:25:29 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: evboards.c,v 1.2 2019/05/12 13:47:09 maya Exp $        */
+/*     $NetBSD: evboards.c,v 1.3 2019/09/19 01:25:29 thorpej Exp $     */
 
 /*-
  * Copyright (c) 2019 The NetBSD Foundation, Inc.
@@ -35,10 +35,11 @@
 
 #include <sys/cdefs.h>
 #if !defined(__lint)
-__RCSID("$NetBSD: evboards.c,v 1.2 2019/05/12 13:47:09 maya Exp $");
+__RCSID("$NetBSD: evboards.c,v 1.3 2019/09/19 01:25:29 thorpej Exp $");
 #endif  /* !__lint */
 
 #include <sys/types.h>
+#include <sys/param.h>         /* for roundup() */
 #include <sys/stat.h>
 #include <assert.h>
 #include <err.h>
@@ -199,6 +200,7 @@
  *               --    "u-boot-install-sdmmc"  (for SD cards)
  *               --    "u-boot-install-emmc"   (for eMMC modules)
  *               --    "u-boot-install-usb"    (for USB block storage)
+ *               --    "u-boot-install-spi"    (for SPI NOR flash)
  *               --
  *               -- These installation steps will be selectable using
  *               -- the "media=..." option to installboot(8).
@@ -324,6 +326,91 @@
  *                     <integer>512</integer>
  *             </dict>
  *     </array>
+ *
+ * There are some addditional directives for installing on raw flash devices:
+ *
+ *     <key>u-boot-install-spi</key>
+ *     <array>
+ *             <!-- This board's SPI NOR flash is 16Mbit (2MB) in size,
+ *               -- arranged as 32 512Kbit (64KB) blocks.
+ *             <dict>
+ *                     <key>file-name</key>
+ *                     <string>u-boot-with-spl.bin</string>
+ *
+ *                     <!-- Key: "input-block-size".
+ *                       -- Value: an integer specifying how much file
+ *                       --        data to read per input block before
+ *                       --        padding.  Must be used in conjunction
+ *                       --        with "input-pad-size".
+ *                       -- (optional)
+ *                       -->
+ *                     <key>input-block-size</key>
+ *                     <integer>2048</integer>
+ *
+ *                     <!-- Key: "input-pad-size".
+ *                       -- Value: an integer specifing the amount of
+ *                       --        zero padding inserted per input block.
+ *                       --        Must be used in cojunction with
+ *                       --        "input-block-size".
+ *                       -- (optional)
+ *                       -->
+ *                     <key>input-pad-size</key>
+ *                     <integer>2048</integer>
+ *
+ *                     <!-- Key: "output-size".
+ *                       -- Value: an integer specifying the total
+ *                       --        size to be written to the output
+ *                       --        device.  This is used when writing
+ *                       --        a bootloader to a raw flash memory
+ *                       --        device such as a SPI NOR flash.
+ *                       --        The boot loader MUST fit within
+ *                       --        this size and the output will be
+ *                       --        padded to this size with zeros.
+ *                       --
+ *                       --        If the "output-block-size" key (below)
+ *                       --        is also specified, then this value
+ *                       --        must be a multiple of the output block
+ *                       --        size.
+ *                       -- (optional)
+ *                       -->
+ *                     <key>output-size</key>
+ *                     <integer>2097152</integer>
+ *
+ *                     <-- Key: "output-block-size"
+ *                      -- Value: an integer specifying the size of
+ *                      --        the blocks used to write to the
+ *                      --        output device.  If the output device
+ *                      --        simulates a disk block storage device,
+ *                      --        then this value must be a multiple of
+ *                      --        the reported sector size.
+ *                      -- (optional)
+ *                      -->
+ *                     <key>output-block-size</key>
+ *                     <integer>65536</integer>
+ *             </dict>
+ *     </array>
+ *
+ * For boards that require a media specification to be provided, it
+ * may be the case that two media types have identical steps.  It
+ * could be confusing for users to see a list of media types that does
+ * not include the media type on which they are installing, so there
+ * is an alias capability:
+ *
+ *     <key>u-boot-install-spi</key>
+ *     <array>
+ *             .
+ *             .
+ *             .
+ *     </array>
+ *     <key>u-boot-install-sdmmc</key>
+ *     <array>
+ *             .
+ *             .
+ *             .
+ *     </array>
+ *     <-- Steps for eMMC are identical to SDMMC on this board. -->
+ *     <key>u-boot-install-emmc</key>
+ *     <string>u-boot-install-sdmmc</string>
  */
 
 /*
@@ -466,6 +553,10 @@
 static const char step_file_offset_key[] = "file-offset";
 static const char step_file_size_key[] = "file-size";
 static const char step_image_offset_key[] = "image-offset";
+static const char step_input_block_size_key[] = "input-block-size";
+static const char step_input_pad_size_key[] = "input-pad-size";
+static const char step_output_size_key[] = "output-size";
+static const char step_output_block_size_key[] = "output-block-size";
 static const char step_preserve_key[] = "preserve";
 
 static bool
@@ -474,11 +565,15 @@
        /*
         * evb_ubstep is a dictionary with the following keys:
         *
-        *      "file-name"     (string) (required)
-        *      "file-offset"   (number) (optional)
-        *      "file-size"     (number) (optional)
-        *      "image-offset"  (number) (optional)
-        *      "preserve"      (bool)   (optional)
+        *      "file-name"         (string) (required)
+        *      "file-offset"       (number) (optional)
+        *      "file-size"         (number) (optional)
+        *      "image-offset"      (number) (optional)
+        *      "input-block-size"  (number) (optional)
+        *      "input-pad-size"    (number) (optional)
+        *      "output-size"       (number) (optional)
+        *      "output-block-size" (number) (optional)
+        *      "preserve"          (bool)   (optional)
         */
        if (prop_object_type(obj) != PROP_TYPE_DICTIONARY)
                return false;
@@ -505,6 +600,37 @@
            prop_object_type(v) != PROP_TYPE_NUMBER)
                return false;
 
+       bool have_input_block_size = false;
+       bool have_input_pad_size = false;
+
+       v = prop_dictionary_get(obj, step_input_block_size_key);
+       if (v != NULL) {
+               have_input_block_size = true;
+               if (prop_object_type(v) != PROP_TYPE_NUMBER)
+                       return false;
+       }
+
+       v = prop_dictionary_get(obj, step_input_pad_size_key);
+       if (v != NULL) {
+               have_input_pad_size = true;
+               if (prop_object_type(v) != PROP_TYPE_NUMBER)
+                       return false;
+       }
+
+       /* Must have both or neither of input-{block,pad}-size. */
+       if (have_input_block_size ^ have_input_pad_size)
+               return false;
+
+       v = prop_dictionary_get(obj, step_output_size_key);
+       if (v != NULL &&
+           prop_object_type(v) != PROP_TYPE_NUMBER)
+               return false;
+
+       v = prop_dictionary_get(obj, step_output_block_size_key);
+       if (v != NULL &&
+           prop_object_type(v) != PROP_TYPE_NUMBER)
+               return false;
+
        v = prop_dictionary_get(obj, step_preserve_key);
        if (v != NULL &&
            prop_object_type(v) != PROP_TYPE_BOOL)
@@ -514,15 +640,34 @@
 }
 
 static bool
-validate_ubinstall_object(evb_ubinstall obj)
+validate_ubinstall_object(evb_board board, evb_ubinstall obj)
 {
        /*
-        * evb_ubinstall is an array with one or more evb_ubstep
-        * objects.
+        * evb_ubinstall is either:
+        * -- an array with one or more evb_ubstep objects.
+        * -- a string representing an alias of another evb_ubinstall
+        *    object
         *
         * (evb_ubsteps is just a convenience type for iterating
         * over the steps.)
         */
+
+       if (prop_object_type(obj) == PROP_TYPE_STRING) {
+               evb_ubinstall tobj = prop_dictionary_get(board,
+                   prop_string_cstring_nocopy((prop_string_t)obj));
+
+               /*
+                * The target evb_ubinstall object must exist
+                * and must itself be a proper evb_ubinstall,
+                * not another alias.
+                */
+               if (tobj == NULL ||
+                   prop_object_type(tobj) != PROP_TYPE_ARRAY) {
+                       return false;
+               }
+               return true;
+       }
+
        if (prop_object_type(obj) != PROP_TYPE_ARRAY)
                return false;
        if (prop_array_count(obj) < 1)
@@ -605,7 +750,7 @@
                }
                v = prop_dictionary_get_keysym(obj, key);
                assert(v != NULL);
-               if (!is_overlay || !validate_ubinstall_object(v))
+               if (!is_overlay || !validate_ubinstall_object(obj, v))
                        break;
        }
        prop_object_iterator_release(iter);
@@ -1287,8 +1432,18 @@
        if (n < 0 || (size_t)n >= sizeof(install_key))
                goto invalid_media;;
        install = prop_dictionary_get(board, install_key);
-       if (install != NULL)
+       if (install != NULL) {
+               if (prop_object_type(install) == PROP_TYPE_STRING) {
+                       /*
+                        * This is an alias.  Fetch the target.  We
+                        * have already validated that the target
+                        * exists.
+                        */
+                       install = prop_dictionary_get(board,
+                           prop_string_cstring_nocopy((prop_string_t)install));
+               }
                return install;
+       }
  invalid_media:
        warnx("invalid media specification: '%s'", params->media);
  list_media:
@@ -1422,6 +1577,64 @@
 }
 
 /*
+ * evb_ubstep_get_input_block_size --
+ *     Returns the input block size to use when reading the boot loader
+ *     file.
+ */
+uint64_t
+evb_ubstep_get_input_block_size(ib_params *params, evb_ubstep step)
+{
+       prop_number_t number = prop_dictionary_get(step,
+                                                  step_input_block_size_key);
+       if (number != NULL)
+               return prop_number_unsigned_integer_value(number);
+       return 0;
+}
+
+/*
+ * evb_ubstep_get_input_pad_size --
+ *     Returns the input pad size to use when reading the boot loader
+ *     file.
+ */
+uint64_t
+evb_ubstep_get_input_pad_size(ib_params *params, evb_ubstep step)
+{
+       prop_number_t number = prop_dictionary_get(step,
+                                                  step_input_pad_size_key);
+       if (number != NULL)
+               return prop_number_unsigned_integer_value(number);
+       return 0;
+}
+
+/*
+ * evb_ubstep_get_output_size --
+ *     Returns the total output size that will be written to the
+ *     output device.
+ */
+uint64_t
+evb_ubstep_get_output_size(ib_params *params, evb_ubstep step)
+{



Home | Main Index | Thread Index | Old Index