Merge pull request #1 from ccollins476ad/verify

Add "verify" functionality
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..21e99b0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,23 @@
+#
+# 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.
+#
+
+*.swp
+*.swo
+*~
+tags
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..c4c0480
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,311 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright {yyyy} {name of copyright owner}
+
+   Licensed 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.
+
+This product bundles pretty, which is available under the MIT license.  For
+details, see:
+     * newt/vendor/github.com/kr/pretty/License
+     * newtmgr/vendor/github.com/kr/pretty/License
+
+This product bundles kr/text, which is available under the MIT license.  For
+details, see:
+     * newt/vendor/github.com/kr/text/License
+     * newtmgr/vendor/github.com/kr/text/License
+
+This product bundles mapstructure, which is available under the MIT license.
+For details, see:
+    * newt/vendor/github.com/mitchellh/mapstructure/LICENSE
+    * newtmgr/vendor/github.com/mitchellh/mapstructure/LICENSE
+
+This product bundles logrus, which is available under the MIT license.  For
+details, see:
+    * newt/vendor/github.com/sirupsen/logrus/LICENSE
+    * newtmgr/vendor/github.com/sirupsen/logrus/LICENSE
+
+This product bundles Cast, which is available under the MIT license.  For
+details, see:
+    * newt/vendor/github.com/spf13/cast/LICENSE
+    * newtmgr/vendor/github.com/spf13/cast/LICENSE
+
+This product bundles jWalterWeatherman, which is available under the MIT
+license.  For details, see:
+    * newt/vendor/github.com/spf13/jwalterweatherman/LICENSE
+    * newtmgr/vendor/github.com/spf13/jwalterweatherman/LICENSE
+
+This product bundles pflag, which is available under the "3-clause BSD"
+license.  For details, see:
+    * newt/vendor/github.com/spf13/pflag/LICENSE
+    * newtmgr/vendor/github.com/spf13/pflag/LICENSE
+
+This product bundles the unix Go package, which is available under the
+"3-clause BSD" license.  For details, see:
+    * newt/vendor/golang.org/x/sys/LICENSE
+    * newtmgr/vendor/golang.org/x/sys/LICENSE
+
+This product bundles fsnotify.v1, which is available under the "3-clause BSD"
+license.  For details, see:
+    * newt/vendor/gopkg.in/fsnotify.v1/LICENSE
+    * newtmgr/vendor/gopkg.in/fsnotify.v1/LICENSE
+
+This product bundles yaml.v2's Go port of libyaml, which is available under the
+MIT license.  For details, see:
+    * newt/vendor/mynewt.apache.org/newt/yaml/apic.go
+    * newt/vendor/mynewt.apache.org/newt/yaml/emitterc.go
+    * newt/vendor/mynewt.apache.org/newt/yaml/parserc.go
+    * newt/vendor/mynewt.apache.org/newt/yaml/readerc.go
+    * newt/vendor/mynewt.apache.org/newt/yaml/scannerc.go
+    * newt/vendor/mynewt.apache.org/newt/yaml/writerc.go
+    * newt/vendor/mynewt.apache.org/newt/yaml/yamlh.go
+    * newt/vendor/mynewt.apache.org/newt/yaml/yamlprivateh.go
+    * newtmgr/vendor/mynewt.apache.org/newt/yaml/apic.go
+    * newtmgr/vendor/mynewt.apache.org/newt/yaml/emitterc.go
+    * newtmgr/vendor/mynewt.apache.org/newt/yaml/parserc.go
+    * newtmgr/vendor/mynewt.apache.org/newt/yaml/readerc.go
+    * newtmgr/vendor/mynewt.apache.org/newt/yaml/scannerc.go
+    * newtmgr/vendor/mynewt.apache.org/newt/yaml/writerc.go
+    * newtmgr/vendor/mynewt.apache.org/newt/yaml/yamlh.go
+    * newtmgr/vendor/mynewt.apache.org/newt/yaml/yamlprivateh.go
+    * yaml/apic.go
+    * yaml/emitterc.go
+    * yaml/parserc.go
+    * yaml/readerc.go
+    * yaml/scannerc.go
+    * yaml/writerc.go
+    * yaml/yamlh.go
+    * yaml/yamlprivateh.go
+
+This product bundles viper, which is available under the MIT license.  For
+details, see:
+    * newt/vendor/mynewt.apache.org/newt/viper/LICENSE
+    * newtmgr/vendor/mynewt.apache.org/newt/viper/LICENSE
+    * viper/LICENSE
+
+This product bundles go-crc16, which is available under the MIT license.  For
+details, see:
+    * newtmgr/vendor/github.com/joaojeronimo/go-crc16/README.md
+
+This product bundles GATT, which is available under the "3-clause BSD" license.
+For details, see:
+    * newtmgr/vendor/github.com/runtimeinc/gatt
+
+This product bundles xpc, which is available under the MIT license.  For
+details, see:
+    * newtmgr/vendor/github.com/runtimeinc/gatt/xpc/LICENSE
+
+This product bundles gioctl, which is available under the MIT license.  For
+details, see:
+    * newtmgr/vendor/github.com/runtimeinc/gatt/linux/gioctl/LICENSE.md
+
+This product bundles tarm/serial, which is available under the "3-clause BSD"
+license.  For details, see:
+    * newtmgr/vendor/github.com/tarm/serial/LICENSE
+
+This product bundles ugorji/go/codec, which is available under the MIT license.
+For details, see:
+    * newtmgr/vendor/github.com/ugorji/go/LICENSE
+
+This product bundles go-coap which is available under the MIT license.
+For details, see:
+    * newtmgr/vendor/github.com/dustin/go-coap/LICENSE
+
+This product bundles go-homedir which is available under the MIT license.
+For details, see:
+    * newtmgr/vendor/github.com/mitchellh/go-homedir/LICENSE
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..410dec9
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,8 @@
+Apache Mynewt
+Copyright 2015-2019 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+Portions of this software were developed at
+Runtime Inc, copyright 2015.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..4e64803
--- /dev/null
+++ b/README.md
@@ -0,0 +1,28 @@
+<!--
+#
+# 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.
+#
+-->
+
+# Mynewt Artifact
+
+Apache Mynewt Artifact is a Go library that parses, manipulates, validates, and outputs Mynewt artifacts.  Supported artifacts are:
+* Images
+* Image manifests
+* Manufacturing images (mfgimages)
+* Manufacturing manifests
diff --git a/errors/errors.go b/errors/errors.go
new file mode 100644
index 0000000..34113a2
--- /dev/null
+++ b/errors/errors.go
@@ -0,0 +1,92 @@
+/**
+ * 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.
+ */
+
+// This is a thin wrapper over the `pkg/errors` package.  It decorates the
+// base package with the following functionality:
+//
+// 1. Wrap and Wrapf produce an error with exactly one stack trace.  If the
+// wrapped error already contains a stack trace, these functions just append
+// text to the message.
+//
+// 2. WithStack produces an error with exactly one stack trace.  If the
+// wrapped error already contains a stack trace, this function returns it
+// unmodified.
+
+package errors
+
+import (
+	"fmt"
+
+	pkgerrors "github.com/pkg/errors"
+)
+
+type stackTracer interface {
+	StackTrace() pkgerrors.StackTrace
+}
+
+// Cause retrieves the underlying cause of an error
+func Cause(err error) error {
+	return pkgerrors.Cause(err)
+}
+
+// Errorf formats according to a format specifier and returns the string
+// as a value that satisfies error.
+// Errorf also records the stack trace at the point it was called.
+func Errorf(format string, args ...interface{}) error {
+	return pkgerrors.Errorf(format, args...)
+}
+
+// New returns an error with the supplied message.
+// New also records the stack trace at the point it was called.
+func New(message string) error {
+	return pkgerrors.New(message)
+}
+
+// Wrap returns an error annotating err with a stack trace at the point Wrap is
+// called, and the supplied message.  If err is nil, Wrap returns nil.
+func Wrap(err error, message string) error {
+	if _, ok := err.(stackTracer); !ok {
+		return pkgerrors.Wrap(err, message)
+	} else {
+		msg := err.Error() + ": " + message
+		return pkgerrors.WithMessage(err, msg)
+	}
+}
+
+// Wrapf returns an error annotating err with a stack trace at the point Wrapf
+// is called, and the format specifier.  If err is nil, Wrapf returns nil.
+func Wrapf(err error, format string, args ...interface{}) error {
+	return Wrap(err, fmt.Sprintf(format, args...))
+}
+
+// WithStack annotates err with a stack trace at the point WithStack was called.
+// If err is nil, WithStack returns nil.
+func WithStack(err error) error {
+	if _, ok := err.(stackTracer); !ok {
+		return pkgerrors.WithStack(err)
+	} else {
+		return err
+	}
+}
+
+// HasStackTrace tells you if the given error contains a stack trace.
+func HasStackTrace(err error) bool {
+	_, ok := err.(stackTracer)
+	return ok
+}
diff --git a/flash/flash.go b/flash/flash.go
index 6b85814..5903fb2 100644
--- a/flash/flash.go
+++ b/flash/flash.go
@@ -99,6 +99,10 @@
 }
 
 func areasDistinct(a FlashArea, b FlashArea) bool {
+	if a.Device != b.Device {
+		return true
+	}
+
 	var lo FlashArea
 	var hi FlashArea
 
@@ -110,7 +114,7 @@
 		hi = a
 	}
 
-	return lo.Device != hi.Device || lo.Offset+lo.Size <= hi.Offset
+	return lo.Offset+lo.Size <= hi.Offset
 }
 
 // @return overlapping-areas, id-conflicts.
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..57b20e8
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,10 @@
+module github.com/apache/mynewt-artifact
+
+go 1.12
+
+require (
+	github.com/NickBall/go-aes-key-wrap v0.0.0-20170929221519-1c3aa3e4dfc5
+	github.com/pkg/errors v0.8.1
+	github.com/stretchr/testify v1.3.0 // indirect
+	golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443
+)
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..ec754ba
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,19 @@
+github.com/NickBall/go-aes-key-wrap v0.0.0-20170929221519-1c3aa3e4dfc5 h1:5BIUS5hwyLM298mOf8e8TEgD3cCYqc86uaJdQCYZo/o=
+github.com/NickBall/go-aes-key-wrap v0.0.0-20170929221519-1c3aa3e4dfc5/go.mod h1:w5D10RxC0NmPYxmQ438CC1S07zaC1zpvuNW7s5sUk2Q=
+github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443 h1:IcSOAf4PyMp3U3XbIEj1/xJ2BjNN2jWv7JoyOsMxXUU=
+golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
diff --git a/image/create.go b/image/create.go
index cbbc410..f51d77b 100644
--- a/image/create.go
+++ b/image/create.go
@@ -28,12 +28,11 @@
 	"crypto/sha256"
 	"encoding/asn1"
 	"encoding/binary"
-	"encoding/hex"
 	"io/ioutil"
 	"math/big"
 
