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/10/23 20:53:33 UTC

incubator-mynewt-core git commit: Manufacturing meta region.

Repository: incubator-mynewt-core
Updated Branches:
  refs/heads/develop 0c892318d -> ed29774fb


Manufacturing meta region.


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/ed29774f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/ed29774f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/ed29774f

Branch: refs/heads/develop
Commit: ed29774fbb3c2937a8592767e706214986c6b6dd
Parents: 0c89231
Author: Christopher Collins <cc...@apache.org>
Authored: Fri Oct 21 18:59:14 2016 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Sun Oct 23 13:52:50 2016 -0700

----------------------------------------------------------------------
 hw/bsp/arduino_primo_nrf52/primo_download.sh    |  30 +-
 hw/bsp/bmd300eval/bmd300eval_download.sh        |  14 +-
 hw/bsp/frdm-k64f/frdm-k64_download.sh           |  18 +-
 .../nrf51dk-16kbram_download.sh                 |   9 +-
 hw/bsp/nrf51-blenano/nrf51dk_download.sh        |  14 +-
 .../nrf51dk-16kbram/nrf51dk-16kbram_download.sh |  14 +-
 hw/bsp/nrf51dk/nrf51dk_download.sh              |  14 +-
 hw/bsp/nrf52dk/nrf52dk_download.sh              |  14 +-
 hw/bsp/nucleo-f401re/nucleo-f401re_download.sh  |   9 +-
 .../olimex_stm32-e407_devboard_download.sh      |   9 +-
 hw/bsp/rb-nano2/rb-nano2_download.sh            |  14 +-
 .../stm32f4discovery_download.sh                |   9 +-
 sys/flash_map/pkg.yml                           |   1 +
 sys/flash_map/src/flash_map.c                   |  91 ++++-
 sys/flash_map/syscfg.yml                        |  21 ++
 sys/id/pkg.yml                                  |   1 +
 sys/id/src/id.c                                 |  37 ++
 sys/mfg/include/mfg/mfg.h                       |  56 +++
 sys/mfg/pkg.yml                                 |  33 ++
 sys/mfg/src/mfg.c                               | 348 +++++++++++++++++++
 20 files changed, 667 insertions(+), 89 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ed29774f/hw/bsp/arduino_primo_nrf52/primo_download.sh
----------------------------------------------------------------------
diff --git a/hw/bsp/arduino_primo_nrf52/primo_download.sh b/hw/bsp/arduino_primo_nrf52/primo_download.sh
index 36f1ef9..c294ed3 100755
--- a/hw/bsp/arduino_primo_nrf52/primo_download.sh
+++ b/hw/bsp/arduino_primo_nrf52/primo_download.sh
@@ -20,21 +20,16 @@
 #  - BSP_PATH is absolute path to hw/bsp/bsp_name
 #  - BIN_BASENAME is the path to prefix to target binary,
 #    .elf appended to name is the ELF file
-#  - IMAGE_SLOT is the image slot to download to
+#  - IMAGE_SLOT is the image slot to download to (for non-mfg-image, non-boot)
 #  - FEATURES holds the target features string
 #  - EXTRA_JTAG_CMD holds extra parameters to pass to jtag software
-#
+#  - MFG_IMAGE is "1" if this is a manufacturing image
 
 if [ -z "$BIN_BASENAME" ]; then
     echo "Need binary to download"
     exit 1
 fi
 
-if [ -z "$IMAGE_SLOT" ]; then
-    echo "Need image slot to download"
-    exit 1
-fi
-
 IS_BOOTLOADER=0
 USE_OPENOCD=0
 GDB_CMD_FILE=.gdb_cmds
@@ -42,14 +37,17 @@ GDB_CMD_FILE=.gdb_cmds
 # Look for 'bootloader' in FEATURES
 for feature in $FEATURES; do
     if [ $feature == "BOOT_LOADER" ]; then
-	IS_BOOTLOADER=1
+        IS_BOOTLOADER=1
     fi
     if [ $feature = "openocd_debug" ]; then
-	USE_OPENOCD=1
+        USE_OPENOCD=1
     fi
 done
 
-if [ $IS_BOOTLOADER -eq 1 ]; then
+if [ "$MFG_IMAGE" -eq 1 ]; then
+    FLASH_OFFSET=0x0
+    FILE_NAME=$BIN_BASENAME.bin
+elif [ $IS_BOOTLOADER -eq 1 ]; then
     FLASH_OFFSET=0x0
     FILE_NAME=$BIN_BASENAME.elf.bin
 elif [ $IMAGE_SLOT -eq 0 ]; then
@@ -72,8 +70,8 @@ fi
 
 if [ $USE_OPENOCD -eq 1 ]; then
     if [ -z "$BSP_PATH" ]; then
-	echo "Need BSP path for openocd script location"
-	exit 1
+        echo "Need BSP path for openocd script location"
+        exit 1
     fi
 
     #
@@ -97,21 +95,21 @@ else
 
     error=`echo $msgs | grep error`
     if [ -n "$error" ]; then
-	exit 1
+        exit 1
     fi
 
     error=`echo $msgs | grep -i failed`
     if [ -n "$error" ]; then
-	exit 1
+        exit 1
     fi
 
     error=`echo $msgs | grep -i "unknown / supported"`
     if [ -n "$error" ]; then
-	exit 1
+        exit 1
     fi
 
     error=`echo $msgs | grep -i "not found"`
     if [ -n "$error" ]; then
-	exit 1
+        exit 1
     fi
 fi

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ed29774f/hw/bsp/bmd300eval/bmd300eval_download.sh
----------------------------------------------------------------------
diff --git a/hw/bsp/bmd300eval/bmd300eval_download.sh b/hw/bsp/bmd300eval/bmd300eval_download.sh
index 6c25243..5c0082c 100755
--- a/hw/bsp/bmd300eval/bmd300eval_download.sh
+++ b/hw/bsp/bmd300eval/bmd300eval_download.sh
@@ -20,21 +20,16 @@
 #  - BSP_PATH is absolute path to hw/bsp/bsp_name
 #  - BIN_BASENAME is the path to prefix to target binary,
 #    .elf appended to name is the ELF file
