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 2019/10/29 20:12:58 UTC

[mynewt-core] branch master updated (e2b3ca8 -> d595640)

This is an automated email from the ASF dual-hosted git repository.

ccollins pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git.


    from e2b3ca8  da1469x_charger: Fix deps to included modules
     new 80970ae  sys/flash_map: Add flash_area_find_idx() function
     new db94259  sys/flash_map: Keep non-overlapping default areas
     new d595640  sys/flash_map: selftests for dflt flash areas

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 sys/flash_map/include/flash_map/flash_map.h        |  10 ++
 sys/flash_map/pkg.yml                              |   1 +
 sys/flash_map/selftest/src/flash_map_test.c        |   2 +
 .../src/testcases/flash_map_test_case_new_areas.c  | 187 +++++++++++++++++++++
 sys/flash_map/src/flash_map.c                      | 135 +++++++++++++--
 5 files changed, 323 insertions(+), 12 deletions(-)
 create mode 100644 sys/flash_map/selftest/src/testcases/flash_map_test_case_new_areas.c


[mynewt-core] 01/03: sys/flash_map: Add flash_area_find_idx() function

Posted by cc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ccollins pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git

commit 80970ae5a0e24ced90b89111c621a907e4b88eea
Author: Christopher Collins <cc...@apache.org>
AuthorDate: Mon Oct 28 12:34:38 2019 -0700

    sys/flash_map: Add flash_area_find_idx() function
    
    This is an internal utility function that will simplify an upcoming
    feature (inclusion of non-overlapping default flash areas).
---
 sys/flash_map/src/flash_map.c | 34 +++++++++++++++++++++++++---------
 1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/sys/flash_map/src/flash_map.c b/sys/flash_map/src/flash_map.c
index 88c11e5..b1b2f99 100644
--- a/sys/flash_map/src/flash_map.c
+++ b/sys/flash_map/src/flash_map.c
@@ -31,25 +31,41 @@
 const struct flash_area *flash_map;
 int flash_map_entries;
 
