You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2016/08/24 00:53:43 UTC
[29/50] [abbrv] incubator-mynewt-core git commit: boot;
don't use NFFS or FCB for keeping status. Interim commit.
boot; don't use NFFS or FCB for keeping status. Interim commit.
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/b2009c9f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/b2009c9f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/b2009c9f
Branch: refs/heads/master
Commit: b2009c9fbce7d7ac8f6f039cda6866e81868b622
Parents: 5de9a72
Author: Marko Kiiskila <ma...@runtime.io>
Authored: Tue Aug 16 18:07:30 2016 -0700
Committer: Marko Kiiskila <ma...@runtime.io>
Committed: Fri Aug 19 15:11:49 2016 -0700
----------------------------------------------------------------------
apps/boot/pkg.yml | 3 +-
apps/boot/src/boot.c | 91 +----
apps/slinky/src/main.c | 1 -
libs/bootutil/include/bootutil/bootutil_misc.h | 4 +-
libs/bootutil/include/bootutil/loader.h | 3 +
libs/bootutil/src/bootutil_misc.c | 264 ++-----------
libs/bootutil/src/bootutil_priv.h | 44 +--
libs/bootutil/src/loader.c | 399 +++++++++++---------
libs/imgmgr/src/imgmgr_boot.c | 6 +-
9 files changed, 291 insertions(+), 524 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/b2009c9f/apps/boot/pkg.yml
----------------------------------------------------------------------
diff --git a/apps/boot/pkg.yml b/apps/boot/pkg.yml
index 10ec482..b877557 100644
--- a/apps/boot/pkg.yml
+++ b/apps/boot/pkg.yml
@@ -29,12 +29,11 @@ pkg.features: bootloader
pkg.deps:
- sys/config
- - fs/nffs
- libs/bootutil
- libs/mbedtls
- libs/os
- libs/util
- - libs/console/stub
+ - libs/console/full
pkg.cflags: -DLOG_LEVEL=255
pkg.cflags.NFFS:
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/b2009c9f/apps/boot/src/boot.c
----------------------------------------------------------------------
diff --git a/apps/boot/src/boot.c b/apps/boot/src/boot.c
index 97a9b32..37172ba 100755
--- a/apps/boot/src/boot.c
+++ b/apps/boot/src/boot.c
@@ -27,19 +27,11 @@
#include <hal/hal_flash.h>
#include <config/config.h>
#include <config/config_file.h>
-#ifdef NFFS_PRESENT
-#include <fs/fs.h>
-#include <nffs/nffs.h>
-#elif FCB_PRESENT
-#include <fcb/fcb.h>
-#include <config/config_fcb.h>
-#else
-#error "Need NFFS or FCB for config storage"
-#endif
#ifdef BOOT_SERIAL
#include <hal/hal_gpio.h>
#include <boot_serial/boot_serial.h>
#endif
+#include <console/console.h>
#include "bootutil/image.h"
#include "bootutil/loader.h"
#include "bootutil/bootutil_misc.h"
@@ -58,76 +50,11 @@ static struct os_task boot_ser_task;
static os_stack_t boot_ser_stack[BOOT_SER_STACK_SZ];
#endif
-#ifdef NFFS_PRESENT
-#define MY_CONFIG_FILE "/cfg/run"
-
-static struct conf_file my_conf = {
- .cf_name = MY_CONFIG_FILE
-};
-
-static void
-setup_for_nffs(void)
-{
- struct nffs_area_desc nffs_descs[NFFS_AREA_MAX + 1];
- int cnt;
- int rc;
-
- /*
- * Make sure we have enough left to initialize the NFFS with the
- * right number of maximum areas otherwise the file-system will not
- * be readable.
- */
- cnt = NFFS_AREA_MAX;
- rc = flash_area_to_nffs_desc(FLASH_AREA_NFFS, &cnt, nffs_descs);
- assert(rc == 0);
-
- /*
- * Initializes the flash driver and file system for use by the boot loader.
- */
- rc = nffs_init();
- if (rc == 0) {
- /* Look for an nffs file system in internal flash. If no file
- * system gets detected, all subsequent file operations will fail,
- * but the boot loader should proceed anyway.
- */
- nffs_detect(nffs_descs);
- }
-
- rc = conf_file_src(&my_conf);
- assert(rc == 0);
- rc = conf_file_dst(&my_conf);
- assert(rc == 0);
-}
-#else
-struct flash_area conf_fcb_area[NFFS_AREA_MAX + 1];
-
-static struct conf_fcb my_conf = {
- .cf_fcb.f_magic = 0xc09f6e5e,
- .cf_fcb.f_sectors = conf_fcb_area
-};
-
-static void
-setup_for_fcb(void)
-{
- int cnt;
- int rc;
-
- rc = flash_area_to_sectors(FLASH_AREA_NFFS, &cnt, NULL);
- assert(rc == 0);
- assert(cnt <= sizeof(conf_fcb_area) / sizeof(conf_fcb_area[0]));
- flash_area_to_sectors(FLASH_AREA_NFFS, &cnt, conf_fcb_area);
-
- my_conf.cf_fcb.f_sector_cnt = cnt;
-
- conf_fcb_src(&my_conf);
- conf_fcb_dst(&my_conf);
-}
-#endif
-
int
main(void)
{
struct flash_area descs[AREA_DESC_MAX];
+ const struct flash_area *fap;
/** Areas representing the beginning of image slots. */
uint8_t img_starts[2];
int cnt;
@@ -149,6 +76,9 @@ main(void)
img_starts[0] = 0;
total = cnt;
+ flash_area_open(FLASH_AREA_IMAGE_0, &fap);
+ req.br_img_sz = fap->fa_size;
+
cnt = BOOT_AREA_DESC_MAX - total;
assert(cnt >= 0);
rc = flash_area_to_sectors(FLASH_AREA_IMAGE_1, &cnt, &descs[total]);
@@ -167,13 +97,8 @@ main(void)
conf_init();
-#ifdef NFFS_PRESENT
- setup_for_nffs();
-#elif FCB_PRESENT
- setup_for_fcb();
-#endif
- bootutil_cfg_register();
-
+ console_init(NULL);
+ console_printf("\nboot_loader\n");
#ifdef BOOT_SERIAL
/*
* Configure a GPIO as input, and compare it against expected value.
@@ -189,6 +114,8 @@ main(void)
#endif
rc = boot_go(&req, &rsp);
assert(rc == 0);
+ console_blocking_mode();
+ console_printf("\nboot_go = %d\n", rc);
system_start((void *)(rsp.br_image_addr + rsp.br_hdr->ih_hdr_size));
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/b2009c9f/apps/slinky/src/main.c
----------------------------------------------------------------------
diff --git a/apps/slinky/src/main.c b/apps/slinky/src/main.c
index 7f724e6..fd68aa4 100755
--- a/apps/slinky/src/main.c
+++ b/apps/slinky/src/main.c
@@ -397,7 +397,6 @@ main(int argc, char **argv)
nmgr_task_init(NEWTMGR_TASK_PRIO, newtmgr_stack, NEWTMGR_TASK_STACK_SIZE);
imgmgr_module_init();
- bootutil_cfg_register();
stats_module_init();
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/b2009c9f/libs/bootutil/include/bootutil/bootutil_misc.h
----------------------------------------------------------------------
diff --git a/libs/bootutil/include/bootutil/bootutil_misc.h b/libs/bootutil/include/bootutil/bootutil_misc.h
index ff42ac8..e8834db 100644
--- a/libs/bootutil/include/bootutil/bootutil_misc.h
+++ b/libs/bootutil/include/bootutil/bootutil_misc.h
@@ -23,9 +23,7 @@
struct image_version;
int boot_vect_read_test(struct image_version *out_ver);
int boot_vect_read_main(struct image_version *out_ver);
-int boot_vect_write_test(struct image_version *ver);
+int boot_vect_write_test(int slot);
int boot_vect_write_main(struct image_version *ver);
-void bootutil_cfg_register(void);
-
#endif /* __BOOTUTIL_MISC_H_ */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/b2009c9f/libs/bootutil/include/bootutil/loader.h
----------------------------------------------------------------------
diff --git a/libs/bootutil/include/bootutil/loader.h b/libs/bootutil/include/bootutil/loader.h
index 86f06ba..57a9eef 100644
--- a/libs/bootutil/include/bootutil/loader.h
+++ b/libs/bootutil/include/bootutil/loader.h
@@ -46,6 +46,9 @@ struct boot_req {
/** The area to use as the image scratch area, index is
index to br_area_descs array, of the */
uint8_t br_scratch_area_idx;
+
+ /** Size of the image slot */
+ uint32_t br_img_sz;
};
/**
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/b2009c9f/libs/bootutil/src/bootutil_misc.c
----------------------------------------------------------------------
diff --git a/libs/bootutil/src/bootutil_misc.c b/libs/bootutil/src/bootutil_misc.c
index 94536ef..8ae5599 100644
--- a/libs/bootutil/src/bootutil_misc.c
+++ b/libs/bootutil/src/bootutil_misc.c
@@ -20,89 +20,11 @@
#include <string.h>
#include <inttypes.h>
#include <hal/hal_flash.h>
-#include <config/config.h>
+#include <hal/flash_map.h>
#include <os/os.h>
#include "bootutil/image.h"
#include "bootutil_priv.h"
-#ifdef USE_STATUS_FILE
-#include <fs/fs.h>
-#include <fs/fsutil.h>
-#endif
-
-static int boot_conf_set(int argc, char **argv, char *val);
-
-static struct image_version boot_main;
-static struct image_version boot_test;
-#ifndef USE_STATUS_FILE
-static struct boot_status boot_saved;
-#endif
-
-static struct conf_handler boot_conf_handler = {
- .ch_name = "boot",
- .ch_get = NULL,
- .ch_set = boot_conf_set,
- .ch_commit = NULL,
- .ch_export = NULL,
-};
-
-static int
-boot_conf_set(int argc, char **argv, char *val)
-{
- int rc;
- int len;
-
- if (argc == 1) {
- if (!strcmp(argv[0], "main")) {
- len = sizeof(boot_main);
- if (val) {
- rc = conf_bytes_from_str(val, &boot_main, &len);
- } else {
- memset(&boot_main, 0, len);
- rc = 0;
- }
- } else if (!strcmp(argv[0], "test")) {
- len = sizeof(boot_test);
- if (val) {
- rc = conf_bytes_from_str(val, &boot_test, &len);
- } else {
- memset(&boot_test, 0, len);
- rc = 0;
- }
-#ifndef USE_STATUS_FILE
- } else if (!strcmp(argv[0], "status")) {
- if (!val) {
- boot_saved.state = 0;
- rc = 0;
- } else {
- rc = conf_value_from_str(val, CONF_INT32,
- &boot_saved.state, sizeof(boot_saved.state));
- }
- } else if (!strcmp(argv[0], "len")) {
- conf_value_from_str(val, CONF_INT32, &boot_saved.length,
- sizeof(boot_saved.length));
- rc = 0;
-#endif
- } else {
- rc = OS_ENOENT;
- }
- } else {
- rc = OS_ENOENT;
- }
- return rc;
-}
-
-static int
-boot_vect_read_one(struct image_version *dst, struct image_version *src)
-{
- if (src->iv_major == 0 && src->iv_minor == 0 &&
- src->iv_revision == 0 && src->iv_build_num == 0) {
- return BOOT_EBADVECT;
- }
- memcpy(dst, src, sizeof(*dst));
- return 0;
-}
-
/**
* Retrieves from the boot vector the version number of the test image (i.e.,
* the image that has not been proven stable, and which will only run once).
@@ -114,7 +36,7 @@ boot_vect_read_one(struct image_version *dst, struct image_version *src)
int
boot_vect_read_test(struct image_version *out_ver)
{
- return boot_vect_read_one(out_ver, &boot_test);
+ return 0;
}
/**
@@ -127,24 +49,7 @@ boot_vect_read_test(struct image_version *out_ver)
int
boot_vect_read_main(struct image_version *out_ver)
{
- return boot_vect_read_one(out_ver, &boot_main);
-}
-
-static int
-boot_vect_write_one(const char *name, struct image_version *ver)
-{
- char str[CONF_STR_FROM_BYTES_LEN(sizeof(struct image_version))];
- char *to_store;
-
- if (!ver) {
- to_store = NULL;
- } else {
- if (!conf_str_from_bytes(ver, sizeof(*ver), str, sizeof(str))) {
- return -1;
- }
- to_store = str;
- }
- return conf_save_one(name, to_store);
+ return 0;
}
/**
@@ -153,15 +58,22 @@ boot_vect_write_one(const char *name, struct image_version *ver)
* @return 0 on success; nonzero on failure.
*/
int
-boot_vect_write_test(struct image_version *ver)
+boot_vect_write_test(int slot)
{
- if (!ver) {
- memset(&boot_test, 0, sizeof(boot_test));
- return boot_vect_write_one("boot/test", NULL);
- } else {
- memcpy(&boot_test, ver, sizeof(boot_test));
- return boot_vect_write_one("boot/test", &boot_test);
+ const struct flash_area *fap;
+ uint32_t off;
+ uint32_t magic;
+ int rc;
+
+ rc = flash_area_open(slot, &fap);
+ if (rc) {
+ return rc;
}
+
+ off = fap->fa_size - sizeof(struct boot_img_trailer);
+ magic = BOOT_IMG_MAGIC;
+
+ return flash_area_write(fap, off, &magic, sizeof(magic));
}
/**
@@ -172,37 +84,12 @@ boot_vect_write_test(struct image_version *ver)
int
boot_vect_write_main(struct image_version *ver)
{
- if (!ver) {
- memset(&boot_main, 0, sizeof(boot_main));
- return boot_vect_write_one("boot/main", NULL);
- } else {
- memcpy(&boot_main, ver, sizeof(boot_main));
- return boot_vect_write_one("boot/main", &boot_main);
- }
-}
-
-static int
-boot_read_image_header(struct image_header *out_hdr,
- const struct boot_image_location *loc)
-{
- int rc;
-
- rc = hal_flash_read(loc->bil_flash_id, loc->bil_address, out_hdr,
- sizeof *out_hdr);
- if (rc != 0) {
- return BOOT_EFLASH;
- }
-
- if (out_hdr->ih_magic != IMAGE_MAGIC) {
- return BOOT_EBADIMAGE;
- }
-
return 0;
}
/**
- * Reads the header of each image present in flash. Headers corresponding to
- * empty image slots are filled with 0xff bytes.
+ * Reads the header of image present in flash. Header corresponding to
+ * empty image slot is filled with 0xff bytes.
*
* @param out_headers Points to an array of image headers. Each
* element is filled with the header of the
@@ -213,118 +100,23 @@ boot_read_image_header(struct image_header *out_hdr,
* also be equal to the lengths of the
* out_headers and addresses arrays.
*/
-void
-boot_read_image_headers(struct image_header *out_headers,
- const struct boot_image_location *addresses,
- int num_addresses)
-{
- struct image_header *hdr;
- int rc;
- int i;
-
- for (i = 0; i < num_addresses; i++) {
- hdr = out_headers + i;
- rc = boot_read_image_header(hdr, &addresses[i]);
- if (rc != 0 || hdr->ih_magic != IMAGE_MAGIC) {
- memset(hdr, 0xff, sizeof *hdr);
- }
- }
-}
-
-void
-bootutil_cfg_register(void)
-{
- conf_register(&boot_conf_handler);
-}
-
-#ifndef USE_STATUS_FILE
-int
-boot_read_status(struct boot_status *bs)
-{
- conf_load();
-
- *bs = boot_saved;
- return (boot_saved.state != 0);
-}
-
-/**
- * Writes the supplied boot status to the flash file system. The boot status
- * contains the current state of an in-progress image copy operation.
- *
- * @param status The boot status base to write.
- *
- * @return 0 on success; nonzero on failure.
- */
-int
-boot_write_status(struct boot_status *bs)
-{
- char str[12];
- int rc;
-
- rc = conf_save_one("boot/len",
- conf_str_from_value(CONF_INT32, &bs->length, str, sizeof(str)));
- if (rc) {
- return rc;
- }
- return conf_save_one("boot/status",
- conf_str_from_value(CONF_INT32, &bs->state, str, sizeof(str)));
-}
-
-/**
- * Erases the boot status from the flash file system. The boot status
- * contains the current state of an in-progress image copy operation. By
- * erasing the boot status, it is implied that there is no copy operation in
- * progress.
- */
-void
-boot_clear_status(void)
-{
- conf_save_one("boot/status", NULL);
-}
-
-#else
-
-/**
- * Reads the boot status from the flash file system. The boot status contains
- * the current state of an interrupted image copy operation. If the boot
- * status is not present in the file system, the implication is that there is
- * no copy operation in progress.
- */
int
-boot_read_status(struct boot_status *bs)
+boot_read_image_header(struct boot_image_location *loc,
+ struct image_header *out_hdr)
{
int rc;
- uint32_t bytes_read;
- conf_load();
-
- rc = fsutil_read_file(BOOT_PATH_STATUS, 0, sizeof(*bs),
- bs, &bytes_read);
- if (rc || bytes_read != sizeof(*bs)) {
- memset(bs, 0, sizeof(*bs));
- return 0;
+ rc = hal_flash_read(loc->bil_flash_id, loc->bil_address, out_hdr,
+ sizeof *out_hdr);
+ if (rc != 0) {
+ rc = BOOT_EFLASH;
+ } else if (out_hdr->ih_magic != IMAGE_MAGIC) {
+ rc = BOOT_EBADIMAGE;
}
- return 1;
-}
-int
-boot_write_status(struct boot_status *bs)
-{
- int rc;
-
- /*
- * XXX point of failure.
- */
- rc = fsutil_write_file(BOOT_PATH_STATUS, bs, sizeof(*bs));
if (rc) {
- rc = BOOT_EFILE;
+ memset(out_hdr, 0xff, sizeof(*out_hdr));
}
return rc;
}
-void
-boot_clear_status(void)
-{
- fs_unlink(BOOT_PATH_STATUS);
-}
-#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/b2009c9f/libs/bootutil/src/bootutil_priv.h
----------------------------------------------------------------------
diff --git a/libs/bootutil/src/bootutil_priv.h b/libs/bootutil/src/bootutil_priv.h
index 98aa29f..3de5dd9 100644
--- a/libs/bootutil/src/bootutil_priv.h
+++ b/libs/bootutil/src/bootutil_priv.h
@@ -6,7 +6,7 @@
* 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,
@@ -21,7 +21,6 @@
#define H_BOOTUTIL_PRIV_
#include "bootutil/image.h"
-struct image_header;
#define BOOT_EFLASH 1
#define BOOT_EFILE 2
@@ -30,37 +29,38 @@ struct image_header;
#define BOOT_EBADSTATUS 5
#define BOOT_ENOMEM 6
-#define BOOT_IMAGE_NUM_NONE 0xff
-
-#define BOOT_PATH_STATUS "/cfg/bst"
-
#define BOOT_TMPBUF_SZ 256
+struct boot_image_location {
+ uint8_t bil_flash_id;
+ uint32_t bil_address;
+};
+
+/*
+ * Maintain state of copy progress.
+ */
struct boot_status {
- uint32_t length;
+ uint32_t idx;
uint32_t state;
};
-/**
- * The boot status header read from the file system, or generated if not
- * present on disk. The boot status indicates the state of the image slots in
- * case the system was restarted while images were being moved in flash.
+/*
+ * End-of-image data structure.
*/
-
-struct boot_image_location {
- uint8_t bil_flash_id;
- uint32_t bil_address;
+#define BOOT_IMG_MAGIC 0x12344321
+struct boot_img_trailer {
+ uint32_t bit_start;
+ uint32_t bit_done;
};
-void boot_read_image_headers(struct image_header *out_headers,
- const struct boot_image_location *addresses,
- int num_addresses);
-int boot_read_status(struct boot_status *);
-int boot_write_status(struct boot_status *);
-void boot_clear_status(void);
-
int bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, int slen,
uint8_t key_id);
+int boot_read_image_header(struct boot_image_location *loc,
+ struct image_header *out_hdr);
+int boot_write_status(struct boot_status *bs);
+int boot_read_status(struct boot_status *bs);
+void boot_clear_status(void);
+
#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/b2009c9f/libs/bootutil/src/loader.c
----------------------------------------------------------------------
diff --git a/libs/bootutil/src/loader.c b/libs/bootutil/src/loader.c
index bd7fbd8..f8a0003 100644
--- a/libs/bootutil/src/loader.c
+++ b/libs/bootutil/src/loader.c
@@ -24,6 +24,7 @@
#include <hal/flash_map.h>
#include <hal/hal_flash.h>
#include <os/os_malloc.h>
+#include <console/console.h>
#include "bootutil/loader.h"
#include "bootutil/image.h"
#include "bootutil/bootutil_misc.h"
@@ -36,13 +37,16 @@
static const struct boot_req *boot_req;
/** Image headers read from flash. */
-struct image_header boot_img_hdrs[2];
+static struct boot_img {
+ struct image_header hdr;
+ struct boot_image_location loc;
+ uint32_t area;
+} boot_img[BOOT_NUM_SLOTS];
static struct boot_status boot_state;
-#define BOOT_PERSIST(idx, st) (((idx) << 8) | (0xff & (st)))
-#define BOOT_PERSIST_IDX(st) (((st) >> 8) & 0xffffff)
-#define BOOT_PERSIST_ST(st) ((st) & 0xff)
+static int boot_erase_area(int area_idx, uint32_t sz);
+static uint32_t boot_copy_sz(int max_idx, int *cnt);
/**
* Calculates the flash offset of the specified image slot.
@@ -52,77 +56,73 @@ static struct boot_status boot_state;
* @return The flash offset of the image slot.
*/
static void
-boot_slot_addr(int slot_num, uint8_t *flash_id, uint32_t *address)
+boot_slot_addr(int slot_num, struct boot_image_location *loc)
{
const struct flash_area *area_desc;
uint8_t area_idx;
- assert(slot_num >= 0 && slot_num < BOOT_NUM_SLOTS);
-
area_idx = boot_req->br_slot_areas[slot_num];
area_desc = boot_req->br_area_descs + area_idx;
- *flash_id = area_desc->fa_flash_id;
- *address = area_desc->fa_off;
+ loc->bil_flash_id = area_desc->fa_flash_id;
+ loc->bil_address = area_desc->fa_off;
}
-/**
- * Searches flash for an image with the specified version number.
- *
- * @param ver The version number to search for.
- *
- * @return The image slot containing the specified image
- * on success; -1 on failure.
- */
-static int
-boot_find_image_slot(const struct image_version *ver)
+static uint32_t
+boot_magic_off(int slot_num)
{
- int i;
+ return boot_img[slot_num].area + boot_img[slot_num].loc.bil_address -
+ sizeof(struct boot_img_trailer);
+}
- for (i = 0; i < 2; i++) {
- if (memcmp(&boot_img_hdrs[i].ih_ver, ver, sizeof *ver) == 0) {
- return i;
- }
- }
+static uint32_t
+boot_scratch_off(void)
+{
+ struct flash_area *scratch;
+ uint32_t off;
+ int cnt;
- return -1;
+ scratch = &boot_req->br_area_descs[boot_req->br_scratch_area_idx];
+ off = boot_copy_sz(boot_req->br_slot_areas[1], &cnt);
+ off += (scratch->fa_off - sizeof(struct boot_img_trailer));
+ return off;
}
-/**
- * Selects a slot number to boot from, based on the contents of the boot
- * vector.
- *
- * @return The slot number to boot from on success;
- * -1 if an appropriate slot could not be
- * determined.
- */
-static int
-boot_select_image_slot(void)
+static void
+boot_slot_magic(int slot_num, struct boot_img_trailer *bit)
{
- struct image_version ver;
- int slot;
- int rc;
+ uint32_t off;
+ struct boot_img *b;
- rc = boot_vect_read_test(&ver);
- if (rc == 0) {
- slot = boot_find_image_slot(&ver);
- if (slot == -1) {
- boot_vect_write_test(NULL);
- } else {
- return slot;
- }
- }
+ b = &boot_img[slot_num];
+ off = boot_magic_off(slot_num);
+ memset(bit, 0xff, sizeof(*bit));
+ hal_flash_read(b->loc.bil_flash_id, off, bit, sizeof(*bit));
+}
- rc = boot_vect_read_main(&ver);
- if (rc == 0) {
- slot = boot_find_image_slot(&ver);
- if (slot == -1) {
- boot_vect_write_main(NULL);
- } else {
- return slot;
- }
- }
+static void
+boot_scratch_magic(struct boot_img_trailer *bit)
+{
+ uint32_t off;
+ struct flash_area *scratch;
+
+ scratch = &boot_req->br_area_descs[boot_req->br_scratch_area_idx];
+
+ off = boot_scratch_off();
+ hal_flash_read(scratch->fa_flash_id, off, bit, sizeof(*bit));
+}
- return -1;
+void
+boot_image_info(void)
+{
+ int i;
+ struct boot_img *b;
+
+ for (i = 0; i < BOOT_NUM_SLOTS; i++) {
+ b = &boot_img[i];
+ boot_slot_addr(i, &b->loc);
+ boot_read_image_header(&b->loc, &b->hdr);
+ b->area = boot_req->br_img_sz;
+ }
}
/*
@@ -146,12 +146,54 @@ boot_image_check(struct image_header *hdr, struct boot_image_location *loc)
return 0;
}
+/**
+ * Selects a slot number to boot from.
+ *
+ * @return The slot number to boot from on success;
+ * -1 if an appropriate slot could not be
+ * determined.
+ */
+static int
+boot_select_image_slot(void)
+{
+ /*
+ * Check for swap magic. Check the integrity of the suggested image.
+ */
+ int rc;
+ int i;
+ struct boot_img *b;
+ struct boot_img_trailer bit;
+
+ for (i = 1; i < BOOT_NUM_SLOTS; i++) {
+ b = &boot_img[i];
+ boot_slot_magic(i, &bit);
+ if (bit.bit_start == BOOT_IMG_MAGIC) {
+ rc = boot_image_check(&b->hdr, &b->loc);
+ if (rc) {
+ /*
+ * Image fails integrity check. Erase it.
+ */
+ boot_erase_area(boot_req->br_slot_areas[i], b->area);
+ } else {
+ return i;
+ }
+ }
+ }
+ return 0;
+}
+
+static int
+boot_status_sz(void)
+{
+ return sizeof(struct boot_img_trailer) + 32 * sizeof(uint32_t);
+}
+
/*
* How many sectors starting from sector[idx] can fit inside scratch.
*
*/
static uint32_t
-boot_copy_sz(int idx, int max_idx, int *cnt)
+boot_copy_sz(int max_idx, int *cnt)
{
int i;
uint32_t sz;
@@ -166,7 +208,7 @@ boot_copy_sz(int idx, int max_idx, int *cnt)
}
sz = 0;
*cnt = 0;
- for (i = idx; i < max_idx; i++) {
+ for (i = max_idx - 1; i >= 0; i--) {
if (sz + boot_req->br_area_descs[i].fa_size > scratch_sz) {
break;
}
@@ -176,7 +218,6 @@ boot_copy_sz(int idx, int max_idx, int *cnt)
return sz;
}
-
static int
boot_erase_area(int area_idx, uint32_t sz)
{
@@ -258,12 +299,11 @@ boot_copy_area(int from_area_idx, int to_area_idx, uint32_t sz)
* @return 0 on success; nonzero on failure.
*/
static int
-boot_swap_areas(int idx, uint32_t sz)
+boot_swap_areas(int idx, uint32_t sz, int end_area)
{
int area_idx_1;
int area_idx_2;
int rc;
- int state;
area_idx_1 = boot_req->br_slot_areas[0] + idx;
area_idx_2 = boot_req->br_slot_areas[1] + idx;
@@ -271,8 +311,7 @@ boot_swap_areas(int idx, uint32_t sz)
assert(area_idx_1 != boot_req->br_scratch_area_idx);
assert(area_idx_2 != boot_req->br_scratch_area_idx);
- state = BOOT_PERSIST_ST(boot_state.state);
- if (state == 0) {
+ if (boot_state.state == 0) {
rc = boot_erase_area(boot_req->br_scratch_area_idx, sz);
if (rc != 0) {
return rc;
@@ -283,26 +322,25 @@ boot_swap_areas(int idx, uint32_t sz)
return rc;
}
- boot_state.state = BOOT_PERSIST(idx, 1);
+ boot_state.state = 1;
(void)boot_write_status(&boot_state);
- state = 1;
}
- if (state == 1) {
+ if (boot_state.state == 1) {
rc = boot_erase_area(area_idx_2, sz);
if (rc != 0) {
return rc;
}
- rc = boot_copy_area(area_idx_1, area_idx_2, sz);
+ rc = boot_copy_area(area_idx_1, area_idx_2,
+ end_area ? (sz - boot_status_sz()) : sz);
if (rc != 0) {
return rc;
}
- boot_state.state = BOOT_PERSIST(idx, 2);
+ boot_state.state = 2;
(void)boot_write_status(&boot_state);
- state = 2;
}
- if (state == 2) {
+ if (boot_state.state == 2) {
rc = boot_erase_area(area_idx_1, sz);
if (rc != 0) {
return rc;
@@ -313,9 +351,9 @@ boot_swap_areas(int idx, uint32_t sz)
return rc;
}
- boot_state.state = BOOT_PERSIST(idx + 1, 0);
+ boot_state.idx++;
+ boot_state.state = 0;
(void)boot_write_status(&boot_state);
- state = 3;
}
return 0;
}
@@ -324,63 +362,129 @@ boot_swap_areas(int idx, uint32_t sz)
* Swaps the two images in flash. If a prior copy operation was interrupted
* by a system reset, this function completes that operation.
*
- * @param img1_length The length, in bytes, of the slot 1 image.
- * @param img2_length The length, in bytes, of the slot 2 image.
- *
* @return 0 on success; nonzero on failure.
*/
static int
boot_copy_image(void)
{
- uint32_t off;
uint32_t sz;
int i;
+ int end_area = 1;
int cnt;
- int rc;
- int state_idx;
-
- state_idx = BOOT_PERSIST_IDX(boot_state.state);
- for (off = 0, i = 0; off < boot_state.length; off += sz, i += cnt) {
- sz = boot_copy_sz(i, boot_req->br_slot_areas[1], &cnt);
- if (i >= state_idx) {
- rc = boot_swap_areas(i, sz);
- assert(rc == 0);
+ int cur_idx;
+
+ for (i = boot_req->br_slot_areas[1], cur_idx = 0; i > 0; cur_idx++) {
+ sz = boot_copy_sz(i, &cnt);
+ i -= cnt;
+ if (cur_idx >= boot_state.idx) {
+ boot_swap_areas(i, sz, end_area);
}
+ end_area = 0;
}
+ boot_clear_status();
return 0;
}
-/**
- * Builds a default boot status corresponding to all images being fully present
- * in their slots. This function is used when a boot status is not present in
- * flash (i.e., in the usual case when the previous boot operation ran to
- * completion).
+
+/*
+ * Is copy in progress?
*/
static void
-boot_build_status(void)
+boot_read_status_bytes(struct boot_status *bs, uint8_t flash_id, uint32_t off)
{
- uint32_t len1;
- uint32_t len2;
+ uint8_t status;
- if (boot_img_hdrs[0].ih_magic == IMAGE_MAGIC) {
- len1 = boot_img_hdrs[0].ih_hdr_size + boot_img_hdrs[0].ih_img_size +
- boot_img_hdrs[0].ih_tlv_size;
- } else {
- len1 = 0;
+ off -= sizeof(status) * 2;
+ while (1) {
+ hal_flash_read(flash_id, off, &status, sizeof(status));
+ if (status == 0xff) {
+ break;
+ }
+ off--;
+ if (bs->state == 2) {
+ bs->idx++;
+ bs->state = 0;
+ } else {
+ bs->state++;
+ }
}
+}
- if (boot_img_hdrs[1].ih_magic == IMAGE_MAGIC) {
- len2 = boot_img_hdrs[1].ih_hdr_size + boot_img_hdrs[1].ih_img_size +
- boot_img_hdrs[0].ih_tlv_size;
- } else {
- len2 = 0;
+int
+boot_read_status(struct boot_status *bs)
+{
+ struct boot_img_trailer bit;
+ struct flash_area *scratch;
+
+ /*
+ * Check if boot_img_trailer is in scratch, or at the end of slot0.
+ */
+ boot_slot_magic(0, &bit);
+ if (bit.bit_start == BOOT_IMG_MAGIC && bit.bit_done == 0xffffffff) {
+ boot_read_status_bytes(bs, boot_img[0].loc.bil_flash_id,
+ boot_magic_off(0));
+ console_printf("status in slot0, %lu/%lu\n", bs->idx, bs->state);
+ return 1;
}
- boot_state.length = len1;
- if (len1 < len2) {
- boot_state.length = len2;
+ boot_scratch_magic(&bit);
+ if (bit.bit_start == BOOT_IMG_MAGIC && bit.bit_done == 0xffffffff) {
+ scratch = &boot_req->br_area_descs[boot_req->br_scratch_area_idx];
+ boot_read_status_bytes(bs, scratch->fa_flash_id, boot_scratch_off());
+ console_printf("status in scratch, %lu/%lu\n", bs->idx, bs->state);
+ return 1;
}
- boot_state.state = 0;
+ return 0;
+}
+
+#include <hal/hal_system.h>
+
+int
+boot_write_status(struct boot_status *bs)
+{
+ uint32_t off;
+ uint8_t flash_id;
+ uint8_t val;
+
+ if (bs->idx == 0) {
+ /*
+ * Write to scratch
+ */
+ off = boot_scratch_off();
+ flash_id =
+ boot_req->br_area_descs[boot_req->br_scratch_area_idx].fa_flash_id;
+ } else {
+ /*
+ * Write to slot 0;
+ */
+ off = boot_magic_off(0);
+ flash_id = boot_img[0].loc.bil_flash_id;
+ }
+ off -= ((3 * sizeof(uint8_t)) * bs->idx +
+ sizeof(uint8_t) * (bs->state + 1));
+
+ console_printf("status write, %lu/%lu -> %lx\n", bs->idx, bs->state, off);
+
+ val = bs->state;
+ hal_flash_write(flash_id, off, &val, sizeof(val));
+
+ return 0;
+}
+
+void
+boot_clear_status(void)
+{
+ uint32_t off;
+ uint32_t val = BOOT_IMG_MAGIC;
+ uint8_t flash_id;
+
+ /*
+ * Write to slot 0;
+ */
+ off = boot_magic_off(0);
+ flash_id = boot_img[0].loc.bil_flash_id;
+ off += sizeof(uint32_t);
+ hal_flash_write(flash_id, off, &val, sizeof(val));
}
/**
@@ -396,23 +500,23 @@ boot_build_status(void)
int
boot_go(const struct boot_req *req, struct boot_rsp *rsp)
{
- struct boot_image_location image_addrs[BOOT_NUM_SLOTS];
int slot;
int rc;
- int i;
/* Set the global boot request object. The remainder of the boot process
* will reference the global.
*/
boot_req = req;
+ /* Attempt to read an image header from each slot. */
+ boot_image_info();
+
/* Read the boot status to determine if an image copy operation was
* interrupted (i.e., the system was reset before the boot loader could
* finish its task last time).
*/
if (boot_read_status(&boot_state)) {
/* We are resuming an interrupted image copy. */
- /* XXX if copy has not actually started yet, validate image */
rc = boot_copy_image();
if (rc != 0) {
/* We failed to put the images back together; there is really no
@@ -422,80 +526,25 @@ boot_go(const struct boot_req *req, struct boot_rsp *rsp)
}
}
- /* Cache the flash address of each image slot. */
- for (i = 0; i < BOOT_NUM_SLOTS; i++) {
- boot_slot_addr(i, &image_addrs[i].bil_flash_id,
- &image_addrs[i].bil_address);
- }
-
- /* Attempt to read an image header from each slot. */
- boot_read_image_headers(boot_img_hdrs, image_addrs, BOOT_NUM_SLOTS);
-
- /* Build a boot status structure indicating the flash location of each
- * image part. This structure will need to be used if an image copy
- * operation is required.
+ /*
+ * Check if we should initiate copy.
*/
- boot_build_status();
-
- /* Determine which image the user wants to run, and where it is located. */
slot = boot_select_image_slot();
if (slot == -1) {
- /* Either there is no image vector, or none of the requested images are
- * present. Just try booting from the first image slot.
- */
- if (boot_img_hdrs[0].ih_magic != IMAGE_MAGIC_NONE) {
- slot = 0;
- } else if (boot_img_hdrs[1].ih_magic != IMAGE_MAGIC_NONE) {
- slot = 1;
- } else {
- /* No images present. */
- return BOOT_EBADIMAGE;
- }
+ return BOOT_EBADIMAGE;
}
- /*
- * If the selected image fails integrity check, try the other one.
- */
- if (boot_image_check(&boot_img_hdrs[slot], &image_addrs[slot])) {
- slot ^= 1;
- if (boot_image_check(&boot_img_hdrs[slot], &image_addrs[slot])) {
- return BOOT_EBADIMAGE;
- }
- }
- switch (slot) {
- case 0:
- rsp->br_hdr = &boot_img_hdrs[0];
- break;
-
- case 1:
- /* The user wants to run the image in the secondary slot. The contents
- * of this slot need to moved to the primary slot.
- */
+ if (slot) {
rc = boot_copy_image();
- if (rc != 0) {
- /* We failed to put the images back together; there is really no
- * solution here.
- */
+ if (rc) {
return rc;
}
-
- rsp->br_hdr = &boot_img_hdrs[1];
- break;
-
- default:
- assert(0);
- break;
}
/* Always boot from the primary slot. */
- rsp->br_flash_id = image_addrs[0].bil_flash_id;
- rsp->br_image_addr = image_addrs[0].bil_address;
-
- /* After successful boot, there should not be a status file. */
- boot_clear_status();
-
- /* If an image is being tested, it should only be booted into once. */
- boot_vect_write_test(NULL);
+ rsp->br_flash_id = boot_img[0].loc.bil_flash_id;
+ rsp->br_image_addr = boot_img[0].loc.bil_address;
+ rsp->br_hdr = &boot_img[0].hdr;
return 0;
}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/b2009c9f/libs/imgmgr/src/imgmgr_boot.c
----------------------------------------------------------------------
diff --git a/libs/imgmgr/src/imgmgr_boot.c b/libs/imgmgr/src/imgmgr_boot.c
index e678b74..c0277b1 100644
--- a/libs/imgmgr/src/imgmgr_boot.c
+++ b/libs/imgmgr/src/imgmgr_boot.c
@@ -132,12 +132,11 @@ imgr_boot_write(struct nmgr_jbuf *njb)
rc = NMGR_ERR_EINVAL;
goto err;
}
- rc = boot_vect_write_test(&ver);
+ rc = boot_vect_write_test(rc);
if (rc) {
rc = NMGR_ERR_EINVAL;
goto err;
}
-
enc = &njb->njb_enc;
json_encode_object_start(enc);
@@ -226,11 +225,12 @@ imgr_boot2_write(struct nmgr_jbuf *njb)
base64_decode(hash_str, hash);
rc = imgr_find_by_hash(hash, &ver);
if (rc >= 0) {
- rc = boot_vect_write_test(&ver);
+ rc = boot_vect_write_test(rc);
if (rc) {
rc = NMGR_ERR_EUNKNOWN;
goto err;
}
+ rc = 0;
} else {
rc = NMGR_ERR_EINVAL;
goto err;