-#  - IMAGE_SLOT is the image slot to download to
+#  - IMAGE_SLOT is the image slot to download to (for non-mfg-image, non-boot)
 #  - FEATURES holds the target features string
 #  - EXTRA_JTAG_CMD holds extra parameters to pass to jtag software
-#
+#  - MFG_IMAGE is "1" if this is a manufacturing image
 
 if [ -z "$BIN_BASENAME" ]; then
     echo "Need binary to download"
     exit 1
 fi
 
-if [ -z "$IMAGE_SLOT" ]; then
-    echo "Need image slot to download"
-    exit 1
-fi
-
 IS_BOOTLOADER=0
 GDB_CMD_FILE=.gdb_cmds
 
@@ -45,7 +40,10 @@ for feature in $FEATURES; do
     fi
 done
 
-if [ $IS_BOOTLOADER -eq 1 ]; then
+if [ "$MFG_IMAGE" -eq 1 ]; then
+    FLASH_OFFSET=0x0
+    FILE_NAME=$BIN_BASENAME.bin
+elif [ $IS_BOOTLOADER -eq 1 ]; then
     FLASH_OFFSET=0x0
     FILE_NAME=$BIN_BASENAME.elf.bin
 elif [ $IMAGE_SLOT -eq 0 ]; then

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ed29774f/hw/bsp/frdm-k64f/frdm-k64_download.sh
----------------------------------------------------------------------
diff --git a/hw/bsp/frdm-k64f/frdm-k64_download.sh b/hw/bsp/frdm-k64f/frdm-k64_download.sh
index e62dc4d..65d4698 100755
--- a/hw/bsp/frdm-k64f/frdm-k64_download.sh
+++ b/hw/bsp/frdm-k64f/frdm-k64_download.sh
@@ -20,21 +20,16 @@
 #  - BSP_PATH is absolute path to hw/bsp/bsp_name
 #  - BIN_BASENAME is the path to prefix to target binary,
 #    .elf appended to name is the ELF file
-#  - IMAGE_SLOT is the image slot to download to
+#  - IMAGE_SLOT is the image slot to download to (for non-mfg-image, non-boot)
 #  - FEATURES holds the target features string
 #  - EXTRA_JTAG_CMD holds extra parameters to pass to jtag software
-#
+#  - MFG_IMAGE is "1" if this is a manufacturing image
 
 if [ -z "${BIN_BASENAME}" ]; then
     echo "Need binary to download"
     exit 1
 fi
 
-if [ -z "${IMAGE_SLOT}" ]; then
-    echo "Need image slot to download"
-    exit 1
-fi
-
 IS_BOOTLOADER=0
 USE_OPENOCD=0
 GDB_CMD_FILE=.gdb_cmds
@@ -42,14 +37,17 @@ GDB_CMD_FILE=.gdb_cmds
 # Look for 'bootloader' in FEATURES
 for feature in ${FEATURES}; do
     if [ ${feature} == "BOOT_LOADER" ]; then
-	IS_BOOTLOADER=1
+        IS_BOOTLOADER=1
     fi
     if [ ${feature} = "openocd_debug" ]; then
-	USE_OPENOCD=1
+        USE_OPENOCD=1
     fi
 done
 
-if [ ${IS_BOOTLOADER} -eq 1 ]; then
+if [ "$MFG_IMAGE" -eq 1 ]; then
+    FLASH_OFFSET=0x0
+    FILE_NAME=$BIN_BASENAME.bin
+elif [ $IS_BOOTLOADER -eq 1 ]; then
     FLASH_OFFSET=0x00000000
     FILE_NAME=${BIN_BASENAME}.elf.bin
 else

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ed29774f/hw/bsp/nrf51-arduino_101/nrf51dk-16kbram_download.sh
----------------------------------------------------------------------
diff --git a/hw/bsp/nrf51-arduino_101/nrf51dk-16kbram_download.sh b/hw/bsp/nrf51-arduino_101/nrf51dk-16kbram_download.sh
index bad01d0..9dc02d7 100755
--- a/hw/bsp/nrf51-arduino_101/nrf51dk-16kbram_download.sh
+++ b/hw/bsp/nrf51-arduino_101/nrf51dk-16kbram_download.sh
@@ -21,10 +21,10 @@
 #  - BSP_PATH is absolute path to hw/bsp/bsp_name
 #  - BIN_BASENAME is the path to prefix to target binary,
 #    .elf appended to name is the ELF file
-#  - IMAGE_SLOT is the image slot to download to
+#  - IMAGE_SLOT is the image slot to download to (for non-mfg-image, non-boot)
 #  - FEATURES holds the target features string
 #  - EXTRA_JTAG_CMD holds extra parameters to pass to jtag software
-#
+#  - MFG_IMAGE is "1" if this is a manufacturing image
 
 if [ -z "$BIN_BASENAME" ]; then
     echo "Need binary to download"
@@ -42,7 +42,10 @@ for feature in $FEATURES; do
     fi
 done
 
-if [ $IS_BOOTLOADER -eq 1 ]; then
+if [ "$MFG_IMAGE" -eq 1 ]; then
+    FLASH_OFFSET=0x0
+    FILE_NAME=$BIN_BASENAME.bin
+elif [ $IS_BOOTLOADER -eq 1 ]; then
     FLASH_OFFSET=0x0
     FILE_NAME=$BIN_BASENAME.elf.bin
 else

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ed29774f/hw/bsp/nrf51-blenano/nrf51dk_download.sh
----------------------------------------------------------------------
diff --git a/hw/bsp/nrf51-blenano/nrf51dk_download.sh b/hw/bsp/nrf51-blenano/nrf51dk_download.sh
index 14ee3f4..c9bdf7d 100755
--- a/hw/bsp/nrf51-blenano/nrf51dk_download.sh
+++ b/hw/bsp/nrf51-blenano/nrf51dk_download.sh
@@ -21,21 +21,16 @@
 #  - BSP_PATH is absolute path to hw/bsp/bsp_name
 #  - BIN_BASENAME is the path to prefix to target binary,
 #    .elf appended to name is the ELF file