-	"mynewt.apache.org/newt/artifact/sec"
-	"mynewt.apache.org/newt/util"
+	"github.com/apache/mynewt-artifact/errors"
+	"github.com/apache/mynewt-artifact/sec"
 )
 
 type ImageCreator struct {
@@ -100,7 +99,7 @@
 	} else if len(cipherSecret) == 24 {
 		encType = IMAGE_TLV_ENC_KEK
 	} else {
-		return ImageTlv{}, util.FmtNewtError("Invalid enc TLV size ")
+		return ImageTlv{}, errors.Errorf("invalid enc TLV size: %d", len(cipherSecret))
 	}
 
 	return ImageTlv{
@@ -120,7 +119,7 @@
 	signature, err := rsa.SignPSS(
 		rand.Reader, key.Rsa, crypto.SHA256, hash, &opts)
 	if err != nil {
-		return nil, util.FmtNewtError("Failed to compute signature: %s", err)
+		return nil, errors.Wrapf(err, "failed to compute signature")
 	}
 
 	return signature, nil
@@ -129,7 +128,7 @@
 func GenerateSigEc(key sec.SignKey, hash []byte) ([]byte, error) {
 	r, s, err := ecdsa.Sign(rand.Reader, key.Ec, hash)
 	if err != nil {
-		return nil, util.FmtNewtError("Failed to compute signature: %s", err)
+		return nil, errors.Wrapf(err, "failed to compute signature")
 	}
 
 	ECDSA := ECDSASig{
@@ -139,12 +138,12 @@
 
 	signature, err := asn1.Marshal(ECDSA)
 	if err != nil {
-		return nil, util.FmtNewtError("Failed to construct signature: %s", err)
+		return nil, errors.Wrapf(err, "failed to construct signature")
 	}
 
 	sigLen := key.SigLen()
 	if len(signature) > int(sigLen) {
-		return nil, util.FmtNewtError("Something is really wrong\n")
+		return nil, errors.Errorf("signature truncated")
 	}
 
 	pad := make([]byte, int(sigLen)-len(signature))
@@ -210,8 +209,7 @@
 func GeneratePlainSecret() ([]byte, error) {
 	plainSecret := make([]byte, 16)
 	if _, err := rand.Read(plainSecret); err != nil {
-		return nil, util.FmtNewtError(
-			"Random generation error: %s\n", err)
+		return nil, errors.Wrapf(err, "random generation error")
 	}
 
 	return plainSecret, nil
@@ -238,7 +236,7 @@
 		return sec.EncryptSecretAes(aesPubKe, plainSecret)
 	}
 
-	return nil, util.FmtNewtError("Invalid image-crypt key")
+	return nil, errors.Errorf("invalid image-crypt key")
 }
 
 func GenerateImage(opts ImageCreateOpts) (Image, error) {
@@ -246,8 +244,7 @@
 
 	srcBin, err := ioutil.ReadFile(opts.SrcBinFilename)
 	if err != nil {
-		return Image{}, util.FmtNewtError(
-			"Can't read app binary: %s", err.Error())
+		return Image{}, errors.Wrapf(err, "Can't read app binary")
 	}
 
 	ic.Body = srcBin
@@ -269,8 +266,7 @@
 
 		pubKeBytes, err := ioutil.ReadFile(opts.SrcEncKeyFilename)
 		if err != nil {
-			return Image{}, util.FmtNewtError(
-				"Error reading pubkey file: %s", err.Error())
+			return Image{}, errors.Wrapf(err, "error reading pubkey file")
 		}
 
 		cipherSecret, err := GenerateCipherSecret(pubKeBytes, plainSecret)
@@ -301,7 +297,7 @@
 			return err
 		}
 		if err := binary.Write(hash, binary.LittleEndian, itf); err != nil {
-			return util.FmtNewtError("Failed to hash data: %s", err.Error())
+			return errors.Wrapf(err, "failed to hash data")
 		}
 
 		return nil
@@ -364,8 +360,8 @@
 		// between the header and the start of the image when it is padded.
 		extra := ic.HeaderSize - IMAGE_HEADER_SIZE
 		if extra < 0 {
-			return img, util.FmtNewtError("Image header must be at "+
-				"least %d bytes", IMAGE_HEADER_SIZE)
+			return img, errors.Errorf(
+				"image header must be at least %d bytes", IMAGE_HEADER_SIZE)
 		}
 
 		img.Header.HdrSz = uint16(ic.HeaderSize)
@@ -388,9 +384,6 @@
 		img.Body = append(img.Body, ic.Body...)
 	}
 
-	util.StatusMessage(util.VERBOSITY_VERBOSE,
-		"Computed Hash for image as %s\n", hex.EncodeToString(hashBytes))
-
 	// Hash TLV.
 	tlv := ImageTlv{
 		Header: ImageTlvHdr{
diff --git a/image/image.go b/image/image.go
index 9855223..7289f52 100644
--- a/image/image.go
+++ b/image/image.go
@@ -20,18 +20,14 @@
 package image
 
 import (
-	"bytes"
 	"encoding/binary"
-	"encoding/hex"
-	"encoding/json"
 	"fmt"
 	"io"
 	"io/ioutil"
 	"os"
-	"strconv"
-	"strings"
 
-	"mynewt.apache.org/newt/util"
+	"github.com/apache/mynewt-artifact/errors"
+	"github.com/apache/mynewt-artifact/sec"
 )
 
 const (
@@ -128,6 +124,11 @@
 	TotalSize int
 }
 
+func ImageTlvTypeIsValid(tlvType uint8) bool {
+	_, ok := imageTlvTypeNameMap[tlvType]
+	return ok
+}
+
 func ImageTlvTypeName(tlvType uint8) string {
 	name, ok := imageTlvTypeNameMap[tlvType]
 	if !ok {
@@ -144,163 +145,72 @@
 		tlvType == IMAGE_TLV_ECDSA256
 }
 
-func ParseVersion(versStr string) (ImageVersion, error) {
-	var err error
-	var major uint64
-	var minor uint64
-	var rev uint64
-	var buildNum uint64
-	var ver ImageVersion
-
-	components := strings.Split(versStr, ".")
-	major, err = strconv.ParseUint(components[0], 10, 8)
-	if err != nil {
-		return ver, util.FmtNewtError("Invalid version string %s", versStr)
-	}
-	if len(components) > 1 {
-		minor, err = strconv.ParseUint(components[1], 10, 8)
-		if err != nil {
-			return ver, util.FmtNewtError("Invalid version string %s", versStr)
-		}
-	}
-	if len(components) > 2 {
-		rev, err = strconv.ParseUint(components[2], 10, 16)
-		if err != nil {
-			return ver, util.FmtNewtError("Invalid version string %s", versStr)
-		}
-	}
-	if len(components) > 3 {
-		buildNum, err = strconv.ParseUint(components[3], 10, 32)
-		if err != nil {
-			return ver, util.FmtNewtError("Invalid version string %s", versStr)
-		}
-	}
-
-	ver.Major = uint8(major)
-	ver.Minor = uint8(minor)
-	ver.Rev = uint16(rev)
-	ver.BuildNum = uint32(buildNum)
-	return ver, nil
-}
-
 func (ver ImageVersion) String() string {
 	return fmt.Sprintf("%d.%d.%d.%d",
 		ver.Major, ver.Minor, ver.Rev, ver.BuildNum)
 }
 
-func (h *ImageHdr) Map(offset int) map[string]interface{} {
-	return map[string]interface{}{
-		"magic":   h.Magic,
-		"hdr_sz":  h.HdrSz,
-		"img_sz":  h.ImgSz,
-		"flags":   h.Flags,
-		"vers":    h.Vers.String(),
-		"_offset": offset,
-	}
-}
-
-func rawBodyMap(offset int) map[string]interface{} {
-	return map[string]interface{}{
-		"_offset": offset,
-	}
-}
-
-func (t *ImageTrailer) Map(offset int) map[string]interface{} {
-	return map[string]interface{}{
-		"magic":       t.Magic,
-		"tlv_tot_len": t.TlvTotLen,
-		"_offset":     offset,
-	}
-}
-
-func (t *ImageTlv) Map(offset int) map[string]interface{} {
-	return map[string]interface{}{
-		"type":     t.Header.Type,
-		"len":      t.Header.Len,
-		"data":     hex.EncodeToString(t.Data),
-		"_typestr": ImageTlvTypeName(t.Header.Type),
-		"_offset":  offset,
-	}
-}
-
-func (img *Image) Map() (map[string]interface{}, error) {
-	offs, err := img.Offsets()
-	if err != nil {
-		return nil, err
-	}
-
-	m := map[string]interface{}{}
-	m["header"] = img.Header.Map(offs.Header)
-	m["body"] = rawBodyMap(offs.Body)
-	trailer := img.Trailer()
-	m["trailer"] = trailer.Map(offs.Trailer)
-
-	tlvMaps := []map[string]interface{}{}
-	for i, tlv := range img.Tlvs {
-		tlvMaps = append(tlvMaps, tlv.Map(offs.Tlvs[i]))
-	}
-	m["tlvs"] = tlvMaps
-
-	return m, nil
-}
-
-func (img *Image) Json() (string, error) {
-	m, err := img.Map()
-	if err != nil {
-		return "", err
-	}
-
-	b, err := json.MarshalIndent(m, "", "    ")
-	if err != nil {
-		return "", util.ChildNewtError(err)
-	}
-
-	return string(b), nil
-}
-
 func (tlv *ImageTlv) Write(w io.Writer) (int, error) {
 	totalSize := 0
 
 	err := binary.Write(w, binary.LittleEndian, &tlv.Header)
 	if err != nil {
-		return totalSize, util.ChildNewtError(err)
+		return totalSize, errors.Wrapf(err, "failed to write image TLV header")
 	}
 	totalSize += IMAGE_TLV_SIZE
 
 	size, err := w.Write(tlv.Data)
 	if err != nil {
-		return totalSize, util.ChildNewtError(err)
+		return totalSize, errors.Wrapf(err, "failed to write image TLV data")
 	}
 	totalSize += size
 
 	return totalSize, nil
 }
 
-func (i *Image) FindTlvs(tlvType uint8) []ImageTlv {
-	var tlvs []ImageTlv
+// FindTlvIndices searches an image for TLVs of the specified type and
+// returns their indices.
+func (i *Image) FindTlvIndices(tlvType uint8) []int {
+	var idxs []int
 
-	for _, tlv := range i.Tlvs {
+	for i, tlv := range i.Tlvs {
 		if tlv.Header.Type == tlvType {
-			tlvs = append(tlvs, tlv)
+			idxs = append(idxs, i)
 		}
 	}
 
+	return idxs
+}
+
+// FindTlvs retrieves all TLVs in an image's footer with the specified type.
+func (i *Image) FindTlvs(tlvType uint8) []*ImageTlv {
+	var tlvs []*ImageTlv
+
+	idxs := i.FindTlvIndices(tlvType)
+	for _, idx := range idxs {
+		tlvs = append(tlvs, &i.Tlvs[idx])
+	}
+
 	return tlvs
 }
 
+// FindUniqueTlv retrieves a TLV in an image's footer with the specified
+// type.  It returns an error if there is more than one TLV with this type.
 func (i *Image) FindUniqueTlv(tlvType uint8) (*ImageTlv, error) {
 	tlvs := i.FindTlvs(tlvType)
 	if len(tlvs) == 0 {
 		return nil, nil
 	}
 	if len(tlvs) > 1 {
-		return nil, util.FmtNewtError("Image contains %d TLVs with type %d",
+		return nil, errors.Errorf("image contains %d TLVs with type %d",
 			len(tlvs), tlvType)
 	}
 
-	return &tlvs[0], nil
+	return tlvs[0], nil
 }
 
+// RemoveTlvsIf removes all TLVs from an image that satisfy the supplied
+// predicate.  It returns a slice of the removed TLVs.
 func (i *Image) RemoveTlvsIf(pred func(tlv ImageTlv) bool) []ImageTlv {
 	rmed := []ImageTlv{}
 
@@ -317,12 +227,15 @@
 	return rmed
 }
 
+// RemoveTlvsWithType removes from an image all TLVs with the specified type.
+// It returns a slice of the removed TLVs.
 func (i *Image) RemoveTlvsWithType(tlvType uint8) []ImageTlv {
 	return i.RemoveTlvsIf(func(tlv ImageTlv) bool {
 		return tlv.Header.Type == tlvType
 	})
 }
 
+// ImageTrailer constructs an image trailer corresponding to the given image.
 func (img *Image) Trailer() ImageTrailer {
 	trailer := ImageTrailer{
 		Magic:     IMAGE_TRAILER_MAGIC,
@@ -335,23 +248,28 @@
 	return trailer
 }
 
+// Hash retrieves the contents of an image's SHA256 TLV.
 func (i *Image) Hash() ([]byte, error) {
 	tlv, err := i.FindUniqueTlv(IMAGE_TLV_SHA256)
 	if err != nil {
-		return nil, err
+		return nil, errors.Wrapf(err, "failed to retrieve image hash")
 	}
 
 	if tlv == nil {
-		return nil, util.FmtNewtError("Image does not contain hash TLV")
+		return nil, errors.Errorf(
+			"failed to retrieve image hash: image does not contain hash TLV")
 	}
 
 	return tlv.Data, nil
 }
 
+// CalcHash calculates a SHA256 of the given image.
 func (i *Image) CalcHash() ([]byte, error) {
 	return calcHash(nil, i.Header, i.Pad, i.Body)
 }
 
+// WritePlusOffsets writes a binary image to the given writer.  It returns
+// the offsets of the image components that got written.
 func (i *Image) WritePlusOffsets(w io.Writer) (ImageOffsets, error) {
 	offs := ImageOffsets{}
 	offset := 0
@@ -360,20 +278,20 @@
 
 	err := binary.Write(w, binary.LittleEndian, &i.Header)
 	if err != nil {
-		return offs, util.ChildNewtError(err)
+		return offs, errors.Wrapf(err, "failed to write image header")
 	}
 	offset += IMAGE_HEADER_SIZE
 
 	err = binary.Write(w, binary.LittleEndian, i.Pad)
 	if err != nil {
-		return offs, util.ChildNewtError(err)
+		return offs, errors.Wrapf(err, "failed to write image padding")
 	}
 	offset += len(i.Pad)
 
 	offs.Body = offset
 	size, err := w.Write(i.Body)
 	if err != nil {
-		return offs, util.ChildNewtError(err)
+		return offs, errors.Wrapf(err, "failed to write image body")
 	}
 	offset += size
 
@@ -381,7 +299,7 @@
 	offs.Trailer = offset
 	err = binary.Write(w, binary.LittleEndian, &trailer)
 	if err != nil {
-		return offs, util.ChildNewtError(err)
+		return offs, errors.Wrapf(err, "failed to write image trailer")
 	}
 	offset += IMAGE_TRAILER_SIZE
 
@@ -389,7 +307,7 @@
 		offs.Tlvs = append(offs.Tlvs, offset)
 		size, err := tlv.Write(w)
 		if err != nil {
-			return offs, util.ChildNewtError(err)
+			return offs, errors.Wrapf(err, "failed to write image TLV")
 		}
 		offset += size
 	}
@@ -399,10 +317,13 @@
 	return offs, nil
 }
 
+// Offsets returns the offsets of each of an image's components if it were
+// serialized.
 func (i *Image) Offsets() (ImageOffsets, error) {
 	return i.WritePlusOffsets(ioutil.Discard)
 }
 
+// TotalSize returns the size of the image if it were serialized, in bytes.
 func (i *Image) TotalSize() (int, error) {
 	offs, err := i.Offsets()
 	if err != nil {
@@ -411,6 +332,7 @@
 	return offs.TotalSize, nil
 }
 
+// Write serializes and writes a Mynewt image.
 func (i *Image) Write(w io.Writer) (int, error) {
 	offs, err := i.WritePlusOffsets(w)
 	if err != nil {
@@ -420,152 +342,49 @@
 	return offs.TotalSize, nil
 }
 
+// WriteToFile writes a Mynewt image to a file.
 func (i *Image) WriteToFile(filename string) error {
 	f, err := os.OpenFile(filename, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
 	if err != nil {
-		return util.ChildNewtError(err)
+		return errors.Wrapf(err, "failed to open image destination file")
 	}
 
 	if _, err := i.Write(f); err != nil {
-		return util.ChildNewtError(err)
+		return errors.Wrapf(err, "failed to write image")
 	}
 
 	return nil
 }
 
-func parseRawHeader(imgData []byte, offset int) (ImageHdr, int, error) {
-	var hdr ImageHdr
+// CollectSigs returns a slice of all signatures present in an image's
+// trailer.
+func (img *Image) CollectSigs() ([]sec.Sig, error) {
+	var sigs []sec.Sig
 
-	r := bytes.NewReader(imgData)
-	r.Seek(int64(offset), io.SeekStart)
+	var keyHashTlv *ImageTlv
+	for i, _ := range img.Tlvs {
+		t := &img.Tlvs[i]
 
-	if err := binary.Read(r, binary.LittleEndian, &hdr); err != nil {
-		return hdr, 0, util.FmtNewtError(
-			"Error reading image header: %s", err.Error())
-	}
+		if t.Header.Type == IMAGE_TLV_KEYHASH {
+			if keyHashTlv != nil {
+				return nil, errors.Errorf(
+					"image contains keyhash tlv without subsequent signature")
+			}
+			keyHashTlv = t
+		} else if ImageTlvTypeIsSig(t.Header.Type) {
+			if keyHashTlv == nil {
+				return nil, errors.Errorf(
+					"image contains signature tlv without preceding keyhash")
+			}
 
-	if hdr.Magic != IMAGE_MAGIC {
-		return hdr, 0, util.FmtNewtError(
-			"Image magic incorrect; expected 0x%08x, got 0x%08x",
-			uint32(IMAGE_MAGIC), hdr.Magic)
-	}
+			sigs = append(sigs, sec.Sig{
+				KeyHash: keyHashTlv.Data,
+				Data:    t.Data,
+			})
 
-	remLen := len(imgData) - offset
-	if remLen < int(hdr.HdrSz) {
-		return hdr, 0, util.FmtNewtError(
-			"Image header incomplete; expected %d bytes, got %d bytes",
-			hdr.HdrSz, remLen)
-	}
-
-	return hdr, int(hdr.HdrSz), nil
-}
-
-func parseRawBody(imgData []byte, hdr ImageHdr,
-	offset int) ([]byte, int, error) {
-
-	imgSz := int(hdr.ImgSz)
-	remLen := len(imgData) - offset
-
-	if remLen < imgSz {
-		return nil, 0, util.FmtNewtError(
-			"Image body incomplete; expected %d bytes, got %d bytes",
-			imgSz, remLen)
-	}
-
-	return imgData[offset : offset+imgSz], imgSz, nil
-}
-
-func parseRawTrailer(imgData []byte, offset int) (ImageTrailer, int, error) {
-	var trailer ImageTrailer
-
-	r := bytes.NewReader(imgData)
-	r.Seek(int64(offset), io.SeekStart)
-
-	if err := binary.Read(r, binary.LittleEndian, &trailer); err != nil {
-		return trailer, 0, util.FmtNewtError(
-			"Image contains invalid trailer at offset %d: %s",
-			offset, err.Error())
-	}
-
-	return trailer, IMAGE_TRAILER_SIZE, nil
-}
-
-func parseRawTlv(imgData []byte, offset int) (ImageTlv, int, error) {
-	tlv := ImageTlv{}
-
-	r := bytes.NewReader(imgData)
-	r.Seek(int64(offset), io.SeekStart)
-
-	if err := binary.Read(r, binary.LittleEndian, &tlv.Header); err != nil {
-		return tlv, 0, util.FmtNewtError(
-			"Image contains invalid TLV at offset %d: %s", offset, err.Error())
-	}
-
-	tlv.Data = make([]byte, tlv.Header.Len)
-	if _, err := r.Read(tlv.Data); err != nil {
-		return tlv, 0, util.FmtNewtError(
-			"Image contains invalid TLV at offset %d: %s", offset, err.Error())
-	}
-
-	return tlv, IMAGE_TLV_SIZE + int(tlv.Header.Len), nil
-}
-
-func ParseImage(imgData []byte) (Image, error) {
-	img := Image{}
-	offset := 0
-
-	hdr, size, err := parseRawHeader(imgData, offset)
-	if err != nil {
-		return img, err
-	}
-	offset += size
-
-	body, size, err := parseRawBody(imgData, hdr, offset)
-	if err != nil {
-		return img, err
-	}
-	offset += size
-
-	trailer, size, err := parseRawTrailer(imgData, offset)
-	if err != nil {
-		return img, err
-	}
-	offset += size
-
-	var tlvs []ImageTlv
-	tlvLen := IMAGE_TRAILER_SIZE
-	for offset < len(imgData) {
-		tlv, size, err := parseRawTlv(imgData, offset)
-		if err != nil {
-			return img, err
+			keyHashTlv = nil
 		}
-
-		tlvs = append(tlvs, tlv)
-		offset += size
-
-		tlvLen += IMAGE_TLV_SIZE + int(tlv.Header.Len)
 	}
 
-	if int(trailer.TlvTotLen) != tlvLen {
-		return img, util.FmtNewtError(
-			"invalid image: trailer indicates TLV-length=%d; actual=%d",
-			trailer.TlvTotLen, tlvLen)
-	}
-
-	img.Header = hdr
-	img.Body = body
-	img.Tlvs = tlvs
-
-	return img, nil
-}
-
-func ReadImage(filename string) (Image, error) {
-	ri := Image{}
-
-	imgData, err := ioutil.ReadFile(filename)
-	if err != nil {
-		return ri, util.ChildNewtError(err)
-	}
-
-	return ParseImage(imgData)
+	return sigs, nil
 }
diff --git a/image/image_test.go b/image/image_test.go
new file mode 100644
index 0000000..83b4295
--- /dev/null
+++ b/image/image_test.go
@@ -0,0 +1,218 @@
+/**
+ * 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.
+ */
+
+package image
+
+import (
+	"fmt"
+	"io/ioutil"
+	"testing"
+
+	"github.com/apache/mynewt-artifact/manifest"
+	"github.com/apache/mynewt-artifact/sec"
+)
+
+const testdataPath = "testdata"
+
+type entry struct {
+	basename  string
+	form      bool
+	integrity bool
+	man       bool
+	sign      bool
+}
+
+func readImageData(basename string) []byte {
+	path := fmt.Sprintf("%s/%s.img", testdataPath, basename)
+
+	data, err := ioutil.ReadFile(path)
+	if err != nil {
+		panic("failed to read image file " + path)
+	}
+
+	return data
+}
+
+func readManifest(basename string) manifest.Manifest {
+	path := fmt.Sprintf("%s/%s.json", testdataPath, basename)
+
+	man, err := manifest.ReadManifest(path)
+	if err != nil {
+		panic("failed to read manifest file " + path)
+	}
+
+	return man
+}
+
+func readPubKey() sec.PubSignKey {
+	path := fmt.Sprintf("%s/sign-key.pem", testdataPath)
+
+	key, err := sec.ReadKey(path)
+	if err != nil {
+		panic("failed to read key file " + path)
+	}
+
+	return key.PubKey()
+}
+
+func testOne(t *testing.T, e entry) {
+	fatalErr := func(field string, have string, want string, err error) {
+		s := fmt.Sprintf("image \"%s\" has unexpected `%s` status: "+
+			"have=%s want=%s", e.basename, field, have, want)
+		if err != nil {
+			s += "; " + err.Error()
+		}
+
+		t.Fatal(s)
+	}
+
+	imgData := readImageData(e.basename)
+
+	img, err := ParseImage(imgData)
+	if !e.form {
+		if err == nil {
+			fatalErr("form", "good", "bad", nil)
+		}
+		return
+	} else {
+		if err != nil {
+			fatalErr("form", "bad", "good", err)
+			return
+		}
+	}
+
+	err = img.Verify()
+	if !e.integrity {
+		if err == nil {
+			fatalErr("integrity", "good", "bad", nil)
+		}
+		return
+	} else {
+		if err != nil {
+			fatalErr("integrity", "bad", "good", err)
+			return
+		}
+	}
+
+	man := readManifest(e.basename)
+
+	err = img.VerifyManifest(man)
+	if !e.man {
+		if err == nil {
+			fatalErr("manifest", "good", "bad", nil)
+		}
+		return
+	} else {
+		if err != nil {
+			fatalErr("manifest", "bad", "good", err)
+			return
+		}
+	}
+
+	key := readPubKey()
+
+	sigs, err := img.CollectSigs()
+	if err != nil {
+		t.Fatalf("failed to collect image signatures: %s", err.Error())
+		return
+	}
+
+	hash, err := img.Hash()
+	if err != nil {
+		t.Fatalf("failed to read image hash: %s", err.Error())
+		return
+	}
+
+	idx, err := sec.VerifySigs(key, sigs, hash)
+	if !e.sign {
+		if err == nil && idx != -1 {
+			fatalErr("signature", "good", "bad", nil)
+		}
+		return
+	} else {
+		if err != nil || idx == -1 {
+			fatalErr("signature", "bad", "good", err)
+		}
+	}
+}
+
+func TestImageVerify(t *testing.T) {
+	entries := []entry{
+		entry{
+			basename:  "garbage",
+			form:      false,
+			integrity: false,
+			man:       false,
+			sign:      false,
+		},
+		entry{
+			basename:  "truncated",
+			form:      false,
+			integrity: false,
+			man:       false,
+			sign:      false,
+		},
+		entry{
+			basename:  "bad-hash",
+			form:      true,
+			integrity: false,
+			man:       false,
+			sign:      false,
+		},
+		entry{
+			basename:  "mismatch-hash",
+			form:      true,
+			integrity: true,
+			man:       false,
+			sign:      false,
+		},
+		entry{
+			basename:  "mismatch-version",
+			form:      true,
+			integrity: true,
+			man:       false,
+			sign:      false,
+		},
+		entry{
+			basename:  "bad-signature",
+			form:      true,
+			integrity: true,
+			man:       true,
+			sign:      false,
+		},
+		entry{
+			basename:  "good-unsigned",
+			form:      true,
+			integrity: true,
+			man:       true,
+			sign:      false,
+		},
+		entry{
+			basename:  "good-signed",
+			form:      true,
+			integrity: true,
+			man:       true,
+			sign:      true,
+		},
+	}
+
+	for _, e := range entries {
+		testOne(t, e)
+	}
+}
diff --git a/image/keys_test.go b/image/keys_test.go
index 769848a..0953570 100644
--- a/image/keys_test.go
+++ b/image/keys_test.go
@@ -24,8 +24,8 @@
 	"os"
 	"testing"
 
-	"mynewt.apache.org/newt/artifact/image"
-	"mynewt.apache.org/newt/artifact/sec"
+	"github.com/apache/mynewt-artifact/image"
+	"github.com/apache/mynewt-artifact/sec"
 )
 
 func TestRSA(t *testing.T) {
@@ -44,18 +44,6 @@
 	signatureTest(t, ecdsaPkcs8Private)
 }
 
-func TestEncryptedRSA(t *testing.T) {
-	sec.KeyPassword = []byte("sample")
-	signatureTest(t, rsaEncryptedPrivate)
-	sec.KeyPassword = []byte{}
-}
-
-func TestEncryptedEcdsa(t *testing.T) {
-	sec.KeyPassword = []byte("sample")
-	signatureTest(t, ecdsaEncryptedPrivate)
-	sec.KeyPassword = []byte{}
-}
-
 func signatureTest(t *testing.T, privateKey []byte) {
 	tmpdir, err := ioutil.TempDir("", "newttest")
 	if err != nil {
@@ -170,48 +158,3 @@
 YuBJCrV1FZj2HkplEgO+ZIMuD7eRvyTEBS2bw6F1aCeKOMUmYVImAbpc
 -----END PRIVATE KEY-----
 `)
-
-// A password-protected RSA private key in PKCS#5/8 format.  The
-// password for this key is "sample".
-var rsaEncryptedPrivate = []byte(`-----BEGIN ENCRYPTED PRIVATE KEY-----
-MIIFHzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIRMifqJThk8kCAggA
-MB0GCWCGSAFlAwQBKgQQTMUBoFpzjJ5UNRnCIeqf4QSCBNDkQvXnUNmss8erKiDo
-Uqs2tf9ZD8MjDThLBmF/gV1dg1q6aDY+3fI2E4yLXJb2PmKcUq82YZ0FDeoCvJRJ
-BCurzM9slur5akpNBTFoFwtFsdHz7nKNS4MHUul22rGBnVFUUNTySmpjl/m+dxWO
-fa6tWpGTAr7tsCy9gF5PxpSw7NR/NpIL0PmpydHWhTs1tl2csqBqK6Tp014Kefi/
-pmmeb2eRl5cmprxW32rW2QBMtv4z91SsbnlVdz4r8txTG+3S4td9v9jD5kqcIiC2
-KQHrbH9y7okUk/ISsp9ANKPJt10fbYDxORiMK57XssXy1enGjpkIIrUGz1TMydkD
-USfwqkmPuIrrzOXnbxU4ef2wC/pA/h9Smby3WWYo8725/1kZyIediNDcgi/Qgrs4
-1VQAYzsD6duwyUNSo+tgmYVFGvZhsottus3fMWe/Ay1biJ6z6Vk8gqKWI1VV/REJ
-zK/I9hgKGxj2N2Ff6E/YkcwQenHWj/iDWLjvokyOBnPFNqzzM2Qqo1XFpzj4EO5D
-0WD4EzZYvUhk3lZZNydvXiuy8RrCVLLJMS08XgOqQaiFqqxj2hjRwv3nBesk7iA8
-5Tv8GMa5QkNrISCnp4/uGBh+v/CjwVRqPTcK3/mctPN2nLhI6H4pF4Y6apXkz1TN
-NMQqxaxmVVg8fyLaS4/xfUr8LAmiEtOwvs0XOhcqCTvvlsO4N+yec4VD4gmsTDY9
-/2b/+YwSlGMpA+GQQbg0FraaF8NyJRG1mSER6WiUGGM1cuKK44nzBbykQbZwzDSA
-kkhjDaadkhv/NPKAUR3sNy2GXVaNL/ItCpQUHRKKcIPp0HhdXsl0YebuwRlHjw/6
-UOdzNYe23e40X/Xl3vmOKRbzhLP/qO2DV21o0wI4ujF8Xu5h1h8s49HPp58G1ldy
-/hJ6durYKX8T5khiR2iXYewoy0YObuccV//Ov1/ySOp/x0/QuCl/swvs8Jf7awnu
-rpRrHPArpCvMmXmt5Y+TFYXFjkJGwsxTew5TcwBebBlIET2XNbo2pbz4WqJ3eVlK
-CNZVDEZ8mMrGT00FBi759Vfw9rhrnqXnLlNtJZ5VCXFUw8Tos302sLaQWXzHYyf8
-4awM8G9PSu5Q9lFcN9od4H95YrAAv/l8F+pcGgEKD8ZuzsgFIalqgx5wzmUMDcPM
-NKV5u9mtHjI92ru6NB8rGesM6sy6kBGvpotsDWawpV2SoCrkbyEkk+kXaGS+fsG7
-D2H37GfktN8R5Ktc0Uf/JJiNfDzq8lk1J4r7LBQlWUbhKbfGMYxt+7Xo0GsqAsLp
-PKSUwx+hTZb3BmW6s4Q6vivI1MdQbWVT1zh41StvfRSNlo70iOFxOM0lU1jjY989
-UKo+gcolddvZbMNwip0ILPO3dsa+he1jJ/gbo9qBHLy7plfsBLLakZP1Nu6xdlqQ
-TSSobaE8uxUMZk+wMWClA9AOZ1TcUr2yRV5GVj/bxG9ab+H37vF9F8vFE+jjJ7yN
-6pjdohm4gXeSVx7ON4SeZLsVwNYkCVYS89E81qLx1jP9F57+6IUGDZN5EMC0aJLT
-ny75MCCLT00KD7BFsb0KDLXxp++eu/L2hinorT3p6dXp/9mUoxmy6wJqEyqCFniZ
-N2GZN7+LDTIbHUxCijVWamU2DQ==
------END ENCRYPTED PRIVATE KEY-----
-`)
-
-// A password-protected ECDSA private key in PKCS#5/8 format.  The
-// password for this key is "sample"
-var ecdsaEncryptedPrivate = []byte(`-----BEGIN ENCRYPTED PRIVATE KEY-----
-MIHeMEkGCSqGSIb3DQEFDTA8MBsGCSqGSIb3DQEFDDAOBAjlKrDSKNg9QQICCAAw
-HQYJYIZIAWUDBAEqBBDliPNzQTNpdlppTcYpmuhWBIGQVhfWaVSzUvi/qIZLiZVn
-Nulfw5jDOlbn3UBX9kp/Z9Pro582Q0kjzLfm5UahvDINEJWxL4pc/28UnGQTBr0Q
-nSEg+RbqpuD099C38H0Gq/YkIM+RDG4aiQrkmzHXyVsHshIbG+z2LsLTIwmU69/Z
-v0nX6/hGErVR8YWcrOne086rCvfJVrxyO5+EUqrkLhEr
------END ENCRYPTED PRIVATE KEY-----
-`)
diff --git a/image/map.go b/image/map.go
new file mode 100644
index 0000000..ac8acef
--- /dev/null
+++ b/image/map.go
@@ -0,0 +1,100 @@
+/**
+ * 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.
+ */
+
+package image
+
+import (
+	"encoding/hex"
+	"encoding/json"
+
+	"github.com/apache/mynewt-artifact/errors"
+)
+
+func (h *ImageHdr) Map(offset int) map[string]interface{} {
+	return map[string]interface{}{
+		"_offset": offset,
+		"flags":   h.Flags,
+		"hdr_sz":  h.HdrSz,
+		"img_sz":  h.ImgSz,
+		"magic":   h.Magic,
+		"vers":    h.Vers.String(),
+	}
+}
+
+func rawBodyMap(offset int) map[string]interface{} {
+	return map[string]interface{}{
+		"_offset": offset,
+	}
+}
+
+func (t *ImageTrailer) Map(offset int) map[string]interface{} {
+	return map[string]interface{}{
+		"_offset":     offset,
+		"magic":       t.Magic,
+		"tlv_tot_len": t.TlvTotLen,
+	}
+}
+
+func (t *ImageTlv) Map(index int, offset int) map[string]interface{} {
+	return map[string]interface{}{
+		"_index":   index,
+		"_offset":  offset,
+		"_typestr": ImageTlvTypeName(t.Header.Type),
+		"data":     hex.EncodeToString(t.Data),
+		"len":      t.Header.Len,
+		"type":     t.Header.Type,
+	}
+}
+
+// Map produces a JSON-friendly map representation of an image.
+func (img *Image) Map() (map[string]interface{}, error) {
+	offs, err := img.Offsets()
+	if err != nil {
+		return nil, err
+	}
+
+	m := map[string]interface{}{}
+	m["header"] = img.Header.Map(offs.Header)
+	m["body"] = rawBodyMap(offs.Body)
+	trailer := img.Trailer()
+	m["trailer"] = trailer.Map(offs.Trailer)
+
+	tlvMaps := []map[string]interface{}{}
+	for i, tlv := range img.Tlvs {
+		tlvMaps = append(tlvMaps, tlv.Map(i, offs.Tlvs[i]))
+	}
+	m["tlvs"] = tlvMaps
+
+	return m, nil
+}
+
+// Json produces a JSON representation of an image.
+func (img *Image) Json() (string, error) {
+	m, err := img.Map()
+	if err != nil {
+		return "", err
+	}
+
+	b, err := json.MarshalIndent(m, "", "    ")
+	if err != nil {
+		return "", errors.Wrapf(err, "failed to marshal image")
+	}
+
+	return string(b), nil
+}
diff --git a/image/parse.go b/image/parse.go
new file mode 100644
index 0000000..200d0f8
--- /dev/null
+++ b/image/parse.go
@@ -0,0 +1,219 @@
+/**
+ * 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.
+ */
+
+package image
+
+import (
+	"bytes"
+	"encoding/binary"
+	"io"
+	"io/ioutil"
+	"strconv"
+	"strings"
+
+	"github.com/apache/mynewt-artifact/errors"
+)
+
+// ParseVersion parses an image version string (e.g., "1.2.3.4")
+func ParseVersion(versStr string) (ImageVersion, error) {
+	var err error
+	var major uint64
+	var minor uint64
+	var rev uint64
+	var buildNum uint64
+	var ver ImageVersion
+
+	components := strings.SplitN(versStr, ".", 4)
+	major, err = strconv.ParseUint(components[0], 10, 8)
+	if err != nil {
+		return ver, errors.Errorf("invalid version string %s", versStr)
+	}
+	if len(components) > 1 {
+		minor, err = strconv.ParseUint(components[1], 10, 8)
+		if err != nil {
+			return ver, errors.Errorf("invalid version string %s", versStr)
+		}
+	}
+	if len(components) > 2 {
+		rev, err = strconv.ParseUint(components[2], 10, 16)
+		if err != nil {
+			return ver, errors.Errorf("invalid version string %s", versStr)
+		}
+	}
+	if len(components) > 3 {
+		buildNum, err = strconv.ParseUint(components[3], 10, 32)
+		if err != nil {
+			return ver, errors.Errorf("invalid version string %s", versStr)
+		}
+	}
+
+	ver.Major = uint8(major)
+	ver.Minor = uint8(minor)
+	ver.Rev = uint16(rev)
+	ver.BuildNum = uint32(buildNum)
+	return ver, nil
+}
+
+func parseRawHeader(imgData []byte, offset int) (ImageHdr, int, error) {
+	var hdr ImageHdr
+
+	r := bytes.NewReader(imgData)
+	r.Seek(int64(offset), io.SeekStart)
+
+	if err := binary.Read(r, binary.LittleEndian, &hdr); err != nil {
+		return hdr, 0, errors.Wrapf(err, "error reading image header")
+	}
+
+	if hdr.Magic != IMAGE_MAGIC {
+		return hdr, 0, errors.Errorf(
+			"image magic incorrect; expected 0x%08x, got 0x%08x",
+			uint32(IMAGE_MAGIC), hdr.Magic)
+	}
+
+	remLen := len(imgData) - offset
+	if remLen < int(hdr.HdrSz) {
+		return hdr, 0, errors.Errorf(
+			"image header incomplete; expected %d bytes, got %d bytes",
+			hdr.HdrSz, remLen)
+	}
+
+	return hdr, int(hdr.HdrSz), nil
+}
+
+func parseRawBody(imgData []byte, hdr ImageHdr,
+	offset int) ([]byte, int, error) {
+
+	imgSz := int(hdr.ImgSz)
+	remLen := len(imgData) - offset
+
+	if remLen < imgSz {
+		return nil, 0, errors.Errorf(
+			"image body incomplete; expected %d bytes, got %d bytes",
+			imgSz, remLen)
+	}
+
+	return imgData[offset : offset+imgSz], imgSz, nil
+}
+
+func parseRawTrailer(imgData []byte, offset int) (ImageTrailer, int, error) {
+	var trailer ImageTrailer
+
+	r := bytes.NewReader(imgData)
+	r.Seek(int64(offset), io.SeekStart)
+
+	if err := binary.Read(r, binary.LittleEndian, &trailer); err != nil {
+		return trailer, 0, errors.Wrapf(err,
+			"image contains invalid trailer at offset %d", offset)
+	}
+
+	return trailer, IMAGE_TRAILER_SIZE, nil
+}
+
+func parseRawTlv(imgData []byte, offset int) (ImageTlv, int, error) {
+	tlv := ImageTlv{}
+
+	r := bytes.NewReader(imgData)
+	r.Seek(int64(offset), io.SeekStart)
+
+	if err := binary.Read(r, binary.LittleEndian, &tlv.Header); err != nil {
+		return tlv, 0, errors.Wrapf(err,
+			"image contains invalid TLV at offset %d", offset)
+	}
+
+	tlv.Data = make([]byte, tlv.Header.Len)
+	if _, err := r.Read(tlv.Data); err != nil {
+		return tlv, 0, errors.Wrapf(err,
+			"image contains invalid TLV at offset %d", offset)
+	}
+
+	return tlv, IMAGE_TLV_SIZE + int(tlv.Header.Len), nil
+}
+
+func ParseImage(imgData []byte) (Image, error) {
+	img := Image{}
+	offset := 0
+
+	hdr, size, err := parseRawHeader(imgData, offset)
+	if err != nil {
+		return img, err
+	}
+	offset += size
+
+	body, size, err := parseRawBody(imgData, hdr, offset)
+	if err != nil {
+		return img, err
+	}
+	offset += size
+
+	trailer, size, err := parseRawTrailer(imgData, offset)
+	if err != nil {
+		return img, err
+	}
+	offset += size
+
+	totalLen := IMAGE_HEADER_SIZE + len(body) + int(trailer.TlvTotLen)
+	if len(imgData) < totalLen {
+		return img, errors.Errorf("image data truncated: have=%d want=%d",
+			len(imgData), totalLen)
+	}
+
+	// Trim excess data following image trailer.
+	imgData = imgData[:totalLen]
+
+	var tlvs []ImageTlv
+	tlvLen := IMAGE_TRAILER_SIZE
+	for offset < len(imgData) {
+		tlv, size, err := parseRawTlv(imgData, offset)
+		if err != nil {
+			return img, err
+		}
+
+		tlvs = append(tlvs, tlv)
+
+		offset += size
+		if offset > len(imgData) {
+			return img, errors.Errorf("TLVs extend beyond end of image")
+		}
+
+		tlvLen += size
+	}
+
+	if int(trailer.TlvTotLen) != tlvLen {
+		return img, errors.Errorf(
+			"invalid image: trailer indicates TLV-length=%d; actual=%d",
+			trailer.TlvTotLen, tlvLen)
+	}
+
+	img.Header = hdr
+	img.Body = body
+	img.Tlvs = tlvs
+
+	return img, nil
+}
+
+func ReadImage(filename string) (Image, error) {
+	ri := Image{}
+
+	imgData, err := ioutil.ReadFile(filename)
+	if err != nil {
+		return ri, errors.Wrapf(err, "failed to read image from file")
+	}
+
+	return ParseImage(imgData)
+}
diff --git a/image/testdata/bad-hash.img b/image/testdata/bad-hash.img
new file mode 100644
index 0000000..f2630ee
--- /dev/null
+++ b/image/testdata/bad-hash.img
Binary files differ
diff --git a/image/testdata/bad-signature.img b/image/testdata/bad-signature.img
new file mode 100644
index 0000000..6d532b0
--- /dev/null
+++ b/image/testdata/bad-signature.img
Binary files differ
diff --git a/image/testdata/bad-signature.json b/image/testdata/bad-signature.json
new file mode 100644
index 0000000..7cfcc65
--- /dev/null
+++ b/image/testdata/bad-signature.json
@@ -0,0 +1,2267 @@
+{
+  "name": "targets/blinky-nordic_pca10040",
+  "build_time": "2019-06-17T18:15:11-07:00",
+  "build_version": "1.0.0.0",
+  "id": "8eb006d574ace63cce18a1f2d8f0f2645f1a0e8630a39fb86bbfbb805d4cd3b9",
+  "image": "/Users/ccollins/proj/myproj/bin/targets/blinky-nordic_pca10040/app/apps/blinky/blinky.img",
+  "image_hash": "8eb006d574ace63cce18a1f2d8f0f2645f1a0e8630a39fb86bbfbb805d4cd3b9",
+  "loader": "",
+  "loader_hash": "",
+  "pkgs": [
+    {
+      "name": "apps/blinky",
+      "repo": "my_project"
+    },
+    {
+      "name": "blinky-nordic_pca10040-sysinit-app",
+      "repo": "my_project"
+    },
+    {
+      "name": "@apache-mynewt-core/compiler/arm-none-eabi-m4",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/bsp/nordic_pca10040",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/cmsis-core",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/drivers/uart",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/drivers/uart/uart_hal",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/hal",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/mcu/nordic",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/mcu/nordic/nrf52xxx",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/kernel/os",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/libc/baselibc",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/console/stub",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/defs",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/flash_map",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/log/common",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/log/modlog",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/log/stub",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/mfg",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/sys",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/sysdown",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/sysinit",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "targets/blinky-nordic_pca10040",
+      "repo": "my_project"
+    },
+    {
+      "name": "@apache-mynewt-core/util/mem",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/util/rwlock",
+      "repo": "apache-mynewt-core"
+    }
+  ],
+  "target": [
+    "target.app=apps/blinky",
+    "target.bsp=@apache-mynewt-core/hw/bsp/nordic_pca10040",
+    "target.build_profile=optimized"
+  ],
+  "repos": [
+    {
+      "name": "apache-mynewt-core",
+      "commit": "fa5e4c31b0bea2b107747e3b0d40002d3bef4132",
+      "url": "git@github.com:apache/mynewt-core.git"
+    },
+    {
+      "name": "my_project",
+      "commit": "UNKNOWN"
+    }
+  ],
+  "syscfg": {
+    "ADC_0": "0",
+    "ADC_0_REFMV_0": "0",
+    "APP_NAME": "\"blinky\"",
+    "APP_blinky": "1",
+    "ARCH_NAME": "\"cortex_m4\"",
+    "ARCH_cortex_m4": "1",
+    "BASELIBC_ASSERT_FILE_LINE": "0",
+    "BASELIBC_PRESENT": "1",
+    "BSP_NAME": "\"nordic_pca10040\"",
+    "BSP_NRF52": "1",
+    "BSP_nordic_pca10040": "1",
+    "CONSOLE_UART_BAUD": "115200",
+    "CONSOLE_UART_DEV": "\"uart0\"",
+    "CONSOLE_UART_FLOW_CONTROL": "UART_FLOW_CTL_NONE",
+    "CRYPTO": "0",
+    "DEBUG_PANIC_ENABLED": "1",
+    "ENC_FLASH_DEV": "0",
+    "FLASH_MAP_MAX_AREAS": "10",
+    "FLASH_MAP_SYSINIT_STAGE": "2",
+    "FLOAT_USER": "0",
+    "GPIO_AS_PIN_RESET": "0",
+    "HAL_FLASH_VERIFY_BUF_SZ": "16",
+    "HAL_FLASH_VERIFY_ERASES": "0",
+    "HAL_FLASH_VERIFY_WRITES": "0",
+    "HAL_SYSTEM_RESET_CB": "0",
+    "HARDFLOAT": "0",
+    "I2C_0": "0",
+    "I2C_0_FREQ_KHZ": "100",
+    "I2C_0_PIN_SCL": "27",
+    "I2C_0_PIN_SDA": "26",
+    "I2C_1": "0",
+    "I2C_1_FREQ_KHZ": "100",
+    "I2C_1_PIN_SCL": "",
+    "I2C_1_PIN_SDA": "",
+    "LOG_CONSOLE": "1",
+    "LOG_FCB": "0",
+    "LOG_FCB_SLOT1": "0",
+    "LOG_LEVEL": "255",
+    "MCU_BUS_DRIVER_I2C_USE_TWIM": "0",
+    "MCU_DCDC_ENABLED": "1",
+    "MCU_DEBUG_IGNORE_BKPT": "0",
+    "MCU_FLASH_MIN_WRITE_SIZE": "1",
+    "MCU_GPIO_USE_PORT_EVENT": "0",
+    "MCU_I2C_RECOVERY_DELAY_USEC": "100",
+    "MCU_LFCLK_SOURCE": "LFXO",
+    "MCU_NRF52832": "0",
+    "MCU_NRF52840": "0",
+    "MCU_TARGET": "nRF52832",
+    "MFG_LOG_MODULE": "128",
+    "MFG_MAX_MMRS": "2",
+    "MFG_SYSINIT_STAGE": "100",
+    "MODLOG_CONSOLE_DFLT": "1",
+    "MODLOG_LOG_MACROS": "0",
+    "MODLOG_MAX_MAPPINGS": "16",
+    "MODLOG_MAX_PRINTF_LEN": "128",
+    "MODLOG_SYSINIT_STAGE": "100",
+    "MSYS_1_BLOCK_COUNT": "12",
+    "MSYS_1_BLOCK_SIZE": "292",
+    "MSYS_1_SANITY_MIN_COUNT": "0",
+    "MSYS_2_BLOCK_COUNT": "0",
+    "MSYS_2_BLOCK_SIZE": "0",
+    "MSYS_2_SANITY_MIN_COUNT": "0",
+    "MSYS_SANITY_TIMEOUT": "60000",
+    "NEWT_FEATURE_LOGCFG": "1",
+    "NEWT_FEATURE_SYSDOWN": "1",
+    "NFC_PINS_AS_GPIO": "1",
+    "OS_ASSERT_CB": "0",
+    "OS_CLI": "0",
+    "OS_COREDUMP": "0",
+    "OS_CPUTIME_FREQ": "1000000",
+    "OS_CPUTIME_TIMER_NUM": "0",
+    "OS_CRASH_FILE_LINE": "0",
+    "OS_CRASH_LOG": "0",
+    "OS_CRASH_RESTORE_REGS": "0",
+    "OS_CRASH_STACKTRACE": "0",
+    "OS_CTX_SW_STACK_CHECK": "0",
+    "OS_CTX_SW_STACK_GUARD": "4",
+    "OS_DEBUG_MODE": "0",
+    "OS_EVENTQ_DEBUG": "0",
+    "OS_EVENTQ_MONITOR": "0",
+    "OS_IDLE_TICKLESS_MS_MAX": "600000",
+    "OS_IDLE_TICKLESS_MS_MIN": "100",
+    "OS_MAIN_STACK_SIZE": "1024",
+    "OS_MAIN_TASK_PRIO": "127",
+    "OS_MAIN_TASK_SANITY_ITVL_MS": "0",
+    "OS_MEMPOOL_CHECK": "0",
+    "OS_MEMPOOL_GUARD": "0",
+    "OS_MEMPOOL_POISON": "0",
+    "OS_SCHEDULING": "1",
+    "OS_SYSINIT_STAGE": "0",
+    "OS_SYSVIEW": "0",
+    "OS_SYSVIEW_TRACE_CALLOUT": "1",
+    "OS_SYSVIEW_TRACE_EVENTQ": "1",
+    "OS_SYSVIEW_TRACE_MBUF": "0",
+    "OS_SYSVIEW_TRACE_MEMPOOL": "0",
+    "OS_SYSVIEW_TRACE_MUTEX": "1",
+    "OS_SYSVIEW_TRACE_SEM": "1",
+    "OS_TIME_DEBUG": "0",
+    "OS_WATCHDOG_MONITOR": "0",
+    "PWM_0": "0",
+    "PWM_1": "0",
+    "PWM_2": "0",
+    "PWM_3": "0",
+    "QSPI_ADDRMODE": "0",
+    "QSPI_DPMCONFIG": "0",
+    "QSPI_ENABLE": "0",
+    "QSPI_FLASH_PAGE_SIZE": "0",
+    "QSPI_FLASH_SECTOR_COUNT": "-1",
+    "QSPI_FLASH_SECTOR_SIZE": "0",
+    "QSPI_PIN_CS": "-1",
+    "QSPI_PIN_DIO0": "-1",
+    "QSPI_PIN_DIO1": "-1",
+    "QSPI_PIN_DIO2": "-1",
+    "QSPI_PIN_DIO3": "-1",
+    "QSPI_PIN_SCK": "-1",
+    "QSPI_READOC": "0",
+    "QSPI_SCK_DELAY": "0",
+    "QSPI_SCK_FREQ": "0",
+    "QSPI_SPI_MODE": "0",
+    "QSPI_WRITEOC": "0",
+    "RAM_RESIDENT": "0",
+    "RWLOCK_DEBUG": "0",
+    "SANITY_INTERVAL": "15000",
+    "SOFT_PWM": "0",
+    "SPI_0_MASTER": "0",
+    "SPI_0_MASTER_PIN_MISO": "25",
+    "SPI_0_MASTER_PIN_MOSI": "24",
+    "SPI_0_MASTER_PIN_SCK": "23",
+    "SPI_0_SLAVE": "0",
+    "SPI_0_SLAVE_PIN_MISO": "25",
+    "SPI_0_SLAVE_PIN_MOSI": "24",
+    "SPI_0_SLAVE_PIN_SCK": "23",
+    "SPI_0_SLAVE_PIN_SS": "22",
+    "SPI_1_MASTER": "0",
+    "SPI_1_MASTER_PIN_MISO": "",
+    "SPI_1_MASTER_PIN_MOSI": "",
+    "SPI_1_MASTER_PIN_SCK": "",
+    "SPI_1_SLAVE": "0",
+    "SPI_1_SLAVE_PIN_MISO": "",
+    "SPI_1_SLAVE_PIN_MOSI": "",
+    "SPI_1_SLAVE_PIN_SCK": "",
+    "SPI_1_SLAVE_PIN_SS": "",
+    "SPI_2_MASTER": "0",
+    "SPI_2_MASTER_PIN_MISO": "",
+    "SPI_2_MASTER_PIN_MOSI": "",
+    "SPI_2_MASTER_PIN_SCK": "",
+    "SPI_2_SLAVE": "0",
+    "SPI_2_SLAVE_PIN_MISO": "",
+    "SPI_2_SLAVE_PIN_MOSI": "",
+    "SPI_2_SLAVE_PIN_SCK": "",
+    "SPI_2_SLAVE_PIN_SS": "",
+    "SPI_3_MASTER": "0",
+    "SPI_3_MASTER_PIN_MISO": "",
+    "SPI_3_MASTER_PIN_MOSI": "",
+    "SPI_3_MASTER_PIN_SCK": "",
+    "SPI_3_SLAVE": "0",
+    "SPI_3_SLAVE_PIN_MISO": "",
+    "SPI_3_SLAVE_PIN_MOSI": "",
+    "SPI_3_SLAVE_PIN_SCK": "",
+    "SPI_3_SLAVE_PIN_SS": "",
+    "SYSDOWN_CONSTRAIN_DOWN": "1",
+    "SYSDOWN_PANIC_FILE_LINE": "0",
+    "SYSDOWN_PANIC_MESSAGE": "0",
+    "SYSDOWN_TIMEOUT_MS": "10000",
+    "SYSINIT_CONSTRAIN_INIT": "1",
+    "SYSINIT_PANIC_FILE_LINE": "0",
+    "SYSINIT_PANIC_MESSAGE": "0",
+    "TARGET_NAME": "\"blinky-nordic_pca10040\"",
+    "TARGET_blinky_nordic_pca10040": "1",
+    "TIMER_0": "1",
+    "TIMER_1": "0",
+    "TIMER_2": "0",
+    "TIMER_3": "0",
+    "TIMER_4": "0",
+    "TIMER_5": "0",
+    "TRNG": "0",
+    "UARTBB_0": "0",
+    "UARTBB_0_PIN_RX": "-1",
+    "UARTBB_0_PIN_TX": "-1",
+    "UART_0": "1",
+    "UART_0_PIN_CTS": "7",
+    "UART_0_PIN_RTS": "5",
+    "UART_0_PIN_RX": "8",
+    "UART_0_PIN_TX": "6",
+    "UART_1": "0",
+    "UART_1_PIN_CTS": "-1",
+    "UART_1_PIN_RTS": "-1",
+    "UART_1_PIN_RX": "",
+    "UART_1_PIN_TX": "",
+    "WATCHDOG_INTERVAL": "30000",
+    "XTAL_32768": "0",
+    "XTAL_32768_SYNTH": "0",
+    "XTAL_RC": "0"
+  },
+  "pkgsz": [
+    {
+      "name": "*fill*",
+      "files": [
+        {
+          "name": "",
+          "sym": [
+            {
+              "name": "*fill*",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 63
+                }
+              ]
+            },
+            {
+              "name": "*fill*",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 233
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "apps/blinky",
+      "files": [
+        {
+          "name": "main.o",
+          "sym": [
+            {
+              "name": "COMMON",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "g_task1_loops",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "startup",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 56
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/hw/bsp/nordic_pca10040",
+      "files": [
+        {
+          "name": "sbrk.o",
+          "sym": [
+            {
+              "name": ".data",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "_sbrkInit",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "gcc_startup_nrf52.o",
+          "sym": [
+            {
+              "name": ".isr_vector",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 216
+                }
+              ]
+            },
+            {
+              "name": ".stack",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 432
+                }
+              ]
+            },
+            {
+              "name": ".text",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 112
+                }
+              ]
+            },
+            {
+              "name": "exidx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 8
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_bsp.o",
+          "sym": [
+            {
+              "name": "hal_bsp_flash_dev",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "hal_bsp_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 14
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/hw/cmsis-core",
+      "files": [
+        {
+          "name": "cmsis_nvic.o",
+          "sym": [
+            {
+              "name": "NVIC_Relocate",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 40
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/hw/drivers/uart/uart_hal",
+      "files": [
+        {
+          "name": "uart_hal.o",
+          "sym": [
+            {
+              "name": "uart_hal_blocking_tx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_close",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 104
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_open",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 114
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_resume",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 44
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_start_rx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_start_tx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_suspend",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 40
+                }
+              ]
+            },
+            {
+              "name": "unlikely",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 14
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/hw/hal",
+      "files": [
+        {
+          "name": "hal_flash.o",
+          "sym": [
+            {
+              "name": "hal_flash_check_addr",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 28
+                }
+              ]
+            },
+            {
+              "name": "hal_flash_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "hal_flash_read",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 68
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/hw/mcu/nordic/nrf52xxx",
+      "files": [
+        {
+          "name": "hal_os_tick.o",
+          "sym": [
+            {
+              "name": "COMMON",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 40
+                }
+              ]
+            },
+            {
+              "name": "nrf52_os_tick_set_ocmp",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 64
+                }
+              ]
+            },
+            {
+              "name": "nrf52_timer_handler",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 80
+                }
+              ]
+            },
+            {
+              "name": "os_tick_idle",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 68
+                }
+              ]
+            },
+            {
+              "name": "os_tick_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 148
+                }
+              ]
+            },
+            {
+              "name": "sub24",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 46
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "system_nrf52.o",
+          "sym": [
+            {
+              "name": "SystemCoreClock",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "SystemInit",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 480
+                }
+              ]
+            },
+            {
+              "name": "errata_16",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 52
+                }
+              ]
+            },
+            {
+              "name": "errata_31",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 64
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_timer.o",
+          "sym": [
+            {
+              "name": "__NVIC_SetPendingIRQ",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 32
+                }
+              ]
+            },
+            {
+              "name": "hal_timer_config",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 212
+                }
+              ]
+            },
+            {
+              "name": "hal_timer_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 88
+                }
+              ]
+            },
+            {
+              "name": "hal_timer_read_bsptimer",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 56
+                }
+              ]
+            },
+            {
+              "name": "nrf52_hal_timers",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 24
+                }
+              ]
+            },
+            {
+              "name": "nrf52_timer0_irq_handler",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 168
+                }
+              ]
+            },
+            {
+              "name": "nrf_timer_set_ocmp",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 126
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_system.o",
+          "sym": [
+            {
+              "name": "hal_debugger_connected",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "hal_system_clock_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 60
+                }
+              ]
+            },
+            {
+              "name": "hal_system_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "hal_system_reset",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 48
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_gpio.o",
+          "sym": [
+            {
+              "name": "hal_gpio_init_out",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 38
+                }
+              ]
+            },
+            {
+              "name": "hal_gpio_read",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 34
+                }
+              ]
+            },
+            {
+              "name": "hal_gpio_toggle",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 26
+                }
+              ]
+            },
+            {
+              "name": "hal_gpio_write",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 24
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_uart.o",
+          "sym": [
+            {
+              "name": "hal_uart_blocking_tx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 80
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_close",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 52
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_config",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 408
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 64
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_init_cbs",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_start_rx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 56
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_start_tx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 72
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_tx_fill_buf",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "uart0",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 28
+                }
+              ]
+            },
+            {
+              "name": "uart0_irq_handler",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 128
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_watchdog.o",
+          "sym": [
+            {
+              "name": "hal_watchdog_enable",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "hal_watchdog_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 112
+                }
+              ]
+            },
+            {
+              "name": "hal_watchdog_tickle",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "nrf52_wdt_irq_handler",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "nrf52_periph.o",
+          "sym": [
+            {
+              "name": "nrf52_periph_create",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 90
+                }
+              ]
+            },
+            {
+              "name": "os_bsp_uart0",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 60
+                }
+              ]
+            },
+            {
+              "name": "os_bsp_uart0_cfg",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 4
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_flash.o",
+          "sym": [
+            {
+              "name": "nrf52k_flash_dev",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 24
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_erase_sector",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 76
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_funcs",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 28
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_read",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 14
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_sector_info",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 32
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_wait_ready",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_write",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 200
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/kernel/os",
+      "files": [
+        {
+          "name": "HAL_CM4.o",
+          "sym": [
+            {
+              "name": ".text",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 200
+                }
+              ]
+            },
+            {
+              "name": "exidx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os.o",
+          "sym": [
+            {
+              "name": "COMMON",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 217
+                }
+              ]
+            },
+            {
+              "name": "g_idle_task_stack",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 256
+                }
+              ]
+            },
+            {
+              "name": "g_os_main_stack",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4096
+                }
+              ]
+            },
+            {
+              "name": "os_idle_task",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 124
+                }
+              ]
+            },
+            {
+              "name": "os_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 149
+                }
+              ]
+            },
+            {
+              "name": "os_init_idle_task",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 93
+                }
+              ]
+            },
+            {
+              "name": "os_main",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 22
+                }
+              ]
+            },
+            {
+              "name": "os_pkg_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 48
+                }
+              ]
+            },
+            {
+              "name": "os_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 26
+                }
+              ]
+            },
+            {
+              "name": "os_started",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_fault.o",
+          "sym": [
+            {
+              "name": "__assert_func",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "os_default_irq",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 24
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_time.o",
+          "sym": [
+            {
+              "name": "basetod",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 48
+                }
+              ]
+            },
+            {
+              "name": "os_deltatime",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 76
+                }
+              ]
+            },
+            {
+              "name": "os_time_advance",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 120
+                }
+              ]
+            },
+            {
+              "name": "os_time_delay",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 40
+                }
+              ]
+            },
+            {
+              "name": "os_time_get",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_msys.o",
+          "sym": [
+            {
+              "name": "g_msys_pool_list",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "os_msys_1_data",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 3504
+                }
+              ]
+            },
+            {
+              "name": "os_msys_1_mbuf_pool",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "os_msys_1_mempool",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 28
+                }
+              ]
+            },
+            {
+              "name": "os_msys_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 103
+                }
+              ]
+            },
+            {
+              "name": "os_msys_register",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 64
+                }
+              ]
+            },
+            {
+              "name": "os_msys_reset",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_dev.o",
+          "sym": [
+            {
+              "name": "g_os_dev_list",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "os_dev_create",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 136
+                }
+              ]
+            },
+            {
+              "name": "os_dev_initialize",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 32
+                }
+              ]
+            },
+            {
+              "name": "os_dev_initialize_all",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 40
+                }
+              ]
+            },
+            {
+              "name": "os_dev_reset",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_sched.o",
+          "sym": [
+            {
+              "name": "g_os_run_list",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "g_os_sleep_list",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "os_sched",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "os_sched_ctx_sw_hook",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 44
+                }
+              ]
+            },
+            {
+              "name": "os_sched_get_current_task",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "os_sched_insert",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 76
+                }
+              ]
+            },
+            {
+              "name": "os_sched_next_task",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "os_sched_os_timer_exp",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 60
+                }
+              ]
+            },
+            {
+              "name": "os_sched_resort",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "os_sched_set_current_task",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "os_sched_sleep",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 116
+                }
+              ]
+            },
+            {
+              "name": "os_sched_wakeup",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 104
+                }
+              ]
+            },
+            {
+              "name": "os_sched_wakeup_ticks",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 52
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_sanity.o",
+          "sym": [
+            {
+              "name": "g_os_sanity_check_list",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_check_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 14
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_check_list_lock",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 28
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_check_list_unlock",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 24
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_check_register",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 32
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_run",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 80
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_arch_arm.o",
+          "sym": [
+            {
+              "name": "os_arch_ctx_sw",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "os_arch_in_critical",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 10
+                }
+              ]
+            },
+            {
+              "name": "os_arch_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "os_arch_os_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 148
+                }
+              ]
+            },
+            {
+              "name": "os_arch_os_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 84
+                }
+              ]
+            },
+            {
+              "name": "os_arch_restore_sr",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 6
+                }
+              ]
+            },
+            {
+              "name": "os_arch_save_sr",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "os_arch_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 48
+                }
+              ]
+            },
+            {
+              "name": "os_arch_task_stack_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 54
+                }
+              ]
+            },
+            {
+              "name": "os_flags",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "timer_handler",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 6
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_callout.o",
+          "sym": [
+            {
+              "name": "os_callout_tick",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 84
+                }
+              ]
+            },
+            {
+              "name": "os_callout_wakeup_ticks",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 48
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_cputime.o",
+          "sym": [
+            {
+              "name": "os_cputime_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 8
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_eventq.o",
+          "sym": [
+            {
+              "name": "os_eventq_dflt_get",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "os_eventq_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "os_eventq_main",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "os_eventq_put",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 104
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_mbuf.o",
+          "sym": [
+            {
+              "name": "os_mbuf_pool_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 10
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_mempool.o",
+          "sym": [
+            {
+              "name": "os_mempool_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 18
+                }
+              ]
+            },
+            {
+              "name": "os_mempool_init_internal",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 104
+                }
+              ]
+            },
+            {
+              "name": "os_mempool_module_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_mutex.o",
+          "sym": [
+            {
+              "name": "os_mutex_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "os_mutex_pend",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 220
+                }
+              ]
+            },
+            {
+              "name": "os_mutex_release",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 160
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_task.o",
+          "sym": [
+            {
+              "name": "os_task_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 228
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/libc/baselibc",
+      "files": [
+        {
+          "name": "start.o",
+          "sym": [
+            {
+              "name": "_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 2
+                }
+              ]
+            },
+            {
+              "name": "_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "memcpy.o",
+          "sym": [
+            {
+              "name": "memcpy",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 26
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "memset.o",
+          "sym": [
+            {
+              "name": "memset",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "strlen.o",
+          "sym": [
+            {
+              "name": "strlen",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/sys/flash_map",
+      "files": [
+        {
+          "name": "flash_map.o",
+          "sym": [
+            {
+              "name": "COMMON",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "flash_area_open",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 60
+                }
+              ]
+            },
+            {
+              "name": "flash_area_read",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "flash_map_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 172
+                }
+              ]
+            },
+            {
+              "name": "mfg_areas",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 120
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/sys/log/modlog",
+      "files": [
+        {
+          "name": "modlog.o",
+          "sym": [
+            {
+              "name": "modlog_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 2
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/sys/mfg",
+      "files": [
+        {
+          "name": "mfg.o",
+          "sym": [
+            {
+              "name": "mfg_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 92
+                }
+              ]
+            },
+            {
+              "name": "mfg_initialized",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 1
+                }
+              ]
+            },
+            {
+              "name": "mfg_mmrs",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 24
+                }
+              ]
+            },
+            {
+              "name": "mfg_num_mmrs",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "mfg_open",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "mfg_read_next_mmr",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 164
+                }
+              ]
+            },
+            {
+              "name": "mfg_read_tlv_body",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 100
+                }
+              ]
+            },
+            {
+              "name": "mfg_read_tlv_flash_area",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 6
+                }
+              ]
+            },
+            {
+              "name": "mfg_read_tlv_mmr_ref",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 6
+                }
+              ]
+            },
+            {
+              "name": "mfg_seek_next",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 128
+                }
+              ]
+            },
+            {
+              "name": "mfg_seek_next_with_type",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 22
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/sys/sysinit",
+      "files": [
+        {
+          "name": "sysinit.o",
+          "sym": [
+            {
+              "name": "COMMON",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 1
+                }
+              ]
+            },
+            {
+              "name": "sysinit_dflt_panic_cb",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 6
+                }
+              ]
+            },
+            {
+              "name": "sysinit_end",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "sysinit_panic_cb",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "sysinit_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/util/mem",
+      "files": [
+        {
+          "name": "mem.o",
+          "sym": [
+            {
+              "name": "mem_init_mbuf_pool",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 50
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "blinky-nordic_pca10040-sysinit-app",
+      "files": [
+        {
+          "name": "blinky-nordic_pca10040-sysflash.o",
+          "sym": [
+            {
+              "name": "sysflash_map_dflt",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 72
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "blinky-nordic_pca10040-sysinit-app.o",
+          "sym": [
+            {
+              "name": "sysinit_app",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 22
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/image/testdata/garbage.img b/image/testdata/garbage.img
new file mode 100644
index 0000000..ce01362
--- /dev/null
+++ b/image/testdata/garbage.img
@@ -0,0 +1 @@
+hello
diff --git a/image/testdata/good-signed.img b/image/testdata/good-signed.img
new file mode 100644
index 0000000..5c34fe8
--- /dev/null
+++ b/image/testdata/good-signed.img
Binary files differ
diff --git a/image/testdata/good-signed.json b/image/testdata/good-signed.json
new file mode 100644
index 0000000..7cfcc65
--- /dev/null
+++ b/image/testdata/good-signed.json
@@ -0,0 +1,2267 @@
+{
+  "name": "targets/blinky-nordic_pca10040",
+  "build_time": "2019-06-17T18:15:11-07:00",
+  "build_version": "1.0.0.0",
+  "id": "8eb006d574ace63cce18a1f2d8f0f2645f1a0e8630a39fb86bbfbb805d4cd3b9",
+  "image": "/Users/ccollins/proj/myproj/bin/targets/blinky-nordic_pca10040/app/apps/blinky/blinky.img",
+  "image_hash": "8eb006d574ace63cce18a1f2d8f0f2645f1a0e8630a39fb86bbfbb805d4cd3b9",
+  "loader": "",
+  "loader_hash": "",
+  "pkgs": [
+    {
+      "name": "apps/blinky",
+      "repo": "my_project"
+    },
+    {
+      "name": "blinky-nordic_pca10040-sysinit-app",
+      "repo": "my_project"
+    },
+    {
+      "name": "@apache-mynewt-core/compiler/arm-none-eabi-m4",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/bsp/nordic_pca10040",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/cmsis-core",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/drivers/uart",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/drivers/uart/uart_hal",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/hal",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/mcu/nordic",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/mcu/nordic/nrf52xxx",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/kernel/os",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/libc/baselibc",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/console/stub",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/defs",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/flash_map",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/log/common",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/log/modlog",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/log/stub",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/mfg",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/sys",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/sysdown",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/sysinit",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "targets/blinky-nordic_pca10040",
+      "repo": "my_project"
+    },
+    {
+      "name": "@apache-mynewt-core/util/mem",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/util/rwlock",
+      "repo": "apache-mynewt-core"
+    }
+  ],
+  "target": [
+    "target.app=apps/blinky",
+    "target.bsp=@apache-mynewt-core/hw/bsp/nordic_pca10040",
+    "target.build_profile=optimized"
+  ],
+  "repos": [
+    {
+      "name": "apache-mynewt-core",
+      "commit": "fa5e4c31b0bea2b107747e3b0d40002d3bef4132",
+      "url": "git@github.com:apache/mynewt-core.git"
+    },
+    {
+      "name": "my_project",
+      "commit": "UNKNOWN"
+    }
+  ],
+  "syscfg": {
+    "ADC_0": "0",
+    "ADC_0_REFMV_0": "0",
+    "APP_NAME": "\"blinky\"",
+    "APP_blinky": "1",
+    "ARCH_NAME": "\"cortex_m4\"",
+    "ARCH_cortex_m4": "1",
+    "BASELIBC_ASSERT_FILE_LINE": "0",
+    "BASELIBC_PRESENT": "1",
+    "BSP_NAME": "\"nordic_pca10040\"",
+    "BSP_NRF52": "1",
+    "BSP_nordic_pca10040": "1",
+    "CONSOLE_UART_BAUD": "115200",
+    "CONSOLE_UART_DEV": "\"uart0\"",
+    "CONSOLE_UART_FLOW_CONTROL": "UART_FLOW_CTL_NONE",
+    "CRYPTO": "0",
+    "DEBUG_PANIC_ENABLED": "1",
+    "ENC_FLASH_DEV": "0",
+    "FLASH_MAP_MAX_AREAS": "10",
+    "FLASH_MAP_SYSINIT_STAGE": "2",
+    "FLOAT_USER": "0",
+    "GPIO_AS_PIN_RESET": "0",
+    "HAL_FLASH_VERIFY_BUF_SZ": "16",
+    "HAL_FLASH_VERIFY_ERASES": "0",
+    "HAL_FLASH_VERIFY_WRITES": "0",
+    "HAL_SYSTEM_RESET_CB": "0",
+    "HARDFLOAT": "0",
+    "I2C_0": "0",
+    "I2C_0_FREQ_KHZ": "100",
+    "I2C_0_PIN_SCL": "27",
+    "I2C_0_PIN_SDA": "26",
+    "I2C_1": "0",
+    "I2C_1_FREQ_KHZ": "100",
+    "I2C_1_PIN_SCL": "",
+    "I2C_1_PIN_SDA": "",
+    "LOG_CONSOLE": "1",
+    "LOG_FCB": "0",
+    "LOG_FCB_SLOT1": "0",
+    "LOG_LEVEL": "255",
+    "MCU_BUS_DRIVER_I2C_USE_TWIM": "0",
+    "MCU_DCDC_ENABLED": "1",
+    "MCU_DEBUG_IGNORE_BKPT": "0",
+    "MCU_FLASH_MIN_WRITE_SIZE": "1",
+    "MCU_GPIO_USE_PORT_EVENT": "0",
+    "MCU_I2C_RECOVERY_DELAY_USEC": "100",
+    "MCU_LFCLK_SOURCE": "LFXO",
+    "MCU_NRF52832": "0",
+    "MCU_NRF52840": "0",
+    "MCU_TARGET": "nRF52832",
+    "MFG_LOG_MODULE": "128",
+    "MFG_MAX_MMRS": "2",
+    "MFG_SYSINIT_STAGE": "100",
+    "MODLOG_CONSOLE_DFLT": "1",
+    "MODLOG_LOG_MACROS": "0",
+    "MODLOG_MAX_MAPPINGS": "16",
+    "MODLOG_MAX_PRINTF_LEN": "128",
+    "MODLOG_SYSINIT_STAGE": "100",
+    "MSYS_1_BLOCK_COUNT": "12",
+    "MSYS_1_BLOCK_SIZE": "292",
+    "MSYS_1_SANITY_MIN_COUNT": "0",
+    "MSYS_2_BLOCK_COUNT": "0",
+    "MSYS_2_BLOCK_SIZE": "0",
+    "MSYS_2_SANITY_MIN_COUNT": "0",
+    "MSYS_SANITY_TIMEOUT": "60000",
+    "NEWT_FEATURE_LOGCFG": "1",
+    "NEWT_FEATURE_SYSDOWN": "1",
+    "NFC_PINS_AS_GPIO": "1",
+    "OS_ASSERT_CB": "0",
+    "OS_CLI": "0",
+    "OS_COREDUMP": "0",
+    "OS_CPUTIME_FREQ": "1000000",
+    "OS_CPUTIME_TIMER_NUM": "0",
+    "OS_CRASH_FILE_LINE": "0",
+    "OS_CRASH_LOG": "0",
+    "OS_CRASH_RESTORE_REGS": "0",
+    "OS_CRASH_STACKTRACE": "0",
+    "OS_CTX_SW_STACK_CHECK": "0",
+    "OS_CTX_SW_STACK_GUARD": "4",
+    "OS_DEBUG_MODE": "0",
+    "OS_EVENTQ_DEBUG": "0",
+    "OS_EVENTQ_MONITOR": "0",
+    "OS_IDLE_TICKLESS_MS_MAX": "600000",
+    "OS_IDLE_TICKLESS_MS_MIN": "100",
+    "OS_MAIN_STACK_SIZE": "1024",
+    "OS_MAIN_TASK_PRIO": "127",
+    "OS_MAIN_TASK_SANITY_ITVL_MS": "0",
+    "OS_MEMPOOL_CHECK": "0",
+    "OS_MEMPOOL_GUARD": "0",
+    "OS_MEMPOOL_POISON": "0",
+    "OS_SCHEDULING": "1",
+    "OS_SYSINIT_STAGE": "0",
+    "OS_SYSVIEW": "0",
+    "OS_SYSVIEW_TRACE_CALLOUT": "1",
+    "OS_SYSVIEW_TRACE_EVENTQ": "1",
+    "OS_SYSVIEW_TRACE_MBUF": "0",
+    "OS_SYSVIEW_TRACE_MEMPOOL": "0",
+    "OS_SYSVIEW_TRACE_MUTEX": "1",
+    "OS_SYSVIEW_TRACE_SEM": "1",
+    "OS_TIME_DEBUG": "0",
+    "OS_WATCHDOG_MONITOR": "0",
+    "PWM_0": "0",
+    "PWM_1": "0",
+    "PWM_2": "0",
+    "PWM_3": "0",
+    "QSPI_ADDRMODE": "0",
+    "QSPI_DPMCONFIG": "0",
+    "QSPI_ENABLE": "0",
+    "QSPI_FLASH_PAGE_SIZE": "0",
+    "QSPI_FLASH_SECTOR_COUNT": "-1",
+    "QSPI_FLASH_SECTOR_SIZE": "0",
+    "QSPI_PIN_CS": "-1",
+    "QSPI_PIN_DIO0": "-1",
+    "QSPI_PIN_DIO1": "-1",
+    "QSPI_PIN_DIO2": "-1",
+    "QSPI_PIN_DIO3": "-1",
+    "QSPI_PIN_SCK": "-1",
+    "QSPI_READOC": "0",
+    "QSPI_SCK_DELAY": "0",
+    "QSPI_SCK_FREQ": "0",
+    "QSPI_SPI_MODE": "0",
+    "QSPI_WRITEOC": "0",
+    "RAM_RESIDENT": "0",
+    "RWLOCK_DEBUG": "0",
+    "SANITY_INTERVAL": "15000",
+    "SOFT_PWM": "0",
+    "SPI_0_MASTER": "0",
+    "SPI_0_MASTER_PIN_MISO": "25",
+    "SPI_0_MASTER_PIN_MOSI": "24",
+    "SPI_0_MASTER_PIN_SCK": "23",
+    "SPI_0_SLAVE": "0",
+    "SPI_0_SLAVE_PIN_MISO": "25",
+    "SPI_0_SLAVE_PIN_MOSI": "24",
+    "SPI_0_SLAVE_PIN_SCK": "23",
+    "SPI_0_SLAVE_PIN_SS": "22",
+    "SPI_1_MASTER": "0",
+    "SPI_1_MASTER_PIN_MISO": "",
+    "SPI_1_MASTER_PIN_MOSI": "",
+    "SPI_1_MASTER_PIN_SCK": "",
+    "SPI_1_SLAVE": "0",
+    "SPI_1_SLAVE_PIN_MISO": "",
+    "SPI_1_SLAVE_PIN_MOSI": "",
+    "SPI_1_SLAVE_PIN_SCK": "",
+    "SPI_1_SLAVE_PIN_SS": "",
+    "SPI_2_MASTER": "0",
+    "SPI_2_MASTER_PIN_MISO": "",
+    "SPI_2_MASTER_PIN_MOSI": "",
+    "SPI_2_MASTER_PIN_SCK": "",
+    "SPI_2_SLAVE": "0",
+    "SPI_2_SLAVE_PIN_MISO": "",
+    "SPI_2_SLAVE_PIN_MOSI": "",
+    "SPI_2_SLAVE_PIN_SCK": "",
+    "SPI_2_SLAVE_PIN_SS": "",
+    "SPI_3_MASTER": "0",
+    "SPI_3_MASTER_PIN_MISO": "",
+    "SPI_3_MASTER_PIN_MOSI": "",
+    "SPI_3_MASTER_PIN_SCK": "",
+    "SPI_3_SLAVE": "0",
+    "SPI_3_SLAVE_PIN_MISO": "",
+    "SPI_3_SLAVE_PIN_MOSI": "",
+    "SPI_3_SLAVE_PIN_SCK": "",
+    "SPI_3_SLAVE_PIN_SS": "",
+    "SYSDOWN_CONSTRAIN_DOWN": "1",
+    "SYSDOWN_PANIC_FILE_LINE": "0",
+    "SYSDOWN_PANIC_MESSAGE": "0",
+    "SYSDOWN_TIMEOUT_MS": "10000",
+    "SYSINIT_CONSTRAIN_INIT": "1",
+    "SYSINIT_PANIC_FILE_LINE": "0",
+    "SYSINIT_PANIC_MESSAGE": "0",
+    "TARGET_NAME": "\"blinky-nordic_pca10040\"",
+    "TARGET_blinky_nordic_pca10040": "1",
+    "TIMER_0": "1",
+    "TIMER_1": "0",
+    "TIMER_2": "0",
+    "TIMER_3": "0",
+    "TIMER_4": "0",
+    "TIMER_5": "0",
+    "TRNG": "0",
+    "UARTBB_0": "0",
+    "UARTBB_0_PIN_RX": "-1",
+    "UARTBB_0_PIN_TX": "-1",
+    "UART_0": "1",
+    "UART_0_PIN_CTS": "7",
+    "UART_0_PIN_RTS": "5",
+    "UART_0_PIN_RX": "8",
+    "UART_0_PIN_TX": "6",
+    "UART_1": "0",
+    "UART_1_PIN_CTS": "-1",
+    "UART_1_PIN_RTS": "-1",
+    "UART_1_PIN_RX": "",
+    "UART_1_PIN_TX": "",
+    "WATCHDOG_INTERVAL": "30000",
+    "XTAL_32768": "0",
+    "XTAL_32768_SYNTH": "0",
+    "XTAL_RC": "0"
+  },
+  "pkgsz": [
+    {
+      "name": "*fill*",
+      "files": [
+        {
+          "name": "",
+          "sym": [
+            {
+              "name": "*fill*",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 63
+                }
+              ]
+            },
+            {
+              "name": "*fill*",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 233
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "apps/blinky",
+      "files": [
+        {
+          "name": "main.o",
+          "sym": [
+            {
+              "name": "COMMON",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "g_task1_loops",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "startup",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 56
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/hw/bsp/nordic_pca10040",
+      "files": [
+        {
+          "name": "sbrk.o",
+          "sym": [
+            {
+              "name": ".data",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "_sbrkInit",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "gcc_startup_nrf52.o",
+          "sym": [
+            {
+              "name": ".isr_vector",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 216
+                }
+              ]
+            },
+            {
+              "name": ".stack",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 432
+                }
+              ]
+            },
+            {
+              "name": ".text",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 112
+                }
+              ]
+            },
+            {
+              "name": "exidx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 8
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_bsp.o",
+          "sym": [
+            {
+              "name": "hal_bsp_flash_dev",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "hal_bsp_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 14
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/hw/cmsis-core",
+      "files": [
+        {
+          "name": "cmsis_nvic.o",
+          "sym": [
+            {
+              "name": "NVIC_Relocate",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 40
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/hw/drivers/uart/uart_hal",
+      "files": [
+        {
+          "name": "uart_hal.o",
+          "sym": [
+            {
+              "name": "uart_hal_blocking_tx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_close",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 104
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_open",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 114
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_resume",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 44
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_start_rx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_start_tx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_suspend",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 40
+                }
+              ]
+            },
+            {
+              "name": "unlikely",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 14
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/hw/hal",
+      "files": [
+        {
+          "name": "hal_flash.o",
+          "sym": [
+            {
+              "name": "hal_flash_check_addr",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 28
+                }
+              ]
+            },
+            {
+              "name": "hal_flash_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "hal_flash_read",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 68
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/hw/mcu/nordic/nrf52xxx",
+      "files": [
+        {
+          "name": "hal_os_tick.o",
+          "sym": [
+            {
+              "name": "COMMON",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 40
+                }
+              ]
+            },
+            {
+              "name": "nrf52_os_tick_set_ocmp",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 64
+                }
+              ]
+            },
+            {
+              "name": "nrf52_timer_handler",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 80
+                }
+              ]
+            },
+            {
+              "name": "os_tick_idle",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 68
+                }
+              ]
+            },
+            {
+              "name": "os_tick_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 148
+                }
+              ]
+            },
+            {
+              "name": "sub24",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 46
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "system_nrf52.o",
+          "sym": [
+            {
+              "name": "SystemCoreClock",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "SystemInit",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 480
+                }
+              ]
+            },
+            {
+              "name": "errata_16",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 52
+                }
+              ]
+            },
+            {
+              "name": "errata_31",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 64
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_timer.o",
+          "sym": [
+            {
+              "name": "__NVIC_SetPendingIRQ",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 32
+                }
+              ]
+            },
+            {
+              "name": "hal_timer_config",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 212
+                }
+              ]
+            },
+            {
+              "name": "hal_timer_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 88
+                }
+              ]
+            },
+            {
+              "name": "hal_timer_read_bsptimer",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 56
+                }
+              ]
+            },
+            {
+              "name": "nrf52_hal_timers",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 24
+                }
+              ]
+            },
+            {
+              "name": "nrf52_timer0_irq_handler",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 168
+                }
+              ]
+            },
+            {
+              "name": "nrf_timer_set_ocmp",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 126
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_system.o",
+          "sym": [
+            {
+              "name": "hal_debugger_connected",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "hal_system_clock_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 60
+                }
+              ]
+            },
+            {
+              "name": "hal_system_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "hal_system_reset",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 48
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_gpio.o",
+          "sym": [
+            {
+              "name": "hal_gpio_init_out",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 38
+                }
+              ]
+            },
+            {
+              "name": "hal_gpio_read",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 34
+                }
+              ]
+            },
+            {
+              "name": "hal_gpio_toggle",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 26
+                }
+              ]
+            },
+            {
+              "name": "hal_gpio_write",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 24
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_uart.o",
+          "sym": [
+            {
+              "name": "hal_uart_blocking_tx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 80
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_close",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 52
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_config",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 408
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 64
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_init_cbs",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_start_rx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 56
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_start_tx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 72
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_tx_fill_buf",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "uart0",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 28
+                }
+              ]
+            },
+            {
+              "name": "uart0_irq_handler",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 128
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_watchdog.o",
+          "sym": [
+            {
+              "name": "hal_watchdog_enable",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "hal_watchdog_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 112
+                }
+              ]
+            },
+            {
+              "name": "hal_watchdog_tickle",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "nrf52_wdt_irq_handler",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "nrf52_periph.o",
+          "sym": [
+            {
+              "name": "nrf52_periph_create",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 90
+                }
+              ]
+            },
+            {
+              "name": "os_bsp_uart0",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 60
+                }
+              ]
+            },
+            {
+              "name": "os_bsp_uart0_cfg",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 4
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_flash.o",
+          "sym": [
+            {
+              "name": "nrf52k_flash_dev",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 24
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_erase_sector",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 76
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_funcs",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 28
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_read",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 14
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_sector_info",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 32
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_wait_ready",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_write",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 200
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/kernel/os",
+      "files": [
+        {
+          "name": "HAL_CM4.o",
+          "sym": [
+            {
+              "name": ".text",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 200
+                }
+              ]
+            },
+            {
+              "name": "exidx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os.o",
+          "sym": [
+            {
+              "name": "COMMON",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 217
+                }
+              ]
+            },
+            {
+              "name": "g_idle_task_stack",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 256
+                }
+              ]
+            },
+            {
+              "name": "g_os_main_stack",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4096
+                }
+              ]
+            },
+            {
+              "name": "os_idle_task",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 124
+                }
+              ]
+            },
+            {
+              "name": "os_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 149
+                }
+              ]
+            },
+            {
+              "name": "os_init_idle_task",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 93
+                }
+              ]
+            },
+            {
+              "name": "os_main",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 22
+                }
+              ]
+            },
+            {
+              "name": "os_pkg_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 48
+                }
+              ]
+            },
+            {
+              "name": "os_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 26
+                }
+              ]
+            },
+            {
+              "name": "os_started",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_fault.o",
+          "sym": [
+            {
+              "name": "__assert_func",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "os_default_irq",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 24
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_time.o",
+          "sym": [
+            {
+              "name": "basetod",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 48
+                }
+              ]
+            },
+            {
+              "name": "os_deltatime",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 76
+                }
+              ]
+            },
+            {
+              "name": "os_time_advance",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 120
+                }
+              ]
+            },
+            {
+              "name": "os_time_delay",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 40
+                }
+              ]
+            },
+            {
+              "name": "os_time_get",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_msys.o",
+          "sym": [
+            {
+              "name": "g_msys_pool_list",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "os_msys_1_data",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 3504
+                }
+              ]
+            },
+            {
+              "name": "os_msys_1_mbuf_pool",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "os_msys_1_mempool",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 28
+                }
+              ]
+            },
+            {
+              "name": "os_msys_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 103
+                }
+              ]
+            },
+            {
+              "name": "os_msys_register",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 64
+                }
+              ]
+            },
+            {
+              "name": "os_msys_reset",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_dev.o",
+          "sym": [
+            {
+              "name": "g_os_dev_list",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "os_dev_create",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 136
+                }
+              ]
+            },
+            {
+              "name": "os_dev_initialize",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 32
+                }
+              ]
+            },
+            {
+              "name": "os_dev_initialize_all",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 40
+                }
+              ]
+            },
+            {
+              "name": "os_dev_reset",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_sched.o",
+          "sym": [
+            {
+              "name": "g_os_run_list",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "g_os_sleep_list",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "os_sched",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "os_sched_ctx_sw_hook",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 44
+                }
+              ]
+            },
+            {
+              "name": "os_sched_get_current_task",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "os_sched_insert",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 76
+                }
+              ]
+            },
+            {
+              "name": "os_sched_next_task",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "os_sched_os_timer_exp",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 60
+                }
+              ]
+            },
+            {
+              "name": "os_sched_resort",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "os_sched_set_current_task",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "os_sched_sleep",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 116
+                }
+              ]
+            },
+            {
+              "name": "os_sched_wakeup",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 104
+                }
+              ]
+            },
+            {
+              "name": "os_sched_wakeup_ticks",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 52
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_sanity.o",
+          "sym": [
+            {
+              "name": "g_os_sanity_check_list",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_check_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 14
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_check_list_lock",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 28
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_check_list_unlock",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 24
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_check_register",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 32
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_run",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 80
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_arch_arm.o",
+          "sym": [
+            {
+              "name": "os_arch_ctx_sw",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "os_arch_in_critical",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 10
+                }
+              ]
+            },
+            {
+              "name": "os_arch_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "os_arch_os_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 148
+                }
+              ]
+            },
+            {
+              "name": "os_arch_os_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 84
+                }
+              ]
+            },
+            {
+              "name": "os_arch_restore_sr",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 6
+                }
+              ]
+            },
+            {
+              "name": "os_arch_save_sr",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "os_arch_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 48
+                }
+              ]
+            },
+            {
+              "name": "os_arch_task_stack_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 54
+                }
+              ]
+            },
+            {
+              "name": "os_flags",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "timer_handler",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 6
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_callout.o",
+          "sym": [
+            {
+              "name": "os_callout_tick",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 84
+                }
+              ]
+            },
+            {
+              "name": "os_callout_wakeup_ticks",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 48
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_cputime.o",
+          "sym": [
+            {
+              "name": "os_cputime_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 8
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_eventq.o",
+          "sym": [
+            {
+              "name": "os_eventq_dflt_get",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "os_eventq_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "os_eventq_main",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "os_eventq_put",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 104
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_mbuf.o",
+          "sym": [
+            {
+              "name": "os_mbuf_pool_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 10
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_mempool.o",
+          "sym": [
+            {
+              "name": "os_mempool_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 18
+                }
+              ]
+            },
+            {
+              "name": "os_mempool_init_internal",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 104
+                }
+              ]
+            },
+            {
+              "name": "os_mempool_module_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_mutex.o",
+          "sym": [
+            {
+              "name": "os_mutex_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "os_mutex_pend",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 220
+                }
+              ]
+            },
+            {
+              "name": "os_mutex_release",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 160
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_task.o",
+          "sym": [
+            {
+              "name": "os_task_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 228
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/libc/baselibc",
+      "files": [
+        {
+          "name": "start.o",
+          "sym": [
+            {
+              "name": "_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 2
+                }
+              ]
+            },
+            {
+              "name": "_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "memcpy.o",
+          "sym": [
+            {
+              "name": "memcpy",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 26
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "memset.o",
+          "sym": [
+            {
+              "name": "memset",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "strlen.o",
+          "sym": [
+            {
+              "name": "strlen",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/sys/flash_map",
+      "files": [
+        {
+          "name": "flash_map.o",
+          "sym": [
+            {
+              "name": "COMMON",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "flash_area_open",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 60
+                }
+              ]
+            },
+            {
+              "name": "flash_area_read",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "flash_map_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 172
+                }
+              ]
+            },
+            {
+              "name": "mfg_areas",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 120
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/sys/log/modlog",
+      "files": [
+        {
+          "name": "modlog.o",
+          "sym": [
+            {
+              "name": "modlog_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 2
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/sys/mfg",
+      "files": [
+        {
+          "name": "mfg.o",
+          "sym": [
+            {
+              "name": "mfg_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 92
+                }
+              ]
+            },
+            {
+              "name": "mfg_initialized",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 1
+                }
+              ]
+            },
+            {
+              "name": "mfg_mmrs",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 24
+                }
+              ]
+            },
+            {
+              "name": "mfg_num_mmrs",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "mfg_open",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "mfg_read_next_mmr",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 164
+                }
+              ]
+            },
+            {
+              "name": "mfg_read_tlv_body",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 100
+                }
+              ]
+            },
+            {
+              "name": "mfg_read_tlv_flash_area",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 6
+                }
+              ]
+            },
+            {
+              "name": "mfg_read_tlv_mmr_ref",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 6
+                }
+              ]
+            },
+            {
+              "name": "mfg_seek_next",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 128
+                }
+              ]
+            },
+            {
+              "name": "mfg_seek_next_with_type",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 22
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/sys/sysinit",
+      "files": [
+        {
+          "name": "sysinit.o",
+          "sym": [
+            {
+              "name": "COMMON",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 1
+                }
+              ]
+            },
+            {
+              "name": "sysinit_dflt_panic_cb",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 6
+                }
+              ]
+            },
+            {
+              "name": "sysinit_end",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "sysinit_panic_cb",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "sysinit_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/util/mem",
+      "files": [
+        {
+          "name": "mem.o",
+          "sym": [
+            {
+              "name": "mem_init_mbuf_pool",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 50
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "blinky-nordic_pca10040-sysinit-app",
+      "files": [
+        {
+          "name": "blinky-nordic_pca10040-sysflash.o",
+          "sym": [
+            {
+              "name": "sysflash_map_dflt",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 72
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "blinky-nordic_pca10040-sysinit-app.o",
+          "sym": [
+            {
+              "name": "sysinit_app",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 22
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/image/testdata/good-unsigned.img b/image/testdata/good-unsigned.img
new file mode 100644
index 0000000..2e5c47a
--- /dev/null
+++ b/image/testdata/good-unsigned.img
Binary files differ
diff --git a/image/testdata/good-unsigned.json b/image/testdata/good-unsigned.json
new file mode 100644
index 0000000..cb9aa19
--- /dev/null
+++ b/image/testdata/good-unsigned.json
@@ -0,0 +1,2267 @@
+{
+  "name": "targets/blinky-nordic_pca10040",
+  "build_time": "2019-06-17T17:16:49-07:00",
+  "build_version": "1.0.0.0",
+  "id": "8eb006d574ace63cce18a1f2d8f0f2645f1a0e8630a39fb86bbfbb805d4cd3b9",
+  "image": "/Users/ccollins/proj/myproj/bin/targets/blinky-nordic_pca10040/app/apps/blinky/blinky.img",
+  "image_hash": "8eb006d574ace63cce18a1f2d8f0f2645f1a0e8630a39fb86bbfbb805d4cd3b9",
+  "loader": "",
+  "loader_hash": "",
+  "pkgs": [
+    {
+      "name": "apps/blinky",
+      "repo": "my_project"
+    },
+    {
+      "name": "blinky-nordic_pca10040-sysinit-app",
+      "repo": "my_project"
+    },
+    {
+      "name": "@apache-mynewt-core/compiler/arm-none-eabi-m4",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/bsp/nordic_pca10040",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/cmsis-core",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/drivers/uart",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/drivers/uart/uart_hal",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/hal",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/mcu/nordic",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/mcu/nordic/nrf52xxx",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/kernel/os",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/libc/baselibc",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/console/stub",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/defs",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/flash_map",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/log/common",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/log/modlog",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/log/stub",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/mfg",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/sys",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/sysdown",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/sysinit",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "targets/blinky-nordic_pca10040",
+      "repo": "my_project"
+    },
+    {
+      "name": "@apache-mynewt-core/util/mem",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/util/rwlock",
+      "repo": "apache-mynewt-core"
+    }
+  ],
+  "target": [
+    "target.app=apps/blinky",
+    "target.bsp=@apache-mynewt-core/hw/bsp/nordic_pca10040",
+    "target.build_profile=optimized"
+  ],
+  "repos": [
+    {
+      "name": "apache-mynewt-core",
+      "commit": "fa5e4c31b0bea2b107747e3b0d40002d3bef4132",
+      "url": "git@github.com:apache/mynewt-core.git"
+    },
+    {
+      "name": "my_project",
+      "commit": "UNKNOWN"
+    }
+  ],
+  "syscfg": {
+    "ADC_0": "0",
+    "ADC_0_REFMV_0": "0",
+    "APP_NAME": "\"blinky\"",
+    "APP_blinky": "1",
+    "ARCH_NAME": "\"cortex_m4\"",
+    "ARCH_cortex_m4": "1",
+    "BASELIBC_ASSERT_FILE_LINE": "0",
+    "BASELIBC_PRESENT": "1",
+    "BSP_NAME": "\"nordic_pca10040\"",
+    "BSP_NRF52": "1",
+    "BSP_nordic_pca10040": "1",
+    "CONSOLE_UART_BAUD": "115200",
+    "CONSOLE_UART_DEV": "\"uart0\"",
+    "CONSOLE_UART_FLOW_CONTROL": "UART_FLOW_CTL_NONE",
+    "CRYPTO": "0",
+    "DEBUG_PANIC_ENABLED": "1",
+    "ENC_FLASH_DEV": "0",
+    "FLASH_MAP_MAX_AREAS": "10",
+    "FLASH_MAP_SYSINIT_STAGE": "2",
+    "FLOAT_USER": "0",
+    "GPIO_AS_PIN_RESET": "0",
+    "HAL_FLASH_VERIFY_BUF_SZ": "16",
+    "HAL_FLASH_VERIFY_ERASES": "0",
+    "HAL_FLASH_VERIFY_WRITES": "0",
+    "HAL_SYSTEM_RESET_CB": "0",
+    "HARDFLOAT": "0",
+    "I2C_0": "0",
+    "I2C_0_FREQ_KHZ": "100",
+    "I2C_0_PIN_SCL": "27",
+    "I2C_0_PIN_SDA": "26",
+    "I2C_1": "0",
+    "I2C_1_FREQ_KHZ": "100",
+    "I2C_1_PIN_SCL": "",
+    "I2C_1_PIN_SDA": "",
+    "LOG_CONSOLE": "1",
+    "LOG_FCB": "0",
+    "LOG_FCB_SLOT1": "0",
+    "LOG_LEVEL": "255",
+    "MCU_BUS_DRIVER_I2C_USE_TWIM": "0",
+    "MCU_DCDC_ENABLED": "1",
+    "MCU_DEBUG_IGNORE_BKPT": "0",
+    "MCU_FLASH_MIN_WRITE_SIZE": "1",
+    "MCU_GPIO_USE_PORT_EVENT": "0",
+    "MCU_I2C_RECOVERY_DELAY_USEC": "100",
+    "MCU_LFCLK_SOURCE": "LFXO",
+    "MCU_NRF52832": "0",
+    "MCU_NRF52840": "0",
+    "MCU_TARGET": "nRF52832",
+    "MFG_LOG_MODULE": "128",
+    "MFG_MAX_MMRS": "2",
+    "MFG_SYSINIT_STAGE": "100",
+    "MODLOG_CONSOLE_DFLT": "1",
+    "MODLOG_LOG_MACROS": "0",
+    "MODLOG_MAX_MAPPINGS": "16",
+    "MODLOG_MAX_PRINTF_LEN": "128",
+    "MODLOG_SYSINIT_STAGE": "100",
+    "MSYS_1_BLOCK_COUNT": "12",
+    "MSYS_1_BLOCK_SIZE": "292",
+    "MSYS_1_SANITY_MIN_COUNT": "0",
+    "MSYS_2_BLOCK_COUNT": "0",
+    "MSYS_2_BLOCK_SIZE": "0",
+    "MSYS_2_SANITY_MIN_COUNT": "0",
+    "MSYS_SANITY_TIMEOUT": "60000",
+    "NEWT_FEATURE_LOGCFG": "1",
+    "NEWT_FEATURE_SYSDOWN": "1",
+    "NFC_PINS_AS_GPIO": "1",
+    "OS_ASSERT_CB": "0",
+    "OS_CLI": "0",
+    "OS_COREDUMP": "0",
+    "OS_CPUTIME_FREQ": "1000000",
+    "OS_CPUTIME_TIMER_NUM": "0",
+    "OS_CRASH_FILE_LINE": "0",
+    "OS_CRASH_LOG": "0",
+    "OS_CRASH_RESTORE_REGS": "0",
+    "OS_CRASH_STACKTRACE": "0",
+    "OS_CTX_SW_STACK_CHECK": "0",
+    "OS_CTX_SW_STACK_GUARD": "4",
+    "OS_DEBUG_MODE": "0",
+    "OS_EVENTQ_DEBUG": "0",
+    "OS_EVENTQ_MONITOR": "0",
+    "OS_IDLE_TICKLESS_MS_MAX": "600000",
+    "OS_IDLE_TICKLESS_MS_MIN": "100",
+    "OS_MAIN_STACK_SIZE": "1024",
+    "OS_MAIN_TASK_PRIO": "127",
+    "OS_MAIN_TASK_SANITY_ITVL_MS": "0",
+    "OS_MEMPOOL_CHECK": "0",
+    "OS_MEMPOOL_GUARD": "0",
+    "OS_MEMPOOL_POISON": "0",
+    "OS_SCHEDULING": "1",
+    "OS_SYSINIT_STAGE": "0",
+    "OS_SYSVIEW": "0",
+    "OS_SYSVIEW_TRACE_CALLOUT": "1",
+    "OS_SYSVIEW_TRACE_EVENTQ": "1",
+    "OS_SYSVIEW_TRACE_MBUF": "0",
+    "OS_SYSVIEW_TRACE_MEMPOOL": "0",
+    "OS_SYSVIEW_TRACE_MUTEX": "1",
+    "OS_SYSVIEW_TRACE_SEM": "1",
+    "OS_TIME_DEBUG": "0",
+    "OS_WATCHDOG_MONITOR": "0",
+    "PWM_0": "0",
+    "PWM_1": "0",
+    "PWM_2": "0",
+    "PWM_3": "0",
+    "QSPI_ADDRMODE": "0",
+    "QSPI_DPMCONFIG": "0",
+    "QSPI_ENABLE": "0",
+    "QSPI_FLASH_PAGE_SIZE": "0",
+    "QSPI_FLASH_SECTOR_COUNT": "-1",
+    "QSPI_FLASH_SECTOR_SIZE": "0",
+    "QSPI_PIN_CS": "-1",
+    "QSPI_PIN_DIO0": "-1",
+    "QSPI_PIN_DIO1": "-1",
+    "QSPI_PIN_DIO2": "-1",
+    "QSPI_PIN_DIO3": "-1",
+    "QSPI_PIN_SCK": "-1",
+    "QSPI_READOC": "0",
+    "QSPI_SCK_DELAY": "0",
+    "QSPI_SCK_FREQ": "0",
+    "QSPI_SPI_MODE": "0",
+    "QSPI_WRITEOC": "0",
+    "RAM_RESIDENT": "0",
+    "RWLOCK_DEBUG": "0",
+    "SANITY_INTERVAL": "15000",
+    "SOFT_PWM": "0",
+    "SPI_0_MASTER": "0",
+    "SPI_0_MASTER_PIN_MISO": "25",
+    "SPI_0_MASTER_PIN_MOSI": "24",
+    "SPI_0_MASTER_PIN_SCK": "23",
+    "SPI_0_SLAVE": "0",
+    "SPI_0_SLAVE_PIN_MISO": "25",
+    "SPI_0_SLAVE_PIN_MOSI": "24",
+    "SPI_0_SLAVE_PIN_SCK": "23",
+    "SPI_0_SLAVE_PIN_SS": "22",
+    "SPI_1_MASTER": "0",
+    "SPI_1_MASTER_PIN_MISO": "",
+    "SPI_1_MASTER_PIN_MOSI": "",
+    "SPI_1_MASTER_PIN_SCK": "",
+    "SPI_1_SLAVE": "0",
+    "SPI_1_SLAVE_PIN_MISO": "",
+    "SPI_1_SLAVE_PIN_MOSI": "",
+    "SPI_1_SLAVE_PIN_SCK": "",
+    "SPI_1_SLAVE_PIN_SS": "",
+    "SPI_2_MASTER": "0",
+    "SPI_2_MASTER_PIN_MISO": "",
+    "SPI_2_MASTER_PIN_MOSI": "",
+    "SPI_2_MASTER_PIN_SCK": "",
+    "SPI_2_SLAVE": "0",
+    "SPI_2_SLAVE_PIN_MISO": "",
+    "SPI_2_SLAVE_PIN_MOSI": "",
+    "SPI_2_SLAVE_PIN_SCK": "",
+    "SPI_2_SLAVE_PIN_SS": "",
+    "SPI_3_MASTER": "0",
+    "SPI_3_MASTER_PIN_MISO": "",
+    "SPI_3_MASTER_PIN_MOSI": "",
+    "SPI_3_MASTER_PIN_SCK": "",
+    "SPI_3_SLAVE": "0",
+    "SPI_3_SLAVE_PIN_MISO": "",
+    "SPI_3_SLAVE_PIN_MOSI": "",
+    "SPI_3_SLAVE_PIN_SCK": "",
+    "SPI_3_SLAVE_PIN_SS": "",
+    "SYSDOWN_CONSTRAIN_DOWN": "1",
+    "SYSDOWN_PANIC_FILE_LINE": "0",
+    "SYSDOWN_PANIC_MESSAGE": "0",
+    "SYSDOWN_TIMEOUT_MS": "10000",
+    "SYSINIT_CONSTRAIN_INIT": "1",
+    "SYSINIT_PANIC_FILE_LINE": "0",
+    "SYSINIT_PANIC_MESSAGE": "0",
+    "TARGET_NAME": "\"blinky-nordic_pca10040\"",
+    "TARGET_blinky_nordic_pca10040": "1",
+    "TIMER_0": "1",
+    "TIMER_1": "0",
+    "TIMER_2": "0",
+    "TIMER_3": "0",
+    "TIMER_4": "0",
+    "TIMER_5": "0",
+    "TRNG": "0",
+    "UARTBB_0": "0",
+    "UARTBB_0_PIN_RX": "-1",
+    "UARTBB_0_PIN_TX": "-1",
+    "UART_0": "1",
+    "UART_0_PIN_CTS": "7",
+    "UART_0_PIN_RTS": "5",
+    "UART_0_PIN_RX": "8",
+    "UART_0_PIN_TX": "6",
+    "UART_1": "0",
+    "UART_1_PIN_CTS": "-1",
+    "UART_1_PIN_RTS": "-1",
+    "UART_1_PIN_RX": "",
+    "UART_1_PIN_TX": "",
+    "WATCHDOG_INTERVAL": "30000",
+    "XTAL_32768": "0",
+    "XTAL_32768_SYNTH": "0",
+    "XTAL_RC": "0"
+  },
+  "pkgsz": [
+    {
+      "name": "*fill*",
+      "files": [
+        {
+          "name": "",
+          "sym": [
+            {
+              "name": "*fill*",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 63
+                }
+              ]
+            },
+            {
+              "name": "*fill*",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 233
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "apps/blinky",
+      "files": [
+        {
+          "name": "main.o",
+          "sym": [
+            {
+              "name": "COMMON",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "g_task1_loops",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "startup",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 56
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/hw/bsp/nordic_pca10040",
+      "files": [
+        {
+          "name": "sbrk.o",
+          "sym": [
+            {
+              "name": ".data",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "_sbrkInit",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "gcc_startup_nrf52.o",
+          "sym": [
+            {
+              "name": ".isr_vector",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 216
+                }
+              ]
+            },
+            {
+              "name": ".stack",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 432
+                }
+              ]
+            },
+            {
+              "name": ".text",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 112
+                }
+              ]
+            },
+            {
+              "name": "exidx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 8
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_bsp.o",
+          "sym": [
+            {
+              "name": "hal_bsp_flash_dev",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "hal_bsp_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 14
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/hw/cmsis-core",
+      "files": [
+        {
+          "name": "cmsis_nvic.o",
+          "sym": [
+            {
+              "name": "NVIC_Relocate",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 40
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/hw/drivers/uart/uart_hal",
+      "files": [
+        {
+          "name": "uart_hal.o",
+          "sym": [
+            {
+              "name": "uart_hal_blocking_tx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_close",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 104
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_open",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 114
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_resume",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 44
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_start_rx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_start_tx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_suspend",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 40
+                }
+              ]
+            },
+            {
+              "name": "unlikely",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 14
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/hw/hal",
+      "files": [
+        {
+          "name": "hal_flash.o",
+          "sym": [
+            {
+              "name": "hal_flash_check_addr",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 28
+                }
+              ]
+            },
+            {
+              "name": "hal_flash_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "hal_flash_read",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 68
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/hw/mcu/nordic/nrf52xxx",
+      "files": [
+        {
+          "name": "hal_os_tick.o",
+          "sym": [
+            {
+              "name": "COMMON",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 40
+                }
+              ]
+            },
+            {
+              "name": "nrf52_os_tick_set_ocmp",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 64
+                }
+              ]
+            },
+            {
+              "name": "nrf52_timer_handler",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 80
+                }
+              ]
+            },
+            {
+              "name": "os_tick_idle",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 68
+                }
+              ]
+            },
+            {
+              "name": "os_tick_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 148
+                }
+              ]
+            },
+            {
+              "name": "sub24",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 46
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "system_nrf52.o",
+          "sym": [
+            {
+              "name": "SystemCoreClock",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "SystemInit",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 480
+                }
+              ]
+            },
+            {
+              "name": "errata_16",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 52
+                }
+              ]
+            },
+            {
+              "name": "errata_31",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 64
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_timer.o",
+          "sym": [
+            {
+              "name": "__NVIC_SetPendingIRQ",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 32
+                }
+              ]
+            },
+            {
+              "name": "hal_timer_config",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 212
+                }
+              ]
+            },
+            {
+              "name": "hal_timer_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 88
+                }
+              ]
+            },
+            {
+              "name": "hal_timer_read_bsptimer",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 56
+                }
+              ]
+            },
+            {
+              "name": "nrf52_hal_timers",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 24
+                }
+              ]
+            },
+            {
+              "name": "nrf52_timer0_irq_handler",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 168
+                }
+              ]
+            },
+            {
+              "name": "nrf_timer_set_ocmp",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 126
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_system.o",
+          "sym": [
+            {
+              "name": "hal_debugger_connected",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "hal_system_clock_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 60
+                }
+              ]
+            },
+            {
+              "name": "hal_system_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "hal_system_reset",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 48
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_gpio.o",
+          "sym": [
+            {
+              "name": "hal_gpio_init_out",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 38
+                }
+              ]
+            },
+            {
+              "name": "hal_gpio_read",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 34
+                }
+              ]
+            },
+            {
+              "name": "hal_gpio_toggle",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 26
+                }
+              ]
+            },
+            {
+              "name": "hal_gpio_write",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 24
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_uart.o",
+          "sym": [
+            {
+              "name": "hal_uart_blocking_tx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 80
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_close",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 52
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_config",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 408
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 64
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_init_cbs",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_start_rx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 56
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_start_tx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 72
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_tx_fill_buf",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "uart0",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 28
+                }
+              ]
+            },
+            {
+              "name": "uart0_irq_handler",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 128
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_watchdog.o",
+          "sym": [
+            {
+              "name": "hal_watchdog_enable",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "hal_watchdog_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 112
+                }
+              ]
+            },
+            {
+              "name": "hal_watchdog_tickle",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "nrf52_wdt_irq_handler",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "nrf52_periph.o",
+          "sym": [
+            {
+              "name": "nrf52_periph_create",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 90
+                }
+              ]
+            },
+            {
+              "name": "os_bsp_uart0",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 60
+                }
+              ]
+            },
+            {
+              "name": "os_bsp_uart0_cfg",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 4
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_flash.o",
+          "sym": [
+            {
+              "name": "nrf52k_flash_dev",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 24
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_erase_sector",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 76
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_funcs",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 28
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_read",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 14
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_sector_info",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 32
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_wait_ready",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_write",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 200
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/kernel/os",
+      "files": [
+        {
+          "name": "HAL_CM4.o",
+          "sym": [
+            {
+              "name": ".text",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 200
+                }
+              ]
+            },
+            {
+              "name": "exidx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os.o",
+          "sym": [
+            {
+              "name": "COMMON",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 217
+                }
+              ]
+            },
+            {
+              "name": "g_idle_task_stack",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 256
+                }
+              ]
+            },
+            {
+              "name": "g_os_main_stack",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4096
+                }
+              ]
+            },
+            {
+              "name": "os_idle_task",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 124
+                }
+              ]
+            },
+            {
+              "name": "os_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 149
+                }
+              ]
+            },
+            {
+              "name": "os_init_idle_task",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 93
+                }
+              ]
+            },
+            {
+              "name": "os_main",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 22
+                }
+              ]
+            },
+            {
+              "name": "os_pkg_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 48
+                }
+              ]
+            },
+            {
+              "name": "os_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 26
+                }
+              ]
+            },
+            {
+              "name": "os_started",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_fault.o",
+          "sym": [
+            {
+              "name": "__assert_func",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "os_default_irq",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 24
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_time.o",
+          "sym": [
+            {
+              "name": "basetod",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 48
+                }
+              ]
+            },
+            {
+              "name": "os_deltatime",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 76
+                }
+              ]
+            },
+            {
+              "name": "os_time_advance",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 120
+                }
+              ]
+            },
+            {
+              "name": "os_time_delay",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 40
+                }
+              ]
+            },
+            {
+              "name": "os_time_get",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_msys.o",
+          "sym": [
+            {
+              "name": "g_msys_pool_list",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "os_msys_1_data",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 3504
+                }
+              ]
+            },
+            {
+              "name": "os_msys_1_mbuf_pool",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "os_msys_1_mempool",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 28
+                }
+              ]
+            },
+            {
+              "name": "os_msys_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 103
+                }
+              ]
+            },
+            {
+              "name": "os_msys_register",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 64
+                }
+              ]
+            },
+            {
+              "name": "os_msys_reset",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_dev.o",
+          "sym": [
+            {
+              "name": "g_os_dev_list",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "os_dev_create",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 136
+                }
+              ]
+            },
+            {
+              "name": "os_dev_initialize",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 32
+                }
+              ]
+            },
+            {
+              "name": "os_dev_initialize_all",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 40
+                }
+              ]
+            },
+            {
+              "name": "os_dev_reset",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_sched.o",
+          "sym": [
+            {
+              "name": "g_os_run_list",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "g_os_sleep_list",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "os_sched",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "os_sched_ctx_sw_hook",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 44
+                }
+              ]
+            },
+            {
+              "name": "os_sched_get_current_task",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "os_sched_insert",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 76
+                }
+              ]
+            },
+            {
+              "name": "os_sched_next_task",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "os_sched_os_timer_exp",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 60
+                }
+              ]
+            },
+            {
+              "name": "os_sched_resort",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "os_sched_set_current_task",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "os_sched_sleep",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 116
+                }
+              ]
+            },
+            {
+              "name": "os_sched_wakeup",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 104
+                }
+              ]
+            },
+            {
+              "name": "os_sched_wakeup_ticks",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 52
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_sanity.o",
+          "sym": [
+            {
+              "name": "g_os_sanity_check_list",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_check_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 14
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_check_list_lock",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 28
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_check_list_unlock",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 24
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_check_register",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 32
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_run",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 80
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_arch_arm.o",
+          "sym": [
+            {
+              "name": "os_arch_ctx_sw",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "os_arch_in_critical",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 10
+                }
+              ]
+            },
+            {
+              "name": "os_arch_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "os_arch_os_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 148
+                }
+              ]
+            },
+            {
+              "name": "os_arch_os_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 84
+                }
+              ]
+            },
+            {
+              "name": "os_arch_restore_sr",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 6
+                }
+              ]
+            },
+            {
+              "name": "os_arch_save_sr",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "os_arch_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 48
+                }
+              ]
+            },
+            {
+              "name": "os_arch_task_stack_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 54
+                }
+              ]
+            },
+            {
+              "name": "os_flags",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "timer_handler",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 6
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_callout.o",
+          "sym": [
+            {
+              "name": "os_callout_tick",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 84
+                }
+              ]
+            },
+            {
+              "name": "os_callout_wakeup_ticks",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 48
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_cputime.o",
+          "sym": [
+            {
+              "name": "os_cputime_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 8
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_eventq.o",
+          "sym": [
+            {
+              "name": "os_eventq_dflt_get",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "os_eventq_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "os_eventq_main",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "os_eventq_put",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 104
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_mbuf.o",
+          "sym": [
+            {
+              "name": "os_mbuf_pool_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 10
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_mempool.o",
+          "sym": [
+            {
+              "name": "os_mempool_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 18
+                }
+              ]
+            },
+            {
+              "name": "os_mempool_init_internal",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 104
+                }
+              ]
+            },
+            {
+              "name": "os_mempool_module_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_mutex.o",
+          "sym": [
+            {
+              "name": "os_mutex_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "os_mutex_pend",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 220
+                }
+              ]
+            },
+            {
+              "name": "os_mutex_release",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 160
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_task.o",
+          "sym": [
+            {
+              "name": "os_task_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 228
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/libc/baselibc",
+      "files": [
+        {
+          "name": "start.o",
+          "sym": [
+            {
+              "name": "_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 2
+                }
+              ]
+            },
+            {
+              "name": "_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "memcpy.o",
+          "sym": [
+            {
+              "name": "memcpy",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 26
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "memset.o",
+          "sym": [
+            {
+              "name": "memset",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "strlen.o",
+          "sym": [
+            {
+              "name": "strlen",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/sys/flash_map",
+      "files": [
+        {
+          "name": "flash_map.o",
+          "sym": [
+            {
+              "name": "COMMON",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "flash_area_open",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 60
+                }
+              ]
+            },
+            {
+              "name": "flash_area_read",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "flash_map_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 172
+                }
+              ]
+            },
+            {
+              "name": "mfg_areas",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 120
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/sys/log/modlog",
+      "files": [
+        {
+          "name": "modlog.o",
+          "sym": [
+            {
+              "name": "modlog_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 2
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/sys/mfg",
+      "files": [
+        {
+          "name": "mfg.o",
+          "sym": [
+            {
+              "name": "mfg_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 92
+                }
+              ]
+            },
+            {
+              "name": "mfg_initialized",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 1
+                }
+              ]
+            },
+            {
+              "name": "mfg_mmrs",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 24
+                }
+              ]
+            },
+            {
+              "name": "mfg_num_mmrs",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "mfg_open",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "mfg_read_next_mmr",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 164
+                }
+              ]
+            },
+            {
+              "name": "mfg_read_tlv_body",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 100
+                }
+              ]
+            },
+            {
+              "name": "mfg_read_tlv_flash_area",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 6
+                }
+              ]
+            },
+            {
+              "name": "mfg_read_tlv_mmr_ref",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 6
+                }
+              ]
+            },
+            {
+              "name": "mfg_seek_next",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 128
+                }
+              ]
+            },
+            {
+              "name": "mfg_seek_next_with_type",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 22
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/sys/sysinit",
+      "files": [
+        {
+          "name": "sysinit.o",
+          "sym": [
+            {
+              "name": "COMMON",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 1
+                }
+              ]
+            },
+            {
+              "name": "sysinit_dflt_panic_cb",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 6
+                }
+              ]
+            },
+            {
+              "name": "sysinit_end",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "sysinit_panic_cb",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "sysinit_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/util/mem",
+      "files": [
+        {
+          "name": "mem.o",
+          "sym": [
+            {
+              "name": "mem_init_mbuf_pool",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 50
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "blinky-nordic_pca10040-sysinit-app",
+      "files": [
+        {
+          "name": "blinky-nordic_pca10040-sysflash.o",
+          "sym": [
+            {
+              "name": "sysflash_map_dflt",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 72
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "blinky-nordic_pca10040-sysinit-app.o",
+          "sym": [
+            {
+              "name": "sysinit_app",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 22
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/image/testdata/mismatch-hash.img b/image/testdata/mismatch-hash.img
new file mode 100644
index 0000000..2e5c47a
--- /dev/null
+++ b/image/testdata/mismatch-hash.img
Binary files differ
diff --git a/image/testdata/mismatch-hash.json b/image/testdata/mismatch-hash.json
new file mode 100644
index 0000000..5da3a66
--- /dev/null
+++ b/image/testdata/mismatch-hash.json
@@ -0,0 +1,2267 @@
+{
+  "name": "targets/blinky-nordic_pca10040",
+  "build_time": "2019-06-17T17:16:49-07:00",
+  "build_version": "1.0.0.0",
+  "id": "aab006d574ace63cce18a1f2d8f0f2645f1a0e8630a39fb86bbfbb805d4cd3b9",
+  "image": "/Users/ccollins/proj/myproj/bin/targets/blinky-nordic_pca10040/app/apps/blinky/blinky.img",
+  "image_hash": "aab006d574ace63cce18a1f2d8f0f2645f1a0e8630a39fb86bbfbb805d4cd3b9",
+  "loader": "",
+  "loader_hash": "",
+  "pkgs": [
+    {
+      "name": "apps/blinky",
+      "repo": "my_project"
+    },
+    {
+      "name": "blinky-nordic_pca10040-sysinit-app",
+      "repo": "my_project"
+    },
+    {
+      "name": "@apache-mynewt-core/compiler/arm-none-eabi-m4",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/bsp/nordic_pca10040",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/cmsis-core",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/drivers/uart",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/drivers/uart/uart_hal",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/hal",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/mcu/nordic",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/mcu/nordic/nrf52xxx",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/kernel/os",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/libc/baselibc",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/console/stub",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/defs",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/flash_map",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/log/common",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/log/modlog",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/log/stub",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/mfg",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/sys",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/sysdown",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/sysinit",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "targets/blinky-nordic_pca10040",
+      "repo": "my_project"
+    },
+    {
+      "name": "@apache-mynewt-core/util/mem",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/util/rwlock",
+      "repo": "apache-mynewt-core"
+    }
+  ],
+  "target": [
+    "target.app=apps/blinky",
+    "target.bsp=@apache-mynewt-core/hw/bsp/nordic_pca10040",
+    "target.build_profile=optimized"
+  ],
+  "repos": [
+    {
+      "name": "apache-mynewt-core",
+      "commit": "fa5e4c31b0bea2b107747e3b0d40002d3bef4132",
+      "url": "git@github.com:apache/mynewt-core.git"
+    },
+    {
+      "name": "my_project",
+      "commit": "UNKNOWN"
+    }
+  ],
+  "syscfg": {
+    "ADC_0": "0",
+    "ADC_0_REFMV_0": "0",
+    "APP_NAME": "\"blinky\"",
+    "APP_blinky": "1",
+    "ARCH_NAME": "\"cortex_m4\"",
+    "ARCH_cortex_m4": "1",
+    "BASELIBC_ASSERT_FILE_LINE": "0",
+    "BASELIBC_PRESENT": "1",
+    "BSP_NAME": "\"nordic_pca10040\"",
+    "BSP_NRF52": "1",
+    "BSP_nordic_pca10040": "1",
+    "CONSOLE_UART_BAUD": "115200",
+    "CONSOLE_UART_DEV": "\"uart0\"",
+    "CONSOLE_UART_FLOW_CONTROL": "UART_FLOW_CTL_NONE",
+    "CRYPTO": "0",
+    "DEBUG_PANIC_ENABLED": "1",
+    "ENC_FLASH_DEV": "0",
+    "FLASH_MAP_MAX_AREAS": "10",
+    "FLASH_MAP_SYSINIT_STAGE": "2",
+    "FLOAT_USER": "0",
+    "GPIO_AS_PIN_RESET": "0",
+    "HAL_FLASH_VERIFY_BUF_SZ": "16",
+    "HAL_FLASH_VERIFY_ERASES": "0",
+    "HAL_FLASH_VERIFY_WRITES": "0",
+    "HAL_SYSTEM_RESET_CB": "0",
+    "HARDFLOAT": "0",
+    "I2C_0": "0",
+    "I2C_0_FREQ_KHZ": "100",
+    "I2C_0_PIN_SCL": "27",
+    "I2C_0_PIN_SDA": "26",
+    "I2C_1": "0",
+    "I2C_1_FREQ_KHZ": "100",
+    "I2C_1_PIN_SCL": "",
+    "I2C_1_PIN_SDA": "",
+    "LOG_CONSOLE": "1",
+    "LOG_FCB": "0",
+    "LOG_FCB_SLOT1": "0",
+    "LOG_LEVEL": "255",
+    "MCU_BUS_DRIVER_I2C_USE_TWIM": "0",
+    "MCU_DCDC_ENABLED": "1",
+    "MCU_DEBUG_IGNORE_BKPT": "0",
+    "MCU_FLASH_MIN_WRITE_SIZE": "1",
+    "MCU_GPIO_USE_PORT_EVENT": "0",
+    "MCU_I2C_RECOVERY_DELAY_USEC": "100",
+    "MCU_LFCLK_SOURCE": "LFXO",
+    "MCU_NRF52832": "0",
+    "MCU_NRF52840": "0",
+    "MCU_TARGET": "nRF52832",
+    "MFG_LOG_MODULE": "128",
+    "MFG_MAX_MMRS": "2",
+    "MFG_SYSINIT_STAGE": "100",
+    "MODLOG_CONSOLE_DFLT": "1",
+    "MODLOG_LOG_MACROS": "0",
+    "MODLOG_MAX_MAPPINGS": "16",
+    "MODLOG_MAX_PRINTF_LEN": "128",
+    "MODLOG_SYSINIT_STAGE": "100",
+    "MSYS_1_BLOCK_COUNT": "12",
+    "MSYS_1_BLOCK_SIZE": "292",
+    "MSYS_1_SANITY_MIN_COUNT": "0",
+    "MSYS_2_BLOCK_COUNT": "0",
+    "MSYS_2_BLOCK_SIZE": "0",
+    "MSYS_2_SANITY_MIN_COUNT": "0",
+    "MSYS_SANITY_TIMEOUT": "60000",
+    "NEWT_FEATURE_LOGCFG": "1",
+    "NEWT_FEATURE_SYSDOWN": "1",
+    "NFC_PINS_AS_GPIO": "1",
+    "OS_ASSERT_CB": "0",
+    "OS_CLI": "0",
+    "OS_COREDUMP": "0",
+    "OS_CPUTIME_FREQ": "1000000",
+    "OS_CPUTIME_TIMER_NUM": "0",
+    "OS_CRASH_FILE_LINE": "0",
+    "OS_CRASH_LOG": "0",
+    "OS_CRASH_RESTORE_REGS": "0",
+    "OS_CRASH_STACKTRACE": "0",
+    "OS_CTX_SW_STACK_CHECK": "0",
+    "OS_CTX_SW_STACK_GUARD": "4",
+    "OS_DEBUG_MODE": "0",
+    "OS_EVENTQ_DEBUG": "0",
+    "OS_EVENTQ_MONITOR": "0",
+    "OS_IDLE_TICKLESS_MS_MAX": "600000",
+    "OS_IDLE_TICKLESS_MS_MIN": "100",
+    "OS_MAIN_STACK_SIZE": "1024",
+    "OS_MAIN_TASK_PRIO": "127",
+    "OS_MAIN_TASK_SANITY_ITVL_MS": "0",
+    "OS_MEMPOOL_CHECK": "0",
+    "OS_MEMPOOL_GUARD": "0",
+    "OS_MEMPOOL_POISON": "0",
+    "OS_SCHEDULING": "1",
+    "OS_SYSINIT_STAGE": "0",
+    "OS_SYSVIEW": "0",
+    "OS_SYSVIEW_TRACE_CALLOUT": "1",
+    "OS_SYSVIEW_TRACE_EVENTQ": "1",
+    "OS_SYSVIEW_TRACE_MBUF": "0",
+    "OS_SYSVIEW_TRACE_MEMPOOL": "0",
+    "OS_SYSVIEW_TRACE_MUTEX": "1",
+    "OS_SYSVIEW_TRACE_SEM": "1",
+    "OS_TIME_DEBUG": "0",
+    "OS_WATCHDOG_MONITOR": "0",
+    "PWM_0": "0",
+    "PWM_1": "0",
+    "PWM_2": "0",
+    "PWM_3": "0",
+    "QSPI_ADDRMODE": "0",
+    "QSPI_DPMCONFIG": "0",
+    "QSPI_ENABLE": "0",
+    "QSPI_FLASH_PAGE_SIZE": "0",
+    "QSPI_FLASH_SECTOR_COUNT": "-1",
+    "QSPI_FLASH_SECTOR_SIZE": "0",
+    "QSPI_PIN_CS": "-1",
+    "QSPI_PIN_DIO0": "-1",
+    "QSPI_PIN_DIO1": "-1",
+    "QSPI_PIN_DIO2": "-1",
+    "QSPI_PIN_DIO3": "-1",
+    "QSPI_PIN_SCK": "-1",
+    "QSPI_READOC": "0",
+    "QSPI_SCK_DELAY": "0",
+    "QSPI_SCK_FREQ": "0",
+    "QSPI_SPI_MODE": "0",
+    "QSPI_WRITEOC": "0",
+    "RAM_RESIDENT": "0",
+    "RWLOCK_DEBUG": "0",
+    "SANITY_INTERVAL": "15000",
+    "SOFT_PWM": "0",
+    "SPI_0_MASTER": "0",
+    "SPI_0_MASTER_PIN_MISO": "25",
+    "SPI_0_MASTER_PIN_MOSI": "24",
+    "SPI_0_MASTER_PIN_SCK": "23",
+    "SPI_0_SLAVE": "0",
+    "SPI_0_SLAVE_PIN_MISO": "25",
+    "SPI_0_SLAVE_PIN_MOSI": "24",
+    "SPI_0_SLAVE_PIN_SCK": "23",
+    "SPI_0_SLAVE_PIN_SS": "22",
+    "SPI_1_MASTER": "0",
+    "SPI_1_MASTER_PIN_MISO": "",
+    "SPI_1_MASTER_PIN_MOSI": "",
+    "SPI_1_MASTER_PIN_SCK": "",
+    "SPI_1_SLAVE": "0",
+    "SPI_1_SLAVE_PIN_MISO": "",
+    "SPI_1_SLAVE_PIN_MOSI": "",
+    "SPI_1_SLAVE_PIN_SCK": "",
+    "SPI_1_SLAVE_PIN_SS": "",
+    "SPI_2_MASTER": "0",
+    "SPI_2_MASTER_PIN_MISO": "",
+    "SPI_2_MASTER_PIN_MOSI": "",
+    "SPI_2_MASTER_PIN_SCK": "",
+    "SPI_2_SLAVE": "0",
+    "SPI_2_SLAVE_PIN_MISO": "",
+    "SPI_2_SLAVE_PIN_MOSI": "",
+    "SPI_2_SLAVE_PIN_SCK": "",
+    "SPI_2_SLAVE_PIN_SS": "",
+    "SPI_3_MASTER": "0",
+    "SPI_3_MASTER_PIN_MISO": "",
+    "SPI_3_MASTER_PIN_MOSI": "",
+    "SPI_3_MASTER_PIN_SCK": "",
+    "SPI_3_SLAVE": "0",
+    "SPI_3_SLAVE_PIN_MISO": "",
+    "SPI_3_SLAVE_PIN_MOSI": "",
+    "SPI_3_SLAVE_PIN_SCK": "",
+    "SPI_3_SLAVE_PIN_SS": "",
+    "SYSDOWN_CONSTRAIN_DOWN": "1",
+    "SYSDOWN_PANIC_FILE_LINE": "0",
+    "SYSDOWN_PANIC_MESSAGE": "0",
+    "SYSDOWN_TIMEOUT_MS": "10000",
+    "SYSINIT_CONSTRAIN_INIT": "1",
+    "SYSINIT_PANIC_FILE_LINE": "0",
+    "SYSINIT_PANIC_MESSAGE": "0",
+    "TARGET_NAME": "\"blinky-nordic_pca10040\"",
+    "TARGET_blinky_nordic_pca10040": "1",
+    "TIMER_0": "1",
+    "TIMER_1": "0",
+    "TIMER_2": "0",
+    "TIMER_3": "0",
+    "TIMER_4": "0",
+    "TIMER_5": "0",
+    "TRNG": "0",
+    "UARTBB_0": "0",
+    "UARTBB_0_PIN_RX": "-1",
+    "UARTBB_0_PIN_TX": "-1",
+    "UART_0": "1",
+    "UART_0_PIN_CTS": "7",
+    "UART_0_PIN_RTS": "5",
+    "UART_0_PIN_RX": "8",
+    "UART_0_PIN_TX": "6",
+    "UART_1": "0",
+    "UART_1_PIN_CTS": "-1",
+    "UART_1_PIN_RTS": "-1",
+    "UART_1_PIN_RX": "",
+    "UART_1_PIN_TX": "",
+    "WATCHDOG_INTERVAL": "30000",
+    "XTAL_32768": "0",
+    "XTAL_32768_SYNTH": "0",
+    "XTAL_RC": "0"
+  },
+  "pkgsz": [
+    {
+      "name": "*fill*",
+      "files": [
+        {
+          "name": "",
+          "sym": [
+            {
+              "name": "*fill*",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 63
+                }
+              ]
+            },
+            {
+              "name": "*fill*",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 233
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "apps/blinky",
+      "files": [
+        {
+          "name": "main.o",
+          "sym": [
+            {
+              "name": "COMMON",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "g_task1_loops",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "startup",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 56
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/hw/bsp/nordic_pca10040",
+      "files": [
+        {
+          "name": "sbrk.o",
+          "sym": [
+            {
+              "name": ".data",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "_sbrkInit",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "gcc_startup_nrf52.o",
+          "sym": [
+            {
+              "name": ".isr_vector",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 216
+                }
+              ]
+            },
+            {
+              "name": ".stack",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 432
+                }
+              ]
+            },
+            {
+              "name": ".text",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 112
+                }
+              ]
+            },
+            {
+              "name": "exidx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 8
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_bsp.o",
+          "sym": [
+            {
+              "name": "hal_bsp_flash_dev",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "hal_bsp_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 14
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/hw/cmsis-core",
+      "files": [
+        {
+          "name": "cmsis_nvic.o",
+          "sym": [
+            {
+              "name": "NVIC_Relocate",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 40
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/hw/drivers/uart/uart_hal",
+      "files": [
+        {
+          "name": "uart_hal.o",
+          "sym": [
+            {
+              "name": "uart_hal_blocking_tx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_close",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 104
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_open",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 114
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_resume",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 44
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_start_rx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_start_tx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_suspend",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 40
+                }
+              ]
+            },
+            {
+              "name": "unlikely",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 14
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/hw/hal",
+      "files": [
+        {
+          "name": "hal_flash.o",
+          "sym": [
+            {
+              "name": "hal_flash_check_addr",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 28
+                }
+              ]
+            },
+            {
+              "name": "hal_flash_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "hal_flash_read",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 68
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/hw/mcu/nordic/nrf52xxx",
+      "files": [
+        {
+          "name": "hal_os_tick.o",
+          "sym": [
+            {
+              "name": "COMMON",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 40
+                }
+              ]
+            },
+            {
+              "name": "nrf52_os_tick_set_ocmp",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 64
+                }
+              ]
+            },
+            {
+              "name": "nrf52_timer_handler",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 80
+                }
+              ]
+            },
+            {
+              "name": "os_tick_idle",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 68
+                }
+              ]
+            },
+            {
+              "name": "os_tick_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 148
+                }
+              ]
+            },
+            {
+              "name": "sub24",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 46
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "system_nrf52.o",
+          "sym": [
+            {
+              "name": "SystemCoreClock",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "SystemInit",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 480
+                }
+              ]
+            },
+            {
+              "name": "errata_16",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 52
+                }
+              ]
+            },
+            {
+              "name": "errata_31",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 64
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_timer.o",
+          "sym": [
+            {
+              "name": "__NVIC_SetPendingIRQ",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 32
+                }
+              ]
+            },
+            {
+              "name": "hal_timer_config",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 212
+                }
+              ]
+            },
+            {
+              "name": "hal_timer_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 88
+                }
+              ]
+            },
+            {
+              "name": "hal_timer_read_bsptimer",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 56
+                }
+              ]
+            },
+            {
+              "name": "nrf52_hal_timers",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 24
+                }
+              ]
+            },
+            {
+              "name": "nrf52_timer0_irq_handler",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 168
+                }
+              ]
+            },
+            {
+              "name": "nrf_timer_set_ocmp",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 126
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_system.o",
+          "sym": [
+            {
+              "name": "hal_debugger_connected",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "hal_system_clock_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 60
+                }
+              ]
+            },
+            {
+              "name": "hal_system_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "hal_system_reset",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 48
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_gpio.o",
+          "sym": [
+            {
+              "name": "hal_gpio_init_out",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 38
+                }
+              ]
+            },
+            {
+              "name": "hal_gpio_read",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 34
+                }
+              ]
+            },
+            {
+              "name": "hal_gpio_toggle",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 26
+                }
+              ]
+            },
+            {
+              "name": "hal_gpio_write",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 24
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_uart.o",
+          "sym": [
+            {
+              "name": "hal_uart_blocking_tx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 80
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_close",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 52
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_config",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 408
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 64
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_init_cbs",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_start_rx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 56
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_start_tx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 72
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_tx_fill_buf",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "uart0",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 28
+                }
+              ]
+            },
+            {
+              "name": "uart0_irq_handler",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 128
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_watchdog.o",
+          "sym": [
+            {
+              "name": "hal_watchdog_enable",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "hal_watchdog_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 112
+                }
+              ]
+            },
+            {
+              "name": "hal_watchdog_tickle",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "nrf52_wdt_irq_handler",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "nrf52_periph.o",
+          "sym": [
+            {
+              "name": "nrf52_periph_create",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 90
+                }
+              ]
+            },
+            {
+              "name": "os_bsp_uart0",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 60
+                }
+              ]
+            },
+            {
+              "name": "os_bsp_uart0_cfg",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 4
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_flash.o",
+          "sym": [
+            {
+              "name": "nrf52k_flash_dev",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 24
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_erase_sector",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 76
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_funcs",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 28
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_read",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 14
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_sector_info",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 32
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_wait_ready",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_write",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 200
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/kernel/os",
+      "files": [
+        {
+          "name": "HAL_CM4.o",
+          "sym": [
+            {
+              "name": ".text",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 200
+                }
+              ]
+            },
+            {
+              "name": "exidx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os.o",
+          "sym": [
+            {
+              "name": "COMMON",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 217
+                }
+              ]
+            },
+            {
+              "name": "g_idle_task_stack",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 256
+                }
+              ]
+            },
+            {
+              "name": "g_os_main_stack",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4096
+                }
+              ]
+            },
+            {
+              "name": "os_idle_task",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 124
+                }
+              ]
+            },
+            {
+              "name": "os_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 149
+                }
+              ]
+            },
+            {
+              "name": "os_init_idle_task",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 93
+                }
+              ]
+            },
+            {
+              "name": "os_main",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 22
+                }
+              ]
+            },
+            {
+              "name": "os_pkg_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 48
+                }
+              ]
+            },
+            {
+              "name": "os_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 26
+                }
+              ]
+            },
+            {
+              "name": "os_started",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_fault.o",
+          "sym": [
+            {
+              "name": "__assert_func",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "os_default_irq",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 24
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_time.o",
+          "sym": [
+            {
+              "name": "basetod",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 48
+                }
+              ]
+            },
+            {
+              "name": "os_deltatime",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 76
+                }
+              ]
+            },
+            {
+              "name": "os_time_advance",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 120
+                }
+              ]
+            },
+            {
+              "name": "os_time_delay",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 40
+                }
+              ]
+            },
+            {
+              "name": "os_time_get",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_msys.o",
+          "sym": [
+            {
+              "name": "g_msys_pool_list",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "os_msys_1_data",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 3504
+                }
+              ]
+            },
+            {
+              "name": "os_msys_1_mbuf_pool",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "os_msys_1_mempool",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 28
+                }
+              ]
+            },
+            {
+              "name": "os_msys_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 103
+                }
+              ]
+            },
+            {
+              "name": "os_msys_register",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 64
+                }
+              ]
+            },
+            {
+              "name": "os_msys_reset",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_dev.o",
+          "sym": [
+            {
+              "name": "g_os_dev_list",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "os_dev_create",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 136
+                }
+              ]
+            },
+            {
+              "name": "os_dev_initialize",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 32
+                }
+              ]
+            },
+            {
+              "name": "os_dev_initialize_all",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 40
+                }
+              ]
+            },
+            {
+              "name": "os_dev_reset",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_sched.o",
+          "sym": [
+            {
+              "name": "g_os_run_list",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "g_os_sleep_list",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "os_sched",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "os_sched_ctx_sw_hook",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 44
+                }
+              ]
+            },
+            {
+              "name": "os_sched_get_current_task",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "os_sched_insert",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 76
+                }
+              ]
+            },
+            {
+              "name": "os_sched_next_task",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "os_sched_os_timer_exp",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 60
+                }
+              ]
+            },
+            {
+              "name": "os_sched_resort",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "os_sched_set_current_task",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "os_sched_sleep",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 116
+                }
+              ]
+            },
+            {
+              "name": "os_sched_wakeup",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 104
+                }
+              ]
+            },
+            {
+              "name": "os_sched_wakeup_ticks",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 52
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_sanity.o",
+          "sym": [
+            {
+              "name": "g_os_sanity_check_list",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_check_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 14
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_check_list_lock",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 28
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_check_list_unlock",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 24
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_check_register",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 32
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_run",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 80
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_arch_arm.o",
+          "sym": [
+            {
+              "name": "os_arch_ctx_sw",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "os_arch_in_critical",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 10
+                }
+              ]
+            },
+            {
+              "name": "os_arch_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "os_arch_os_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 148
+                }
+              ]
+            },
+            {
+              "name": "os_arch_os_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 84
+                }
+              ]
+            },
+            {
+              "name": "os_arch_restore_sr",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 6
+                }
+              ]
+            },
+            {
+              "name": "os_arch_save_sr",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "os_arch_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 48
+                }
+              ]
+            },
+            {
+              "name": "os_arch_task_stack_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 54
+                }
+              ]
+            },
+            {
+              "name": "os_flags",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "timer_handler",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 6
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_callout.o",
+          "sym": [
+            {
+              "name": "os_callout_tick",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 84
+                }
+              ]
+            },
+            {
+              "name": "os_callout_wakeup_ticks",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 48
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_cputime.o",
+          "sym": [
+            {
+              "name": "os_cputime_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 8
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_eventq.o",
+          "sym": [
+            {
+              "name": "os_eventq_dflt_get",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "os_eventq_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "os_eventq_main",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "os_eventq_put",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 104
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_mbuf.o",
+          "sym": [
+            {
+              "name": "os_mbuf_pool_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 10
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_mempool.o",
+          "sym": [
+            {
+              "name": "os_mempool_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 18
+                }
+              ]
+            },
+            {
+              "name": "os_mempool_init_internal",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 104
+                }
+              ]
+            },
+            {
+              "name": "os_mempool_module_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_mutex.o",
+          "sym": [
+            {
+              "name": "os_mutex_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "os_mutex_pend",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 220
+                }
+              ]
+            },
+            {
+              "name": "os_mutex_release",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 160
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_task.o",
+          "sym": [
+            {
+              "name": "os_task_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 228
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/libc/baselibc",
+      "files": [
+        {
+          "name": "start.o",
+          "sym": [
+            {
+              "name": "_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 2
+                }
+              ]
+            },
+            {
+              "name": "_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "memcpy.o",
+          "sym": [
+            {
+              "name": "memcpy",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 26
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "memset.o",
+          "sym": [
+            {
+              "name": "memset",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "strlen.o",
+          "sym": [
+            {
+              "name": "strlen",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/sys/flash_map",
+      "files": [
+        {
+          "name": "flash_map.o",
+          "sym": [
+            {
+              "name": "COMMON",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "flash_area_open",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 60
+                }
+              ]
+            },
+            {
+              "name": "flash_area_read",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "flash_map_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 172
+                }
+              ]
+            },
+            {
+              "name": "mfg_areas",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 120
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/sys/log/modlog",
+      "files": [
+        {
+          "name": "modlog.o",
+          "sym": [
+            {
+              "name": "modlog_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 2
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/sys/mfg",
+      "files": [
+        {
+          "name": "mfg.o",
+          "sym": [
+            {
+              "name": "mfg_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 92
+                }
+              ]
+            },
+            {
+              "name": "mfg_initialized",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 1
+                }
+              ]
+            },
+            {
+              "name": "mfg_mmrs",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 24
+                }
+              ]
+            },
+            {
+              "name": "mfg_num_mmrs",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "mfg_open",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "mfg_read_next_mmr",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 164
+                }
+              ]
+            },
+            {
+              "name": "mfg_read_tlv_body",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 100
+                }
+              ]
+            },
+            {
+              "name": "mfg_read_tlv_flash_area",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 6
+                }
+              ]
+            },
+            {
+              "name": "mfg_read_tlv_mmr_ref",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 6
+                }
+              ]
+            },
+            {
+              "name": "mfg_seek_next",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 128
+                }
+              ]
+            },
+            {
+              "name": "mfg_seek_next_with_type",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 22
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/sys/sysinit",
+      "files": [
+        {
+          "name": "sysinit.o",
+          "sym": [
+            {
+              "name": "COMMON",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 1
+                }
+              ]
+            },
+            {
+              "name": "sysinit_dflt_panic_cb",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 6
+                }
+              ]
+            },
+            {
+              "name": "sysinit_end",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "sysinit_panic_cb",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "sysinit_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/util/mem",
+      "files": [
+        {
+          "name": "mem.o",
+          "sym": [
+            {
+              "name": "mem_init_mbuf_pool",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 50
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "blinky-nordic_pca10040-sysinit-app",
+      "files": [
+        {
+          "name": "blinky-nordic_pca10040-sysflash.o",
+          "sym": [
+            {
+              "name": "sysflash_map_dflt",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 72
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "blinky-nordic_pca10040-sysinit-app.o",
+          "sym": [
+            {
+              "name": "sysinit_app",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 22
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
diff --git a/image/testdata/mismatch-version.img b/image/testdata/mismatch-version.img
new file mode 100644
index 0000000..2e5c47a
--- /dev/null
+++ b/image/testdata/mismatch-version.img
Binary files differ
diff --git a/image/testdata/mismatch-version.json b/image/testdata/mismatch-version.json
new file mode 100644
index 0000000..c8b4872
--- /dev/null
+++ b/image/testdata/mismatch-version.json
@@ -0,0 +1,2267 @@
+{
+  "name": "targets/blinky-nordic_pca10040",
+  "build_time": "2019-06-17T17:16:49-07:00",
+  "build_version": "9.0.0.0",
+  "id": "8eb006d574ace63cce18a1f2d8f0f2645f1a0e8630a39fb86bbfbb805d4cd3b9",
+  "image": "/Users/ccollins/proj/myproj/bin/targets/blinky-nordic_pca10040/app/apps/blinky/blinky.img",
+  "image_hash": "8eb006d574ace63cce18a1f2d8f0f2645f1a0e8630a39fb86bbfbb805d4cd3b9",
+  "loader": "",
+  "loader_hash": "",
+  "pkgs": [
+    {
+      "name": "apps/blinky",
+      "repo": "my_project"
+    },
+    {
+      "name": "blinky-nordic_pca10040-sysinit-app",
+      "repo": "my_project"
+    },
+    {
+      "name": "@apache-mynewt-core/compiler/arm-none-eabi-m4",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/bsp/nordic_pca10040",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/cmsis-core",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/drivers/uart",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/drivers/uart/uart_hal",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/hal",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/mcu/nordic",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/hw/mcu/nordic/nrf52xxx",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/kernel/os",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/libc/baselibc",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/console/stub",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/defs",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/flash_map",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/log/common",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/log/modlog",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/log/stub",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/mfg",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/sys",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/sysdown",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/sys/sysinit",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "targets/blinky-nordic_pca10040",
+      "repo": "my_project"
+    },
+    {
+      "name": "@apache-mynewt-core/util/mem",
+      "repo": "apache-mynewt-core"
+    },
+    {
+      "name": "@apache-mynewt-core/util/rwlock",
+      "repo": "apache-mynewt-core"
+    }
+  ],
+  "target": [
+    "target.app=apps/blinky",
+    "target.bsp=@apache-mynewt-core/hw/bsp/nordic_pca10040",
+    "target.build_profile=optimized"
+  ],
+  "repos": [
+    {
+      "name": "apache-mynewt-core",
+      "commit": "fa5e4c31b0bea2b107747e3b0d40002d3bef4132",
+      "url": "git@github.com:apache/mynewt-core.git"
+    },
+    {
+      "name": "my_project",
+      "commit": "UNKNOWN"
+    }
+  ],
+  "syscfg": {
+    "ADC_0": "0",
+    "ADC_0_REFMV_0": "0",
+    "APP_NAME": "\"blinky\"",
+    "APP_blinky": "1",
+    "ARCH_NAME": "\"cortex_m4\"",
+    "ARCH_cortex_m4": "1",
+    "BASELIBC_ASSERT_FILE_LINE": "0",
+    "BASELIBC_PRESENT": "1",
+    "BSP_NAME": "\"nordic_pca10040\"",
+    "BSP_NRF52": "1",
+    "BSP_nordic_pca10040": "1",
+    "CONSOLE_UART_BAUD": "115200",
+    "CONSOLE_UART_DEV": "\"uart0\"",
+    "CONSOLE_UART_FLOW_CONTROL": "UART_FLOW_CTL_NONE",
+    "CRYPTO": "0",
+    "DEBUG_PANIC_ENABLED": "1",
+    "ENC_FLASH_DEV": "0",
+    "FLASH_MAP_MAX_AREAS": "10",
+    "FLASH_MAP_SYSINIT_STAGE": "2",
+    "FLOAT_USER": "0",
+    "GPIO_AS_PIN_RESET": "0",
+    "HAL_FLASH_VERIFY_BUF_SZ": "16",
+    "HAL_FLASH_VERIFY_ERASES": "0",
+    "HAL_FLASH_VERIFY_WRITES": "0",
+    "HAL_SYSTEM_RESET_CB": "0",
+    "HARDFLOAT": "0",
+    "I2C_0": "0",
+    "I2C_0_FREQ_KHZ": "100",
+    "I2C_0_PIN_SCL": "27",
+    "I2C_0_PIN_SDA": "26",
+    "I2C_1": "0",
+    "I2C_1_FREQ_KHZ": "100",
+    "I2C_1_PIN_SCL": "",
+    "I2C_1_PIN_SDA": "",
+    "LOG_CONSOLE": "1",
+    "LOG_FCB": "0",
+    "LOG_FCB_SLOT1": "0",
+    "LOG_LEVEL": "255",
+    "MCU_BUS_DRIVER_I2C_USE_TWIM": "0",
+    "MCU_DCDC_ENABLED": "1",
+    "MCU_DEBUG_IGNORE_BKPT": "0",
+    "MCU_FLASH_MIN_WRITE_SIZE": "1",
+    "MCU_GPIO_USE_PORT_EVENT": "0",
+    "MCU_I2C_RECOVERY_DELAY_USEC": "100",
+    "MCU_LFCLK_SOURCE": "LFXO",
+    "MCU_NRF52832": "0",
+    "MCU_NRF52840": "0",
+    "MCU_TARGET": "nRF52832",
+    "MFG_LOG_MODULE": "128",
+    "MFG_MAX_MMRS": "2",
+    "MFG_SYSINIT_STAGE": "100",
+    "MODLOG_CONSOLE_DFLT": "1",
+    "MODLOG_LOG_MACROS": "0",
+    "MODLOG_MAX_MAPPINGS": "16",
+    "MODLOG_MAX_PRINTF_LEN": "128",
+    "MODLOG_SYSINIT_STAGE": "100",
+    "MSYS_1_BLOCK_COUNT": "12",
+    "MSYS_1_BLOCK_SIZE": "292",
+    "MSYS_1_SANITY_MIN_COUNT": "0",
+    "MSYS_2_BLOCK_COUNT": "0",
+    "MSYS_2_BLOCK_SIZE": "0",
+    "MSYS_2_SANITY_MIN_COUNT": "0",
+    "MSYS_SANITY_TIMEOUT": "60000",
+    "NEWT_FEATURE_LOGCFG": "1",
+    "NEWT_FEATURE_SYSDOWN": "1",
+    "NFC_PINS_AS_GPIO": "1",
+    "OS_ASSERT_CB": "0",
+    "OS_CLI": "0",
+    "OS_COREDUMP": "0",
+    "OS_CPUTIME_FREQ": "1000000",
+    "OS_CPUTIME_TIMER_NUM": "0",
+    "OS_CRASH_FILE_LINE": "0",
+    "OS_CRASH_LOG": "0",
+    "OS_CRASH_RESTORE_REGS": "0",
+    "OS_CRASH_STACKTRACE": "0",
+    "OS_CTX_SW_STACK_CHECK": "0",
+    "OS_CTX_SW_STACK_GUARD": "4",
+    "OS_DEBUG_MODE": "0",
+    "OS_EVENTQ_DEBUG": "0",
+    "OS_EVENTQ_MONITOR": "0",
+    "OS_IDLE_TICKLESS_MS_MAX": "600000",
+    "OS_IDLE_TICKLESS_MS_MIN": "100",
+    "OS_MAIN_STACK_SIZE": "1024",
+    "OS_MAIN_TASK_PRIO": "127",
+    "OS_MAIN_TASK_SANITY_ITVL_MS": "0",
+    "OS_MEMPOOL_CHECK": "0",
+    "OS_MEMPOOL_GUARD": "0",
+    "OS_MEMPOOL_POISON": "0",
+    "OS_SCHEDULING": "1",
+    "OS_SYSINIT_STAGE": "0",
+    "OS_SYSVIEW": "0",
+    "OS_SYSVIEW_TRACE_CALLOUT": "1",
+    "OS_SYSVIEW_TRACE_EVENTQ": "1",
+    "OS_SYSVIEW_TRACE_MBUF": "0",
+    "OS_SYSVIEW_TRACE_MEMPOOL": "0",
+    "OS_SYSVIEW_TRACE_MUTEX": "1",
+    "OS_SYSVIEW_TRACE_SEM": "1",
+    "OS_TIME_DEBUG": "0",
+    "OS_WATCHDOG_MONITOR": "0",
+    "PWM_0": "0",
+    "PWM_1": "0",
+    "PWM_2": "0",
+    "PWM_3": "0",
+    "QSPI_ADDRMODE": "0",
+    "QSPI_DPMCONFIG": "0",
+    "QSPI_ENABLE": "0",
+    "QSPI_FLASH_PAGE_SIZE": "0",
+    "QSPI_FLASH_SECTOR_COUNT": "-1",
+    "QSPI_FLASH_SECTOR_SIZE": "0",
+    "QSPI_PIN_CS": "-1",
+    "QSPI_PIN_DIO0": "-1",
+    "QSPI_PIN_DIO1": "-1",
+    "QSPI_PIN_DIO2": "-1",
+    "QSPI_PIN_DIO3": "-1",
+    "QSPI_PIN_SCK": "-1",
+    "QSPI_READOC": "0",
+    "QSPI_SCK_DELAY": "0",
+    "QSPI_SCK_FREQ": "0",
+    "QSPI_SPI_MODE": "0",
+    "QSPI_WRITEOC": "0",
+    "RAM_RESIDENT": "0",
+    "RWLOCK_DEBUG": "0",
+    "SANITY_INTERVAL": "15000",
+    "SOFT_PWM": "0",
+    "SPI_0_MASTER": "0",
+    "SPI_0_MASTER_PIN_MISO": "25",
+    "SPI_0_MASTER_PIN_MOSI": "24",
+    "SPI_0_MASTER_PIN_SCK": "23",
+    "SPI_0_SLAVE": "0",
+    "SPI_0_SLAVE_PIN_MISO": "25",
+    "SPI_0_SLAVE_PIN_MOSI": "24",
+    "SPI_0_SLAVE_PIN_SCK": "23",
+    "SPI_0_SLAVE_PIN_SS": "22",
+    "SPI_1_MASTER": "0",
+    "SPI_1_MASTER_PIN_MISO": "",
+    "SPI_1_MASTER_PIN_MOSI": "",
+    "SPI_1_MASTER_PIN_SCK": "",
+    "SPI_1_SLAVE": "0",
+    "SPI_1_SLAVE_PIN_MISO": "",
+    "SPI_1_SLAVE_PIN_MOSI": "",
+    "SPI_1_SLAVE_PIN_SCK": "",
+    "SPI_1_SLAVE_PIN_SS": "",
+    "SPI_2_MASTER": "0",
+    "SPI_2_MASTER_PIN_MISO": "",
+    "SPI_2_MASTER_PIN_MOSI": "",
+    "SPI_2_MASTER_PIN_SCK": "",
+    "SPI_2_SLAVE": "0",
+    "SPI_2_SLAVE_PIN_MISO": "",
+    "SPI_2_SLAVE_PIN_MOSI": "",
+    "SPI_2_SLAVE_PIN_SCK": "",
+    "SPI_2_SLAVE_PIN_SS": "",
+    "SPI_3_MASTER": "0",
+    "SPI_3_MASTER_PIN_MISO": "",
+    "SPI_3_MASTER_PIN_MOSI": "",
+    "SPI_3_MASTER_PIN_SCK": "",
+    "SPI_3_SLAVE": "0",
+    "SPI_3_SLAVE_PIN_MISO": "",
+    "SPI_3_SLAVE_PIN_MOSI": "",
+    "SPI_3_SLAVE_PIN_SCK": "",
+    "SPI_3_SLAVE_PIN_SS": "",
+    "SYSDOWN_CONSTRAIN_DOWN": "1",
+    "SYSDOWN_PANIC_FILE_LINE": "0",
+    "SYSDOWN_PANIC_MESSAGE": "0",
+    "SYSDOWN_TIMEOUT_MS": "10000",
+    "SYSINIT_CONSTRAIN_INIT": "1",
+    "SYSINIT_PANIC_FILE_LINE": "0",
+    "SYSINIT_PANIC_MESSAGE": "0",
+    "TARGET_NAME": "\"blinky-nordic_pca10040\"",
+    "TARGET_blinky_nordic_pca10040": "1",
+    "TIMER_0": "1",
+    "TIMER_1": "0",
+    "TIMER_2": "0",
+    "TIMER_3": "0",
+    "TIMER_4": "0",
+    "TIMER_5": "0",
+    "TRNG": "0",
+    "UARTBB_0": "0",
+    "UARTBB_0_PIN_RX": "-1",
+    "UARTBB_0_PIN_TX": "-1",
+    "UART_0": "1",
+    "UART_0_PIN_CTS": "7",
+    "UART_0_PIN_RTS": "5",
+    "UART_0_PIN_RX": "8",
+    "UART_0_PIN_TX": "6",
+    "UART_1": "0",
+    "UART_1_PIN_CTS": "-1",
+    "UART_1_PIN_RTS": "-1",
+    "UART_1_PIN_RX": "",
+    "UART_1_PIN_TX": "",
+    "WATCHDOG_INTERVAL": "30000",
+    "XTAL_32768": "0",
+    "XTAL_32768_SYNTH": "0",
+    "XTAL_RC": "0"
+  },
+  "pkgsz": [
+    {
+      "name": "*fill*",
+      "files": [
+        {
+          "name": "",
+          "sym": [
+            {
+              "name": "*fill*",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 63
+                }
+              ]
+            },
+            {
+              "name": "*fill*",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 233
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "apps/blinky",
+      "files": [
+        {
+          "name": "main.o",
+          "sym": [
+            {
+              "name": "COMMON",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "g_task1_loops",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "startup",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 56
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/hw/bsp/nordic_pca10040",
+      "files": [
+        {
+          "name": "sbrk.o",
+          "sym": [
+            {
+              "name": ".data",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "_sbrkInit",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "gcc_startup_nrf52.o",
+          "sym": [
+            {
+              "name": ".isr_vector",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 216
+                }
+              ]
+            },
+            {
+              "name": ".stack",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 432
+                }
+              ]
+            },
+            {
+              "name": ".text",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 112
+                }
+              ]
+            },
+            {
+              "name": "exidx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 8
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_bsp.o",
+          "sym": [
+            {
+              "name": "hal_bsp_flash_dev",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "hal_bsp_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 14
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/hw/cmsis-core",
+      "files": [
+        {
+          "name": "cmsis_nvic.o",
+          "sym": [
+            {
+              "name": "NVIC_Relocate",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 40
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/hw/drivers/uart/uart_hal",
+      "files": [
+        {
+          "name": "uart_hal.o",
+          "sym": [
+            {
+              "name": "uart_hal_blocking_tx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_close",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 104
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_open",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 114
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_resume",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 44
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_start_rx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_start_tx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "uart_hal_suspend",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 40
+                }
+              ]
+            },
+            {
+              "name": "unlikely",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 14
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/hw/hal",
+      "files": [
+        {
+          "name": "hal_flash.o",
+          "sym": [
+            {
+              "name": "hal_flash_check_addr",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 28
+                }
+              ]
+            },
+            {
+              "name": "hal_flash_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "hal_flash_read",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 68
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/hw/mcu/nordic/nrf52xxx",
+      "files": [
+        {
+          "name": "hal_os_tick.o",
+          "sym": [
+            {
+              "name": "COMMON",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 40
+                }
+              ]
+            },
+            {
+              "name": "nrf52_os_tick_set_ocmp",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 64
+                }
+              ]
+            },
+            {
+              "name": "nrf52_timer_handler",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 80
+                }
+              ]
+            },
+            {
+              "name": "os_tick_idle",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 68
+                }
+              ]
+            },
+            {
+              "name": "os_tick_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 148
+                }
+              ]
+            },
+            {
+              "name": "sub24",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 46
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "system_nrf52.o",
+          "sym": [
+            {
+              "name": "SystemCoreClock",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "SystemInit",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 480
+                }
+              ]
+            },
+            {
+              "name": "errata_16",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 52
+                }
+              ]
+            },
+            {
+              "name": "errata_31",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 64
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_timer.o",
+          "sym": [
+            {
+              "name": "__NVIC_SetPendingIRQ",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 32
+                }
+              ]
+            },
+            {
+              "name": "hal_timer_config",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 212
+                }
+              ]
+            },
+            {
+              "name": "hal_timer_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 88
+                }
+              ]
+            },
+            {
+              "name": "hal_timer_read_bsptimer",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 56
+                }
+              ]
+            },
+            {
+              "name": "nrf52_hal_timers",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 24
+                }
+              ]
+            },
+            {
+              "name": "nrf52_timer0_irq_handler",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 168
+                }
+              ]
+            },
+            {
+              "name": "nrf_timer_set_ocmp",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 126
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_system.o",
+          "sym": [
+            {
+              "name": "hal_debugger_connected",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "hal_system_clock_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 60
+                }
+              ]
+            },
+            {
+              "name": "hal_system_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "hal_system_reset",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 48
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_gpio.o",
+          "sym": [
+            {
+              "name": "hal_gpio_init_out",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 38
+                }
+              ]
+            },
+            {
+              "name": "hal_gpio_read",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 34
+                }
+              ]
+            },
+            {
+              "name": "hal_gpio_toggle",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 26
+                }
+              ]
+            },
+            {
+              "name": "hal_gpio_write",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 24
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_uart.o",
+          "sym": [
+            {
+              "name": "hal_uart_blocking_tx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 80
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_close",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 52
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_config",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 408
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 64
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_init_cbs",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_start_rx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 56
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_start_tx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 72
+                }
+              ]
+            },
+            {
+              "name": "hal_uart_tx_fill_buf",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "uart0",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 28
+                }
+              ]
+            },
+            {
+              "name": "uart0_irq_handler",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 128
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_watchdog.o",
+          "sym": [
+            {
+              "name": "hal_watchdog_enable",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "hal_watchdog_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 112
+                }
+              ]
+            },
+            {
+              "name": "hal_watchdog_tickle",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "nrf52_wdt_irq_handler",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "nrf52_periph.o",
+          "sym": [
+            {
+              "name": "nrf52_periph_create",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 90
+                }
+              ]
+            },
+            {
+              "name": "os_bsp_uart0",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 60
+                }
+              ]
+            },
+            {
+              "name": "os_bsp_uart0_cfg",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 4
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "hal_flash.o",
+          "sym": [
+            {
+              "name": "nrf52k_flash_dev",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 24
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_erase_sector",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 76
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_funcs",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 28
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_read",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 14
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_sector_info",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 32
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_wait_ready",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "nrf52k_flash_write",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 200
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/kernel/os",
+      "files": [
+        {
+          "name": "HAL_CM4.o",
+          "sym": [
+            {
+              "name": ".text",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 200
+                }
+              ]
+            },
+            {
+              "name": "exidx",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os.o",
+          "sym": [
+            {
+              "name": "COMMON",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 217
+                }
+              ]
+            },
+            {
+              "name": "g_idle_task_stack",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 256
+                }
+              ]
+            },
+            {
+              "name": "g_os_main_stack",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4096
+                }
+              ]
+            },
+            {
+              "name": "os_idle_task",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 124
+                }
+              ]
+            },
+            {
+              "name": "os_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 149
+                }
+              ]
+            },
+            {
+              "name": "os_init_idle_task",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 93
+                }
+              ]
+            },
+            {
+              "name": "os_main",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 22
+                }
+              ]
+            },
+            {
+              "name": "os_pkg_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 48
+                }
+              ]
+            },
+            {
+              "name": "os_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 26
+                }
+              ]
+            },
+            {
+              "name": "os_started",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_fault.o",
+          "sym": [
+            {
+              "name": "__assert_func",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "os_default_irq",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 24
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_time.o",
+          "sym": [
+            {
+              "name": "basetod",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 48
+                }
+              ]
+            },
+            {
+              "name": "os_deltatime",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 76
+                }
+              ]
+            },
+            {
+              "name": "os_time_advance",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 120
+                }
+              ]
+            },
+            {
+              "name": "os_time_delay",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 40
+                }
+              ]
+            },
+            {
+              "name": "os_time_get",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_msys.o",
+          "sym": [
+            {
+              "name": "g_msys_pool_list",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "os_msys_1_data",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 3504
+                }
+              ]
+            },
+            {
+              "name": "os_msys_1_mbuf_pool",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "os_msys_1_mempool",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 28
+                }
+              ]
+            },
+            {
+              "name": "os_msys_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 103
+                }
+              ]
+            },
+            {
+              "name": "os_msys_register",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 64
+                }
+              ]
+            },
+            {
+              "name": "os_msys_reset",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_dev.o",
+          "sym": [
+            {
+              "name": "g_os_dev_list",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "os_dev_create",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 136
+                }
+              ]
+            },
+            {
+              "name": "os_dev_initialize",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 32
+                }
+              ]
+            },
+            {
+              "name": "os_dev_initialize_all",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 40
+                }
+              ]
+            },
+            {
+              "name": "os_dev_reset",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_sched.o",
+          "sym": [
+            {
+              "name": "g_os_run_list",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "g_os_sleep_list",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "os_sched",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "os_sched_ctx_sw_hook",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 44
+                }
+              ]
+            },
+            {
+              "name": "os_sched_get_current_task",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "os_sched_insert",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 76
+                }
+              ]
+            },
+            {
+              "name": "os_sched_next_task",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "os_sched_os_timer_exp",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 60
+                }
+              ]
+            },
+            {
+              "name": "os_sched_resort",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "os_sched_set_current_task",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "os_sched_sleep",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 116
+                }
+              ]
+            },
+            {
+              "name": "os_sched_wakeup",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 104
+                }
+              ]
+            },
+            {
+              "name": "os_sched_wakeup_ticks",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 52
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_sanity.o",
+          "sym": [
+            {
+              "name": "g_os_sanity_check_list",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_check_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 14
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_check_list_lock",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 28
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_check_list_unlock",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 24
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_check_register",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 32
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "os_sanity_run",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 80
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_arch_arm.o",
+          "sym": [
+            {
+              "name": "os_arch_ctx_sw",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "os_arch_in_critical",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 10
+                }
+              ]
+            },
+            {
+              "name": "os_arch_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "os_arch_os_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 148
+                }
+              ]
+            },
+            {
+              "name": "os_arch_os_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 84
+                }
+              ]
+            },
+            {
+              "name": "os_arch_restore_sr",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 6
+                }
+              ]
+            },
+            {
+              "name": "os_arch_save_sr",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "os_arch_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 48
+                }
+              ]
+            },
+            {
+              "name": "os_arch_task_stack_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 54
+                }
+              ]
+            },
+            {
+              "name": "os_flags",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "timer_handler",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 6
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_callout.o",
+          "sym": [
+            {
+              "name": "os_callout_tick",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 84
+                }
+              ]
+            },
+            {
+              "name": "os_callout_wakeup_ticks",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 48
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_cputime.o",
+          "sym": [
+            {
+              "name": "os_cputime_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 8
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_eventq.o",
+          "sym": [
+            {
+              "name": "os_eventq_dflt_get",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "os_eventq_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "os_eventq_main",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "os_eventq_put",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 104
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_mbuf.o",
+          "sym": [
+            {
+              "name": "os_mbuf_pool_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 10
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_mempool.o",
+          "sym": [
+            {
+              "name": "os_mempool_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 18
+                }
+              ]
+            },
+            {
+              "name": "os_mempool_init_internal",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 104
+                }
+              ]
+            },
+            {
+              "name": "os_mempool_module_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_mutex.o",
+          "sym": [
+            {
+              "name": "os_mutex_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            },
+            {
+              "name": "os_mutex_pend",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 220
+                }
+              ]
+            },
+            {
+              "name": "os_mutex_release",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 160
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "os_task.o",
+          "sym": [
+            {
+              "name": "os_task_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 228
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/libc/baselibc",
+      "files": [
+        {
+          "name": "start.o",
+          "sym": [
+            {
+              "name": "_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 2
+                }
+              ]
+            },
+            {
+              "name": "_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 20
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "memcpy.o",
+          "sym": [
+            {
+              "name": "memcpy",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 26
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "memset.o",
+          "sym": [
+            {
+              "name": "memset",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "strlen.o",
+          "sym": [
+            {
+              "name": "strlen",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/sys/flash_map",
+      "files": [
+        {
+          "name": "flash_map.o",
+          "sym": [
+            {
+              "name": "COMMON",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 8
+                }
+              ]
+            },
+            {
+              "name": "flash_area_open",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 60
+                }
+              ]
+            },
+            {
+              "name": "flash_area_read",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 36
+                }
+              ]
+            },
+            {
+              "name": "flash_map_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 172
+                }
+              ]
+            },
+            {
+              "name": "mfg_areas",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 120
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/sys/log/modlog",
+      "files": [
+        {
+          "name": "modlog.o",
+          "sym": [
+            {
+              "name": "modlog_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 2
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/sys/mfg",
+      "files": [
+        {
+          "name": "mfg.o",
+          "sym": [
+            {
+              "name": "mfg_init",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 92
+                }
+              ]
+            },
+            {
+              "name": "mfg_initialized",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 1
+                }
+              ]
+            },
+            {
+              "name": "mfg_mmrs",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 24
+                }
+              ]
+            },
+            {
+              "name": "mfg_num_mmrs",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "mfg_open",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 16
+                }
+              ]
+            },
+            {
+              "name": "mfg_read_next_mmr",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 164
+                }
+              ]
+            },
+            {
+              "name": "mfg_read_tlv_body",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 100
+                }
+              ]
+            },
+            {
+              "name": "mfg_read_tlv_flash_area",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 6
+                }
+              ]
+            },
+            {
+              "name": "mfg_read_tlv_mmr_ref",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 6
+                }
+              ]
+            },
+            {
+              "name": "mfg_seek_next",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 128
+                }
+              ]
+            },
+            {
+              "name": "mfg_seek_next_with_type",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 22
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/sys/sysinit",
+      "files": [
+        {
+          "name": "sysinit.o",
+          "sym": [
+            {
+              "name": "COMMON",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 1
+                }
+              ]
+            },
+            {
+              "name": "sysinit_dflt_panic_cb",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 6
+                }
+              ]
+            },
+            {
+              "name": "sysinit_end",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            },
+            {
+              "name": "sysinit_panic_cb",
+              "areas": [
+                {
+                  "name": "RAM",
+                  "size": 4
+                }
+              ]
+            },
+            {
+              "name": "sysinit_start",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 12
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "@apache-mynewt-core/util/mem",
+      "files": [
+        {
+          "name": "mem.o",
+          "sym": [
+            {
+              "name": "mem_init_mbuf_pool",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 50
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "name": "blinky-nordic_pca10040-sysinit-app",
+      "files": [
+        {
+          "name": "blinky-nordic_pca10040-sysflash.o",
+          "sym": [
+            {
+              "name": "sysflash_map_dflt",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 72
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "name": "blinky-nordic_pca10040-sysinit-app.o",
+          "sym": [
+            {
+              "name": "sysinit_app",
+              "areas": [
+                {
+                  "name": "FLASH",
+                  "size": 22
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
diff --git a/image/testdata/sign-key-pub.der b/image/testdata/sign-key-pub.der
new file mode 100644
index 0000000..bd50d37
--- /dev/null
+++ b/image/testdata/sign-key-pub.der
Binary files differ
diff --git a/image/testdata/sign-key.pem b/image/testdata/sign-key.pem
new file mode 100644
index 0000000..4dd360a
--- /dev/null
+++ b/image/testdata/sign-key.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEApydXFYw0I2tS5/Z7o/e/AOTxcQsQA80L02KfAqMT6LsLDGLV
+1DKfKLLgCOdBjcafKw4updsvW9dPqCB6q4Y58j99D2B7fzw+HIWH5IyL73Nt/ytI
+cJ0CSL/bfGpaI0dY1V92ooEq8cp2ZZCjrTCWmg/oP5SQ9aDEbpTYh1VdHbsxObMQ
+6A/aaQa1hevjcE7gTFOntKN1QDLaDZXz9CqIkiuNQuQhXA0zxDJkWwu7U18fVpxa
+3ozdU0nLRQp6Edo09MulskwJYF6VCbNEesn/7rSbwwI3Wa5RFWcQPRlO2SdqRiYl
+XSX2fYhp7r/tkBdJSYLns0193zTixECQwjI9BQIDAQABAoIBAB7zWt2ji1fvnHdV
+HYm76wMYYViEKt/5TLJEdZsAZURXtfECMAPNp8jabj9XyrycxYYsZxjQ4BEKajaA
+ZRZzkTE47kg1nkht+DZBx2rbV2HsJrbz5cLsX6rm05ZS/wO/R0SjG411i2UgDxI5
+WQVNlOVMAr4bHUhOD3FGYF2WwdoqLZTXnOm+1MOQgi8wpYe8fGzumeiGfW5L0NCx
+iHAVdqPAQsK81wTyRuLgYmfV0e4l8sqjH1lHK+7qk9y1EYmXyrN6fgelZgahS1b5
+GbQJGX8QQde8ATYdu5W933+cRytrTHgI0VvptcmZ6zsIs4FwlrDZdhFbpkin3CuN
+eIWqJTUCgYEAzyEtdVbI+mi+rp4a+egN+yEmfg5fhUkS07tIl0tBQa1zAYnyumZo
+wJIBhMYjqFj1Z7e4Gwq8aKZK/y+9DSLzAQ/699i7TM+Qd3H4sACt9c2PWDpCNtZF
+Emu9Te7RDp0cnyE8NEJ3J1ibFQ0pk/mdX/hQ+CYkJv5u9ul3Te2ffQMCgYEAzpeU
+O30dTh0n8fwSYQh0HOU+GyzJQ9j5RNxDQRMGtjEBkcGEMXxViIq/CIukAJVIAdL1
+Vl7eP4MRF5RtrRfivsjA3hKJYYkpYKa4A1rOpfDs4Ex7YLrKD4Y2UQ1f4hGAs5Kr
+mEZO1CMuq2A0+wLtxJRswM51prLoSlW9wxy/61cCgYEAqp9n9PrSgAR83xb6ndZc
+ffxm2vw4D3GMgsIKICcr0FBzJldejdIChG9BtQALK4hsT0316MDFR2eE7AWFNCcQ
+ClYBpNzyHWn2VY6bD1Df/FWiuUj0dnu3Vl9OB76sk980TplwIJSH1u+UgJjhITZE
+P2QsPt4cdcqt2dOkJZuS/8UCgYBo3UQe1ikz51TJXfwuSM43hJ17ycX3rIEK1QtG
+UtQLUuDLDYF+ZPA9uL+zJL6AlUXRtzVVPB5v+qWIZI0vWXp9AQX1M0+MtMTODJJH
+EabnUF3MlMXjmazLKIMVrUZISD4d6Is1ZirJP3qG/vSlnRz3tadmTuYlUZbbdJ44
+FbXNTQKBgBTwNcuDR6ExhSclY/pgAq6OU5l8Os0qHNjR+Hch2/vttx7E35a5m59l
+68ns5xGVxeHiadFmx7YDf19wWZtOMMvKGeUXUC4ENhwHVLaips6ZS6IULn3Uj/sG
+ZFahALjXYXt8DNM0+jUBQzzED17y96sIj4URORAUVRSnRsjLjaEP
+-----END RSA PRIVATE KEY-----
diff --git a/image/testdata/truncated.img b/image/testdata/truncated.img
new file mode 100644
index 0000000..12174c2
--- /dev/null
+++ b/image/testdata/truncated.img
Binary files differ
diff --git a/image/v1.go b/image/v1.go
index 67a451f..0b82086 100644
--- a/image/v1.go
+++ b/image/v1.go
@@ -30,12 +30,11 @@
 	"crypto/rsa"
 	"crypto/sha256"
 	"encoding/binary"
-	"encoding/hex"
 	"io"
 	"io/ioutil"
 
-	"mynewt.apache.org/newt/artifact/sec"
-	"mynewt.apache.org/newt/util"
+	"github.com/apache/mynewt-artifact/errors"
+	"github.com/apache/mynewt-artifact/sec"
 )
 
 const IMAGEv1_MAGIC = 0x96f3b83c /* Image header magic */
@@ -95,10 +94,10 @@
 func (img *ImageV1) Hash() ([]byte, error) {
 	tlvs := img.FindTlvs(IMAGEv1_TLV_SHA256)
 	if len(tlvs) == 0 {
-		return nil, util.FmtNewtError("Image does not contain hash TLV")
+		return nil, errors.Errorf("image does not contain hash TLV")
 	}
 	if len(tlvs) > 1 {
-		return nil, util.FmtNewtError("Image contains %d hash TLVs", len(tlvs))
+		return nil, errors.Errorf("image contains %d hash TLVs", len(tlvs))
 	}
 
 	return tlvs[0].Data, nil
@@ -112,14 +111,14 @@
 
 	err := binary.Write(w, binary.LittleEndian, &img.Header)
 	if err != nil {
-		return offs, util.ChildNewtError(err)
+		return offs, errors.Wrapf(err, "failed to write image header")
 	}
 	offset += IMAGE_HEADER_SIZE
 
 	offs.Body = offset
 	size, err := w.Write(img.Body)
 	if err != nil {
-		return offs, util.ChildNewtError(err)
+		return offs, errors.Wrapf(err, "failed to write image body")
 	}
 	offset += size
 
@@ -127,7 +126,7 @@
 		offs.Tlvs = append(offs.Tlvs, offset)
 		size, err := tlv.Write(w)
 		if err != nil {
-			return offs, util.ChildNewtError(err)
+			return offs, errors.Wrapf(err, "failed to write image TLV")
 		}
 		offset += size
 	}
@@ -174,7 +173,7 @@
 		case "P-256":
 			return IMAGEv1_F_ECDSA256_SHA256, nil
 		default:
-			return 0, util.FmtNewtError("Unsupported ECC curve")
+			return 0, errors.Errorf("unsupported ECC curve")
 		}
 	}
 }
@@ -211,7 +210,7 @@
 			rand.Reader, key, crypto.SHA256, hash)
 	}
 	if err != nil {
-		return nil, util.FmtNewtError("Failed to compute signature: %s", err)
+		return nil, errors.Wrapf(err, "failed to compute signature")
 	}
 
 	return signature, nil
@@ -241,20 +240,19 @@
 
 	sigLen := key.SigLen()
 	if len(sig) > int(sigLen) {
-		return ImageTlv{}, util.FmtNewtError("Something is really wrong\n")
+		return ImageTlv{}, errors.Errorf("signature truncated")
 	}
 
 	b := &bytes.Buffer{}
 
 	if _, err := b.Write(sig); err != nil {
-		return ImageTlv{},
-			util.FmtNewtError("Failed to append sig: %s", err.Error())
+		return ImageTlv{}, errors.Wrapf(err, "failed to append sig")
 	}
 
 	pad := make([]byte, int(sigLen)-len(sig))
 	if _, err := b.Write(pad); err != nil {
-		return ImageTlv{}, util.FmtNewtError(
-			"Failed to serialize image trailer: %s", err.Error())
+		return ImageTlv{}, errors.Wrapf(err,
+			"failed to serialize image trailer")
 	}
 
 	return ImageTlv{
@@ -284,7 +282,7 @@
 
 	add := func(itf interface{}) error {
 		if err := binary.Write(hash, binary.LittleEndian, itf); err != nil {
-			return util.FmtNewtError("Failed to hash data: %s", err.Error())
+			return errors.Wrapf(err, "failed to hash data")
 		}
 
 		return nil
@@ -319,8 +317,8 @@
 	ri := ImageV1{}
 
 	if len(ic.SigKeys) > 1 {
-		return ri, util.FmtNewtError(
-			"V1 image format only allows one key, %d keys specified",
+		return ri, errors.Errorf(
+			"v1 image format only allows one key, %d keys specified",
 			len(ic.SigKeys))
 	}
 
@@ -349,8 +347,8 @@
 		 * the image when it is padded.
 		 */
 		if ic.HeaderSize < IMAGE_HEADER_SIZE {
-			return ri, util.FmtNewtError("Image header must be at "+
-				"least %d bytes", IMAGE_HEADER_SIZE)
+			return ri, errors.Errorf(
+				"image header must be at least %d bytes", IMAGE_HEADER_SIZE)
 		}
 
 		hdr.HdrSz = uint16(ic.HeaderSize)
@@ -372,8 +370,8 @@
 		// the image when it is padded.
 		extra := ic.HeaderSize - IMAGE_HEADER_SIZE
 		if extra < 0 {
-			return ri, util.FmtNewtError("Image header must be at "+
-				"least %d bytes", IMAGE_HEADER_SIZE)
+			return ri, errors.Errorf(
+				"image header must be at least %d bytes", IMAGE_HEADER_SIZE)
 		}
 
 		hdr.HdrSz = uint16(ic.HeaderSize)
@@ -387,9 +385,6 @@
 		return ri, err
 	}
 
-	util.StatusMessage(util.VERBOSITY_VERBOSE,
-		"Computed Hash for image as %s\n", hex.EncodeToString(hashBytes))
-
 	/*
 	 * Followed by data.
 	 */
@@ -399,16 +394,14 @@
 	for {
 		cnt, err := r.Read(dataBuf)
 		if err != nil && err != io.EOF {
-			return ri, util.FmtNewtError(
-				"Failed to read from image body: %s", err.Error())
+			return ri, errors.Wrapf(err, "failed to read from image body")
 		}
 		if cnt == 0 {
 			break
 		}
 
 		if _, err = w.Write(dataBuf[0:cnt]); err != nil {
-			return ri, util.FmtNewtError(
-				"Failed to write to image body: %s", err.Error())
+			return ri, errors.Wrapf(err, "failed to write to image body")
 		}
 	}
 	ri.Body = w.Bytes()
@@ -448,8 +441,7 @@
 
 	srcBin, err := ioutil.ReadFile(opts.SrcBinFilename)
 	if err != nil {
-		return ImageV1{}, util.FmtNewtError(
-			"Can't read app binary: %s", err.Error())
+		return ImageV1{}, errors.Wrapf(err, "can't read app binary")
 	}
 
 	ic.Body = srcBin
@@ -471,8 +463,7 @@
 
 		pubKeBytes, err := ioutil.ReadFile(opts.SrcEncKeyFilename)
 		if err != nil {
-			return ImageV1{}, util.FmtNewtError(
-				"Error reading pubkey file: %s", err.Error())
+			return ImageV1{}, errors.Wrapf(err, "error reading pubkey file")
 		}
 		cipherSecret, err := GenerateCipherSecret(pubKeBytes, plainSecret)
 		if err != nil {
diff --git a/image/verify.go b/image/verify.go
new file mode 100644
index 0000000..0ac2b25
--- /dev/null
+++ b/image/verify.go
@@ -0,0 +1,106 @@
+/**
+ * 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.
+ */
+
+package image
+
+import (
+	"bytes"
+	"encoding/hex"
+
+	"github.com/apache/mynewt-artifact/errors"
+	"github.com/apache/mynewt-artifact/manifest"
+)
+
+// VerifyManifest compares an image's structure to its manifest.  It returns
+// an error if the image doesn't match the manifest.
+func (img *Image) VerifyManifest(man manifest.Manifest) error {
+	ver, err := ParseVersion(man.Version)
+	if err != nil {
+		return errors.Wrapf(err, "manifest contains invalid `version` field")
+	}
+
+	if ver.Major != img.Header.Vers.Major ||
+		ver.Minor != img.Header.Vers.Minor ||
+		ver.Rev != img.Header.Vers.Rev ||
+		ver.BuildNum != img.Header.Vers.BuildNum {
+
+		return errors.Errorf(
+			"manifest version different from image header: man=%s img=%s",
+			ver.String(), img.Header.Vers.String())
+	}
+
+	var imgHash string
+	if hash, err := img.Hash(); err == nil {
+		imgHash = hex.EncodeToString(hash)
+	}
+
+	// A manifest contains two image hashes: `id` and `image_hash`.  Check
+	// both.
+
+	checkHash := func(manHash string) error {
+		if imgHash != manHash {
+			return errors.Errorf(
+				"manifest image hash different from image TLV: man=%s img=%s",
+				manHash, imgHash)
+		}
+		return nil
+	}
+
+	if err := checkHash(man.BuildID); err != nil {
+		return err
+	}
+	if err := checkHash(man.ImageHash); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// Verify checks an image's structure and internal consistency.  It returns
+// an error if the image is incorrect.
+func (img *Image) Verify() error {
+	// Verify the hash.
+
+	haveHash, err := img.Hash()
+	if err != nil {
+		return err
+	}
+
+	wantHash, err := img.CalcHash()
+	if err != nil {
+		return err
+	}
+
+	if !bytes.Equal(haveHash, wantHash) {
+		return errors.Errorf(
+			"image manifest contains incorrect hash: have=%x want=%x",
+			haveHash, wantHash)
+	}
+
+	// Verify that each TLV has a valid "type" field.
+	for _, t := range img.Tlvs {
+		if !ImageTlvTypeIsValid(t.Header.Type) {
+			return errors.Errorf(
+				"image contains TLV with invalid `type` field: %d",
+				t.Header.Type)
+		}
+	}
+
+	return nil
+}
diff --git a/manifest/manifest.go b/manifest/manifest.go
index 95c76c6..7508bc0 100644
--- a/manifest/manifest.go
+++ b/manifest/manifest.go
@@ -23,8 +23,9 @@
 	"encoding/json"
 	"io"
 	"io/ioutil"
+	"strings"
 
-	"mynewt.apache.org/newt/util"
+	"github.com/apache/mynewt-artifact/errors"
 )
 
 /*
@@ -81,33 +82,47 @@
 	LoaderPkgSizes []*ManifestSizePkg `json:"loader_pkgsz,omitempty"`
 }
 
+// ReadManifest reads a JSON manifest from a file.
 func ReadManifest(path string) (Manifest, error) {
 	m := Manifest{}
 
 	content, err := ioutil.ReadFile(path)
 	if err != nil {
-		return m, util.ChildNewtError(err)
+		return m, errors.Wrapf(err, "failed to read manifest file")
 	}
 
 	if err := json.Unmarshal(content, &m); err != nil {
-		return m, util.FmtNewtError(
-			"Failure decoding manifest with path \"%s\": %s",
-			path, err.Error())
+		return m, errors.Wrapf(
+			err, "failure decoding manifest with path \"%s\"", path)
 	}
 
 	return m, nil
 }
 
+// Write serializes a manifest as JSON and writes it to the given writer.
 func (m *Manifest) Write(w io.Writer) (int, error) {
 	buffer, err := json.MarshalIndent(m, "", "  ")
 	if err != nil {
-		return 0, util.FmtNewtError("Cannot encode manifest: %s", err.Error())
+		return 0, errors.Wrapf(err, "Cannot encode manifest")
 	}
 
 	cnt, err := w.Write(buffer)
 	if err != nil {
-		return 0, util.FmtNewtError("Cannot write manifest: %s", err.Error())
+		return 0, errors.Wrapf(err, "Cannot write manifest")
 	}
 
 	return cnt, nil
 }
+
+// FindTargetVar searches a manifest's target definition for a setting with
+// the specified key.  Examples of keys are: "app", "bsp", and "syscfg".
+func (m *Manifest) FindTargetVar(key string) string {
+	for _, tv := range m.TgtVars {
+		parts := strings.SplitN(tv, "=", 2)
+		if len(parts) == 2 && parts[0] == key {
+			return parts[1]
+		}
+	}
+
+	return ""
+}
diff --git a/manifest/mfg_manifest.go b/manifest/mfg_manifest.go
index f2c506c..f742e12 100644
--- a/manifest/mfg_manifest.go
+++ b/manifest/mfg_manifest.go
@@ -20,11 +20,13 @@
 package manifest
 
 import (
+	"encoding/hex"
 	"encoding/json"
 	"io/ioutil"
 
-	"mynewt.apache.org/newt/artifact/flash"
-	"mynewt.apache.org/newt/util"
+	"github.com/apache/mynewt-artifact/errors"
+	"github.com/apache/mynewt-artifact/flash"
+	"github.com/apache/mynewt-artifact/sec"
 )
 
 type MfgManifestTarget struct {
@@ -48,7 +50,6 @@
 	Hash      bool                 `json:"hash_present"`
 	FlashMap  bool                 `json:"flash_map_present"`
 	Mmrs      []MfgManifestMetaMmr `json:"mmrs,omitempty"`
-	// XXX: refhash
 }
 
 type MfgManifestSig struct {
@@ -66,6 +67,7 @@
 	BinPath    string            `json:"bin_path"`
 	HexPath    string            `json:"hex_path"`
 	Bsp        string            `json:"bsp"`
+	EraseVal   byte              `json:"erase_val"`
 	Signatures []MfgManifestSig  `json:"signatures,omitempty"`
 	FlashAreas []flash.FlashArea `json:"flash_map"`
 
@@ -73,29 +75,111 @@
 	Meta    *MfgManifestMeta    `json:"meta,omitempty"`
 }
 
-func ReadMfgManifest(path string) (MfgManifest, error) {
-	m := MfgManifest{}
-
-	content, err := ioutil.ReadFile(path)
-	if err != nil {
-		return m, util.ChildNewtError(err)
+// ReadMfgManifest reads a JSON mfg manifest from a byte slice and produces an
+// MfgManifest object.
+func ParseMfgManifest(jsonText []byte) (MfgManifest, error) {
+	m := MfgManifest{
+		// Backwards compatibility: assume 0xff if unspecified.
+		EraseVal: 0xff,
 	}
 
-	if err := json.Unmarshal(content, &m); err != nil {
-		return m, util.FmtNewtError(
-			"Failure decoding mfg manifest with path \"%s\": %s",
-			path, err.Error())
+	if err := json.Unmarshal(jsonText, &m); err != nil {
+		return m, errors.Wrapf(err, "failure decoding mfg manifest")
 	}
 
 	return m, nil
 }
 
+// ReadMfgManifest reads a JSON mfg manifest from a file and produces an
+// MfgManifest object.
+func ReadMfgManifest(path string) (MfgManifest, error) {
+	content, err := ioutil.ReadFile(path)
+	if err != nil {
+		return MfgManifest{}, errors.Wrapf(err,
+			"failed to read mfg manifest file")
+	}
+
+	m, err := ParseMfgManifest(content)
+	if err != nil {
+		return m, errors.Wrapf(err, "path=%s", path)
+	}
+
+	return m, nil
+}
+
+// IsBoot indicates whether an mfg manifest target is a boot loader.
+func (mt *MfgManifestTarget) IsBoot() bool {
+	return mt.BinPath != ""
+}
+
+// MarshalJson produces a JSON representation of an mfg manifest.
 func (m *MfgManifest) MarshalJson() ([]byte, error) {
 	buffer, err := json.MarshalIndent(m, "", "  ")
 	if err != nil {
-		return nil, util.FmtNewtError(
-			"Cannot encode mfg manifest: %s", err.Error())
+		return nil, errors.Wrapf(err, "cannot encode mfg manifest")
 	}
 
 	return buffer, nil
 }
+
+// FindFlashAreaDevOff searches an mfg manifest for a flash area with the
+// specified device and offset.
+func (m *MfgManifest) FindFlashAreaDevOff(device int, offset int) *flash.FlashArea {
+	for i, _ := range m.FlashAreas {
+		fa := &m.FlashAreas[i]
+		if fa.Device == device && fa.Offset == offset {
+			return fa
+		}
+	}
+
+	return nil
+}
+
+// FindFlashAreaName searches an mfg manifest for a flash area with the
+// specified name.
+func (m *MfgManifest) FindFlashAreaName(name string) *flash.FlashArea {
+	for i, _ := range m.FlashAreas {
+		fa := &m.FlashAreas[i]
+		if fa.Name == name {
+			return fa
+		}
+	}
+
+	return nil
+}
+
+// SecSig converts the provided mfg manifest signature into a sec.Sig object.
+func (ms *MfgManifestSig) SecSig() (sec.Sig, error) {
+	keyHash, err := hex.DecodeString(ms.Key)
+	if err != nil {
+		return sec.Sig{}, errors.Errorf(
+			"invalid hex-encoded key hash: %s", ms.Key)
+	}
+
+	data, err := hex.DecodeString(ms.Sig)
+	if err != nil {
+		return sec.Sig{}, errors.Errorf(
+			"invalid hex-encoded signature: %s", ms.Sig)
+	}
+
+	return sec.Sig{
+		KeyHash: keyHash,
+		Data:    data,
+	}, nil
+}
+
+// SecSigs converts all the signutures in the provided mfg manifest into
+// sec.Sig objects.
+func (m *MfgManifest) SecSigs() ([]sec.Sig, error) {
+	var sigs []sec.Sig
+	for _, ms := range m.Signatures {
+		s, err := ms.SecSig()
+		if err != nil {
+			return nil, err
+		}
+
+		sigs = append(sigs, s)
+	}
+
+	return sigs, nil
+}
diff --git a/mfg/map_meta.go b/mfg/map_meta.go
index b16c37e..99714ff 100644
--- a/mfg/map_meta.go
+++ b/mfg/map_meta.go
@@ -25,7 +25,7 @@
 	"encoding/hex"
 	"encoding/json"
 
-	"mynewt.apache.org/newt/util"
+	"github.com/apache/mynewt-artifact/errors"
 )
 
 func (t *MetaTlv) bodyMap() (map[string]interface{}, error) {
@@ -33,8 +33,7 @@
 
 	readBody := func(dst interface{}) error {
 		if err := binary.Read(r, binary.LittleEndian, dst); err != nil {
-			return util.FmtNewtError(
-				"Error parsing TLV data: %s", err.Error())
+			return errors.Wrapf(err, "error parsing TLV data")
 		}
 		return nil
 	}
@@ -62,8 +61,7 @@
 		return body.Map(), nil
 
 	default:
-		return nil, util.FmtNewtError(
-			"Unknown meta TLV type: %d", t.Header.Type)
+		return nil, errors.Errorf("unknown meta TLV type: %d", t.Header.Type)
 	}
 }
 
@@ -88,7 +86,8 @@
 	}
 }
 
-func (t *MetaTlv) Map(offset int) map[string]interface{} {
+// Map produces a JSON-friendly map representation of an MMR TLV.
+func (t *MetaTlv) Map(index int, offset int) map[string]interface{} {
 	hmap := map[string]interface{}{
 		"_type_name": MetaTlvTypeName(t.Header.Type),
 		"type":       t.Header.Type,
@@ -105,12 +104,14 @@
 	}
 
 	return map[string]interface{}{
+		"_index":  index,
 		"_offset": offset,
 		"header":  hmap,
 		"data":    body,
 	}
 }
 
+// Map produces a JSON-friendly map representation of an MMR footer.
 func (f *MetaFooter) Map(offset int) map[string]interface{} {
 	return map[string]interface{}{
 		"_offset": offset,
@@ -120,13 +121,14 @@
 	}
 }
 
+// Map produces a JSON-friendly map representation of an MMR.
 func (m *Meta) Map(endOffset int) map[string]interface{} {
 	offsets := m.Offsets()
 	startOffset := endOffset - int(m.Footer.Size)
 
 	tlvs := []map[string]interface{}{}
 	for i, t := range m.Tlvs {
-		tlv := t.Map(startOffset + offsets.Tlvs[i])
+		tlv := t.Map(i, startOffset+offsets.Tlvs[i])
 		tlvs = append(tlvs, tlv)
 	}
 
@@ -141,12 +143,13 @@
 	}
 }
 
+// Json produces a JSON representation of an MMR.
 func (m *Meta) Json(offset int) (string, error) {
 	mmap := m.Map(offset)
 
 	bin, err := json.MarshalIndent(mmap, "", "    ")
 	if err != nil {
-		return "", util.ChildNewtError(err)
+		return "", errors.Wrapf(err, "failed to marshal MMR")
 	}
 
 	return string(bin), nil
diff --git a/mfg/meta.go b/mfg/meta.go
index 4521a89..1e7029c 100644
--- a/mfg/meta.go
+++ b/mfg/meta.go
@@ -25,7 +25,7 @@
 	"io"
 	"io/ioutil"
 
-	"mynewt.apache.org/newt/util"
+	"github.com/apache/mynewt-artifact/errors"
 )
 
 // The "manufacturing meta region" is located at the end of the boot loader
@@ -139,7 +139,7 @@
 func writeElem(elem interface{}, w io.Writer) error {
 	/* XXX: Assume target platform uses little endian. */
 	if err := binary.Write(w, binary.LittleEndian, elem); err != nil {
-		return util.ChildNewtError(err)
+		return errors.Wrapf(err, "failed to write MMR element")
 	}
 	return nil
 }
@@ -160,6 +160,47 @@
 	return sz, nil
 }
 
+// StructuredBody constructs the appropriate "body" object from a raw TLV
+// (e.g., MetaTlvBodyHash from a TLV with type=META_TLV_TYPE_HASH).
+func (tlv *MetaTlv) StructuredBody() (interface{}, error) {
+	r := bytes.NewReader(tlv.Data)
+
+	readBody := func(dst interface{}) error {
+		if err := binary.Read(r, binary.LittleEndian, dst); err != nil {
+			return errors.Wrapf(err, "error parsing TLV data")
+		}
+		return nil
+	}
+
+	switch tlv.Header.Type {
+	case META_TLV_TYPE_HASH:
+		var body MetaTlvBodyHash
+		if err := readBody(&body); err != nil {
+			return nil, err
+		}
+		return &body, nil
+
+	case META_TLV_TYPE_FLASH_AREA:
+		var body MetaTlvBodyFlashArea
+		if err := readBody(&body); err != nil {
+			return nil, err
+		}
+		return &body, nil
+
+	case META_TLV_TYPE_MMR_REF:
+		var body MetaTlvBodyMmrRef
+		if err := readBody(&body); err != nil {
+			return nil, err
+		}
+		return &body, nil
+
+	default:
+		return nil, errors.Errorf("unknown meta TLV type: %d", tlv.Header.Type)
+	}
+}
+
+// WritePlusOffsets writes a binary MMR to the given writer.  It returns the
+// offsets of the mfgimage components that got written.
 func (meta *Meta) WritePlusOffsets(w io.Writer) (MetaOffsets, error) {
 	mo := MetaOffsets{}
 	sz := 0
@@ -184,11 +225,14 @@
 	return mo, nil
 }
 
+// Offsets returns the offsets of each of an MMR's components if it were
+// serialized.
 func (meta *Meta) Offsets() MetaOffsets {
 	mo, _ := meta.WritePlusOffsets(ioutil.Discard)
 	return mo
 }
 
+// Write serializes and writes an MMR.
 func (meta *Meta) Write(w io.Writer) (int, error) {
 	mo, err := meta.WritePlusOffsets(w)
 	if err != nil {
@@ -198,10 +242,12 @@
 	return mo.TotalSize, nil
 }
 
+// Size calculates the total size of an MMR if it were serialied.
 func (meta *Meta) Size() int {
 	return meta.Offsets().TotalSize
 }
 
+// Bytes serializes an MMR to binary form.
 func (meta *Meta) Bytes() ([]byte, error) {
 	b := &bytes.Buffer{}
 
@@ -213,6 +259,8 @@
 	return b.Bytes(), nil
 }
 
+// FindTlvIndices searches an MMR for TLVs of the specified type and returns
+// their indices.
 func (meta *Meta) FindTlvIndices(typ uint8) []int {
 	indices := []int{}
 
@@ -225,6 +273,7 @@
 	return indices
 }
 
+// FindTlvIndices searches an MMR for all TLVs of the specified type.
 func (meta *Meta) FindTlvs(typ uint8) []*MetaTlv {
 	indices := meta.FindTlvIndices(typ)
 
@@ -236,15 +285,18 @@
 	return tlvs
 }
 
+// FindTlvIndices searches an MMR for the first TLV of the specified type.
 func (meta *Meta) FindFirstTlv(typ uint8) *MetaTlv {
-	indices := meta.FindTlvIndices(typ)
-	if len(indices) == 0 {
+	tlvs := meta.FindTlvs(typ)
+	if len(tlvs) == 0 {
 		return nil
 	}
 
-	return &meta.Tlvs[indices[0]]
+	return tlvs[0]
 }
 
+// HashOffset calculates the offset of the SHA256 TLV in an MMR if it were
+// serialized.
 func (meta *Meta) HashOffset() int {
 	mo := meta.Offsets()
 	indices := meta.FindTlvIndices(META_TLV_TYPE_HASH)
@@ -255,6 +307,7 @@
 	return META_TLV_HEADER_SZ + mo.Tlvs[indices[0]]
 }
 
+// ClearHash zeroes out an MMRs SHA256 TLV.
 func (meta *Meta) ClearHash() {
 	tlv := meta.FindFirstTlv(META_TLV_TYPE_HASH)
 	if tlv != nil {
@@ -262,6 +315,8 @@
 	}
 }
 
+// Hash locates an MMR's SHA256 TLV and returns its value.  It returns nil if
+// the MMR doesn't have a SHA256 TLV.
 func (meta *Meta) Hash() []byte {
 	tlv := meta.FindFirstTlv(META_TLV_TYPE_HASH)
 	if tlv == nil {
@@ -270,83 +325,19 @@
 	return tlv.Data
 }
 
-func parseMetaTlv(bin []byte) (MetaTlv, int, error) {
-	r := bytes.NewReader(bin)
-
-	tlv := MetaTlv{}
-	if err := binary.Read(r, binary.LittleEndian, &tlv.Header); err != nil {
-		return tlv, 0, util.FmtNewtError(
-			"Error reading TLV header: %s", err.Error())
-	}
-
-	data := make([]byte, tlv.Header.Size)
-	sz, err := r.Read(data)
-	if err != nil {
-		return tlv, 0, util.FmtNewtError(
-			"Error reading %d bytes of TLV data: %s",
-			tlv.Header.Size, err.Error())
-	}
-	if sz != len(data) {
-		return tlv, 0, util.FmtNewtError(
-			"Error reading %d bytes of TLV data: incomplete read",
-			tlv.Header.Size)
-	}
-	tlv.Data = data
-
-	return tlv, META_TLV_HEADER_SZ + int(tlv.Header.Size), nil
-}
-
-func parseMetaFooter(bin []byte) (MetaFooter, int, error) {
-	r := bytes.NewReader(bin)
-
-	var ftr MetaFooter
-	if err := binary.Read(r, binary.LittleEndian, &ftr); err != nil {
-		return ftr, 0, util.FmtNewtError(
-			"Error reading meta footer: %s", err.Error())
-	}
-
-	if ftr.Magic != META_MAGIC {
-		return ftr, 0, util.FmtNewtError(
-			"Meta footer contains invalid magic; exp:0x%08x, got:0x%08x",
-			META_MAGIC, ftr.Magic)
-	}
-
-	return ftr, META_FOOTER_SZ, nil
-}
-
-func ParseMeta(bin []byte) (Meta, int, error) {
-	if len(bin) < META_FOOTER_SZ {
-		return Meta{}, 0, util.FmtNewtError(
-			"Binary too small to accommodate meta footer; "+
-				"bin-size=%d ftr-size=%d", len(bin), META_FOOTER_SZ)
-	}
-
-	ftr, _, err := parseMetaFooter(bin[len(bin)-META_FOOTER_SZ:])
-	if err != nil {
-		return Meta{}, 0, err
-	}
-
-	if int(ftr.Size) > len(bin) {
-		return Meta{}, 0, util.FmtNewtError(
-			"Binary too small to accommodate meta region; "+
-				"bin-size=%d meta-size=%d", len(bin), ftr.Size)
-	}
-
-	ftrOff := len(bin) - META_FOOTER_SZ
-	off := len(bin) - int(ftr.Size)
-
-	tlvs := []MetaTlv{}
-	for off < ftrOff {
-		tlv, sz, err := parseMetaTlv(bin[off:])
-		if err != nil {
-			return Meta{}, 0, err
+// Clone performs a deep copy of an MMR.
+func (meta *Meta) Clone() Meta {
+	tlvs := make([]MetaTlv, len(meta.Tlvs))
+	for i, src := range meta.Tlvs {
+		tlvs[i] = MetaTlv{
+			Header: src.Header,
+			Data:   make([]byte, len(src.Data)),
 		}
-		tlvs = append(tlvs, tlv)
-		off += sz
+		copy(tlvs[i].Data, src.Data)
 	}
 
 	return Meta{
 		Tlvs:   tlvs,
-		Footer: ftr,
-	}, off, nil
+		Footer: meta.Footer,
+	}
 }
diff --git a/mfg/mfg.go b/mfg/mfg.go
index 2d5df83..2667003 100644
--- a/mfg/mfg.go
+++ b/mfg/mfg.go
@@ -22,7 +22,8 @@
 import (
 	"crypto/sha256"
 
-	"mynewt.apache.org/newt/util"
+	"github.com/apache/mynewt-artifact/errors"
+	"github.com/apache/mynewt-artifact/flash"
 )
 
 const MFG_BIN_IMG_FILENAME = "mfgimg.bin"
@@ -37,23 +38,9 @@
 	MetaOff int
 }
 
-func Parse(data []byte, metaEndOff int, eraseVal byte) (Mfg, error) {
-	m := Mfg{
-		Bin: data,
-	}
-
-	if metaEndOff >= 0 {
-		meta, _, err := ParseMeta(data[:metaEndOff])
-		if err != nil {
-			return m, err
-		}
-		m.Meta = &meta
-		m.MetaOff = metaEndOff - int(meta.Footer.Size)
-	}
-
-	return m, nil
-}
-
+// StripPadding produces a new byte slice by removing padding from an
+// existing byte slice.  Padding is defined as a sequence of trailing bytes,
+// all with the specified value.
 func StripPadding(b []byte, eraseVal byte) []byte {
 	var pad int
 	for pad = 0; pad < len(b); pad++ {
@@ -66,6 +53,8 @@
 	return b[:len(b)-pad]
 }
 
+// AddPadding produces a new byte slice by adding extra bytes to the end of
+// an existing slice.
 func AddPadding(b []byte, eraseVal byte, padLen int) []byte {
 	for i := 0; i < padLen; i++ {
 		b = append(b, eraseVal)
@@ -85,52 +74,69 @@
 	return hash[:]
 }
 
-func (m *Mfg) RecalcHash(eraseVal byte) error {
-	if m.Meta == nil || m.Meta.Hash() == nil {
+func (m *Mfg) RecalcHash(eraseVal byte) ([]byte, error) {
+	// The hash TLV needs to be zeroed out in order to calculate the mfg
+	// hash.  Duplicate the mfg object so that we don't modify the
+	// original.
+	dup := m.Clone()
+	if dup.Meta != nil {
+		dup.Meta.ClearHash()
+	}
+
+	bin, err := dup.Bytes(eraseVal)
+	if err != nil {
+		return nil, err
+	}
+
+	return CalcHash(bin), nil
+}
+
+// RefillHash replace's the contents of an mfgimage's SHA256 TLV with a newly
+// calculated hash.
+func (m *Mfg) RefillHash(eraseVal byte) error {
+	if m.Meta == nil {
+		return nil
+	}
+	tlv := m.Meta.FindFirstTlv(META_TLV_TYPE_HASH)
+	if tlv == nil {
 		return nil
 	}
 
-	// First, write with zeroed hash.
-	m.Meta.ClearHash()
-	bin, err := m.Bytes(eraseVal)
+	// Calculate hash.
+	hash, err := m.RecalcHash(eraseVal)
 	if err != nil {
 		return err
 	}
 
-	// Calculate hash and fill TLV.
-	tlv := m.Meta.FindFirstTlv(META_TLV_TYPE_HASH)
-	if tlv != nil {
-		hashData := CalcHash(bin)
-		copy(tlv.Data, hashData)
-
-		hashOff := m.MetaOff + m.Meta.HashOffset()
-		if hashOff+META_HASH_SZ > len(bin) {
-			return util.FmtNewtError(
-				"unexpected error: hash extends beyond end " +
-					"of manufacturing image")
-		}
-	}
+	// Fill hash TLV.
+	copy(tlv.Data, hash)
 
 	return nil
 }
 
-func (m *Mfg) Hash() ([]byte, error) {
+// Hash retrieves the SHA256 value associated with an mfgimage.  If the
+// mfgimage has an MMR with a SHA256 TLV, the TLV's value is returned.
+// Otherwise, the hash is calculated and returned.
+func (m *Mfg) Hash(eraseVal byte) ([]byte, error) {
 	var hashBytes []byte
+
 	if m.Meta != nil {
 		hashBytes = m.Meta.Hash()
 	}
+
 	if hashBytes == nil {
 		// No hash TLV; calculate hash manually.
-		bin, err := m.Bytes(0xff)
+		b, err := m.RecalcHash(eraseVal)
 		if err != nil {
 			return nil, err
 		}
-		hashBytes = CalcHash(bin)
+		hashBytes = b
 	}
 
 	return hashBytes, nil
 }
 
+// Bytes serializes an mfgimage into binary form.
 func (m *Mfg) Bytes(eraseVal byte) ([]byte, error) {
 	binCopy := make([]byte, len(m.Bin))
 	copy(binCopy, m.Bin)
@@ -149,3 +155,58 @@
 
 	return binCopy, nil
 }
+
+// Clone performs a deep copy of an mfgimage.
+func (m *Mfg) Clone() Mfg {
+	var meta *Meta
+	if m.Meta != nil {
+		metaDup := m.Meta.Clone()
+		meta = &metaDup
+	}
+
+	bin := make([]byte, len(m.Bin))
+	copy(bin, m.Bin)
+
+	return Mfg{
+		Bin:     bin,
+		Meta:    meta,
+		MetaOff: m.MetaOff,
+	}
+}
+
+// ExtractFlashArea copies a portion out of a serialized mfgimage.  The
+// offset and size to copy indicated by the provided FlashArea.
+func (m *Mfg) ExtractFlashArea(area flash.FlashArea,
+	eraseVal byte) ([]byte, error) {
+
+	b, err := m.Bytes(eraseVal)
+	if err != nil {
+		return nil, err
+	}
+
+	if area.Offset >= len(b) {
+		return nil, errors.Errorf(
+			"flash area in mmr (\"%s\") is beyond end of mfgimage "+
+				"(offset=%d mfgimg_len=%d)",
+			area.Name, area.Offset, len(b))
+	}
+
+	// If the end of the target contains unwritten bytes, it gets truncated
+	// from the mfgimage.
+	end := area.Offset + area.Size
+	if end > len(b) {
+		end = len(b)
+	}
+
+	return b[area.Offset:end], nil
+}
+
+// Tlvs retrieves the slice of TLVs present in an mfgimage's MMR.  It returns
+// nil if the mfgimage has no MMR.
+func (m *Mfg) Tlvs() []MetaTlv {
+	if m.Meta == nil {
+		return nil
+	} else {
+		return m.Meta.Tlvs
+	}
+}
diff --git a/mfg/mfg_test.go b/mfg/mfg_test.go
new file mode 100644
index 0000000..60f51fd
--- /dev/null
+++ b/mfg/mfg_test.go
@@ -0,0 +1,248 @@
+/**
+ * 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.
+ */
+
+package mfg
+
+import (
+	"fmt"
+	"io/ioutil"
+	"testing"
+
+	"github.com/apache/mynewt-artifact/manifest"
+	"github.com/apache/mynewt-artifact/sec"
+)
+
+const testdataPath = "testdata"
+
+type entry struct {
+	basename  string
+	form      bool
+	integrity bool
+	man       bool
+	sign      bool
+}
+
+func readMfgData(basename string) []byte {
+	path := fmt.Sprintf("%s/%s.bin", testdataPath, basename)
+
+	data, err := ioutil.ReadFile(path)
+	if err != nil {
+		panic("failed to read mfgimage file " + path)
+	}
+
+	return data
+}
+
+func readManifest(basename string) manifest.MfgManifest {
+	path := fmt.Sprintf("%s/%s.json", testdataPath, basename)
+
+	man, err := manifest.ReadMfgManifest(path)
+	if err != nil {
+		panic("failed to read manifest file " + path)
+	}
+
+	return man
+}
+
+func readPubKey() sec.PubSignKey {
+	path := fmt.Sprintf("%s/sign-key.pem", testdataPath)
+
+	key, err := sec.ReadKey(path)
+	if err != nil {
+		panic("failed to read key file " + path)
+	}
+
+	return key.PubKey()
+}
+
+func testOne(t *testing.T, e entry) {
+	fatalErr := func(field string, have string, want string, err error) {
+		s := fmt.Sprintf("mfgimage \"%s\" has unexpected `%s` status: "+
+			"have=%s want=%s", e.basename, field, have, want)
+		if err != nil {
+			s += "; " + err.Error()
+		}
+
+		t.Fatal(s)
+	}
+
+	mfgData := readMfgData(e.basename)
+	man := readManifest(e.basename)
+
+	var metaOff int
+	if man.Meta != nil {
+		metaOff = man.Meta.EndOffset
+	} else {
+		metaOff = -1
+	}
+
+	m, err := Parse(mfgData, metaOff, man.EraseVal)
+	if !e.form {
+		if err == nil {
+			fatalErr("form", "good", "bad", nil)
+		}
+		return
+	} else {
+		if err != nil {
+			fatalErr("form", "bad", "good", err)
+			return
+		}
+	}
+
+	err = m.Verify(man.EraseVal)
+	if !e.integrity {
+		if err == nil {
+			fatalErr("integrity", "good", "bad", nil)
+		}
+		return
+	} else {
+		if err != nil {
+			fatalErr("integrity", "bad", "good", err)
+			return
+		}
+	}
+
+	err = m.VerifyManifest(man)
+	if !e.man {
+		if err == nil {
+			fatalErr("manifest", "good", "bad", nil)
+		}
+		return
+	} else {
+		if err != nil {
+			fatalErr("manifest", "bad", "good", err)
+			return
+		}
+	}
+
+	key := readPubKey()
+
+	sigs, err := man.SecSigs()
+	if err != nil {
+		t.Fatalf("failed to collect mfg signatures: %s", err.Error())
+		return
+	}
+
+	hash, err := m.Hash(man.EraseVal)
+	if err != nil {
+		t.Fatalf("failed to read mfg hash: %s", err.Error())
+		return
+	}
+
+	idx, err := sec.VerifySigs(key, sigs, hash)
+	if !e.sign {
+		if err == nil && idx != -1 {
+			fatalErr("signature", "good", "bad", nil)
+		}
+		return
+	} else {
+		if err != nil || idx == -1 {
+			fatalErr("signature", "bad", "good", err)
+		}
+	}
+}
+
+func TestMfgVerify(t *testing.T) {
+	entries := []entry{
+		// Not an mfgimage.
+		entry{
+			basename:  "garbage",
+			form:      false,
+			integrity: false,
+			man:       false,
+			sign:      false,
+		},
+		// Contains a TLV with type=0xaa.
+		entry{
+			basename:  "unknown-tlv",
+			form:      true,
+			integrity: false,
+			man:       false,
+			sign:      false,
+		},
+		// MMR and manifest contain the same incorrect hash.
+		entry{
+			basename:  "hashx-fm1-ext0-tgts1-sign0",
+			form:      true,
+			integrity: false,
+			man:       false,
+			sign:      false,
+		},
+		// MMR hash doesn't match manifest.
+		entry{
+			basename:  "hashm-fm1-ext0-tgts1-sign0",
+			form:      true,
+			integrity: true,
+			man:       false,
+			sign:      false,
+		},
+		// MMR flash map doesn't match manifest.
+		entry{
+			basename:  "hash1-fmm-ext1-tgts1-sign0",
+			form:      true,
+			integrity: true,
+			man:       false,
+			sign:      false,
+		},
+		// MMR ext ref doesn't match manifest.
+		entry{
+			basename:  "hash1-fm1-extm-tgts1-sign0",
+			form:      true,
+			integrity: true,
+			man:       false,
+			sign:      false,
+		},
+		// Manifest indicates build where there is none.
+		entry{
+			basename:  "hash1-fm1-ext1-tgtsm-sign0",
+			form:      true,
+			integrity: true,
+			man:       false,
+			sign:      false,
+		},
+		// Good unsigned mfgimage without ref ext TLV.
+		entry{
+			basename:  "hash1-fm1-ext0-tgts1-sign0",
+			form:      true,
+			integrity: true,
+			man:       true,
+			sign:      false,
+		},
+		// Good unsigned mfgimage.
+		entry{
+			basename:  "hash1-fm1-ext1-tgts1-sign0",
+			form:      true,
+			integrity: true,
+			man:       true,
+			sign:      false,
+		},
+		// Good signed mfgimage.
+		entry{
+			basename:  "hash1-fm1-ext1-tgts1-sign1",
+			form:      true,
+			integrity: true,
+			man:       true,
+			sign:      true,
+		},
+	}
+
+	for _, e := range entries {
+		testOne(t, e)
+	}
+}
diff --git a/mfg/parse.go b/mfg/parse.go
new file mode 100644
index 0000000..78343e7
--- /dev/null
+++ b/mfg/parse.go
@@ -0,0 +1,137 @@
+/**
+ * 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.
+ */
+
+package mfg
+
+import (
+	"bytes"
+	"encoding/binary"
+
+	"github.com/apache/mynewt-artifact/errors"
+)
+
+func parseMetaFooter(bin []byte) (MetaFooter, int, error) {
+	r := bytes.NewReader(bin)
+
+	var ftr MetaFooter
+	if err := binary.Read(r, binary.LittleEndian, &ftr); err != nil {
+		return ftr, 0, errors.Wrapf(err,
+			"error reading meta footer")
+	}
+
+	if ftr.Magic != META_MAGIC {
+		return ftr, 0, errors.Errorf(
+			"meta footer contains invalid magic; exp:0x%08x, got:0x%08x",
+			META_MAGIC, ftr.Magic)
+	}
+
+	return ftr, META_FOOTER_SZ, nil
+}
+
+func parseMetaTlv(bin []byte) (MetaTlv, int, error) {
+	r := bytes.NewReader(bin)
+
+	tlv := MetaTlv{}
+	if err := binary.Read(r, binary.LittleEndian, &tlv.Header); err != nil {
+		return tlv, 0, errors.Wrapf(err, "error reading TLV header")
+	}
+
+	data := make([]byte, tlv.Header.Size)
+	sz, err := r.Read(data)
+	if err != nil {
+		return tlv, 0, errors.Wrapf(err,
+			"error reading %d bytes of TLV data",
+			tlv.Header.Size)
+	}
+	if sz != len(data) {
+		return tlv, 0, errors.Errorf(
+			"error reading %d bytes of TLV data: incomplete read",
+			tlv.Header.Size)
+	}
+	tlv.Data = data
+
+	return tlv, META_TLV_HEADER_SZ + int(tlv.Header.Size), nil
+}
+
+func parseMeta(bin []byte) (Meta, error) {
+	if len(bin) < META_FOOTER_SZ {
+		return Meta{}, errors.Errorf(
+			"binary too small to accommodate meta footer; "+
+				"bin-size=%d ftr-size=%d", len(bin), META_FOOTER_SZ)
+	}
+
+	ftr, _, err := parseMetaFooter(bin[len(bin)-META_FOOTER_SZ:])
+	if err != nil {
+		return Meta{}, err
+	}
+
+	if int(ftr.Size) > len(bin) {
+		return Meta{}, errors.Errorf(
+			"binary too small to accommodate meta region; "+
+				"bin-size=%d meta-size=%d", len(bin), ftr.Size)
+	}
+
+	ftrOff := len(bin) - META_FOOTER_SZ
+	off := len(bin) - int(ftr.Size)
+
+	tlvs := []MetaTlv{}
+	for off < ftrOff {
+		tlv, sz, err := parseMetaTlv(bin[off:])
+		if err != nil {
+			return Meta{}, err
+		}
+		tlvs = append(tlvs, tlv)
+		off += sz
+	}
+
+	return Meta{
+		Tlvs:   tlvs,
+		Footer: ftr,
+	}, nil
+}
+
+// Parse parses a serialized mfgimage (e.g., "mfgimg.bin") and produces an
+// Mfg object.  metaEndOff is the offset immediately following the MMR, or -1
+// if there is no MMR.
+func Parse(data []byte, metaEndOff int, eraseVal byte) (Mfg, error) {
+	m := Mfg{
+		Bin: data,
+	}
+
+	if metaEndOff >= 0 {
+		if metaEndOff > len(data) {
+			return m, errors.Errorf(
+				"MMR offset (%d) beyond end of mfgimage (%d)",
+				metaEndOff, len(data))
+		}
+
+		meta, err := parseMeta(data[:metaEndOff])
+		if err != nil {
+			return m, err
+		}
+		m.Meta = &meta
+		m.MetaOff = metaEndOff - int(meta.Footer.Size)
+
+		for i := 0; i < int(meta.Footer.Size); i++ {
+			m.Bin[m.MetaOff+i] = eraseVal
+		}
+	}
+
+	return m, nil
+}
diff --git a/mfg/testdata/garbage.bin b/mfg/testdata/garbage.bin
new file mode 100644
index 0000000..ce01362
--- /dev/null
+++ b/mfg/testdata/garbage.bin
@@ -0,0 +1 @@
+hello
diff --git a/mfg/testdata/garbage.json b/mfg/testdata/garbage.json
new file mode 100644
index 0000000..ee2106b
--- /dev/null
+++ b/mfg/testdata/garbage.json
@@ -0,0 +1,78 @@
+{
+  "name": "mfgs/boot-blinky-nordic_pca10040",
+  "build_time": "2019-06-18T10:30:43-07:00",
+  "format": 2,
+  "mfg_hash": "4e7b95c4a1170919bcaa086f06aed784377396fc15dab300718ef6eb152d117c",
+  "version": "1.0.0.0",
+  "device": 0,
+  "bin_path": "mfgimg.bin",
+  "hex_path": "mfgimg.hex",
+  "bsp": "@apache-mynewt-core/hw/bsp/nordic_pca10040",
+  "erase_val": 255,
+  "flash_map": [
+    {
+      "name": "FLASH_AREA_BOOTLOADER",
+      "id": 0,
+      "device": 0,
+      "offset": 0,
+      "size": 16384
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_0",
+      "id": 1,
+      "device": 0,
+      "offset": 32768,
+      "size": 237568
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_1",
+      "id": 2,
+      "device": 0,
+      "offset": 270336,
+      "size": 237568
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_SCRATCH",
+      "id": 3,
+      "device": 0,
+      "offset": 507904,
+      "size": 4096
+    },
+    {
+      "name": "FLASH_AREA_REBOOT_LOG",
+      "id": 16,
+      "device": 0,
+      "offset": 16384,
+      "size": 16384
+    },
+    {
+      "name": "FLASH_AREA_NFFS",
+      "id": 17,
+      "device": 0,
+      "offset": 512000,
+      "size": 12288
+    }
+  ],
+  "targets": [
+    {
+      "name": "targets/boot-nordic_pca10040",
+      "offset": 0,
+      "bin_path": "targets/0/binary.bin",
+      "hex_path": "targets/0/image.hex",
+      "manifest_path": "targets/0/manifest.json"
+    },
+    {
+      "name": "targets/blinky-nordic_pca10040",
+      "offset": 32768,
+      "image_path": "targets/1/image.img",
+      "hex_path": "targets/1/image.hex",
+      "manifest_path": "targets/1/manifest.json"
+    }
+  ],
+  "meta": {
+    "end_offset": 16384,
+    "size": 114,
+    "hash_present": true,
+    "flash_map_present": true
+  }
+}
\ No newline at end of file
diff --git a/mfg/testdata/hash1-fm1-ext0-tgts1-sign0.bin b/mfg/testdata/hash1-fm1-ext0-tgts1-sign0.bin
new file mode 100644
index 0000000..1d4e130
--- /dev/null
+++ b/mfg/testdata/hash1-fm1-ext0-tgts1-sign0.bin
Binary files differ
diff --git a/mfg/testdata/hash1-fm1-ext0-tgts1-sign0.json b/mfg/testdata/hash1-fm1-ext0-tgts1-sign0.json
new file mode 100644
index 0000000..ee2106b
--- /dev/null
+++ b/mfg/testdata/hash1-fm1-ext0-tgts1-sign0.json
@@ -0,0 +1,78 @@
+{
+  "name": "mfgs/boot-blinky-nordic_pca10040",
+  "build_time": "2019-06-18T10:30:43-07:00",
+  "format": 2,
+  "mfg_hash": "4e7b95c4a1170919bcaa086f06aed784377396fc15dab300718ef6eb152d117c",
+  "version": "1.0.0.0",
+  "device": 0,
+  "bin_path": "mfgimg.bin",
+  "hex_path": "mfgimg.hex",
+  "bsp": "@apache-mynewt-core/hw/bsp/nordic_pca10040",
+  "erase_val": 255,
+  "flash_map": [
+    {
+      "name": "FLASH_AREA_BOOTLOADER",
+      "id": 0,
+      "device": 0,
+      "offset": 0,
+      "size": 16384
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_0",
+      "id": 1,
+      "device": 0,
+      "offset": 32768,
+      "size": 237568
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_1",
+      "id": 2,
+      "device": 0,
+      "offset": 270336,
+      "size": 237568
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_SCRATCH",
+      "id": 3,
+      "device": 0,
+      "offset": 507904,
+      "size": 4096
+    },
+    {
+      "name": "FLASH_AREA_REBOOT_LOG",
+      "id": 16,
+      "device": 0,
+      "offset": 16384,
+      "size": 16384
+    },
+    {
+      "name": "FLASH_AREA_NFFS",
+      "id": 17,
+      "device": 0,
+      "offset": 512000,
+      "size": 12288
+    }
+  ],
+  "targets": [
+    {
+      "name": "targets/boot-nordic_pca10040",
+      "offset": 0,
+      "bin_path": "targets/0/binary.bin",
+      "hex_path": "targets/0/image.hex",
+      "manifest_path": "targets/0/manifest.json"
+    },
+    {
+      "name": "targets/blinky-nordic_pca10040",
+      "offset": 32768,
+      "image_path": "targets/1/image.img",
+      "hex_path": "targets/1/image.hex",
+      "manifest_path": "targets/1/manifest.json"
+    }
+  ],
+  "meta": {
+    "end_offset": 16384,
+    "size": 114,
+    "hash_present": true,
+    "flash_map_present": true
+  }
+}
\ No newline at end of file
diff --git a/mfg/testdata/hash1-fm1-ext1-tgts1-sign0.bin b/mfg/testdata/hash1-fm1-ext1-tgts1-sign0.bin
new file mode 100644
index 0000000..8ef27c5
--- /dev/null
+++ b/mfg/testdata/hash1-fm1-ext1-tgts1-sign0.bin
Binary files differ
diff --git a/mfg/testdata/hash1-fm1-ext1-tgts1-sign0.json b/mfg/testdata/hash1-fm1-ext1-tgts1-sign0.json
new file mode 100644
index 0000000..6da70a2
--- /dev/null
+++ b/mfg/testdata/hash1-fm1-ext1-tgts1-sign0.json
@@ -0,0 +1,85 @@
+{
+  "name": "mfgs/boot-blinky-nordic_pca10040",
+  "build_time": "2019-06-18T11:37:55-07:00",
+  "format": 2,
+  "mfg_hash": "aaf06a2d96aeaea196118dac3c1c1be86d386c4ca219cb7a69531444219f7139",
+  "version": "1.0.0.0",
+  "device": 0,
+  "bin_path": "mfgimg.bin",
+  "hex_path": "mfgimg.hex",
+  "bsp": "@apache-mynewt-core/hw/bsp/nordic_pca10040",
+  "erase_val": 255,
+  "flash_map": [
+    {
+      "name": "FLASH_AREA_BOOTLOADER",
+      "id": 0,
+      "device": 0,
+      "offset": 0,
+      "size": 16384
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_0",
+      "id": 1,
+      "device": 0,
+      "offset": 32768,
+      "size": 237568
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_1",
+      "id": 2,
+      "device": 0,
+      "offset": 270336,
+      "size": 237568
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_SCRATCH",
+      "id": 3,
+      "device": 0,
+      "offset": 507904,
+      "size": 4096
+    },
+    {
+      "name": "FLASH_AREA_REBOOT_LOG",
+      "id": 16,
+      "device": 0,
+      "offset": 16384,
+      "size": 16384
+    },
+    {
+      "name": "FLASH_AREA_NFFS",
+      "id": 17,
+      "device": 0,
+      "offset": 512000,
+      "size": 12288
+    }
+  ],
+  "targets": [
+    {
+      "name": "targets/boot-nordic_pca10040",
+      "offset": 0,
+      "bin_path": "targets/0/binary.bin",
+      "hex_path": "targets/0/image.hex",
+      "manifest_path": "targets/0/manifest.json"
+    },
+    {
+      "name": "targets/blinky-nordic_pca10040",
+      "offset": 32768,
+      "image_path": "targets/1/image.img",
+      "hex_path": "targets/1/image.hex",
+      "manifest_path": "targets/1/manifest.json"
+    }
+  ],
+  "meta": {
+    "end_offset": 16384,
+    "size": 117,
+    "hash_present": true,
+    "flash_map_present": true,
+    "mmrs": [
+      {
+        "area": "FLASH_AREA_REBOOT_LOG",
+        "_device": 0,
+        "_end_offset": 32768
+      }
+    ]
+  }
+}
\ No newline at end of file
diff --git a/mfg/testdata/hash1-fm1-ext1-tgts1-sign1.bin b/mfg/testdata/hash1-fm1-ext1-tgts1-sign1.bin
new file mode 100644
index 0000000..8ef27c5
--- /dev/null
+++ b/mfg/testdata/hash1-fm1-ext1-tgts1-sign1.bin
Binary files differ
diff --git a/mfg/testdata/hash1-fm1-ext1-tgts1-sign1.json b/mfg/testdata/hash1-fm1-ext1-tgts1-sign1.json
new file mode 100644
index 0000000..77cf26c
--- /dev/null
+++ b/mfg/testdata/hash1-fm1-ext1-tgts1-sign1.json
@@ -0,0 +1,91 @@
+{
+  "name": "mfgs/boot-blinky-nordic_pca10040",
+  "build_time": "2019-06-18T11:40:06-07:00",
+  "format": 2,
+  "mfg_hash": "aaf06a2d96aeaea196118dac3c1c1be86d386c4ca219cb7a69531444219f7139",
+  "version": "1.0.0.0",
+  "device": 0,
+  "bin_path": "mfgimg.bin",
+  "hex_path": "mfgimg.hex",
+  "bsp": "@apache-mynewt-core/hw/bsp/nordic_pca10040",
+  "erase_val": 255,
+  "signatures": [
+    {
+      "key": "b02c7387",
+      "sig": "1b7900658aa75d7d037112de85889812308b90b7f7ce259c58ecb779c4582de4f80b4acf80489e161b45935169f684bc12b2c488ea9d96003e9e02d92ff0f22b5e724f7342f63de7f1ae185c846c779f0c3a6f5fa6ccb057871571bbdc4d5290295e08fd8e2db67560ddc837881b363c92745c882fe21a529b4ec5e0d85c176cf43c1402403d3ec1679fbbd01405382458b5f704700c398b7bba6bcf9e8249ff833387f234884ae80f4543ceb9b0949579a68cf4d7b0949b8853e345a02453a38f10be0bfca8061b25cae22f15ecac19fa74313ac782d3b17d8af54c85dc4201204f01780fea09327901aa4f1f11b83c1b9aba37bb8e4b271c9de0238069fece"
+    }
+  ],
+  "flash_map": [
+    {
+      "name": "FLASH_AREA_BOOTLOADER",
+      "id": 0,
+      "device": 0,
+      "offset": 0,
+      "size": 16384
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_0",
+      "id": 1,
+      "device": 0,
+      "offset": 32768,
+      "size": 237568
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_1",
+      "id": 2,
+      "device": 0,
+      "offset": 270336,
+      "size": 237568
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_SCRATCH",
+      "id": 3,
+      "device": 0,
+      "offset": 507904,
+      "size": 4096
+    },
+    {
+      "name": "FLASH_AREA_REBOOT_LOG",
+      "id": 16,
+      "device": 0,
+      "offset": 16384,
+      "size": 16384
+    },
+    {
+      "name": "FLASH_AREA_NFFS",
+      "id": 17,
+      "device": 0,
+      "offset": 512000,
+      "size": 12288
+    }
+  ],
+  "targets": [
+    {
+      "name": "targets/boot-nordic_pca10040",
+      "offset": 0,
+      "bin_path": "targets/0/binary.bin",
+      "hex_path": "targets/0/image.hex",
+      "manifest_path": "targets/0/manifest.json"
+    },
+    {
+      "name": "targets/blinky-nordic_pca10040",
+      "offset": 32768,
+      "image_path": "targets/1/image.img",
+      "hex_path": "targets/1/image.hex",
+      "manifest_path": "targets/1/manifest.json"
+    }
+  ],
+  "meta": {
+    "end_offset": 16384,
+    "size": 117,
+    "hash_present": true,
+    "flash_map_present": true,
+    "mmrs": [
+      {
+        "area": "FLASH_AREA_REBOOT_LOG",
+        "_device": 0,
+        "_end_offset": 32768
+      }
+    ]
+  }
+}
\ No newline at end of file
diff --git a/mfg/testdata/hash1-fm1-ext1-tgtsm-sign0.bin b/mfg/testdata/hash1-fm1-ext1-tgtsm-sign0.bin
new file mode 100644
index 0000000..8ef27c5
--- /dev/null
+++ b/mfg/testdata/hash1-fm1-ext1-tgtsm-sign0.bin
Binary files differ
diff --git a/mfg/testdata/hash1-fm1-ext1-tgtsm-sign0.json b/mfg/testdata/hash1-fm1-ext1-tgtsm-sign0.json
new file mode 100644
index 0000000..b90da64
--- /dev/null
+++ b/mfg/testdata/hash1-fm1-ext1-tgtsm-sign0.json
@@ -0,0 +1,92 @@
+{
+  "name": "mfgs/boot-blinky-nordic_pca10040",
+  "build_time": "2019-06-18T11:37:55-07:00",
+  "format": 2,
+  "mfg_hash": "aaf06a2d96aeaea196118dac3c1c1be86d386c4ca219cb7a69531444219f7139",
+  "version": "1.0.0.0",
+  "device": 0,
+  "bin_path": "mfgimg.bin",
+  "hex_path": "mfgimg.hex",
+  "bsp": "@apache-mynewt-core/hw/bsp/nordic_pca10040",
+  "erase_val": 255,
+  "flash_map": [
+    {
+      "name": "FLASH_AREA_BOOTLOADER",
+      "id": 0,
+      "device": 0,
+      "offset": 0,
+      "size": 16384
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_0",
+      "id": 1,
+      "device": 0,
+      "offset": 32768,
+      "size": 237568
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_1",
+      "id": 2,
+      "device": 0,
+      "offset": 270336,
+      "size": 237568
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_SCRATCH",
+      "id": 3,
+      "device": 0,
+      "offset": 507904,
+      "size": 4096
+    },
+    {
+      "name": "FLASH_AREA_REBOOT_LOG",
+      "id": 16,
+      "device": 0,
+      "offset": 16384,
+      "size": 16384
+    },
+    {
+      "name": "FLASH_AREA_NFFS",
+      "id": 17,
+      "device": 0,
+      "offset": 512000,
+      "size": 12288
+    }
+  ],
+  "targets": [
+    {
+      "name": "targets/boot-nordic_pca10040",
+      "offset": 0,
+      "bin_path": "targets/0/binary.bin",
+      "hex_path": "targets/0/image.hex",
+      "manifest_path": "targets/0/manifest.json"
+    },
+    {
+      "name": "targets/blinky-nordic_pca10040",
+      "offset": 32768,
+      "image_path": "targets/1/image.img",
+      "hex_path": "targets/1/image.hex",
+      "manifest_path": "targets/1/manifest.json"
+    },
+    {
+      "name": "targets/blinky-nordic_pca10040",
+      "offset": 40000,
+      "image_path": "targets/2/image.img",
+      "hex_path": "targets/2/image.hex",
+      "manifest_path": "targets/2/manifest.json"
+    }
+  ],
+  "meta": {
+    "end_offset": 16384,
+    "size": 117,
+    "hash_present": true,
+    "flash_map_present": true,
+    "mmrs": [
+      {
+        "area": "FLASH_AREA_REBOOT_LOG",
+        "_device": 0,
+        "_end_offset": 32768
+      }
+    ]
+  }
+}
diff --git a/mfg/testdata/hash1-fm1-extm-tgts1-sign0.bin b/mfg/testdata/hash1-fm1-extm-tgts1-sign0.bin
new file mode 100644
index 0000000..1d4e130
--- /dev/null
+++ b/mfg/testdata/hash1-fm1-extm-tgts1-sign0.bin
Binary files differ
diff --git a/mfg/testdata/hash1-fm1-extm-tgts1-sign0.json b/mfg/testdata/hash1-fm1-extm-tgts1-sign0.json
new file mode 100644
index 0000000..b6ea5ca
--- /dev/null
+++ b/mfg/testdata/hash1-fm1-extm-tgts1-sign0.json
@@ -0,0 +1,85 @@
+{
+  "name": "mfgs/boot-blinky-nordic_pca10040",
+  "build_time": "2019-06-18T11:37:55-07:00",
+  "format": 2,
+  "mfg_hash": "4e7b95c4a1170919bcaa086f06aed784377396fc15dab300718ef6eb152d117c",
+  "version": "1.0.0.0",
+  "device": 0,
+  "bin_path": "mfgimg.bin",
+  "hex_path": "mfgimg.hex",
+  "bsp": "@apache-mynewt-core/hw/bsp/nordic_pca10040",
+  "erase_val": 255,
+  "flash_map": [
+    {
+      "name": "FLASH_AREA_BOOTLOADER",
+      "id": 0,
+      "device": 0,
+      "offset": 0,
+      "size": 16384
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_0",
+      "id": 1,
+      "device": 0,
+      "offset": 32768,
+      "size": 237568
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_1",
+      "id": 2,
+      "device": 0,
+      "offset": 270336,
+      "size": 237568
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_SCRATCH",
+      "id": 3,
+      "device": 0,
+      "offset": 507904,
+      "size": 4096
+    },
+    {
+      "name": "FLASH_AREA_REBOOT_LOG",
+      "id": 16,
+      "device": 0,
+      "offset": 16384,
+      "size": 16384
+    },
+    {
+      "name": "FLASH_AREA_NFFS",
+      "id": 17,
+      "device": 0,
+      "offset": 512000,
+      "size": 12288
+    }
+  ],
+  "targets": [
+    {
+      "name": "targets/boot-nordic_pca10040",
+      "offset": 0,
+      "bin_path": "targets/0/binary.bin",
+      "hex_path": "targets/0/image.hex",
+      "manifest_path": "targets/0/manifest.json"
+    },
+    {
+      "name": "targets/blinky-nordic_pca10040",
+      "offset": 32768,
+      "image_path": "targets/1/image.img",
+      "hex_path": "targets/1/image.hex",
+      "manifest_path": "targets/1/manifest.json"
+    }
+  ],
+  "meta": {
+    "end_offset": 16384,
+    "size": 117,
+    "hash_present": true,
+    "flash_map_present": true,
+    "mmrs": [
+      {
+        "area": "FLASH_AREA_REBOOT_LOG",
+        "_device": 0,
+        "_end_offset": 32768
+      }
+    ]
+  }
+}
diff --git a/mfg/testdata/hash1-fmm-ext1-tgts1-sign0.bin b/mfg/testdata/hash1-fmm-ext1-tgts1-sign0.bin
new file mode 100644
index 0000000..04eb2a4
--- /dev/null
+++ b/mfg/testdata/hash1-fmm-ext1-tgts1-sign0.bin
Binary files differ
diff --git a/mfg/testdata/hash1-fmm-ext1-tgts1-sign0.json b/mfg/testdata/hash1-fmm-ext1-tgts1-sign0.json
new file mode 100644
index 0000000..2de147b
--- /dev/null
+++ b/mfg/testdata/hash1-fmm-ext1-tgts1-sign0.json
@@ -0,0 +1,85 @@
+{
+  "name": "mfgs/boot-blinky-nordic_pca10040",
+  "build_time": "2019-06-18T11:37:55-07:00",
+  "format": 2,
+  "mfg_hash": "e65d22dd9d1f8fd16ac7eb9a458d7d51c947df712e00034062efaaf8c5b264cf",
+  "version": "1.0.0.0",
+  "device": 0,
+  "bin_path": "mfgimg.bin",
+  "hex_path": "mfgimg.hex",
+  "bsp": "@apache-mynewt-core/hw/bsp/nordic_pca10040",
+  "erase_val": 255,
+  "flash_map": [
+    {
+      "name": "FLASH_AREA_BOOTLOADER",
+      "id": 0,
+      "device": 0,
+      "offset": 0,
+      "size": 16384
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_0",
+      "id": 1,
+      "device": 0,
+      "offset": 32768,
+      "size": 237568
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_1",
+      "id": 2,
+      "device": 0,
+      "offset": 270336,
+      "size": 237568
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_SCRATCH",
+      "id": 3,
+      "device": 0,
+      "offset": 507904,
+      "size": 4096
+    },
+    {
+      "name": "FLASH_AREA_REBOOT_LOG",
+      "id": 16,
+      "device": 0,
+      "offset": 16384,
+      "size": 16384
+    },
+    {
+      "name": "FLASH_AREA_NFFS",
+      "id": 17,
+      "device": 0,
+      "offset": 512000,
+      "size": 12288
+    }
+  ],
+  "targets": [
+    {
+      "name": "targets/boot-nordic_pca10040",
+      "offset": 0,
+      "bin_path": "targets/0/binary.bin",
+      "hex_path": "targets/0/image.hex",
+      "manifest_path": "targets/0/manifest.json"
+    },
+    {
+      "name": "targets/blinky-nordic_pca10040",
+      "offset": 32768,
+      "image_path": "targets/1/image.img",
+      "hex_path": "targets/1/image.hex",
+      "manifest_path": "targets/1/manifest.json"
+    }
+  ],
+  "meta": {
+    "end_offset": 16384,
+    "size": 117,
+    "hash_present": true,
+    "flash_map_present": true,
+    "mmrs": [
+      {
+        "area": "FLASH_AREA_REBOOT_LOG",
+        "_device": 0,
+        "_end_offset": 32768
+      }
+    ]
+  }
+}
diff --git a/mfg/testdata/hashm-fm1-ext0-tgts1-sign0.bin b/mfg/testdata/hashm-fm1-ext0-tgts1-sign0.bin
new file mode 100644
index 0000000..1d4e130
--- /dev/null
+++ b/mfg/testdata/hashm-fm1-ext0-tgts1-sign0.bin
Binary files differ
diff --git a/mfg/testdata/hashm-fm1-ext0-tgts1-sign0.json b/mfg/testdata/hashm-fm1-ext0-tgts1-sign0.json
new file mode 100644
index 0000000..ffa4c4e
--- /dev/null
+++ b/mfg/testdata/hashm-fm1-ext0-tgts1-sign0.json
@@ -0,0 +1,78 @@
+{
+  "name": "mfgs/boot-blinky-nordic_pca10040",
+  "build_time": "2019-06-18T10:30:43-07:00",
+  "format": 2,
+  "mfg_hash": "aa7b95c4a1170919bcaa086f06aed784377396fc15dab300718ef6eb152d117c",
+  "version": "1.0.0.0",
+  "device": 0,
+  "bin_path": "mfgimg.bin",
+  "hex_path": "mfgimg.hex",
+  "bsp": "@apache-mynewt-core/hw/bsp/nordic_pca10040",
+  "erase_val": 255,
+  "flash_map": [
+    {
+      "name": "FLASH_AREA_BOOTLOADER",
+      "id": 0,
+      "device": 0,
+      "offset": 0,
+      "size": 16384
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_0",
+      "id": 1,
+      "device": 0,
+      "offset": 32768,
+      "size": 237568
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_1",
+      "id": 2,
+      "device": 0,
+      "offset": 270336,
+      "size": 237568
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_SCRATCH",
+      "id": 3,
+      "device": 0,
+      "offset": 507904,
+      "size": 4096
+    },
+    {
+      "name": "FLASH_AREA_REBOOT_LOG",
+      "id": 16,
+      "device": 0,
+      "offset": 16384,
+      "size": 16384
+    },
+    {
+      "name": "FLASH_AREA_NFFS",
+      "id": 17,
+      "device": 0,
+      "offset": 512000,
+      "size": 12288
+    }
+  ],
+  "targets": [
+    {
+      "name": "targets/boot-nordic_pca10040",
+      "offset": 0,
+      "bin_path": "targets/0/binary.bin",
+      "hex_path": "targets/0/image.hex",
+      "manifest_path": "targets/0/manifest.json"
+    },
+    {
+      "name": "targets/blinky-nordic_pca10040",
+      "offset": 32768,
+      "image_path": "targets/1/image.img",
+      "hex_path": "targets/1/image.hex",
+      "manifest_path": "targets/1/manifest.json"
+    }
+  ],
+  "meta": {
+    "end_offset": 16384,
+    "size": 114,
+    "hash_present": true,
+    "flash_map_present": true
+  }
+}
diff --git a/mfg/testdata/hashx-fm1-ext0-tgts1-sign0.bin b/mfg/testdata/hashx-fm1-ext0-tgts1-sign0.bin
new file mode 100644
index 0000000..08ebef0
--- /dev/null
+++ b/mfg/testdata/hashx-fm1-ext0-tgts1-sign0.bin
Binary files differ
diff --git a/mfg/testdata/hashx-fm1-ext0-tgts1-sign0.json b/mfg/testdata/hashx-fm1-ext0-tgts1-sign0.json
new file mode 100644
index 0000000..ffa4c4e
--- /dev/null
+++ b/mfg/testdata/hashx-fm1-ext0-tgts1-sign0.json
@@ -0,0 +1,78 @@
+{
+  "name": "mfgs/boot-blinky-nordic_pca10040",
+  "build_time": "2019-06-18T10:30:43-07:00",
+  "format": 2,
+  "mfg_hash": "aa7b95c4a1170919bcaa086f06aed784377396fc15dab300718ef6eb152d117c",
+  "version": "1.0.0.0",
+  "device": 0,
+  "bin_path": "mfgimg.bin",
+  "hex_path": "mfgimg.hex",
+  "bsp": "@apache-mynewt-core/hw/bsp/nordic_pca10040",
+  "erase_val": 255,
+  "flash_map": [
+    {
+      "name": "FLASH_AREA_BOOTLOADER",
+      "id": 0,
+      "device": 0,
+      "offset": 0,
+      "size": 16384
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_0",
+      "id": 1,
+      "device": 0,
+      "offset": 32768,
+      "size": 237568
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_1",
+      "id": 2,
+      "device": 0,
+      "offset": 270336,
+      "size": 237568
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_SCRATCH",
+      "id": 3,
+      "device": 0,
+      "offset": 507904,
+      "size": 4096
+    },
+    {
+      "name": "FLASH_AREA_REBOOT_LOG",
+      "id": 16,
+      "device": 0,
+      "offset": 16384,
+      "size": 16384
+    },
+    {
+      "name": "FLASH_AREA_NFFS",
+      "id": 17,
+      "device": 0,
+      "offset": 512000,
+      "size": 12288
+    }
+  ],
+  "targets": [
+    {
+      "name": "targets/boot-nordic_pca10040",
+      "offset": 0,
+      "bin_path": "targets/0/binary.bin",
+      "hex_path": "targets/0/image.hex",
+      "manifest_path": "targets/0/manifest.json"
+    },
+    {
+      "name": "targets/blinky-nordic_pca10040",
+      "offset": 32768,
+      "image_path": "targets/1/image.img",
+      "hex_path": "targets/1/image.hex",
+      "manifest_path": "targets/1/manifest.json"
+    }
+  ],
+  "meta": {
+    "end_offset": 16384,
+    "size": 114,
+    "hash_present": true,
+    "flash_map_present": true
+  }
+}
diff --git a/mfg/testdata/sign-key-pub.der b/mfg/testdata/sign-key-pub.der
new file mode 100644
index 0000000..bd50d37
--- /dev/null
+++ b/mfg/testdata/sign-key-pub.der
Binary files differ
diff --git a/mfg/testdata/sign-key.pem b/mfg/testdata/sign-key.pem
new file mode 100644
index 0000000..4dd360a
--- /dev/null
+++ b/mfg/testdata/sign-key.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEApydXFYw0I2tS5/Z7o/e/AOTxcQsQA80L02KfAqMT6LsLDGLV
+1DKfKLLgCOdBjcafKw4updsvW9dPqCB6q4Y58j99D2B7fzw+HIWH5IyL73Nt/ytI
+cJ0CSL/bfGpaI0dY1V92ooEq8cp2ZZCjrTCWmg/oP5SQ9aDEbpTYh1VdHbsxObMQ
+6A/aaQa1hevjcE7gTFOntKN1QDLaDZXz9CqIkiuNQuQhXA0zxDJkWwu7U18fVpxa
+3ozdU0nLRQp6Edo09MulskwJYF6VCbNEesn/7rSbwwI3Wa5RFWcQPRlO2SdqRiYl
+XSX2fYhp7r/tkBdJSYLns0193zTixECQwjI9BQIDAQABAoIBAB7zWt2ji1fvnHdV
+HYm76wMYYViEKt/5TLJEdZsAZURXtfECMAPNp8jabj9XyrycxYYsZxjQ4BEKajaA
+ZRZzkTE47kg1nkht+DZBx2rbV2HsJrbz5cLsX6rm05ZS/wO/R0SjG411i2UgDxI5
+WQVNlOVMAr4bHUhOD3FGYF2WwdoqLZTXnOm+1MOQgi8wpYe8fGzumeiGfW5L0NCx
+iHAVdqPAQsK81wTyRuLgYmfV0e4l8sqjH1lHK+7qk9y1EYmXyrN6fgelZgahS1b5
+GbQJGX8QQde8ATYdu5W933+cRytrTHgI0VvptcmZ6zsIs4FwlrDZdhFbpkin3CuN
+eIWqJTUCgYEAzyEtdVbI+mi+rp4a+egN+yEmfg5fhUkS07tIl0tBQa1zAYnyumZo
+wJIBhMYjqFj1Z7e4Gwq8aKZK/y+9DSLzAQ/699i7TM+Qd3H4sACt9c2PWDpCNtZF
+Emu9Te7RDp0cnyE8NEJ3J1ibFQ0pk/mdX/hQ+CYkJv5u9ul3Te2ffQMCgYEAzpeU
+O30dTh0n8fwSYQh0HOU+GyzJQ9j5RNxDQRMGtjEBkcGEMXxViIq/CIukAJVIAdL1
+Vl7eP4MRF5RtrRfivsjA3hKJYYkpYKa4A1rOpfDs4Ex7YLrKD4Y2UQ1f4hGAs5Kr
+mEZO1CMuq2A0+wLtxJRswM51prLoSlW9wxy/61cCgYEAqp9n9PrSgAR83xb6ndZc
+ffxm2vw4D3GMgsIKICcr0FBzJldejdIChG9BtQALK4hsT0316MDFR2eE7AWFNCcQ
+ClYBpNzyHWn2VY6bD1Df/FWiuUj0dnu3Vl9OB76sk980TplwIJSH1u+UgJjhITZE
+P2QsPt4cdcqt2dOkJZuS/8UCgYBo3UQe1ikz51TJXfwuSM43hJ17ycX3rIEK1QtG
+UtQLUuDLDYF+ZPA9uL+zJL6AlUXRtzVVPB5v+qWIZI0vWXp9AQX1M0+MtMTODJJH
+EabnUF3MlMXjmazLKIMVrUZISD4d6Is1ZirJP3qG/vSlnRz3tadmTuYlUZbbdJ44
+FbXNTQKBgBTwNcuDR6ExhSclY/pgAq6OU5l8Os0qHNjR+Hch2/vttx7E35a5m59l
+68ns5xGVxeHiadFmx7YDf19wWZtOMMvKGeUXUC4ENhwHVLaips6ZS6IULn3Uj/sG
+ZFahALjXYXt8DNM0+jUBQzzED17y96sIj4URORAUVRSnRsjLjaEP
+-----END RSA PRIVATE KEY-----
diff --git a/mfg/testdata/unknown-tlv.bin b/mfg/testdata/unknown-tlv.bin
new file mode 100644
index 0000000..25f5aac
--- /dev/null
+++ b/mfg/testdata/unknown-tlv.bin
Binary files differ
diff --git a/mfg/testdata/unknown-tlv.json b/mfg/testdata/unknown-tlv.json
new file mode 100644
index 0000000..8b2e5ce
--- /dev/null
+++ b/mfg/testdata/unknown-tlv.json
@@ -0,0 +1,78 @@
+{
+  "name": "mfgs/boot-blinky-nordic_pca10040",
+  "build_time": "2019-06-18T10:30:43-07:00",
+  "format": 2,
+  "mfg_hash": "48a981723c77d1f7a029ccd51ba28bc2077be56d90ac165124325ce0ed508650",
+  "version": "1.0.0.0",
+  "device": 0,
+  "bin_path": "mfgimg.bin",
+  "hex_path": "mfgimg.hex",
+  "bsp": "@apache-mynewt-core/hw/bsp/nordic_pca10040",
+  "erase_val": 255,
+  "flash_map": [
+    {
+      "name": "FLASH_AREA_BOOTLOADER",
+      "id": 0,
+      "device": 0,
+      "offset": 0,
+      "size": 16384
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_0",
+      "id": 1,
+      "device": 0,
+      "offset": 32768,
+      "size": 237568
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_1",
+      "id": 2,
+      "device": 0,
+      "offset": 270336,
+      "size": 237568
+    },
+    {
+      "name": "FLASH_AREA_IMAGE_SCRATCH",
+      "id": 3,
+      "device": 0,
+      "offset": 507904,
+      "size": 4096
+    },
+    {
+      "name": "FLASH_AREA_REBOOT_LOG",
+      "id": 16,
+      "device": 0,
+      "offset": 16384,
+      "size": 16384
+    },
+    {
+      "name": "FLASH_AREA_NFFS",
+      "id": 17,
+      "device": 0,
+      "offset": 512000,
+      "size": 12288
+    }
+  ],
+  "targets": [
+    {
+      "name": "targets/boot-nordic_pca10040",
+      "offset": 0,
+      "bin_path": "targets/0/binary.bin",
+      "hex_path": "targets/0/image.hex",
+      "manifest_path": "targets/0/manifest.json"
+    },
+    {
+      "name": "targets/blinky-nordic_pca10040",
+      "offset": 32768,
+      "image_path": "targets/1/image.img",
+      "hex_path": "targets/1/image.hex",
+      "manifest_path": "targets/1/manifest.json"
+    }
+  ],
+  "meta": {
+    "end_offset": 16384,
+    "size": 114,
+    "hash_present": true,
+    "flash_map_present": true
+  }
+}
diff --git a/mfg/verify.go b/mfg/verify.go
new file mode 100644
index 0000000..7fc9f22
--- /dev/null
+++ b/mfg/verify.go
@@ -0,0 +1,221 @@
+/**
+ * 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.
+ */
+
+package mfg
+
+import (
+	"bytes"
+	"encoding/hex"
+
+	"github.com/apache/mynewt-artifact/errors"
+	"github.com/apache/mynewt-artifact/flash"
+	"github.com/apache/mynewt-artifact/image"
+	"github.com/apache/mynewt-artifact/manifest"
+)
+
+func (m *Mfg) validateManFlashMap(man manifest.MfgManifest) error {
+	idAreaMap := map[int]flash.FlashArea{}
+	for _, area := range man.FlashAreas {
+		if _, dup := idAreaMap[area.Id]; dup {
+			return errors.Errorf(
+				"mfg manifest contains duplicate flash area: %d", area.Id)
+		}
+
+		idAreaMap[area.Id] = area
+	}
+
+	seen := map[int]struct{}{}
+
+	mmrHasFlash := man.Meta != nil && man.Meta.FlashMap
+
+	for _, t := range m.Tlvs() {
+		if t.Header.Type == META_TLV_TYPE_FLASH_AREA {
+			if !mmrHasFlash {
+				return errors.Errorf(
+					"mmr contains flash map; manifest indicates otherwise")
+			}
+
+			body, err := t.StructuredBody()
+			if err != nil {
+				return err
+			}
+			flashBody := body.(*MetaTlvBodyFlashArea)
+			if _, ok := idAreaMap[int(flashBody.Area)]; !ok {
+				return errors.Errorf(
+					"flash area %d missing from mfg manifest", flashBody.Area)
+			}
+
+			seen[int(flashBody.Area)] = struct{}{}
+		}
+	}
+
+	if mmrHasFlash {
+		for _, area := range man.FlashAreas {
+			if _, ok := seen[area.Id]; !ok {
+				return errors.Errorf("flash area %d missing from mmr", area.Id)
+			}
+		}
+	}
+
+	return nil
+}
+
+func (m *Mfg) validateManMmrs(man manifest.MfgManifest) error {
+	areaMap := map[int]struct{}{}
+	if man.Meta != nil {
+		for _, mmr := range man.Meta.Mmrs {
+			fa := man.FindFlashAreaName(mmr.Area)
+			if fa == nil {
+				return errors.Errorf(
+					"flash area %s missing from mfg manifest", mmr.Area)
+			}
+
+			if _, dup := areaMap[fa.Id]; dup {
+				return errors.Errorf(
+					"mfg manifest contains duplicate mmr ref: %s", mmr.Area)
+			}
+
+			areaMap[fa.Id] = struct{}{}
+		}
+	}
+
+	seen := map[int]struct{}{}
+	for _, t := range m.Tlvs() {
+		if t.Header.Type == META_TLV_TYPE_MMR_REF {
+			body, err := t.StructuredBody()
+			if err != nil {
+				return err
+			}
+
+			mmrBody := body.(*MetaTlvBodyMmrRef)
+			if _, ok := areaMap[int(mmrBody.Area)]; !ok {
+				return errors.Errorf(
+					"mmr ref %d missing from mfg manifest", mmrBody.Area)
+			}
+
+			seen[int(mmrBody.Area)] = struct{}{}
+		}
+	}
+
+	for area, _ := range areaMap {
+		if _, ok := seen[area]; !ok {
+			return errors.Errorf("mmr ref %d missing from mmr", area)
+		}
+	}
+
+	return nil
+}
+
+func (m *Mfg) validateManTargets(man manifest.MfgManifest) error {
+	for _, t := range man.Targets {
+		fa := man.FindFlashAreaDevOff(man.Device, t.Offset)
+		if fa == nil {
+			return errors.Errorf(
+				"no flash area in mfgimage corresponding to target \"%s\"",
+				t.Name)
+		}
+
+		data, err := m.ExtractFlashArea(*fa, man.EraseVal)
+		if err != nil {
+			return err
+		}
+
+		if !t.IsBoot() {
+			img, err := image.ParseImage(data)
+			if err != nil {
+				return errors.Wrapf(err,
+					"error parsing build \"%s\" embedded in mfgimage", t.Name)
+			}
+
+			if err := img.Verify(); err != nil {
+				return errors.Wrapf(err,
+					"mfgimage contains invalid build \"%s\"", t.Name)
+			}
+		}
+	}
+
+	return nil
+}
+
+// VerifyManifest compares an mfgimage's structure to its manifest.  It
+// returns an error if the mfgimage doesn't match the manifest.
+func (m *Mfg) VerifyManifest(man manifest.MfgManifest) error {
+	if man.Format != 2 {
+		return errors.Errorf(
+			"only mfgimage format 2 supported (have=%d)", man.Format)
+	}
+
+	mfgHash, err := m.Hash(man.EraseVal)
+	if err != nil {
+		return err
+	}
+	hashStr := hex.EncodeToString(mfgHash)
+	if hashStr != man.MfgHash {
+		return errors.Errorf(
+			"manifest mfg hash different from mmr: man=%s mfg=%s",
+			man.MfgHash, hashStr)
+	}
+
+	if err := m.validateManFlashMap(man); err != nil {
+		return err
+	}
+
+	if err := m.validateManMmrs(man); err != nil {
+		return err
+	}
+
+	// Verify each embedded build.
+	if err := m.validateManTargets(man); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// Verify checks an mfgimage's structure and internal consistency.  It
+// returns an error if the mfgimage is incorrect.
+func (m *Mfg) Verify(eraseVal byte) error {
+	for _, t := range m.Tlvs() {
+		// Verify that TLV has a valid `type` field.
+		body, err := t.StructuredBody()
+		if err != nil {
+			return err
+		}
+
+		// Verify contents of hash TLV.
+		switch t.Header.Type {
+		case META_TLV_TYPE_HASH:
+			hashBody := body.(*MetaTlvBodyHash)
+
+			hash, err := m.RecalcHash(eraseVal)
+			if err != nil {
+				return err
+			}
+
+			if !bytes.Equal(hash, hashBody.Hash[:]) {
+				return errors.Errorf(
+					"mmr contains incorrect hash: have=%s want=%s",
+					hex.EncodeToString(hashBody.Hash[:]),
+					hex.EncodeToString(hash))
+			}
+		}
+	}
+
+	return nil
+}
diff --git a/misc/misc.go b/misc/misc.go
deleted file mode 100644
index 2f685e1..0000000
--- a/misc/misc.go
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * 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.
- */
-
-package misc
-
-import (
-	"fmt"
-)
-
-func HashString(hash []byte) string {
-	return fmt.Sprintf("%x", hash)
-}
diff --git a/sec/encrypt.go b/sec/encrypt.go
index 35ecdd7..d58806c 100644
--- a/sec/encrypt.go
+++ b/sec/encrypt.go
@@ -25,13 +25,13 @@
 	"crypto/cipher"
 	"io"
 
-	"mynewt.apache.org/newt/util"
+	"github.com/apache/mynewt-artifact/errors"
 )
 
 func EncryptAES(plain []byte, secret []byte) ([]byte, error) {
 	block, err := aes.NewCipher(secret)
 	if err != nil {
-		return nil, util.NewNewtError("Failed to create block cipher")
+		return nil, errors.Errorf("Failed to create block cipher")
 	}
 	nonce := make([]byte, 16)
 	stream := cipher.NewCTR(block, nonce)
@@ -43,8 +43,7 @@
 	for {
 		cnt, err := r.Read(dataBuf)
 		if err != nil && err != io.EOF {
-			return nil, util.FmtNewtError(
-				"Failed to read from plaintext: %s", err.Error())
+			return nil, errors.Wrapf(err, "Failed to read from plaintext")
 		}
 		if cnt == 0 {
 			break
@@ -52,8 +51,7 @@
 
 		stream.XORKeyStream(encBuf, dataBuf[0:cnt])
 		if _, err = w.Write(encBuf[0:cnt]); err != nil {
-			return nil, util.FmtNewtError(
-				"Failed to write ciphertext: %s", err.Error())
+			return nil, errors.Wrapf(err, "failed to write ciphertext")
 		}
 	}
 
diff --git a/sec/key.go b/sec/key.go
index 9d073bd..dabbd1f 100644
--- a/sec/key.go
+++ b/sec/key.go
@@ -33,8 +33,7 @@
 	"io/ioutil"
 
 	keywrap "github.com/NickBall/go-aes-key-wrap"
-
-	"mynewt.apache.org/newt/util"
+	"github.com/apache/mynewt-artifact/errors"
 )
 
 type SignKey struct {
@@ -43,6 +42,11 @@
 	Ec  *ecdsa.PrivateKey
 }
 
+type PubSignKey struct {
+	Rsa *rsa.PublicKey
+	Ec  *ecdsa.PublicKey
+}
+
 func ParsePrivateKey(keyBytes []byte) (interface{}, error) {
 	var privKey interface{}
 	var err error
@@ -63,8 +67,7 @@
 		 */
 		privKey, err = x509.ParsePKCS1PrivateKey(block.Bytes)
 		if err != nil {
-			return nil, util.FmtNewtError(
-				"Private key parsing failed: %s", err)
+			return nil, errors.Wrapf(err, "Private key parsing failed")
 		}
 	}
 	if block != nil && block.Type == "EC PRIVATE KEY" {
@@ -73,8 +76,7 @@
 		 */
 		privKey, err = x509.ParseECPrivateKey(block.Bytes)
 		if err != nil {
-			return nil, util.FmtNewtError(
-				"Private key parsing failed: %s", err)
+			return nil, errors.Wrapf(err, "Private key parsing failed")
 		}
 	}
 	if block != nil && block.Type == "PRIVATE KEY" {
@@ -83,8 +85,7 @@
 		// the key itself.
 		privKey, err = x509.ParsePKCS8PrivateKey(block.Bytes)
 		if err != nil {
-			return nil, util.FmtNewtError(
-				"Private key parsing failed: %s", err)
+			return nil, errors.Wrapf(err, "Private key parsing failed")
 		}
 	}
 	if block != nil && block.Type == "ENCRYPTED PRIVATE KEY" {
@@ -92,12 +93,12 @@
 		// encryption.
 		privKey, err = parseEncryptedPrivateKey(block.Bytes)
 		if err != nil {
-			return nil, util.FmtNewtError(
-				"Unable to decode encrypted private key: %s", err)
+			return nil, errors.Wrapf(
+				err, "Unable to decode encrypted private key")
 		}
 	}
 	if privKey == nil {
-		return nil, util.NewNewtError(
+		return nil, errors.Errorf(
 			"Unknown private key format, EC/RSA private " +
 				"key in PEM format only.")
 	}
@@ -119,7 +120,7 @@
 	case *ecdsa.PrivateKey:
 		key.Ec = priv
 	default:
-		return key, util.NewNewtError("Unknown private key format")
+		return key, errors.Errorf("Unknown private key format")
 	}
 
 	return key, nil
@@ -128,8 +129,7 @@
 func ReadKey(filename string) (SignKey, error) {
 	keyBytes, err := ioutil.ReadFile(filename)
 	if err != nil {
-		return SignKey{}, util.FmtNewtError(
-			"Error reading key file: %s", err)
+		return SignKey{}, errors.Wrapf(err, "Error reading key file")
 	}
 
 	return BuildPrivateKey(keyBytes)
@@ -154,31 +154,21 @@
 	if key.Rsa == nil && key.Ec == nil {
 		panic("invalid key; neither RSA nor ECC")
 	}
+}
 
-	if key.Rsa != nil && key.Ec != nil {
-		panic("invalid key; neither RSA nor ECC")
+func (key *SignKey) PubKey() PubSignKey {
+	key.AssertValid()
+
+	if key.Rsa != nil {
+		return PubSignKey{Rsa: &key.Rsa.PublicKey}
+	} else {
+		return PubSignKey{Ec: &key.Ec.PublicKey}
 	}
 }
 
-func (key *SignKey) PubBytes() ([]uint8, error) {
-	key.AssertValid()
-
-	var pubkey []byte
-
-	if key.Rsa != nil {
-		pubkey, _ = asn1.Marshal(key.Rsa.PublicKey)
-	} else {
-		switch key.Ec.Curve.Params().Name {
-		case "P-224":
-			fallthrough
-		case "P-256":
-			pubkey, _ = x509.MarshalPKIXPublicKey(&key.Ec.PublicKey)
-		default:
-			return nil, util.NewNewtError("Unsupported ECC curve")
-		}
-	}
-
-	return pubkey, nil
+func (key *SignKey) PubBytes() ([]byte, error) {
+	pk := key.PubKey()
+	return pk.Bytes()
 }
 
 func RawKeyHash(pubKeyBytes []byte) []byte {
@@ -211,13 +201,12 @@
 	}
 
 	if b.Type != "PUBLIC KEY" && b.Type != "RSA PUBLIC KEY" {
-		return nil, util.NewNewtError("Invalid PEM file")
+		return nil, errors.Errorf("Invalid PEM file")
 	}
 
 	pub, err := x509.ParsePKIXPublicKey(b.Bytes)
 	if err != nil {
-		return nil, util.FmtNewtError(
-			"Error parsing pubkey file: %s", err.Error())
+		return nil, errors.Wrapf(err, "Error parsing pubkey file")
 	}
 
 	var pubk *rsa.PublicKey
@@ -225,8 +214,7 @@
 	case *rsa.PublicKey:
 		pubk = pub.(*rsa.PublicKey)
 	default:
-		return nil, util.FmtNewtError(
-			"Error parsing pubkey file: %s", err.Error())
+		return nil, errors.Wrapf(err, "Error parsing pubkey file")
 	}
 
 	return pubk, nil
@@ -235,8 +223,7 @@
 func ParsePrivKeDer(keyBytes []byte) (*rsa.PrivateKey, error) {
 	privKey, err := x509.ParsePKCS1PrivateKey(keyBytes)
 	if err != nil {
-		return nil, util.FmtNewtError(
-			"Error parsing private key file: %s", err.Error())
+		return nil, errors.Wrapf(err, "Error parsing private key file")
 	}
 
 	return privKey, nil
@@ -247,8 +234,7 @@
 	cipherSecret, err := rsa.EncryptOAEP(
 		sha256.New(), rng, pubk, plainSecret, nil)
 	if err != nil {
-		return nil, util.FmtNewtError(
-			"Error from encryption: %s\n", err.Error())
+		return nil, errors.Wrapf(err, "Error from encryption")
 	}
 
 	return cipherSecret, nil
@@ -261,8 +247,7 @@
 	plainSecret, err := rsa.DecryptOAEP(
 		sha256.New(), rng, privk, cipherSecret, nil)
 	if err != nil {
-		return nil, util.FmtNewtError(
-			"Error from encryption: %s\n", err.Error())
+		return nil, errors.Wrapf(err, "Error from encryption")
 	}
 
 	return plainSecret, nil
@@ -271,18 +256,15 @@
 func ParseKeBase64(keyBytes []byte) (cipher.Block, error) {
 	kek, err := base64.StdEncoding.DecodeString(string(keyBytes))
 	if err != nil {
-		return nil, util.FmtNewtError(
-			"Error decoding kek: %s", err.Error())
+		return nil, errors.Wrapf(err, "error decoding kek")
 	}
 	if len(kek) != 16 {
-		return nil, util.FmtNewtError(
-			"Unexpected key size: %d != 16", len(kek))
+		return nil, errors.Errorf("unexpected key size: %d != 16", len(kek))
 	}
 
 	cipher, err := aes.NewCipher(kek)
 	if err != nil {
-		return nil, util.FmtNewtError(
-			"Error creating keywrap cipher: %s", err.Error())
+		return nil, errors.Wrapf(err, "error creating keywrap cipher")
 	}
 
 	return cipher, nil
@@ -291,8 +273,39 @@
 func EncryptSecretAes(c cipher.Block, plainSecret []byte) ([]byte, error) {
 	cipherSecret, err := keywrap.Wrap(c, plainSecret)
 	if err != nil {
-		return nil, util.FmtNewtError("Error key-wrapping: %s", err.Error())
+		return nil, errors.Wrapf(err, "error key-wrapping")
 	}
 
 	return cipherSecret, nil
 }
+
+func (key *PubSignKey) AssertValid() {
+	if key.Rsa == nil && key.Ec == nil {
+		panic("invalid public key; neither RSA nor ECC")
+	}
+}
+
+func (key *PubSignKey) Bytes() ([]byte, error) {
+	key.AssertValid()
+
+	var b []byte
+
+	if key.Rsa != nil {
+		var err error
+		b, err = asn1.Marshal(*key.Rsa)
+		if err != nil {
+			return nil, err
+		}
+	} else {
+		switch key.Ec.Curve.Params().Name {
+		case "P-224":
+			fallthrough
+		case "P-256":
+			b, _ = x509.MarshalPKIXPublicKey(*key.Ec)
+		default:
+			return nil, errors.Errorf("unsupported ECC curve")
+		}
+	}
+
+	return b, nil
+}
diff --git a/sec/sig.go b/sec/sig.go
new file mode 100644
index 0000000..26a57ac
--- /dev/null
+++ b/sec/sig.go
@@ -0,0 +1,74 @@
+/**
+ * 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.
+ */
+
+package sec
+
+import (
+	"bytes"
+	"crypto"
+	"crypto/rsa"
+
+	"github.com/apache/mynewt-artifact/errors"
+)
+
+type Sig struct {
+	KeyHash []byte
+	Data    []byte
+}
+
+func checkOneKeyOneSig(k PubSignKey, sig Sig, hash []byte) (bool, error) {
+	pubBytes, err := k.Bytes()
+	if err != nil {
+		return false, errors.WithStack(err)
+	}
+	keyHash := RawKeyHash(pubBytes)
+
+	if !bytes.Equal(keyHash, sig.KeyHash) {
+		return false, nil
+	}
+
+	if k.Rsa != nil {
+		opts := rsa.PSSOptions{
+			SaltLength: rsa.PSSSaltLengthEqualsHash,
+		}
+		err := rsa.VerifyPSS(k.Rsa, crypto.SHA256, hash, sig.Data, &opts)
+		return err == nil, nil
+	}
+
+	if k.Ec != nil {
+		return false, errors.Errorf(
+			"ecdsa signature verification not supported")
+	}
+
+	return false, nil
+}
+
+func VerifySigs(key PubSignKey, sigs []Sig, hash []byte) (int, error) {
+	for i, s := range sigs {
+		match, err := checkOneKeyOneSig(key, s, hash)
+		if err != nil {
+			return -1, err
+		}
+		if match {
+			return i, nil
+		}
+	}
+
+	return -1, nil
+}