-int
-flash_area_open(uint8_t id, const struct flash_area **fap)
+static int
+flash_area_find_idx(uint8_t id)
 {
-    const struct flash_area *area;
     int i;
 
     if (flash_map == NULL) {
-        return SYS_EACCES;
+        return -1;
     }
 
     for (i = 0; i < flash_map_entries; i++) {
-        area = flash_map + i;
-        if (area->fa_id == id) {
-            *fap = area;
-            return 0;
+        if (flash_map[i].fa_id == id) {
+            return i;
         }
     }
 
-    return SYS_ENOENT;
+    return -1;
+}
+
+int
+flash_area_open(uint8_t id, const struct flash_area **fap)
+{
+    int idx;
+
+    if (flash_map == NULL) {
+        return SYS_EACCES;
+    }
+
+    idx = flash_area_find_idx(id);
+    if (idx == -1) {
+        return SYS_ENOENT;
+    }
+
+    *fap = &flash_map[idx];
+
+    return 0;
 }
 
 int


[mynewt-core] 03/03: sys/flash_map: selftests for dflt flash areas

Posted by cc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ccollins pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git

commit d59564091d141bda7761e871bf50a0dc48670b7a
Author: Christopher Collins <cc...@apache.org>
AuthorDate: Mon Oct 28 12:37:00 2019 -0700

    sys/flash_map: selftests for dflt flash areas
    
    Add some self tests for the recent "Include areas from default flash
    map" feature.
---
 sys/flash_map/selftest/src/flash_map_test.c        |   2 +
 .../src/testcases/flash_map_test_case_new_areas.c  | 187 +++++++++++++++++++++
 2 files changed, 189 insertions(+)

diff --git a/sys/flash_map/selftest/src/flash_map_test.c b/sys/flash_map/selftest/src/flash_map_test.c
index e1ad72f..1961a92 100644
--- a/sys/flash_map/selftest/src/flash_map_test.c
+++ b/sys/flash_map/selftest/src/flash_map_test.c
@@ -37,12 +37,14 @@ struct flash_area *fa_sectors;
 TEST_CASE_DECL(flash_map_test_case_1)
 TEST_CASE_DECL(flash_map_test_case_2)
 TEST_CASE_DECL(flash_map_test_case_3)
+TEST_CASE_DECL(flash_map_test_case_new_areas)
 
 TEST_SUITE(flash_map_test_suite)
 {
     flash_map_test_case_1();
     flash_map_test_case_2();
     flash_map_test_case_3();
+    flash_map_test_case_new_areas();
 }
 
 int
diff --git a/sys/flash_map/selftest/src/testcases/flash_map_test_case_new_areas.c b/sys/flash_map/selftest/src/testcases/flash_map_test_case_new_areas.c
new file mode 100644
index 0000000..5a1f900
--- /dev/null
+++ b/sys/flash_map/selftest/src/testcases/flash_map_test_case_new_areas.c
@@ -0,0 +1,187 @@
+/*
+ * 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 "flash_map_test.h"
+
+static struct flash_area scratch_flash_map[100];
+
+static int
+flash_area_cmp(const struct flash_area *fa, const struct flash_area *fb)
+{
+    int64_t diff;
+
+    diff = fb->fa_id - fa->fa_id;
+    if (diff != 0) {
+        return diff;
+    }
+
+    diff = fb->fa_device_id - fa->fa_device_id;
+    if (diff != 0) {
+        return diff;
+    }
+
+    diff = fb->fa_off - fa->fa_off;
+    if (diff != 0) {
+        return diff;
+    }
+
+    diff = fb->fa_size - fa->fa_size;
+    if (diff != 0) {
+        return diff;
+    }
+
+    return 0;
+}
+
+static int
+flash_map_cmp(const struct flash_area *fma, int fma_size,
+              const struct flash_area *fmb, int fmb_size)
+{
+    const struct flash_area *fa;
+    const struct flash_area *fb;
+    bool found;
+    int diff;
+    int ai;
+    int bi;
+
+    diff = fmb_size - fma_size;
+    if (diff != 0) {
+        return diff;
+    }
+
+    for (ai = 0; ai < fma_size; ai++) {
+        fa = &fma[ai];
+
+        found = false;
+        for (bi = 0; bi < fmb_size; bi++) {
+            fb = &fmb[bi];
+
+            if (fa->fa_id == fb->fa_id) {
+                diff = flash_area_cmp(fa, fb);
+                if (diff != 0) {
+                    return diff;
+                }
+
+                found = true;
+                break;
+            }
+        }
+
+        if (!found) {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+TEST_CASE_SELF(flash_map_test_case_new_areas)
+{
+    const int sysflash_map_dflt_sz = 
+        sizeof sysflash_map_dflt / sizeof sysflash_map_dflt[0];
+
+    bool found;
+    int scratch_num_areas;
+    int rc;
+    int i;
+
+    /*** No new areas. */
+
+    flash_map = scratch_flash_map;
+    memcpy(scratch_flash_map, sysflash_map_dflt, sizeof sysflash_map_dflt);
+    flash_map_entries = sysflash_map_dflt_sz;
+
+    flash_map_add_new_dflt_areas_extern();
+    rc = flash_map_cmp(flash_map, flash_map_entries,
+                       sysflash_map_dflt, sysflash_map_dflt_sz);
+    TEST_ASSERT(rc == 0);
+
+    /*** All new areas. */
+
+    flash_map = scratch_flash_map;
+    flash_map_entries = 0;
+
+    flash_map_add_new_dflt_areas_extern();
+    rc = flash_map_cmp(flash_map, flash_map_entries,
+                       sysflash_map_dflt, sysflash_map_dflt_sz);
+    TEST_ASSERT(rc == 0);
+
+    /*** One new area sandwiched between existing areas. */
+
+    memcpy(scratch_flash_map, sysflash_map_dflt, sizeof sysflash_map_dflt);
+
+    /* Remove image slot 1 from flash map. */
+    found = false;
+    for (i = 0; i < sysflash_map_dflt_sz - 1; i++) {
+        if (!found && scratch_flash_map[i].fa_id == FLASH_AREA_IMAGE_1) {
+            found = true;
+        }
+
+        if (found) {
+            scratch_flash_map[i] = scratch_flash_map[i + 1];
+        }
+    }
+
+    flash_map = scratch_flash_map;
+    flash_map_entries = sysflash_map_dflt_sz - 1;
+
+    flash_map_add_new_dflt_areas_extern();
+    rc = flash_map_cmp(flash_map, flash_map_entries,
+                       sysflash_map_dflt, sysflash_map_dflt_sz);
+    TEST_ASSERT(rc == 0);
+
+    /*** One new area that overlaps; ensure new area doesn't get added. */
+
+    memcpy(scratch_flash_map, sysflash_map_dflt, sizeof sysflash_map_dflt);
+    scratch_num_areas = sysflash_map_dflt_sz - 1;
+    scratch_flash_map[scratch_num_areas - 1].fa_size += 4096;
+    flash_map = scratch_flash_map;
+    flash_map_entries = scratch_num_areas;
+
+    flash_map_add_new_dflt_areas_extern();
+    rc = flash_map_cmp(flash_map, flash_map_entries,
+                       scratch_flash_map, scratch_num_areas);
+    TEST_ASSERT(rc == 0);
+
+    /***
+     * Two new areas - one overlaps, the other doesn't.  Ensure only the
+     * non-overlapping area gets added.
+     */
+
+    memcpy(scratch_flash_map, sysflash_map_dflt, sizeof sysflash_map_dflt);
+    scratch_num_areas = sysflash_map_dflt_sz - 2;
+    scratch_flash_map[0].fa_size += 4096;
+    flash_map = scratch_flash_map;
+    flash_map_entries = scratch_num_areas;
+
+    flash_map_add_new_dflt_areas_extern();
+
+    /* Ensure none of the common areas changed. */
+    rc = flash_map_cmp(flash_map, scratch_num_areas,
+                       scratch_flash_map, scratch_num_areas);
+    TEST_ASSERT(rc == 0);
+
+    /* Make sure only one area got added. */
+    TEST_ASSERT_FATAL(flash_map_entries == scratch_num_areas + 1);
+
+    /* Verify the correct area got added. */
+    rc = flash_area_cmp(&flash_map[flash_map_entries - 1],
+                        &sysflash_map_dflt[sysflash_map_dflt_sz - 1]);
+    TEST_ASSERT_FATAL(rc == 0);
+}