-#  - IMAGE_SLOT is the image slot to download to
+#  - IMAGE_SLOT is the image slot to download to (for non-mfg-image, non-boot)
 #  - FEATURES holds the target features string
 #  - EXTRA_JTAG_CMD holds extra parameters to pass to jtag software
-#
+#  - MFG_IMAGE is "1" if this is a manufacturing image
 
 if [ -z "$BIN_BASENAME" ]; then
     echo "Need binary to download"
     exit 1
 fi
 
-if [ -z "$IMAGE_SLOT" ]; then
-    echo "Need image slot to download"
-    exit 1
-fi
-
 IS_BOOTLOADER=0
 #JLINK_SCRIPT=.download.jlink
 GDB_CMD_FILE=.gdb_cmds
@@ -47,7 +42,10 @@ for feature in $FEATURES; do
     fi
 done
 
-if [ $IS_BOOTLOADER -eq 1 ]; then
+if [ "$MFG_IMAGE" -eq 1 ]; then
+    FLASH_OFFSET=0x0
+    FILE_NAME=$BIN_BASENAME.bin
+elif [ $IS_BOOTLOADER -eq 1 ]; then
     FLASH_OFFSET=0x0
     FILE_NAME=$BIN_BASENAME.elf.bin
 elif [ $IMAGE_SLOT -eq 0 ]; then

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ed29774f/hw/bsp/nrf51dk-16kbram/nrf51dk-16kbram_download.sh
----------------------------------------------------------------------
diff --git a/hw/bsp/nrf51dk-16kbram/nrf51dk-16kbram_download.sh b/hw/bsp/nrf51dk-16kbram/nrf51dk-16kbram_download.sh
index c6a1ef6..005e3f3 100755
--- a/hw/bsp/nrf51dk-16kbram/nrf51dk-16kbram_download.sh
+++ b/hw/bsp/nrf51dk-16kbram/nrf51dk-16kbram_download.sh
@@ -21,21 +21,16 @@
 #  - BSP_PATH is absolute path to hw/bsp/bsp_name
 #  - BIN_BASENAME is the path to prefix to target binary,
 #    .elf appended to name is the ELF file
-#  - IMAGE_SLOT is the image slot to download to
+#  - IMAGE_SLOT is the image slot to download to (for non-mfg-image, non-boot)
 #  - FEATURES holds the target features string
 #  - EXTRA_JTAG_CMD holds extra parameters to pass to jtag software
-#
+#  - MFG_IMAGE is "1" if this is a manufacturing image
 
 if [ -z "$BIN_BASENAME" ]; then
     echo "Need binary to download"
     exit 1
 fi
 
-if [ -z "$IMAGE_SLOT" ]; then
-    echo "Need image slot to download"
-    exit 1
-fi
-
 IS_BOOTLOADER=0
 #JLINK_SCRIPT=.download.jlink
 GDB_CMD_FILE=.gdb_cmds
@@ -47,7 +42,10 @@ for feature in $FEATURES; do
     fi
 done
 
-if [ $IS_BOOTLOADER -eq 1 ]; then
+if [ "$MFG_IMAGE" -eq 1 ]; then
+    FLASH_OFFSET=0x0
+    FILE_NAME=$BIN_BASENAME.bin
+elif [ $IS_BOOTLOADER -eq 1 ]; then
     FLASH_OFFSET=0x0
     FILE_NAME=$BIN_BASENAME.elf.bin
 elif [ $IMAGE_SLOT -eq 0 ]; then

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ed29774f/hw/bsp/nrf51dk/nrf51dk_download.sh
----------------------------------------------------------------------
diff --git a/hw/bsp/nrf51dk/nrf51dk_download.sh b/hw/bsp/nrf51dk/nrf51dk_download.sh
index ee3fc3f..10b3c43 100755
--- a/hw/bsp/nrf51dk/nrf51dk_download.sh
+++ b/hw/bsp/nrf51dk/nrf51dk_download.sh
@@ -21,21 +21,16 @@
 #  - BSP_PATH is absolute path to hw/bsp/bsp_name
 #  - BIN_BASENAME is the path to prefix to target binary,
 #    .elf appended to name is the ELF file
-#  - IMAGE_SLOT is the image slot to download to
+#  - IMAGE_SLOT is the image slot to download to (for non-mfg-image, non-boot)
 #  - FEATURES holds the target features string
 #  - EXTRA_JTAG_CMD holds extra parameters to pass to jtag software
-#
+#  - MFG_IMAGE is "1" if this is a manufacturing image
 
 if [ -z "$BIN_BASENAME" ]; then
     echo "Need binary to download"
     exit 1
 fi
 
-if [ -z "$IMAGE_SLOT" ]; then
-    echo "Need image slot to download"
-    exit 1
-fi
-
 IS_BOOTLOADER=0
 #JLINK_SCRIPT=.download.jlink
 GDB_CMD_FILE=.gdb_cmds
@@ -47,7 +42,10 @@ for feature in $FEATURES; do
     fi
 done
 
-if [ $IS_BOOTLOADER -eq 1 ]; then
+if [ "$MFG_IMAGE" -eq 1 ]; then
+    FLASH_OFFSET=0x0
+    FILE_NAME=$BIN_BASENAME.bin
+elif [ $IS_BOOTLOADER -eq 1 ]; then
     FLASH_OFFSET=0x0
     FILE_NAME=$BIN_BASENAME.elf.bin
 elif [ $IMAGE_SLOT -eq 0 ]; then

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ed29774f/hw/bsp/nrf52dk/nrf52dk_download.sh
----------------------------------------------------------------------
diff --git a/hw/bsp/nrf52dk/nrf52dk_download.sh b/hw/bsp/nrf52dk/nrf52dk_download.sh
index 6c25243..5c0082c 100755
--- a/hw/bsp/nrf52dk/nrf52dk_download.sh
+++ b/hw/bsp/nrf52dk/nrf52dk_download.sh
@@ -20,21 +20,16 @@
 #  - BSP_PATH is absolute path to hw/bsp/bsp_name
 #  - BIN_BASENAME is the path to prefix to target binary,
 #    .elf appended to name is the ELF file
