Boot: add original files from MCUBoot and Zephyr project

Aligned with MCUBoot version 1.0.0
MCUBoot files:
 -- bl2/ext/mcuboot

Aligned with Zephyr version 1.10.0
Zephyr files:
 -- bl2/ext/mcuboot/include/util.h
 -- platform/ext/target/common/flash.h

Change-Id: I314c3efa2bd2c13a4a2eaefeb5da43e53e988638
Signed-off-by: Tamas Ban <tamas.ban@arm.com>
diff --git a/bl2/ext/mcuboot/bootutil/src/bootutil_misc.c b/bl2/ext/mcuboot/bootutil/src/bootutil_misc.c
new file mode 100644
index 0000000..bf4e9b8
--- /dev/null
+++ b/bl2/ext/mcuboot/bootutil/src/bootutil_misc.c
@@ -0,0 +1,559 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <inttypes.h>
+#include <stddef.h>
+
+#include "sysflash/sysflash.h"
+#include "hal/hal_bsp.h"
+#include "hal/hal_flash.h"
+#include "flash_map/flash_map.h"
+#include "os/os.h"
+#include "bootutil/image.h"
+#include "bootutil/bootutil.h"
+#include "bootutil_priv.h"
+
+#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_INFO
+#include "bootutil/bootutil_log.h"
+
+int boot_current_slot;
+
+const uint32_t boot_img_magic[] = {
+    0xf395c277,
+    0x7fefd260,
+    0x0f505235,
+    0x8079b62c,
+};
+
+const uint32_t BOOT_MAGIC_SZ = sizeof boot_img_magic;
+const uint32_t BOOT_MAX_ALIGN = MAX_FLASH_ALIGN;
+
+struct boot_swap_table {
+    /** * For each field, a value of 0 means "any". */
+    uint8_t magic_slot0;
+    uint8_t magic_slot1;
+    uint8_t image_ok_slot0;
+    uint8_t image_ok_slot1;
+    uint8_t copy_done_slot0;
+
+    uint8_t swap_type;
+};
+
+/**
+ * This set of tables maps image trailer contents to swap operation type.
+ * When searching for a match, these tables must be iterated sequentially.
+ *
+ * NOTE: the table order is very important. The settings in Slot 1 always
+ * are priority to Slot 0 and should be located earlier in the table.
+ *
+ * The table lists only states where there is action needs to be taken by
+ * the bootloader, as in starting/finishing a swap operation.
+ */
+static const struct boot_swap_table boot_swap_tables[] = {
+    {
+        .magic_slot0 =      0,
+        .magic_slot1 =      BOOT_MAGIC_GOOD,
+        .image_ok_slot0 =   0,
+        .image_ok_slot1 =   0xff,
+        .copy_done_slot0 =  0,
+        .swap_type =        BOOT_SWAP_TYPE_TEST,
+    },
+    {
+        .magic_slot0 =      0,
+        .magic_slot1 =      BOOT_MAGIC_GOOD,
+        .image_ok_slot0 =   0,
+        .image_ok_slot1 =   0x01,
+        .copy_done_slot0 =  0,
+        .swap_type =        BOOT_SWAP_TYPE_PERM,
+    },
+    {
+        .magic_slot0 =      BOOT_MAGIC_GOOD,
+        .magic_slot1 =      BOOT_MAGIC_UNSET,
+        .image_ok_slot0 =   0xff,
+        .image_ok_slot1 =   0,
+        .copy_done_slot0 =  0x01,
+        .swap_type =        BOOT_SWAP_TYPE_REVERT,
+    },
+};
+
+#define BOOT_SWAP_TABLES_COUNT \
+    (sizeof boot_swap_tables / sizeof boot_swap_tables[0])
+
+int
+boot_magic_code(const uint32_t *magic)
+{
+    int i;
+
+    if (memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0) {
+        return BOOT_MAGIC_GOOD;
+    }
+
+    for (i = 0; i < BOOT_MAGIC_SZ / sizeof *magic; i++) {
+        if (magic[i] != 0xffffffff) {
+            return BOOT_MAGIC_BAD;
+        }
+    }
+
+    return BOOT_MAGIC_UNSET;
+}
+
+uint32_t
+boot_slots_trailer_sz(uint8_t min_write_sz)
+{
+    return /* state for all sectors */
+           BOOT_STATUS_MAX_ENTRIES * BOOT_STATUS_STATE_COUNT * min_write_sz +
+           BOOT_MAX_ALIGN * 3 /* copy_done + image_ok + swap_size */        +
+           BOOT_MAGIC_SZ;
+}
+
+static uint32_t
+boot_scratch_trailer_sz(uint8_t min_write_sz)
+{
+    return BOOT_STATUS_STATE_COUNT * min_write_sz +  /* state for one sector */
+           BOOT_MAX_ALIGN * 2                     +  /* image_ok + swap_size */
+           BOOT_MAGIC_SZ;
+}
+
+static uint32_t
+boot_magic_off(const struct flash_area *fap)
+{
+    assert(offsetof(struct image_trailer, magic) == 16);
+    return fap->fa_size - BOOT_MAGIC_SZ;
+}
+
+int
+boot_status_entries(const struct flash_area *fap)
+{
+    switch (fap->fa_id) {
+    case FLASH_AREA_IMAGE_0:
+    case FLASH_AREA_IMAGE_1:
+        return BOOT_STATUS_STATE_COUNT * BOOT_STATUS_MAX_ENTRIES;
+    case FLASH_AREA_IMAGE_SCRATCH:
+        return BOOT_STATUS_STATE_COUNT;
+    default:
+        return BOOT_EBADARGS;
+    }
+}
+
+uint32_t
+boot_status_off(const struct flash_area *fap)
+{
+    uint32_t off_from_end;
+    uint8_t elem_sz;
+
+    elem_sz = flash_area_align(fap);
+
+    if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
+        off_from_end = boot_scratch_trailer_sz(elem_sz);
+    } else {
+        off_from_end = boot_slots_trailer_sz(elem_sz);
+    }
+
+    assert(off_from_end <= fap->fa_size);
+    return fap->fa_size - off_from_end;
+}
+
+static uint32_t
+boot_copy_done_off(const struct flash_area *fap)
+{
+    assert(fap->fa_id != FLASH_AREA_IMAGE_SCRATCH);
+    assert(offsetof(struct image_trailer, copy_done) == 0);
+    return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2;
+}
+
+static uint32_t
+boot_image_ok_off(const struct flash_area *fap)
+{
+    assert(offsetof(struct image_trailer, image_ok) == 8);
+    return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN;
+}
+
+static uint32_t
+boot_swap_size_off(const struct flash_area *fap)
+{
+    /*
+     * The "swap_size" field if located just before the trailer.
+     * The scratch slot doesn't store "copy_done"...
+     */
+    if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
+        return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2;
+    }
+
+    return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 3;
+}
+
+int
+boot_read_swap_state(const struct flash_area *fap,
+                     struct boot_swap_state *state)
+{
+    uint32_t magic[BOOT_MAGIC_SZ];
+    uint32_t off;
+    int rc;
+
+    off = boot_magic_off(fap);
+    rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
+    if (rc != 0) {
+        return BOOT_EFLASH;
+    }
+    state->magic = boot_magic_code(magic);
+
+    if (fap->fa_id != FLASH_AREA_IMAGE_SCRATCH) {
+        off = boot_copy_done_off(fap);
+        rc = flash_area_read(fap, off, &state->copy_done, sizeof state->copy_done);
+        if (rc != 0) {
+            return BOOT_EFLASH;
+        }
+    }
+
+    off = boot_image_ok_off(fap);
+    rc = flash_area_read(fap, off, &state->image_ok, sizeof state->image_ok);
+    if (rc != 0) {
+        return BOOT_EFLASH;
+    }
+
+    return 0;
+}
+
+/**
+ * Reads the image trailer from the scratch area.
+ */
+int
+boot_read_swap_state_by_id(int flash_area_id, struct boot_swap_state *state)
+{
+    const struct flash_area *fap;
+    int rc;
+
+    switch (flash_area_id) {
+    case FLASH_AREA_IMAGE_SCRATCH:
+    case FLASH_AREA_IMAGE_0:
+    case FLASH_AREA_IMAGE_1:
+        rc = flash_area_open(flash_area_id, &fap);
+        if (rc != 0) {
+            return BOOT_EFLASH;
+        }
+        break;
+    default:
+        return BOOT_EBADARGS;
+    }
+
+    rc = boot_read_swap_state(fap, state);
+    flash_area_close(fap);
+    return rc;
+}
+
+int
+boot_read_swap_size(uint32_t *swap_size)
+{
+    uint32_t magic[BOOT_MAGIC_SZ];
+    uint32_t off;
+    const struct flash_area *fap;
+    int rc;
+
+    /*
+     * In the middle a swap, tries to locate the saved swap size. Looks
+     * for a valid magic, first on Slot 0, then on scratch. Both "slots"
+     * can end up being temporary storage for a swap and it is assumed
+     * that if magic is valid then swap size is too, because magic is
+     * always written in the last step.
+     */
+
+    rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
+    if (rc != 0) {
+        return BOOT_EFLASH;
+    }
+
+    off = boot_magic_off(fap);
+    rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
+    if (rc != 0) {
+        rc = BOOT_EFLASH;
+        goto out;
+    }
+
+    if (memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) != 0) {
+        /*
+         * If Slot 0 's magic is not valid, try scratch...
+         */
+
+        flash_area_close(fap);
+
+        rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, &fap);
+        if (rc != 0) {
+            return BOOT_EFLASH;
+        }
+
+        off = boot_magic_off(fap);
+        rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
+        if (rc != 0) {
+            rc = BOOT_EFLASH;
+            goto out;
+        }
+
+        assert(memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0);
+    }
+
+    off = boot_swap_size_off(fap);
+    rc = flash_area_read(fap, off, swap_size, sizeof *swap_size);
+    if (rc != 0) {
+        rc = BOOT_EFLASH;
+    }
+
+out:
+    flash_area_close(fap);
+    return rc;
+}
+
+
+int
+boot_write_magic(const struct flash_area *fap)
+{
+    uint32_t off;
+    int rc;
+
+    off = boot_magic_off(fap);
+
+    rc = flash_area_write(fap, off, boot_img_magic, BOOT_MAGIC_SZ);
+    if (rc != 0) {
+        return BOOT_EFLASH;
+    }
+
+    return 0;
+}
+
+static int
+boot_write_flag(int flag, const struct flash_area *fap)
+{
+    uint32_t off;
+    int rc;
+    uint8_t buf[BOOT_MAX_ALIGN];
+    uint8_t align;
+
+    switch (flag) {
+    case BOOT_FLAG_COPY_DONE:
+        off = boot_copy_done_off(fap);
+        break;
+    case BOOT_FLAG_IMAGE_OK:
+        off = boot_image_ok_off(fap);
+        break;
+    default:
+        return BOOT_EBADARGS;
+    }
+
+    align = hal_flash_align(fap->fa_device_id);
+    assert(align <= BOOT_MAX_ALIGN);
+    memset(buf, 0xFF, BOOT_MAX_ALIGN);
+    buf[0] = BOOT_FLAG_SET;
+
+    rc = flash_area_write(fap, off, buf, align);
+    if (rc != 0) {
+        return BOOT_EFLASH;
+    }
+
+    return 0;
+}
+
+int
+boot_write_copy_done(const struct flash_area *fap)
+{
+    return boot_write_flag(BOOT_FLAG_COPY_DONE, fap);
+}
+
+int
+boot_write_image_ok(const struct flash_area *fap)
+{
+    return boot_write_flag(BOOT_FLAG_IMAGE_OK, fap);
+}
+
+int
+boot_write_swap_size(const struct flash_area *fap, uint32_t swap_size)
+{
+    uint32_t off;
+    int rc;
+    uint8_t buf[BOOT_MAX_ALIGN];
+    uint8_t align;
+
+    off = boot_swap_size_off(fap);
+    align = hal_flash_align(fap->fa_device_id);
+    assert(align <= BOOT_MAX_ALIGN);
+    if (align < sizeof swap_size) {
+        align = sizeof swap_size;
+    }
+    memset(buf, 0xFF, BOOT_MAX_ALIGN);
+    memcpy(buf, (uint8_t *)&swap_size, sizeof swap_size);
+
+    rc = flash_area_write(fap, off, buf, align);
+    if (rc != 0) {
+        return BOOT_EFLASH;
+    }
+
+    return 0;
+}
+
+int
+boot_swap_type(void)
+{
+    const struct boot_swap_table *table;
+    struct boot_swap_state slot0;
+    struct boot_swap_state slot1;
+    int rc;
+    int i;
+
+    rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_0, &slot0);
+    if (rc) {
+        return BOOT_SWAP_TYPE_PANIC;
+    }
+
+    rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_1, &slot1);
+    if (rc) {
+        return BOOT_SWAP_TYPE_PANIC;
+    }
+
+    for (i = 0; i < BOOT_SWAP_TABLES_COUNT; i++) {
+        table = boot_swap_tables + i;
+
+        if ((!table->magic_slot0     || table->magic_slot0     == slot0.magic    ) &&
+            (!table->magic_slot1     || table->magic_slot1     == slot1.magic    ) &&
+            (!table->image_ok_slot0  || table->image_ok_slot0  == slot0.image_ok ) &&
+            (!table->image_ok_slot1  || table->image_ok_slot1  == slot1.image_ok ) &&
+            (!table->copy_done_slot0 || table->copy_done_slot0 == slot0.copy_done)) {
+            BOOT_LOG_INF("Swap type: %s",
+                         table->swap_type == BOOT_SWAP_TYPE_TEST   ? "test"   :
+                         table->swap_type == BOOT_SWAP_TYPE_PERM   ? "perm"   :
+                         table->swap_type == BOOT_SWAP_TYPE_REVERT ? "revert" :
+                         "BUG; can't happen");
+            assert(table->swap_type == BOOT_SWAP_TYPE_TEST ||
+                   table->swap_type == BOOT_SWAP_TYPE_PERM ||
+                   table->swap_type == BOOT_SWAP_TYPE_REVERT);
+            return table->swap_type;
+        }
+    }
+
+    BOOT_LOG_INF("Swap type: none");
+    return BOOT_SWAP_TYPE_NONE;
+}
+
+/**
+ * Marks the image in slot 1 as pending.  On the next reboot, the system will
+ * perform a one-time boot of the slot 1 image.
+ *
+ * @param permanent         Whether the image should be used permanently or
+ *                              only tested once:
+ *                                  0=run image once, then confirm or revert.
+ *                                  1=run image forever.
+ *
+ * @return                  0 on success; nonzero on failure.
+ */
+int
+boot_set_pending(int permanent)
+{
+    const struct flash_area *fap;
+    struct boot_swap_state state_slot1;
+    int rc;
+
+    rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_1, &state_slot1);
+    if (rc != 0) {
+        return rc;
+    }
+
+    switch (state_slot1.magic) {
+    case BOOT_MAGIC_GOOD:
+        /* Swap already scheduled. */
+        return 0;
+
+    case BOOT_MAGIC_UNSET:
+        rc = flash_area_open(FLASH_AREA_IMAGE_1, &fap);
+        if (rc != 0) {
+            rc = BOOT_EFLASH;
+        } else {
+            rc = boot_write_magic(fap);
+        }
+
+        if (rc == 0 && permanent) {
+            rc = boot_write_image_ok(fap);
+        }
+
+        flash_area_close(fap);
+        return rc;
+
+    default:
+        /* XXX: Temporary assert. */
+        assert(0);
+        return -1;
+    }
+}
+
+/**
+ * Marks the image in slot 0 as confirmed.  The system will continue booting into the image in slot 0 until told to boot from a different slot.
+ *
+ * @return                  0 on success; nonzero on failure.
+ */
+int
+boot_set_confirmed(void)
+{
+    const struct flash_area *fap;
+    struct boot_swap_state state_slot0;
+    int rc;
+
+    rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_0, &state_slot0);
+    if (rc != 0) {
+        return rc;
+    }
+
+    switch (state_slot0.magic) {
+    case BOOT_MAGIC_GOOD:
+        /* Confirm needed; proceed. */
+        break;
+
+    case BOOT_MAGIC_UNSET:
+        /* Already confirmed. */
+        return 0;
+
+    case BOOT_MAGIC_BAD:
+        /* Unexpected state. */
+        return BOOT_EBADVECT;
+    }
+
+    if (state_slot0.copy_done == BOOT_FLAG_UNSET) {
+        /* Swap never completed.  This is unexpected. */
+        return BOOT_EBADVECT;
+    }
+
+    if (state_slot0.image_ok != BOOT_FLAG_UNSET) {
+        /* Already confirmed. */
+        return 0;
+    }
+
+    rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
+    if (rc) {
+        rc = BOOT_EFLASH;
+        goto done;
+    }
+
+    rc = boot_write_image_ok(fap);
+    if (rc != 0) {
+        goto done;
+    }
+
+    rc = 0;
+
+done:
+    flash_area_close(fap);
+    return rc;
+}