[mynewt-core] 02/03: sys/flash_map: Keep non-overlapping default areas

Posted by cc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ccollins pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git

commit db942599ee19d3a31bc07e80db496bb109531f7c
Author: Christopher Collins <cc...@apache.org>
AuthorDate: Mon Oct 28 12:37:06 2019 -0700

    sys/flash_map: Keep non-overlapping default areas
    
    Prior to this commit, a device with a flash map in its manufacturing
    meta region (MMR) would completely ignore the default flash map
    hardcoded in a firmware image.  The rationale was that changes to the
    default flash map should not cause devices in the field to lose data
    present in the affected flash areas.
    
    This is reasonable, but there is one issue - if we add new flash areas
    to unused portions of flash, devices in the field will not be able to
    use them since they would not be present in the devices' flash maps.
    
    This commit allows a device to use new flash areas hardcoded in the
    image.  The device will incorporate such a flash area into its flash map
    if it meets both of these criteria:
    
    1. The area has a unique ID
    2. The area does not overlap with any other flash areas in the MMR flash
       map.
    
    The first criterion means that if a firmware image rearranges or resizes
    some existing flash areas, these changes will *not* be incorporated into
    the device's flash map.  These areas are not new, they are just
    modified, so their IDs are already present in the device's MMR flash
    map.
    
    The second criterion means that the device will only incorporate a new
    flash area into its flash map if the area resides entirely in unused
    flash.  If the area overlaps any other areas, it is ignored.
---
 sys/flash_map/include/flash_map/flash_map.h |  10 +++
 sys/flash_map/pkg.yml                       |   1 +
 sys/flash_map/src/flash_map.c               | 101 +++++++++++++++++++++++++++-
 3 files changed, 109 insertions(+), 3 deletions(-)