-#  - IMAGE_SLOT is the image slot to download to
+#  - IMAGE_SLOT is the image slot to download to (for non-mfg-image, non-boot)
 #  - FEATURES holds the target features string
 #  - EXTRA_JTAG_CMD holds extra parameters to pass to jtag software
-#
+#  - MFG_IMAGE is "1" if this is a manufacturing image
 
 if [ -z "$BIN_BASENAME" ]; then
     echo "Need binary to download"
     exit 1
 fi
 
-if [ -z "$IMAGE_SLOT" ]; then
-    echo "Need image slot to download"
-    exit 1
-fi
-
 IS_BOOTLOADER=0
 GDB_CMD_FILE=.gdb_cmds
 
@@ -45,7 +40,10 @@ for feature in $FEATURES; do
     fi
 done
 
-if [ $IS_BOOTLOADER -eq 1 ]; then
+if [ "$MFG_IMAGE" -eq 1 ]; then
+    FLASH_OFFSET=0x0
+    FILE_NAME=$BIN_BASENAME.bin
+elif [ $IS_BOOTLOADER -eq 1 ]; then
     FLASH_OFFSET=0x0
     FILE_NAME=$BIN_BASENAME.elf.bin
 elif [ $IMAGE_SLOT -eq 0 ]; then

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ed29774f/hw/bsp/nucleo-f401re/nucleo-f401re_download.sh
----------------------------------------------------------------------
diff --git a/hw/bsp/nucleo-f401re/nucleo-f401re_download.sh b/hw/bsp/nucleo-f401re/nucleo-f401re_download.sh
index 0ecd779..3dd7032 100755
--- a/hw/bsp/nucleo-f401re/nucleo-f401re_download.sh
+++ b/hw/bsp/nucleo-f401re/nucleo-f401re_download.sh
@@ -21,10 +21,10 @@
 #  - BSP_PATH is absolute path to hw/bsp/bsp_name
 #  - BIN_BASENAME is the path to prefix to target binary,
 #    .elf appended to name is the ELF file
-#  - IMAGE_SLOT is the image slot to download to
+#  - IMAGE_SLOT is the image slot to download to (for non-mfg-image, non-boot)
 #  - FEATURES holds the target features string
 #  - EXTRA_JTAG_CMD holds extra parameters to pass to jtag software
-#
+#  - MFG_IMAGE is "1" if this is a manufacturing image
 set -x
 if [ -z "$BIN_BASENAME" ]; then
     echo "Need binary to download"
@@ -40,7 +40,10 @@ for feature in $FEATURES; do
     fi
 done
 
-if [ $IS_BOOTLOADER -eq 1 ]; then
+if [ "$MFG_IMAGE" -eq 1 ]; then
+    FLASH_OFFSET=0x0
+    FILE_NAME=$BIN_BASENAME.bin
+elif [ $IS_BOOTLOADER -eq 1 ]; then
     FLASH_OFFSET=0x08000000
     FILE_NAME=$BIN_BASENAME.elf.bin
 else

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ed29774f/hw/bsp/olimex_stm32-e407_devboard/olimex_stm32-e407_devboard_download.sh
----------------------------------------------------------------------
diff --git a/hw/bsp/olimex_stm32-e407_devboard/olimex_stm32-e407_devboard_download.sh b/hw/bsp/olimex_stm32-e407_devboard/olimex_stm32-e407_devboard_download.sh
index dd5b783..7b3aa84 100755
--- a/hw/bsp/olimex_stm32-e407_devboard/olimex_stm32-e407_devboard_download.sh
+++ b/hw/bsp/olimex_stm32-e407_devboard/olimex_stm32-e407_devboard_download.sh
@@ -21,10 +21,10 @@
 #  - BSP_PATH is absolute path to hw/bsp/bsp_name
 #  - BIN_BASENAME is the path to prefix to target binary,
 #    .elf appended to name is the ELF file
-#  - IMAGE_SLOT is the image slot to download to
+#  - IMAGE_SLOT is the image slot to download to (for non-mfg-image, non-boot)
 #  - FEATURES holds the target features string
 #  - EXTRA_JTAG_CMD holds extra parameters to pass to jtag software
-#
+#  - MFG_IMAGE is "1" if this is a manufacturing image
 
 if [ -z "$BIN_BASENAME" ]; then
     echo "Need binary to download"
@@ -40,7 +40,10 @@ for feature in $FEATURES; do
     fi
 done
 
-if [ $IS_BOOTLOADER -eq 1 ]; then
+if [ "$MFG_IMAGE" -eq 1 ]; then
+    FLASH_OFFSET=0x0
+    FILE_NAME=$BIN_BASENAME.bin
+elif [ $IS_BOOTLOADER -eq 1 ]; then
     FLASH_OFFSET=0x08000000
     FILE_NAME=$BIN_BASENAME.elf.bin
 else

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ed29774f/hw/bsp/rb-nano2/rb-nano2_download.sh
----------------------------------------------------------------------
diff --git a/hw/bsp/rb-nano2/rb-nano2_download.sh b/hw/bsp/rb-nano2/rb-nano2_download.sh
index d461450..8230d24 100755
--- a/hw/bsp/rb-nano2/rb-nano2_download.sh
+++ b/hw/bsp/rb-nano2/rb-nano2_download.sh
@@ -21,21 +21,16 @@
 #  - BSP_PATH is absolute path to hw/bsp/bsp_name
 #  - BIN_BASENAME is the path to prefix to target binary,
 #    .elf appended to name is the ELF file
-#  - IMAGE_SLOT is the image slot to download to
+#  - IMAGE_SLOT is the image slot to download to (for non-mfg-image, non-boot)
 #  - FEATURES holds the target features string
 #  - EXTRA_JTAG_CMD holds extra parameters to pass to jtag software
-#
+#  - MFG_IMAGE is "1" if this is a manufacturing image
 
 if [ -z "$BIN_BASENAME" ]; then
     echo "Need binary to download"
     exit 1
 fi
 
-if [ -z "$IMAGE_SLOT" ]; then
-    echo "Need image slot to download"
-    exit 1
-fi
-
 IS_BOOTLOADER=0
 #JLINK_SCRIPT=.download.jlink
 GDB_CMD_FILE=.gdb_cmds
