You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2016/11/10 22:38:28 UTC

[16/50] incubator-mynewt-newt git commit: newt - expose paths of mfg artifacts.

newt - expose paths of mfg artifacts.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/commit/141160b2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/tree/141160b2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/diff/141160b2

Branch: refs/heads/master
Commit: 141160b285ac529cc376c8353a374c0c881db940
Parents: bc70c6a
Author: Christopher Collins <cc...@apache.org>
Authored: Fri Oct 28 13:42:16 2016 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Fri Oct 28 13:42:16 2016 -0700

----------------------------------------------------------------------
 newt/builder/paths.go |  22 +-----
 newt/cli/mfg_cmds.go  |  14 ++--
 newt/flash/flash.go   |  16 +++++
 newt/mfg/create.go    |  75 +++++++++++++-------
 newt/mfg/load.go      |  61 +++++++++++++++--
 newt/mfg/mfg.go       |  35 ++++++++++
 newt/mfg/paths.go     | 167 +++++++++++++++++++++++++++++++++++++++++++++
 newt/mfg/read.go      |   2 +-
 8 files changed, 335 insertions(+), 57 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/141160b2/newt/builder/paths.go
----------------------------------------------------------------------
diff --git a/newt/builder/paths.go b/newt/builder/paths.go
index 3f84a62..fa9e940 100644
--- a/newt/builder/paths.go
+++ b/newt/builder/paths.go
@@ -20,9 +20,7 @@
 package builder
 
 import (
-	"fmt"
 	"path/filepath"
-	"strconv"
 
 	"mynewt.apache.org/newt/newt/pkg"
 	"mynewt.apache.org/newt/newt/project"
@@ -89,28 +87,10 @@ func MfgBinDir(mfgPkgName string) string {
 	return BinRoot() + "/" + mfgPkgName
 }
 
-func MfgBinBootDir(mfgPkgName string) string {
+func MfgBootDir(mfgPkgName string) string {
 	return MfgBinDir(mfgPkgName) + "/bootloader"
 }
 
-// Image indices start at 0.
-func MfgBinImageDir(mfgPkgName string, imageIdx int) string {
-	return MfgBinDir(mfgPkgName) + "/image" + strconv.Itoa(imageIdx)
-}
-
-func MfgSectionDir(mfgPkgName string) string {
-	return MfgBinDir(mfgPkgName) + "/sections"
-}
-
-func MfgSectionPath(mfgPkgName string, sectionNum int) string {
-	return fmt.Sprintf("%s/%s-s%d.bin", MfgSectionDir(mfgPkgName),
-		filepath.Base(mfgPkgName), sectionNum)
-}
-
-func MfgManifestPath(mfgPkgName string) string {
-	return MfgBinDir(mfgPkgName) + "/manifest.json"
-}
-
 func (b *Builder) BinDir() string {
 	return BinDir(b.targetPkg.Name(), b.buildName)
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/141160b2/newt/cli/mfg_cmds.go
----------------------------------------------------------------------
diff --git a/newt/cli/mfg_cmds.go b/newt/cli/mfg_cmds.go
index ee9d731..a8831c6 100644
--- a/newt/cli/mfg_cmds.go
+++ b/newt/cli/mfg_cmds.go
@@ -55,23 +55,25 @@ func resolveMfgPkg(pkgName string) (*pkg.LocalPackage, error) {
 
 func mfgCreate(mi *mfg.MfgImage) {
 	pathStr := ""
-	for _, path := range mi.SrcPaths() {
+	for _, path := range mi.FromPaths() {
 		pathStr += "    * " + path + "\n"
 	}
 
 	util.StatusMessage(util.VERBOSITY_DEFAULT,
-		"Creating a manufacturing image from the following files:\n%s",
+		"Creating a manufacturing image from the following files:\n%s\n",
 		pathStr)
 
-	sectionPaths, err := mi.CreateMfgImage()
+	outputPaths, err := mi.CreateMfgImage()
 	if err != nil {
 		NewtUsage(nil, err)
 	}
 
-	for _, sectionPath := range sectionPaths {
-		util.StatusMessage(util.VERBOSITY_DEFAULT,
-			"Created manufacturing section: %s\n", sectionPath)
+	pathStr = ""
+	for _, path := range outputPaths {
+		pathStr += "    * " + path + "\n"
 	}
+	util.StatusMessage(util.VERBOSITY_DEFAULT,
+		"Generated the following files:\n%s", pathStr)
 }
 
 func mfgLoad(mi *mfg.MfgImage) {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/141160b2/newt/flash/flash.go
----------------------------------------------------------------------
diff --git a/newt/flash/flash.go b/newt/flash/flash.go
index 4d7c3be..ea13e25 100644
--- a/newt/flash/flash.go
+++ b/newt/flash/flash.go
@@ -205,6 +205,22 @@ func (flashMap FlashMap) SortedAreas() []FlashArea {
 	return areas
 }
 
+func (flashMap FlashMap) DeviceIds() []int {
+	deviceMap := map[int]struct{}{}
+
+	for _, area := range flashMap.Areas {
+		deviceMap[area.Device] = struct{}{}
+	}
+
+	devices := make([]int, 0, len(deviceMap))
+	for device, _ := range deviceMap {
+		devices = append(devices, device)
+	}
+	sort.Ints(devices)
+
+	return devices
+}
+
 func areasDistinct(a FlashArea, b FlashArea) bool {
 	var lo FlashArea
 	var hi FlashArea

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/141160b2/newt/mfg/create.go
----------------------------------------------------------------------
diff --git a/newt/mfg/create.go b/newt/mfg/create.go
index 46058f3..2a7f36f 100644
--- a/newt/mfg/create.go
+++ b/newt/mfg/create.go
@@ -172,7 +172,7 @@ func (mi *MfgImage) rawEntryParts() []mfgPart {
 	return parts
 }
 
-func bootLoaderBinPaths(t *target.Target) []string {
+func bootLoaderFromPaths(t *target.Target) []string {
 	return []string{
 		/* boot.elf */
 		builder.AppElfPath(t.Name(), builder.BUILD_NAME_APP, t.App().Name()),
@@ -185,7 +185,7 @@ func bootLoaderBinPaths(t *target.Target) []string {
 	}
 }
 
-func loaderBinPaths(t *target.Target) []string {
+func loaderFromPaths(t *target.Target) []string {
 	if t.LoaderName == "" {
 		return nil
 	}
@@ -201,7 +201,7 @@ func loaderBinPaths(t *target.Target) []string {
 	}
 }
 
-func appBinPaths(t *target.Target) []string {
+func appFromPaths(t *target.Target) []string {
 	return []string{
 		/* <app>.elf */
 		builder.AppElfPath(t.Name(), builder.BUILD_NAME_APP, t.App().Name()),
@@ -214,9 +214,9 @@ func appBinPaths(t *target.Target) []string {
 	}
 }
 
-func imageBinPaths(t *target.Target) []string {
-	paths := loaderBinPaths(t)
-	paths = append(paths, appBinPaths(t)...)
+func imageFromPaths(t *target.Target) []string {
+	paths := loaderFromPaths(t)
+	paths = append(paths, appFromPaths(t)...)
 	return paths
 }
 
@@ -234,22 +234,22 @@ func (mi *MfgImage) copyBinFile(srcPath string, dstDir string) error {
 }
 
 func (mi *MfgImage) copyBinFiles() error {
-	dstPath := builder.MfgBinDir(mi.basePkg.Name())
+	dstPath := MfgBinDir(mi.basePkg.Name())
 	if err := os.MkdirAll(filepath.Dir(dstPath), 0755); err != nil {
 		return util.ChildNewtError(err)
 	}
 
-	bootPaths := bootLoaderBinPaths(mi.boot)
+	bootPaths := bootLoaderFromPaths(mi.boot)
 	for _, path := range bootPaths {
-		dstDir := builder.MfgBinBootDir(mi.basePkg.Name())
+		dstDir := MfgBootDir(mi.basePkg.Name())
 		if err := mi.copyBinFile(path, dstDir); err != nil {
 			return err
 		}
 	}
 
 	for i, imgTarget := range mi.images {
-		imgPaths := imageBinPaths(imgTarget)
-		dstDir := builder.MfgBinImageDir(mi.basePkg.Name(), i)
+		imgPaths := imageFromPaths(imgTarget)
+		dstDir := MfgImageBinDir(mi.basePkg.Name(), i)
 		for _, path := range imgPaths {
 			if err := mi.copyBinFile(path, dstDir); err != nil {
 				return err
@@ -266,7 +266,7 @@ func (mi *MfgImage) dstBootBinPath() string {
 	}
 
 	return fmt.Sprintf("%s/%s.elf.bin",
-		builder.MfgBinBootDir(mi.basePkg.Name()),
+		MfgBootDir(mi.basePkg.Name()),
 		pkg.ShortName(mi.boot.App()))
 }
 
@@ -305,7 +305,7 @@ func (mi *MfgImage) dstImgPath(slotIdx int) string {
 	}
 
 	return fmt.Sprintf("%s/%s.img",
-		builder.MfgBinImageDir(mi.basePkg.Name(), imgIdx), pkg.ShortName(pack))
+		MfgImageBinDir(mi.basePkg.Name(), imgIdx), pkg.ShortName(pack))
 }
 
 func (mi *MfgImage) targetParts() ([]mfgPart, error) {
@@ -343,17 +343,17 @@ func (mi *MfgImage) targetParts() ([]mfgPart, error) {
 
 // Returns a slice containing the path of each file required to build the
 // manufacturing image.
-func (mi *MfgImage) SrcPaths() []string {
+func (mi *MfgImage) FromPaths() []string {
 	paths := []string{}
 
 	if mi.boot != nil {
-		paths = append(paths, bootLoaderBinPaths(mi.boot)...)
+		paths = append(paths, bootLoaderFromPaths(mi.boot)...)
 	}
 	if len(mi.images) >= 1 {
-		paths = append(paths, imageBinPaths(mi.images[0])...)
+		paths = append(paths, imageFromPaths(mi.images[0])...)
 	}
 	if len(mi.images) >= 2 {
-		paths = append(paths, imageBinPaths(mi.images[1])...)
+		paths = append(paths, imageFromPaths(mi.images[1])...)
 	}
 
 	for _, raw := range mi.rawEntries {
@@ -401,25 +401,52 @@ func (mi *MfgImage) createManifest(hash []byte) ([]byte, error) {
 	return buffer, nil
 }
 
-// @return                      [paths-of-sections], error
+func appendNonEmptyStr(dst []string, src string) []string {
+	if src != "" {
+		dst = append(dst, src)
+	}
+
+	return dst
+}
+
+func (mi *MfgImage) ToPaths() []string {
+	paths := []string{}
+
+	paths = appendNonEmptyStr(paths, mi.BootBinPath())
+	paths = appendNonEmptyStr(paths, mi.BootElfPath())
+	paths = appendNonEmptyStr(paths, mi.BootManifestPath())
+
+	for i := 0; i < len(mi.images); i++ {
+		paths = appendNonEmptyStr(paths, mi.LoaderImgPath(i))
+		paths = appendNonEmptyStr(paths, mi.LoaderElfPath(i))
+		paths = appendNonEmptyStr(paths, mi.AppImgPath(i))
+		paths = appendNonEmptyStr(paths, mi.AppElfPath(i))
+		paths = appendNonEmptyStr(paths, mi.ImageManifestPath(i))
+	}
+
+	paths = append(paths, mi.SectionBinPaths()...)
+	paths = append(paths, mi.ManifestPath())
+
+	return paths
+}
+
+// @return                      [paths-of-artifacts], error
 func (mi *MfgImage) CreateMfgImage() ([]string, error) {
 	sections, hash, err := mi.build()
 	if err != nil {
 		return nil, err
 	}
 
-	sectionDir := builder.MfgSectionDir(mi.basePkg.Name())
+	sectionDir := MfgSectionBinDir(mi.basePkg.Name())
 	if err := os.MkdirAll(sectionDir, 0755); err != nil {
 		return nil, util.ChildNewtError(err)
 	}
 
-	sectionPaths := make([]string, len(sections))
 	for i, section := range sections {
-		sectionPath := builder.MfgSectionPath(mi.basePkg.Name(), i)
+		sectionPath := MfgSectionBinPath(mi.basePkg.Name(), i)
 		if err := ioutil.WriteFile(sectionPath, section, 0644); err != nil {
 			return nil, util.ChildNewtError(err)
 		}
-		sectionPaths[i] = sectionPath
 	}
 
 	manifest, err := mi.createManifest(hash)
@@ -427,11 +454,11 @@ func (mi *MfgImage) CreateMfgImage() ([]string, error) {
 		return nil, err
 	}
 
-	manifestPath := builder.MfgManifestPath(mi.basePkg.Name())
+	manifestPath := mi.ManifestPath()
 	if err := ioutil.WriteFile(manifestPath, manifest, 0644); err != nil {
 		return nil, util.FmtNewtError("Failed to write mfg manifest file: %s",
 			err.Error())
 	}
 
-	return sectionPaths, nil
+	return mi.ToPaths(), nil
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/141160b2/newt/mfg/load.go
----------------------------------------------------------------------
diff --git a/newt/mfg/load.go b/newt/mfg/load.go
index d8e660f..6e986ae 100644
--- a/newt/mfg/load.go
+++ b/newt/mfg/load.go
@@ -23,6 +23,7 @@ import (
 	"fmt"
 	"io/ioutil"
 	"sort"
+	"strconv"
 	"strings"
 
 	"github.com/spf13/cast"
@@ -82,23 +83,36 @@ func (mi *MfgImage) loadRawEntry(
 
 	raw := MfgRawEntry{}
 
+	var err error
+
+	deviceStr := rawEntry["device"]
+	if deviceStr == "" {
+		return raw, mi.loadError(
+			"raw entry %d missing required \"device\" field", entryIdx)
+	}
+
+	raw.device, err = util.AtoiNoOct(deviceStr)
+	if err != nil {
+		return raw, mi.loadError(
+			"raw entry %d contains invalid offset: %s", entryIdx, deviceStr)
+	}
+
 	offsetStr := rawEntry["offset"]
 	if offsetStr == "" {
 		return raw, mi.loadError(
-			"raw rawEntry %d missing required \"offset\" field", entryIdx)
+			"raw entry %d missing required \"offset\" field", entryIdx)
 	}
 
-	var err error
 	raw.offset, err = util.AtoiNoOct(offsetStr)
 	if err != nil {
 		return raw, mi.loadError(
-			"raw rawEntry %d contains invalid offset: %s", entryIdx, offsetStr)
+			"raw entry %d contains invalid offset: %s", entryIdx, offsetStr)
 	}
 
 	raw.filename = rawEntry["file"]
 	if raw.filename == "" {
 		return raw, mi.loadError(
-			"raw rawEntry %d missing required \"file\" field", entryIdx)
+			"raw entry %d missing required \"file\" field", entryIdx)
 	}
 
 	if !strings.HasPrefix(raw.filename, "/") {
@@ -108,7 +122,7 @@ func (mi *MfgImage) loadRawEntry(
 	raw.data, err = ioutil.ReadFile(raw.filename)
 	if err != nil {
 		return raw, mi.loadError(
-			"error loading file for raw rawEntry %d; filename=%s: %s",
+			"error loading file for raw entry %d; filename=%s: %s",
 			entryIdx, raw.filename, err.Error())
 	}
 
@@ -130,6 +144,39 @@ func (mi *MfgImage) areaNameToPart(areaName string) (mfgPart, bool) {
 	return part, true
 }
 
+func (mi *MfgImage) detectInvalidDevices() error {
+	sectionIds := mi.sectionIds()
+	deviceIds := mi.bsp.FlashMap.DeviceIds()
+
+	deviceMap := map[int]struct{}{}
+	for _, device := range deviceIds {
+		deviceMap[device] = struct{}{}
+	}
+
+	invalidIds := []int{}
+	for _, sectionId := range sectionIds {
+		if _, ok := deviceMap[sectionId]; !ok {
+			invalidIds = append(invalidIds, sectionId)
+		}
+	}
+
+	if len(invalidIds) == 0 {
+		return nil
+	}
+
+	listStr := ""
+	for i, id := range invalidIds {
+		if i != 0 {
+			listStr += ", "
+		}
+		listStr += strconv.Itoa(id)
+	}
+
+	return util.FmtNewtError(
+		"image specifies flash devices that are not present in the BSP's "+
+			"flash map: %s", listStr)
+}
+
 func (mi *MfgImage) detectOverlaps() error {
 	type overlap struct {
 		part0 mfgPart
@@ -275,6 +322,10 @@ func Load(basePkg *pkg.LocalPackage) (*MfgImage, error) {
 		}
 	}
 
+	if err := mi.detectInvalidDevices(); err != nil {
+		return nil, err
+	}
+
 	if err := mi.detectOverlaps(); err != nil {
 		return nil, err
 	}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/141160b2/newt/mfg/mfg.go
----------------------------------------------------------------------
diff --git a/newt/mfg/mfg.go b/newt/mfg/mfg.go
index 30e25b2..6805ab9 100644
--- a/newt/mfg/mfg.go
+++ b/newt/mfg/mfg.go
@@ -20,6 +20,8 @@
 package mfg
 
 import (
+	"sort"
+
 	"mynewt.apache.org/newt/newt/pkg"
 	"mynewt.apache.org/newt/newt/target"
 )
@@ -27,6 +29,7 @@ import (
 const MFG_YAML_FILENAME string = "mfg.yml"
 
 type MfgRawEntry struct {
+	device   int
 	offset   int
 	filename string
 	data     []byte
@@ -49,3 +52,35 @@ type MfgImage struct {
 	images     []*target.Target
 	rawEntries []MfgRawEntry
 }
+
+func (mi *MfgImage) imgApps(imageIdx int) (
+	app *pkg.LocalPackage, loader *pkg.LocalPackage) {
+
+	if imageIdx >= len(mi.images) {
+		return
+	}
+
+	t := mi.images[imageIdx]
+	app = t.App()
+	loader = t.Loader()
+	return
+}
+
+func (mi *MfgImage) sectionIds() []int {
+	idMap := map[int]struct{}{}
+
+	// The bootloader and images always go in section 0.
+	idMap[0] = struct{}{}
+
+	for _, entry := range mi.rawEntries {
+		idMap[entry.device] = struct{}{}
+	}
+
+	ids := make([]int, 0, len(idMap))
+	for id, _ := range idMap {
+		ids = append(ids, id)
+	}
+	sort.Ints(ids)
+
+	return ids
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/141160b2/newt/mfg/paths.go
----------------------------------------------------------------------
diff --git a/newt/mfg/paths.go b/newt/mfg/paths.go
new file mode 100644
index 0000000..cd9d38f
--- /dev/null
+++ b/newt/mfg/paths.go
@@ -0,0 +1,167 @@
+/**
+ * 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"
+	"path/filepath"
+	"strconv"
+
+	"mynewt.apache.org/newt/newt/builder"
+	"mynewt.apache.org/newt/newt/pkg"
+)
+
+func MfgBinDir(mfgPkgName string) string {
+	return builder.BinRoot() + "/" + mfgPkgName
+}
+
+func MfgBootDir(mfgPkgName string) string {
+	return MfgBinDir(mfgPkgName) + "/bootloader"
+}
+
+func MfgBootBinPath(mfgPkgName string, appName string) string {
+	return MfgBootDir(mfgPkgName) + "/" + appName + ".elf.bin"
+}
+
+func MfgBootElfPath(mfgPkgName string, appName string) string {
+	return MfgBootDir(mfgPkgName) + "/" + appName + ".elf"
+}
+
+func MfgBootManifestPath(mfgPkgName string, appName string) string {
+	return MfgBootDir(mfgPkgName) + "/manifest.json"
+}
+
+// Image indices start at 0.
+func MfgImageBinDir(mfgPkgName string, imageIdx int) string {
+	return MfgBinDir(mfgPkgName) + "/image" + strconv.Itoa(imageIdx)
+}
+
+func MfgImageImgPath(mfgPkgName string, imageIdx int,
+	appName string) string {
+
+	return MfgImageBinDir(mfgPkgName, imageIdx) + "/" + appName + ".img"
+}
+
+func MfgImageElfPath(mfgPkgName string, imageIdx int,
+	appName string) string {
+
+	return MfgImageBinDir(mfgPkgName, imageIdx) + "/" + appName + ".elf"
+}
+
+func MfgImageManifestPath(mfgPkgName string, imageIdx int) string {
+	return MfgImageBinDir(mfgPkgName, imageIdx) + "/manifest.json"
+}
+
+func MfgSectionBinDir(mfgPkgName string) string {
+	return MfgBinDir(mfgPkgName) + "/sections"
+}
+
+func MfgSectionBinPath(mfgPkgName string, sectionNum int) string {
+	return fmt.Sprintf("%s/%s-s%d.bin", MfgSectionBinDir(mfgPkgName),
+		filepath.Base(mfgPkgName), sectionNum)
+}
+
+func MfgManifestPath(mfgPkgName string) string {
+	return MfgBinDir(mfgPkgName) + "/manifest.json"
+}
+
+func (mi *MfgImage) ManifestPath() string {
+	return MfgManifestPath(mi.basePkg.Name())
+}
+
+func (mi *MfgImage) BootBinPath() string {
+	if mi.boot == nil {
+		return ""
+	}
+
+	return MfgBootBinPath(mi.basePkg.Name(),
+		pkg.ShortName(mi.boot.Package()))
+}
+
+func (mi *MfgImage) BootElfPath() string {
+	if mi.boot == nil {
+		return ""
+	}
+
+	return MfgBootElfPath(mi.basePkg.Name(), pkg.ShortName(mi.boot.Package()))
+}
+
+func (mi *MfgImage) BootManifestPath() string {
+	if mi.boot == nil {
+		return ""
+	}
+
+	return MfgBootManifestPath(mi.basePkg.Name(),
+		pkg.ShortName(mi.boot.Package()))
+}
+
+func (mi *MfgImage) AppImgPath(imageIdx int) string {
+	app, _ := mi.imgApps(imageIdx)
+	if app == nil {
+		return ""
+	}
+
+	return MfgImageImgPath(mi.basePkg.Name(), imageIdx, pkg.ShortName(app))
+}
+
+func (mi *MfgImage) AppElfPath(imageIdx int) string {
+	app, _ := mi.imgApps(imageIdx)
+	if app == nil {
+		return ""
+	}
+
+	return MfgImageElfPath(mi.basePkg.Name(), imageIdx, pkg.ShortName(app))
+}
+
+func (mi *MfgImage) LoaderImgPath(imageIdx int) string {
+	_, loader := mi.imgApps(imageIdx)
+	if loader == nil {
+		return ""
+	}
+
+	return MfgImageImgPath(mi.basePkg.Name(), imageIdx, pkg.ShortName(loader))
+}
+
+func (mi *MfgImage) LoaderElfPath(imageIdx int) string {
+	_, loader := mi.imgApps(imageIdx)
+	if loader == nil {
+		return ""
+	}
+
+	return MfgImageElfPath(mi.basePkg.Name(), imageIdx, pkg.ShortName(loader))
+}
+
+func (mi *MfgImage) ImageManifestPath(imageIdx int) string {
+	if imageIdx >= len(mi.images) {
+		return ""
+	}
+
+	return MfgImageManifestPath(mi.basePkg.Name(), imageIdx)
+}
+
+func (mi *MfgImage) SectionBinPaths() []string {
+	sectionIds := mi.sectionIds()
+
+	paths := make([]string, len(sectionIds))
+	for i, sectionId := range sectionIds {
+		paths[i] = MfgSectionBinPath(mi.basePkg.Name(), sectionId)
+	}
+	return paths
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/141160b2/newt/mfg/read.go
----------------------------------------------------------------------
diff --git a/newt/mfg/read.go b/newt/mfg/read.go
index a947494..04520db 100644
--- a/newt/mfg/read.go
+++ b/newt/mfg/read.go
@@ -28,7 +28,7 @@ import (
 // @return						mfg-image-path, error
 func (mi *MfgImage) Upload() (string, error) {
 	// For now, we always upload section 0 only.
-	section0Path := builder.MfgSectionPath(mi.basePkg.Name(), 0)
+	section0Path := MfgSectionBinPath(mi.basePkg.Name(), 0)
 	baseName := strings.TrimSuffix(section0Path, ".bin")
 
 	envSettings := map[string]string{"MFG_IMAGE": "1"}