diff --git a/sys/flash_map/include/flash_map/flash_map.h b/sys/flash_map/include/flash_map/flash_map.h
index 217cf53..131bc30 100644
--- a/sys/flash_map/include/flash_map/flash_map.h
+++ b/sys/flash_map/include/flash_map/flash_map.h
@@ -44,6 +44,8 @@ extern "C" {
 #include <stdbool.h>
 #include <inttypes.h>
 
+#include "syscfg/syscfg.h"
+
 struct flash_area {
     uint8_t fa_id;
     uint8_t fa_device_id;
@@ -131,6 +133,14 @@ int flash_area_getnext_sector(int id, int *sec_id, struct flash_area *ret);
 int flash_area_id_from_image_slot(int slot);
 int flash_area_id_to_image_slot(int area_id);
 
+#if MYNEWT_VAL(SELFTEST)
+/**
+ * Adds areas from the hardcoded flash map that aren't present in, and don't
+ * overlap with, the manufacturing flash map.  Only exposed to unit tests.
+ */
+void flash_map_add_new_dflt_areas_extern(void);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/sys/flash_map/pkg.yml b/sys/flash_map/pkg.yml
index 686f2c7..2482833 100644
--- a/sys/flash_map/pkg.yml
+++ b/sys/flash_map/pkg.yml
@@ -28,6 +28,7 @@ pkg.keywords:
 pkg.deps:
     - "@apache-mynewt-core/sys/defs"
     - "@apache-mynewt-core/sys/mfg"
+    - "@apache-mynewt-core/sys/log/modlog"
 
 pkg.init:
     flash_map_init: 'MYNEWT_VAL(FLASH_MAP_SYSINIT_STAGE)'
diff --git a/sys/flash_map/src/flash_map.c b/sys/flash_map/src/flash_map.c
index b1b2f99..6d3dcca 100644
--- a/sys/flash_map/src/flash_map.c
+++ b/sys/flash_map/src/flash_map.c
@@ -406,6 +406,84 @@ flash_map_read_mfg(int max_areas,
     }
 }
 
+/**
+ * Determines if the specified flash area overlaps any areas in the flash map.
+ *
+ * @param area1                 The flash area to compare against the flash
+ *                                  map.
+ *
+ * @return                      True if there is an overlap; false otherwise.
+ */
+static bool
+flash_map_area_overlaps(const struct flash_area *area1)
+{
+    const struct flash_area *area2;
+    uint32_t end1;
+    uint32_t end2;
+    int i;
+
+    for (i = 0; i < flash_map_entries; i++) {
+        area2 = &flash_map[i];
+
+        if (area1->fa_device_id == area2->fa_device_id) {
+            end1 = area1->fa_off + area1->fa_size;
+            end2 = area2->fa_off + area2->fa_size;
+
+            if (end1 > area2->fa_off && area1->fa_off < end2) {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+/**
+ * Adds areas from the hardcoded flash map that aren't present in, and don't
+ * overlap with, the manufacturing flash map.
+ */
+static void
+flash_map_add_new_dflt_areas(void)
+{
+    static const int num_dflt_entries =
+        sizeof sysflash_map_dflt / sizeof sysflash_map_dflt[0];
+
+    const struct flash_area *dflt_area;
+    struct flash_area *dst_area;
+    int i;
+    
+    for (i = 0; i < num_dflt_entries; i++) {
+        dflt_area = &sysflash_map_dflt[i];
+
+        /* If there is already a manufacturing area with this ID, discard the
+         * default area.
+         */
+        if (flash_area_find_idx(dflt_area->fa_id) == -1) {
+            /* Default flash map contains a new entry. */
+            if (flash_map_entries >= MYNEWT_VAL(FLASH_MAP_MAX_AREAS)) {
+                DFLT_LOG_DEBUG("failed to add default flash area: "
+                               "no room: id=%d",
+                               dflt_area->fa_id);
+                DEBUG_PANIC();
+                return;
+            } 
+
+            /* Add the default entry if it doesn't cause any overlaps. */
+            if (flash_map_area_overlaps(dflt_area)) {
+                DFLT_LOG_DEBUG("failed to add default flash area: "
+                               "overlap: id=%d",
+                               dflt_area->fa_id);
+            } else {
+                /* Cast away const. */
+                dst_area = (struct flash_area *) &flash_map[flash_map_entries];
+
+                *dst_area = *dflt_area;
+                flash_map_entries++;
+            }
+        }
+    }
+}
+
 void
 flash_map_init(void)
 {
@@ -436,8 +514,25 @@ flash_map_init(void)
      */
     rc = flash_map_read_mfg(sizeof mfg_areas / sizeof mfg_areas[0],
                             mfg_areas, &num_areas);
-    if (rc == 0 && num_areas > 0) {
-        flash_map = mfg_areas;
-        flash_map_entries = num_areas;
+    if (rc != 0 || num_areas == 0) {
+        return;
     }
+    flash_map = mfg_areas;
+    flash_map_entries = num_areas;
+
+    /* The hardcoded flash map may contain new areas that aren't present in the
+     * manufacturing flash map.  Try including them if they don't overlap with
+     * any mfg areas.
+     */
+    flash_map_add_new_dflt_areas();
+}
+
+#if MYNEWT_VAL(SELFTEST)
+
+void
+flash_map_add_new_dflt_areas_extern(void)
+{
+    flash_map_add_new_dflt_areas();
 }
+
+#endif