@@ -47,7 +42,10 @@ for feature in $FEATURES; do
     fi
 done
 
-if [ $IS_BOOTLOADER -eq 1 ]; then
+if [ "$MFG_IMAGE" -eq 1 ]; then
+    FLASH_OFFSET=0x0
+    FILE_NAME=$BIN_BASENAME.bin
+elif [ $IS_BOOTLOADER -eq 1 ]; then
     FLASH_OFFSET=0x0
     FILE_NAME=$BIN_BASENAME.elf.bin
 elif [ $IMAGE_SLOT -eq 0 ]; then

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ed29774f/hw/bsp/stm32f4discovery/stm32f4discovery_download.sh
----------------------------------------------------------------------
diff --git a/hw/bsp/stm32f4discovery/stm32f4discovery_download.sh b/hw/bsp/stm32f4discovery/stm32f4discovery_download.sh
index 42ee39d..9e7a34a 100755
--- a/hw/bsp/stm32f4discovery/stm32f4discovery_download.sh
+++ b/hw/bsp/stm32f4discovery/stm32f4discovery_download.sh
@@ -21,10 +21,10 @@
 #  - BSP_PATH is absolute path to hw/bsp/bsp_name
 #  - BIN_BASENAME is the path to prefix to target binary,
 #    .elf appended to name is the ELF file
-#  - IMAGE_SLOT is the image slot to download to
+#  - IMAGE_SLOT is the image slot to download to (for non-mfg-image, non-boot)
 #  - FEATURES holds the target features string
 #  - EXTRA_JTAG_CMD holds extra parameters to pass to jtag software
-#
+#  - MFG_IMAGE is "1" if this is a manufacturing image
 
 if [ -z "$BIN_BASENAME" ]; then
     echo "Need binary to download"
@@ -40,7 +40,10 @@ for feature in $FEATURES; do
     fi
 done
 
-if [ $IS_BOOTLOADER -eq 1 ]; then
+if [ "$MFG_IMAGE" -eq 1 ]; then
+    FLASH_OFFSET=0x0
+    FILE_NAME=$BIN_BASENAME.bin
+elif [ $IS_BOOTLOADER -eq 1 ]; then
     FLASH_OFFSET=0x08000000
     FILE_NAME=$BIN_BASENAME.elf.bin
 else

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ed29774f/sys/flash_map/pkg.yml
----------------------------------------------------------------------
diff --git a/sys/flash_map/pkg.yml b/sys/flash_map/pkg.yml
index 2f455d3..400ae47 100644
--- a/sys/flash_map/pkg.yml
+++ b/sys/flash_map/pkg.yml
@@ -28,6 +28,7 @@ pkg.keywords:
 pkg.deps:
     - sys/defs
     - sys/flash_map
+    - sys/mfg
 
 pkg.init_function: flash_map_init
 pkg.init_stage: 0

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ed29774f/sys/flash_map/src/flash_map.c
----------------------------------------------------------------------
diff --git a/sys/flash_map/src/flash_map.c b/sys/flash_map/src/flash_map.c
index 6cbfad6..bc4706c 100644
--- a/sys/flash_map/src/flash_map.c
+++ b/sys/flash_map/src/flash_map.c
@@ -28,6 +28,7 @@
 #include "hal/hal_bsp.h"
 #include "hal/hal_flash.h"
 #include "hal/hal_flash_int.h"
+#include "mfg/mfg.h"
 #include "flash_map/flash_map.h"
 
 const struct flash_area *flash_map;
@@ -166,18 +167,102 @@ flash_area_id_to_image_slot(int area_id)
     }
 }
 
