You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ad...@apache.org on 2016/11/15 01:12:10 UTC

[09/21] incubator-mynewt-site git commit: New Bootloader Doc

New Bootloader Doc


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/commit/9aff0aef
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/tree/9aff0aef
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/diff/9aff0aef

Branch: refs/heads/develop
Commit: 9aff0aef9a3a70221e09c57a76ef8f857773957e
Parents: 7970734
Author: David G. Simmons <sa...@mac.com>
Authored: Fri Nov 4 11:11:49 2016 -0400
Committer: David G. Simmons <sa...@mac.com>
Committed: Fri Nov 4 11:11:49 2016 -0400

----------------------------------------------------------------------
 docs/os/modules/bootloader/bootloader.md | 373 +++++++++++++++++++++++++-
 1 file changed, 368 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/9aff0aef/docs/os/modules/bootloader/bootloader.md
----------------------------------------------------------------------
diff --git a/docs/os/modules/bootloader/bootloader.md b/docs/os/modules/bootloader/bootloader.md
index 55b6d44..6841875 100644
--- a/docs/os/modules/bootloader/bootloader.md
+++ b/docs/os/modules/bootloader/bootloader.md
@@ -1,15 +1,378 @@
 #Bootloader
 
-Insert synopsis here
+The bootutil library performs most of the functions of a boot loader.  In
+particular, the piece that is missing is the final step of actually jumping to
+the main image.  This last step should instead be implemented in an
+architecture-specific project.  Boot loader functionality is separated in this
+manner for the following two reasons:
 
+1. By keeping architecture-dependent code separate, the bootutil library can be
+   reused among several boot loaders.
+2. By excluding the last boot step from the library, the rest of the code can
+   be tested in a sim environment.
 
-###Description
+There is a boot loader project specific to the olimex_stm32-e407 devboard
+called *boot*.  This project provides an example of how the bootutil library
+should be used.
 
-Describe module here, special features, how pieces fit together etc.
+###Limitations
 
-###Data structures
+The boot loader currently only supports images with the following
+characteristics:
 