+/**
+ * Reads the flash map layout from the manufacturing meta region.  This
+ * function requires that the flash map be populated with a
+ * FLASH_AREA_BOOTLOADER entry, as the meta region is stored at the end of the
+ * boot loader area.
+ *
+ * @param max_areas             The maximum number of flash areas to read.  If
+ *                                  the count of flash area TLVs in the meta
+ *                                  region is greater than this number, this
+ *                                  function fails.
+ * @param out_areas (out)       An array of flash areas.  On success, the flash
+ *                                  map stored in the meta region gets written
+ *                                  here.
+ * @param out_num_areas (out)   On success, the number of flash areas read gets
+ *                                  written here.
+ *
+ * @return                      0 on success; nonzero on failure.
+ */
+static int
+flash_map_read_mfg(int max_areas,
+                   struct flash_area *out_areas, int *out_num_areas)
+{
+    struct mfg_meta_flash_area meta_flash_area;
+    struct mfg_meta_tlv tlv;
+    struct flash_area *fap;
+    uint32_t off;
+    int rc;
+
+    *out_num_areas = 0;
+    off = 0;
+
+    /* Ensure manufacturing meta region has been located in flash. */
+    rc = mfg_init();
+    if (rc != 0) {
+        return rc;
+    }
+
+    while (1) {
+        if (*out_num_areas >= max_areas) {
+            return -1;
+        }
+
+        rc = mfg_next_tlv_with_type(&tlv, &off, MFG_META_TLV_TYPE_FLASH_AREA);
+        switch (rc) {
+        case 0:
+            break;
+        case MFG_EDONE:
+            return 0;
+        default:
+            return rc;
+        }
+
+        rc = mfg_read_tlv_flash_area(&tlv, off, &meta_flash_area);
+        if (rc != 0) {
+            return rc;
+        }
+
+        fap = out_areas + *out_num_areas;
+        fap->fa_id = meta_flash_area.area_id;
+        fap->fa_device_id = meta_flash_area.device_id;
+        fap->fa_off = meta_flash_area.offset;
+        fap->fa_size = meta_flash_area.size;
+
+        (*out_num_areas)++;
+    }
+}
+
 void
 flash_map_init(void)
 {
+    static struct flash_area mfg_areas[MYNEWT_VAL(FLASH_MAP_MAX_AREAS)];
+
+    int num_areas;
     int rc;
 
     rc = hal_flash_init();
     SYSINIT_PANIC_ASSERT(rc == 0);
 
-    /* XXX: Attempt to read from meta region; for now we always use default
-     * map
+    /* Use the hardcoded default flash map.  This is done for two reasons:
+     * 1. A minimal flash map configuration is required to boot strap the
+     *    process of reading the flash map from the manufacturing meta region.
+     *    In particular, a FLASH_AREA_BOOTLOADER entry is required, as the meta
+     *    region is located at the end of the boot loader area.
+     * 2. If we fail to read the flash map from the meta region, the system
+     *    continues to use the default flash map.
      */
-
     flash_map = sysflash_map_dflt;
     flash_map_entries = sizeof sysflash_map_dflt / sizeof sysflash_map_dflt[0];
+
+    /* Attempt to read the flash map from the manufacturing meta region.  On
+     * success, use the new flash map instead of the default hardcoded one.
+     */
+    rc = flash_map_read_mfg(sizeof mfg_areas / sizeof mfg_areas[0],
+                            mfg_areas, &num_areas);
+    if (rc == 0) {
+        flash_map = mfg_areas;
+        flash_map_entries = num_areas;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ed29774f/sys/flash_map/syscfg.yml
----------------------------------------------------------------------
diff --git a/sys/flash_map/syscfg.yml b/sys/flash_map/syscfg.yml
new file mode 100644
index 0000000..8f49d44
--- /dev/null
+++ b/sys/flash_map/syscfg.yml
@@ -0,0 +1,21 @@
+# 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.
+
+syscfg.defs:
+    FLASH_MAP_MAX_AREAS:
+        description: 'TBD'
+        value: 10

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ed29774f/sys/id/pkg.yml
----------------------------------------------------------------------
diff --git a/sys/id/pkg.yml b/sys/id/pkg.yml
index 751d71b..c9499dc 100644
--- a/sys/id/pkg.yml
+++ b/sys/id/pkg.yml
@@ -30,6 +30,7 @@ pkg.deps:
     - hw/hal
     - kernel/os
     - sys/config
+    - sys/mfg
     - encoding/base64
 
 pkg.init_function: id_init

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ed29774f/sys/id/src/id.c
----------------------------------------------------------------------
diff --git a/sys/id/src/id.c b/sys/id/src/id.c
index e7b2bd5..c6ede4e 100644
--- a/sys/id/src/id.c
+++ b/sys/id/src/id.c
@@ -26,6 +26,7 @@
 #include "os/os.h"
 #include "config/config.h"
 #include "base64/base64.h"
+#include "mfg/mfg.h"
 
 #include "id/id.h"
 
@@ -47,6 +48,9 @@ static const char *app_str = "";
 
 static char serial[ID_SERIAL_MAX_LEN];
 
+/** Base64-encoded null-terminated manufacturing hash. */
+static char id_mfghash[BASE64_ENCODE_SIZE(MFG_HASH_SZ) + 1];
+
 struct conf_handler id_conf = {
     .ch_name = "id",
     .ch_get = id_conf_get,
@@ -72,6 +76,8 @@ id_conf_get(int argc, char **argv, char *val, int val_len_max)
             return (char *)app_str;
         } else if (!strcmp(argv[0], "serial")) {
             return serial;
+        } else if (!strcmp(argv[0], "mfghash")) {
+            return id_mfghash;
         }
     }
     return NULL;
@@ -104,12 +110,40 @@ id_conf_export(void (*export_func)(char *name, char *val),
         export_func("id/hwid", str);
         export_func("id/bsp", (char *)bsp_str);
         export_func("id/app", (char *)app_str);
+        export_func("id/mfghash", (char *)id_mfghash);
     }
     export_func("id/serial", serial);
 
     return 0;
 }
 
+static void
+id_read_mfghash(void)
+{
+    uint8_t raw_hash[MFG_HASH_SZ];
+    struct mfg_meta_tlv tlv;
+    uint32_t off;
+    int rc;
+
+    memset(id_mfghash, 0, sizeof id_mfghash);
+
+    /* Find hash TLV in the manufacturing meta region. */
+    off = 0;
+    rc = mfg_next_tlv_with_type(&tlv, &off, MFG_META_TLV_TYPE_HASH);
+    if (rc != 0) {
+        return;
+    }
+
+    /* Read the TLV contents. */
+    rc = mfg_read_tlv_hash(&tlv, off, raw_hash);
+    if (rc != 0) {
+        return;
+    }
+
+    /* Store the SHA256 hash as a base64-encoded string. */
+    base64_encode(raw_hash, sizeof raw_hash, id_mfghash, 1);
+}
+
 void
 id_init(void)
 {
@@ -117,4 +151,7 @@ id_init(void)
 
     rc = conf_register(&id_conf);
     SYSINIT_PANIC_ASSERT(rc == 0);
+
+    /* Attempt to read the manufacturing image hash from the meta region. */
+    id_read_mfghash();
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ed29774f/sys/mfg/include/mfg/mfg.h
----------------------------------------------------------------------
diff --git a/sys/mfg/include/mfg/mfg.h b/sys/mfg/include/mfg/mfg.h
new file mode 100644
index 0000000..acd478d
--- /dev/null
+++ b/sys/mfg/include/mfg/mfg.h
@@ -0,0 +1,56 @@
+/**
+ * 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.
+ */
+
+#ifndef H_MFG_
+#define H_MFG_
+
+#define MFG_EUNINIT                     1
+#define MFG_EBADDATA                    2
+#define MFG_EDONE                       3
+#define MFG_EFLASH                      4
+
+#define MFG_HASH_SZ                     32
+
+#define MFG_META_TLV_TYPE_HASH          0x01
+#define MFG_META_TLV_TYPE_FLASH_AREA    0x02
+
+struct mfg_meta_tlv {
+    uint8_t type;
+    uint8_t size;
+    /* Followed by packed data. */
+};
+
+struct mfg_meta_flash_area {
+    uint8_t area_id;
+    uint8_t device_id;
+    uint16_t pad16;
+    uint32_t offset;
+    uint32_t size;
+};
+
+int mfg_next_tlv(struct mfg_meta_tlv *tlv, uint32_t *off);
+int mfg_next_tlv_with_type(struct mfg_meta_tlv *tlv, uint32_t *off,
+                           uint8_t type);
+int mfg_read_tlv_flash_area(const struct mfg_meta_tlv *tlv, uint32_t off,
+                            struct mfg_meta_flash_area *out_mfa);
+int mfg_read_tlv_hash(const struct mfg_meta_tlv *tlv, uint32_t off,
+                      void *out_hash);
+int mfg_init(void);
+
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ed29774f/sys/mfg/pkg.yml
----------------------------------------------------------------------
diff --git a/sys/mfg/pkg.yml b/sys/mfg/pkg.yml
new file mode 100644
index 0000000..4c999dc
--- /dev/null
+++ b/sys/mfg/pkg.yml
@@ -0,0 +1,33 @@
+#
+# 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.
+#
+
+pkg.name: sys/mfg
+pkg.description: Utilities for reading manufacturing configuration.
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+    - manufacturing
+
+pkg.deps:
+    - kernel/os
+    - sys/flash_map
+
+# sys/flash_map must get initialized before sys/mfg.
+pkg.init_function: mfg_init
+pkg.init_stage: 1

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ed29774f/sys/mfg/src/mfg.c
----------------------------------------------------------------------
diff --git a/sys/mfg/src/mfg.c b/sys/mfg/src/mfg.c
new file mode 100644
index 0000000..68f836f
--- /dev/null
+++ b/sys/mfg/src/mfg.c
@@ -0,0 +1,348 @@
+/**
+ * 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 <string.h>
+
+#include "sysflash/sysflash.h"
+
+#include "os/os.h"
+#include "mfg/mfg.h"
+
+/**
+ * The "manufacturing meta region" is located at the end of the boot loader
+ * flash area.  This region has the following structure.
+ *
+ *  0                   1                   2                   3
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |Version (0x01) |                  0xff padding                 |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |   TLV type    |   TLV size    | TLV data ("TLV size" bytes)   ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               ~
+ * ~                                                               ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |   TLV type    |   TLV size    | TLV data ("TLV size" bytes)   ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               ~
+ * ~                                                               ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |   Region size                 |         0xff padding          |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                       Magic (0x3bb2a269)                      |
+ * +-+-+-+-+-+--+-+-+-+-end of boot loader area+-+-+-+-+-+-+-+-+-+-+
+ *
+ * The number of TLVs is variable; two are shown above for illustrative
+ * purposes.
+ *
+ * Fields:
+ * <Header>
+ * 1. Version: Manufacturing meta version number; always 0x01.
+ *
+ * <TLVs>
+ * 2. TLV type: Indicates the type of data to follow.
+ * 3. TLV size: The number of bytes of data to follow.
+ * 4. TLV data: "TLV size" bytes of data.
+ *
+ * <Footer>
+ * 5. Region size: The size, in bytes, of the entire manufacturing meta region;
+ *    includes header, TLVs, and footer.
+ * 6. Magic: indicates the presence of the manufacturing meta region.
+ */
+
+#define MFG_META_MAGIC          0x3bb2a269
+#define MFG_META_HEADER_SZ      4
+#define MFG_META_FOOTER_SZ      8
+#define MFG_META_TLV_SZ         2
+#define MFG_META_FLASH_AREA_SZ  12
+
+struct {
+    uint8_t valid:1;
+    uint32_t off;
+    uint32_t size;
+} mfg_state;
+
+struct mfg_meta_header {
+    uint8_t version;
+    uint8_t pad8;
+    uint16_t pad16;
+};
+
+struct mfg_meta_footer {
+    uint16_t size;
+    uint16_t pad16;
+    uint32_t magic;
+};
+
+_Static_assert(sizeof (struct mfg_meta_header) == MFG_META_HEADER_SZ,
+               "mfg_meta_header must be 4 bytes");
+_Static_assert(sizeof (struct mfg_meta_footer) == MFG_META_FOOTER_SZ,
+               "mfg_meta_footer must be 8 bytes");
+_Static_assert(sizeof (struct mfg_meta_flash_area) == MFG_META_FLASH_AREA_SZ,
+               "mfg_meta_flash_area must be 12 bytes");
+
+/**
+ * Retrieves a TLV header from the mfg meta region.  To request the first TLV
+ * in the region, specify an offset of 0.  To request a subsequent TLV, specify
+ * the values retrieved by the previous call to this function.
+ *
+ * @param tlv (in / out)        Input: The previously-read TLV header; not used
+ *                                  as input when requesting the first TLV.
+ *                              Output: On success, the requested TLV header
+ *                                  gets written here.
+ * @param off (in / out)        Input: The flash-area-offset of the previously
+ *                                  read TLV header; 0 when requesting the
+ *                                  first TLV.
+ *                              Output: On success, the flash-area-offset of
+ *                                  the retrieved TLV header.
+ *
+ * @return                      0 if a TLV header was successfully retrieved;
+ *                              MFG_EDONE if there are no additional TLVs to
+ *                                  read;
+ *                              Other MFG error code on failure.
+ */
+int
+mfg_next_tlv(struct mfg_meta_tlv *tlv, uint32_t *off)
+{
+    const struct flash_area *fap;
+    int rc;
+
+    if (!mfg_state.valid) {
+        return MFG_EUNINIT;
+    }
+
+    rc = flash_area_open(FLASH_AREA_BOOTLOADER, &fap);
+    if (rc != 0) {
+        rc = MFG_EFLASH;
+        goto done;
+    }
+
+    if (*off == 0) {
+        *off = mfg_state.off + MFG_META_HEADER_SZ;
+    } else {
+        /* Advance past current TLV. */
+        *off += MFG_META_TLV_SZ + tlv->size;
+    }
+
+    if (*off + MFG_META_FOOTER_SZ >= fap->fa_size) {
+        /* Reached end of boot area; no more TLVs. */
+        return MFG_EDONE;
+    }
+
+    /* Read next TLV. */
+    memset(tlv, 0, sizeof *tlv);
+    rc = flash_area_read(fap, *off, tlv, MFG_META_TLV_SZ);
+    if (rc != 0) {
+        rc = MFG_EFLASH;
+        goto done;
+    }
+
+    rc = 0;
+
+done:
+    flash_area_close(fap);
+    return rc;
+}
+
+/**
+ * Retrieves a TLV header of the specified type from the mfg meta region.  To
+ * request the first TLV in the region, specify an offset of 0.  To request a
+ * subsequent TLV, specify the values retrieved by the previous call to this
+ * function.
+ *
+ * @param tlv (in / out)        Input: The previously-read TLV header; not used
+ *                                  as input when requesting the first TLV.
+ *                              Output: On success, the requested TLV header
+ *                                  gets written here.
+ * @param off (in / out)        Input: The flash-area-offset of the previously
+ *                                  read TLV header; 0 when requesting the
+ *                                  first TLV.
+ *                              Output: On success, the flash-area-offset of
+ *                                  the retrieved TLV header.
+ * @param type                  The type of TLV to retrieve; one of the
+ *                                  MFG_META_TLV_TYPE_[...] constants.
+ *
+ * @return                      0 if a TLV header was successfully retrieved;
+ *                              MFG_EDONE if there are no additional TLVs of
+ *                                  the specified type to read;
+ *                              Other MFG error code on failure.
+ */
+int
+mfg_next_tlv_with_type(struct mfg_meta_tlv *tlv, uint32_t *off, uint8_t type)
+{
+    int rc;
+
+    while (1) {
+        rc = mfg_next_tlv(tlv, off);
+        if (rc != 0) {
+            break;
+        }
+
+        if (tlv->type == type) {
+            break;
+        }
+
+        /* Proceed to next TLV. */
+    }
+
+    return rc;
+}
+
+/**
+ * Reads a flash-area TLV from the manufacturing meta region.  This function
+ * should only be called after a TLV has been identified as having the
+ * MFG_META_TLV_TYPE_FLASH_AREA type.
+ *
+ * @param tlv                   The header of the TLV to read.  This header
+ *                                  should have been retrieved via a call to
+ *                                  mfg_next_tlv() or mfg_next_tlv_with_type().
+ * @param off                   The flash-area-offset of the TLV header.  Note:
+ *                                  this is the offset of the TLV header, not
+ *                                  the TLV data.
+ * @param out_mfa (out)         On success, the retrieved flash area
+ *                                  information gets written here.
+ *
+ * @return                      0 on success; MFG error code on failure.
+ */
+int
+mfg_read_tlv_flash_area(const struct mfg_meta_tlv *tlv, uint32_t off,
+                        struct mfg_meta_flash_area *out_mfa)
+{
+    const struct flash_area *fap;
+    int read_sz;
+    int rc;
+
+    rc = flash_area_open(FLASH_AREA_BOOTLOADER, &fap);
+    if (rc != 0) {
+        rc = MFG_EFLASH;
+        goto done;
+    }
+
+    memset(out_mfa, 0, sizeof *out_mfa);
+
+    read_sz = min(MFG_META_FLASH_AREA_SZ, tlv->size);
+    rc = flash_area_read(fap, off + MFG_META_TLV_SZ, out_mfa, read_sz);
+    if (rc != 0) {
+        rc = MFG_EFLASH;
+        goto done;
+    }
+
+    rc = 0;
+
+done:
+    flash_area_close(fap);
+    return rc;
+}
+
+/**
+ * Reads a hash TLV from the manufacturing meta region.  This function should
+ * only be called after a TLV has been identified as having the
+ * MFG_META_TLV_TYPE_HASH type.
+ *
+ * @param tlv                   The header of the TLV to read.  This header
+ *                                  should have been retrieved via a call to
+ *                                  mfg_next_tlv() or mfg_next_tlv_with_type().
+ * @param off                   The flash-area-offset of the TLV header.  Note:
+ *                                  this is the offset of the TLV header, not
+ *                                  the TLV data.
+ * @param out_hash (out)        On success, the retrieved SHA256 hash gets
+ *                                  written here.  This buffer must be at least
+ *                                  32 bytes wide.
+ *
+ * @return                      0 on success; MFG error code on failure.
+ */
+int
+mfg_read_tlv_hash(const struct mfg_meta_tlv *tlv, uint32_t off, void *out_hash)
+{
+    const struct flash_area *fap;
+    int read_sz;
+    int rc;
+
+    rc = flash_area_open(FLASH_AREA_BOOTLOADER, &fap);
+    if (rc != 0) {
+        rc = MFG_EFLASH;
+        goto done;
+    }
+
+    read_sz = min(MFG_HASH_SZ, tlv->size);
+    rc = flash_area_read(fap, off + MFG_META_TLV_SZ, out_hash, read_sz);
+    if (rc != 0) {
+        rc = MFG_EFLASH;
+        goto done;
+    }
+
+    rc = 0;
+
+done:
+    flash_area_close(fap);
+    return rc;
+}
+
+/**
+ * Locates the manufacturing meta region in flash.  This function must be
+ * called before any TLVs can be read.  No-op if this function has already
+ * executed successfully.
+ *
+ * @return                      0 on success; MFG error code on failure.
+ */
+int
+mfg_init(void)
+{
+    const struct flash_area *fap;
+    struct mfg_meta_footer ftr;
+    uint16_t off;
+    int rc;
+
+    if (mfg_state.valid) {
+        /* Already initialized. */
+        return 0;
+    }
+
+    mfg_state.valid = 0;
+
+    rc = flash_area_open(FLASH_AREA_BOOTLOADER, &fap);
+    if (rc != 0) {
+        rc = MFG_EFLASH;
+        goto done;
+    }
+
+    off = fap->fa_size - sizeof ftr;
+    rc = flash_area_read(fap, off, &ftr, sizeof ftr);
+    if (rc != 0) {
+        rc = MFG_EFLASH;
+        goto done;
+    }
+
+    if (ftr.magic != MFG_META_MAGIC) {
+        rc = MFG_EBADDATA;
+        goto done;
+    }
+    if (ftr.size > fap->fa_size) {
+        rc = MFG_EBADDATA;
+        goto done;
+    }
+
+    mfg_state.valid = 1;
+    mfg_state.off = fap->fa_size - ftr.size;
+    mfg_state.size = ftr.size;
+
+    rc = 0;
+
+done:
+    flash_area_close(fap);
+    return rc;
+}