-Replace this with the list of data structures used, why, any neat features
+* Built to run from flash.
+* Build to run from a fixed location (i.e., position-independent).
+
+These limitations will likely be addressed soon.
+
+
+###Image Format
+
+The following definitions describe the image header format.
+
+```c
+#define IMAGE_MAGIC                 0x96f3b83c
+
+struct image_version {
+    uint8_t iv_major;
+    uint8_t iv_minor;
+    uint16_t iv_revision;
+    uint32_t iv_build_num;
+};
+
+/** Image header.  All fields are in little endian byte order. */
+struct image_header {
+    uint32_t ih_magic;
+    uint32_t ih_crc32; /* Covers remainder of header and all of image body. */
+    uint32_t ih_hdr_size;
+    uint32_t ih_img_size; /* Does not include header. */
+    uint32_t ih_flags;
+    struct image_version ih_ver;
+};
+```
+
+At this time, no flags have been defined.
+
+The `ih_hdr_size` field indicates the length of the header, and therefore the
+offset of the image itself.  This field provides for backwards compatibility in
+case of changes to the format of the image header.
+
+When security is added, security data will likely go in a footer at the end of
+the image.
+
+
+###Flash Areas
+
+Bootutil uses the same concept of "flash areas" as the nffs file system.
+Briefly, an area is a region of disk with the following properties:
+1. An area can be fully erased without affecting any other areas.
+2. A write to one area does not restrict writes to other areas.
+
+The areas used for image data must not be used for anything else.  In
+particular, these areas must be kept separate from the nffs file system.
+
+
+###Image Slots
+
+A portion of the flash memory is partitioned into two image slots: a primary
+slot and a secondary slot.  The boot loader will only run an image from the
+primary slot, so images must be built such that they can run from that fixed
+location in flash.  If the boot loader needs to run the image resident in the
+secondary slot, it must swap the two images in flash prior to booting.
+
+In addition to the two image slots, the boot loader requires a scratch area to
+allow for reliable image swapping.
+
+All areas used by image data (including the scratch area) must be the same
+size.
+
+
+###Boot Vector
+
+Bootutil determines which image it should boot into by reading the contents of
+the boot vector.  The boot vector comprises the following files in the flash
+file system:
+
+```c
+#define BOOT_PATH_MAIN      "/boot/main"
+#define BOOT_PATH_TEST      "/boot/test"
+```
+
+Each file, if present, must contain a 64-bit image version.  This version is
+simply a "binary dump" of an `image_version` struct.  The test file is used to
+indicate that an image is being "tested out," and should only be booted once.
+The main file indicates the "last known good" image which should be booted
+repeatedly.
+
+The boot loader uses the following procedure to determine which image to boot:
+
+1. If the test file is present and contains a valid image version:
+    * Delete the test file.
+    * Boot into the specified image.
+2. Else if the main file is present and contains a valid image version:
+    * Boot into the specified image.
+3. Else:
+    * Just boot into whichever image is in the primary slot.  If there is no
+image in the primary slot, boot into the image in the secondary slot.
+
+If a vector file contains a version which doesn't correspond to an image
+actually present in flash, the boot loader deletes the file and procedes as
+though the file was not present.
+
+
+###Boot Status
+
+The boot status file allows the boot loader to recover in case it was reset
+while in the middle of an image swap operation.  Image swapping is discussed
+later in this document; the structure of the boot status file is presented
+here.  To ensure recovery is always possible, bootutil updates the status file
+at each step throughout the image swap process.  The boot status is contained
+in the following file:
+
+```c
+#define BOOT_PATH_STATUS    "/boot/status"
+```
+
+The contents of the boot status file are defined below.
+
+```c
+struct boot_status {
+    uint32_t bs_img1_length;
+    uint32_t bs_img2_length;
+    /* Followed by sequence of boot status entries; file size indicates number
+     * of entries.
+     */
+};
+
+struct boot_status_entry {
+    uint8_t bse_image_num;
+    uint8_t bse_part_num;
+};
+
+#define BOOT_IMAGE_NUM_NONE     0xff
+```
+
+There is a separate boot status entry for each flash area used by the boot
+loader (i.e., each area in the two slots, plus one for the scratch area).  The
+entries are placed in the file in the same order as their corresponding areas
+in flash.  Each entry indicates which image part is resident in the
+corresponding flash area.  If a flash area does not contain any image data, its
+corresponding entry will have a `bse_image_num` value of `BOOT_IMAGE_NUM_NONE`.
+
+Consider the following example:
+
+Five flash areas are dedicated to image data, as follows:
+
+| Area | Slot | Value |
+|------|------|-------|
+| Area 0 | slot 0 | 0/1 |
+| Area 1 | slot 0 | 1/1 |
+| Area 2 | slot 1 | 0/1 |
+| Area 3 | slot 1 | 1/1 |
+| Area 4 | scratch ||
+
+The following array of boot status entries is read from the status file:
+
+```c
+    [0] = {
+        .bse_image_num = 0,
+        .bse_part_num = 0,
+    },
+    [1] = { 
+        .bse_image_num = 0,
+        .bse_part_num = 1,
+    },
+    [2] = { 
+        .bse_image_num = 1,
+        .bse_part_num = 0,
+    },
+    [3] = { 
+        .bse_image_num = 1,
+        .bse_part_num = 1,
+    },
+    [4] = { 
+        .bse_image_num = 0xff,
+        .bse_part_num = 0xff,
+    },
+```
+    
+This status file indicates the following image placement:
+
+| Area | Image | Part |
+|------|------|-------|
+| Area 0 | image 0 | part 0 |
+| Area 1 | image 0 |  part 1 |
+| Area 2 | image 1 | part 0 |
+| Area 3 | image 1 | part 1 |
+| Scratch area | empty ||
+
+Images don't have an instrinsic image number.  When a swap operation is
+started, the image initially in the primary slot is labelled `image 0`, and the
+image in the secondary slot is labelled `image 1`.  All swap operations end with
+`image 1` in the primary slot, and `image 0` in the secondary slot.
+
+The boot status header containing the image sizes is necessary so that `bootutil`
+can determine how many flash areas each image occupies.  Without this
+information, `bootutil` would need to swap the full contents of the image slots,
+including useless data after the end of each image.
+
+The status file is always deleted upon successful boot.
+
+
+###Image Swapping
+
+If the boot vector indicates that the image in the secondary slot should be
+run, the boot loader needs to copy it to the primary slot.  The image currently
+in the primary slot also needs to be retained in flash so that it can be used
+later.  Furthermore, both images need to be recoverable if the boot loader
+resets in the middle of the process.  The two images are swapped according to
+the following procedure:
+
+1. Determine how many flash areas are required to hold the desired image.
+2. For each required area in the primary slot ("destination area"):
+    a. Identify the flash area in the secondary slot which contains the
+           required image data ("source area").
+    b. Erase scratch area.
+    c. Copy destination area to scratch area.
+    d. Write updated boot status to the file system.
+    e. Erase destination area.
+    f. Copy source area to destination area.
+    g. Write updated boot status to the file system.
+    h. Erase source area.
+    i. Copy scratch area to source area.
+    j. Write updated boot status to the file system.
+3. Determine how many flash areas are required to hold image 1.
+4. For each required area in the secondary slot ("destination area"):
+    a. If the destination area already contains the required image data,
+           advance to the next image part.
+    b. Else, identify the flash area in the primary slot which contains the
+           required image data ("source area").
+    c. Repeat steps b through j from step 2.
+
+This procedure ensures that the contents of the boot status file are always
+accurate, so the boot loader can recover after an unexpected reset.
+
+Step 4 is necessary in case the two images do not occupy the same number of
+flash areas.
+
+
+###Reset Recovery
+
+If the boot loader resets in the middle of a swap operation, the two images may
+be discontiguous in flash.  Bootutil recovers from this condition by using the
+boot status file to determine how the image parts are placed in flash.
+
+If the boot status file indicates that the images are not contiguous, bootutil
+completes the swap operation that was in progress when the system was reset.
+In other words, it applies the procedure defined in the previous section,
+moving image 1 into slot 0 and image 0 into slot 1.  If the boot status file
+indicates that an image part is present in the scratch area, this part is
+copied into the correct location by starting at step e or step h in the
+area-swap procedure, depending on whether the part belongs to image 0 or image
+1.
+
+After the swap operation has been completed, the boot loader proceeds as though
+it had just been started.
+
+
+###API
+
+The API consists of a single function:
+
+```c
+int boot_go(const struct boot_req *req, struct boot_rsp *rsp)
+```
+        
+The request and response structures are defined as follows:
+
+```c
+struct boot_req {
+    
+    struct nffs_area_desc *br_area_descs;
+
+    uint8_t *br_image_areas;
+
+    uint8_t *br_slot_areas;
+
+    uint8_t br_num_image_areas;
+
+
+    uint8_t br_scratch_area_idx;
+};
+```
+
+```c
+struct boot_rsp {
+    const struct image_header *br_hdr;
+
+    uint32_t br_image_addr;
+};
+```
+
+###Example
+
+In this example, each image slot consists of three flash areas.
+
+```c
+/** Internal flash layout. */
+static struct nffs_area_desc boot_area_descs[] = {
+    [0] =  { 0x08000000, 16 * 1024 },
+    [1] =  { 0x08004000, 16 * 1024 },
+    [2] =  { 0x08008000, 16 * 1024 },
+    [3] =  { 0x0800c000, 16 * 1024 },
+    [4] =  { 0x08010000, 64 * 1024 },
+    [5] =  { 0x08020000, 128 * 1024 }, /* Image data; 0,0. */
+    [6] =  { 0x08040000, 128 * 1024 }, /* Image data; 0,1. */
+    [7] =  { 0x08060000, 128 * 1024 }, /* Image data; 0,2. */
+    [8] =  { 0x08080000, 128 * 1024 }, /* Image data; 1,0. */
+    [9] =  { 0x080a0000, 128 * 1024 }, /* Image data; 1,1. */
+    [10] = { 0x080c0000, 128 * 1024 }, /* Image data; 1,2. */
+    [11] = { 0x080e0000, 128 * 1024 }, /* Image scratch area. */
+    { 0, 0 },
+};
+
+/** Contains indices of the areas which can contain image data. */
+static uint8_t boot_img_areas[] = {
+    5, 6, 7, 8, 9, 10, 11,
+};
+
+/** Areas representing the beginning of image slots. */
+static uint8_t boot_slot_areas[] = {
+    5, 8,
+};
+
+#define BOOT_NUM_IMG_AREAS \
+    ((int)(sizeof boot_img_areas / sizeof boot_img_areas[0]))
+
+/** The scratch area to use during an image swap operation. */
+#define BOOT_AREA_IDX_SCRATCH 11
+
+int
+main(void)
+{
+    struct boot_rsp rsp;
+    int rc;
+
+    const struct boot_req req = {
+        .br_area_descs = boot_area_descs,
+        .br_image_areas = boot_img_areas,
+        .br_slot_areas = boot_slot_areas,
+        .br_num_image_areas = BOOT_NUM_IMG_AREAS,
+        .br_scratch_area_idx = BOOT_AREA_IDX_SCRATCH,
+    };
+
+    rc = boot_go(&req, &rsp);
+    assert(rc == 0);
+
+    /* Perform jump to address indicated by the response object. */
+
+    return 0;
+}
+```
+
+###Dependencies
+* `nffs` (for the boot vector and boot status files).
+* `os` (for `os_malloc()` and `os_free()`).
 
 ###List of Functions