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

[1/3] incubator-mynewt-newt git commit: Mfg - collect instead of build; include img files

Repository: incubator-mynewt-newt
Updated Branches:
  refs/heads/develop 7177ff641 -> fa889a748


Mfg - collect instead of build; include img files

The "newt mfg create" command no longer builds the constituent targets.
Instead it expects the targets / images to have already been built.

Rationale: There is some extra configuration required for building
images: version numbers, build ID, and security material.  If the mfg
commands are responsible for creating images, an mfg configuration would
need to contain this information just so that it could forward it to the
create image command.


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

Branch: refs/heads/develop
Commit: 3e7b198ef44652876894c6b9226c6f3c14922791
Parents: 7177ff6
Author: Christopher Collins <cc...@apache.org>
Authored: Tue Oct 18 18:08:03 2016 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Tue Oct 25 20:10:11 2016 -0700

----------------------------------------------------------------------
 newt/builder/buildutil.go   | 103 -------------
 newt/builder/paths.go       | 164 ++++++++++++++++++++
 newt/builder/targetbuild.go |   4 +-
 newt/cli/build_cmds.go      |   2 +-
 newt/cli/mfg_cmds.go        |  20 +--
 newt/mfg/create.go          | 326 +++++++++++++++++++++++++++------------
 newt/mfg/meta.go            |  22 +--
 newt/mfg/read.go            | 113 --------------
 8 files changed, 410 insertions(+), 344 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/3e7b198e/newt/builder/buildutil.go
----------------------------------------------------------------------
diff --git a/newt/builder/buildutil.go b/newt/builder/buildutil.go
index 052c920..a36d3f2 100644
--- a/newt/builder/buildutil.go
+++ b/newt/builder/buildutil.go
@@ -21,117 +21,14 @@ package builder
 
 import (
 	"bytes"
-	"fmt"
-	"path/filepath"
 	"sort"
 	"strings"
 
 	log "github.com/Sirupsen/logrus"
 
 	"mynewt.apache.org/newt/newt/pkg"
-	"mynewt.apache.org/newt/newt/project"
-	"mynewt.apache.org/newt/newt/target"
 )
 
-func BinRoot() string {
-	return project.GetProject().Path() + "/bin"
-}
-
-func TargetBinDir(target *target.Target) string {
-	return BinRoot() + "/" + target.Name()
-}
-
-func GeneratedBaseDir(targetName string) string {
-	return BinRoot() + "/" + targetName + "/generated"
-}
-
-func GeneratedSrcDir(targetName string) string {
-	return GeneratedBaseDir(targetName) + "/src"
-}
-
-func GeneratedIncludeDir(targetName string) string {
-	return GeneratedBaseDir(targetName) + "/include"
-}
-
-func GeneratedBinDir(targetName string) string {
-	return GeneratedBaseDir(targetName) + "/bin"
-}
-
-func SysinitArchivePath(targetName string) string {
-	return GeneratedBinDir(targetName) + "/sysinit.a"
-}
-
-func (b *Builder) BinDir() string {
-	return BinRoot() + "/" + b.targetPkg.Name() + "/" + b.buildName
-}
-
-func (b *Builder) FileBinDir(pkgName string) string {
-	return b.BinDir() + "/" + pkgName
-}
-
-func (b *Builder) PkgBinDir(bpkg *BuildPackage) string {
-	switch bpkg.Type() {
-	case pkg.PACKAGE_TYPE_GENERATED:
-		return GeneratedBinDir(b.targetPkg.Name())
-	default:
-		return b.FileBinDir(bpkg.Name())
-	}
-}
-
-// Generates the path+filename of the specified package's .a file.
-func (b *Builder) ArchivePath(bpkg *BuildPackage) string {
-	return b.PkgBinDir(bpkg) + "/" + filepath.Base(bpkg.Name()) + ".a"
-}
-
-func (b *Builder) AppTempElfPath() string {
-	return b.PkgBinDir(b.appPkg) + "/" + filepath.Base(b.appPkg.Name()) +
-		"_tmp.elf"
-}
-
-func (b *Builder) AppElfPath() string {
-	return b.PkgBinDir(b.appPkg) + "/" + filepath.Base(b.appPkg.Name()) +
-		".elf"
-}
-
-func (b *Builder) AppLinkerElfPath() string {
-	return b.PkgBinDir(b.appPkg) + "/" + filepath.Base(b.appPkg.Name()) +
-		"linker.elf"
-}
-
-func (b *Builder) AppImgPath() string {
-	return b.PkgBinDir(b.appPkg) + "/" + filepath.Base(b.appPkg.Name()) +
-		".img"
-}
-
-func (b *Builder) AppBinPath() string {
-	return b.AppElfPath() + ".bin"
-}
-
-func (b *Builder) AppPath() string {
-	return b.PkgBinDir(b.appPkg) + "/"
-}
-
-func (b *Builder) ManifestPath() string {
-	return b.AppPath() + "/manifest.json"
-}
-
-func (b *Builder) AppBinBasePath() string {
-	return b.PkgBinDir(b.appPkg) + "/" + filepath.Base(b.appPkg.Name())
-}
-
-func MfgBinDir(mfgPkgName string) string {
-	return BinRoot() + "/" + mfgPkgName
-}
-
-func MfgBinPath(mfgPkgName string) string {
-	return MfgBinDir(mfgPkgName) + "/" + filepath.Base(mfgPkgName) + ".mfg"
-}
-
-func MfgSectionPath(mfgPkgName string, sectionNum int) string {
-	return fmt.Sprintf("%s/%s-s%d.bin", MfgBinDir(mfgPkgName),
-		filepath.Base(mfgPkgName), sectionNum)
-}
-
 func TestTargetName(testPkgName string) string {
 	return strings.Replace(testPkgName, "/", "_", -1)
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/3e7b198e/newt/builder/paths.go
----------------------------------------------------------------------
diff --git a/newt/builder/paths.go b/newt/builder/paths.go
new file mode 100644
index 0000000..9a27b80
--- /dev/null
+++ b/newt/builder/paths.go
@@ -0,0 +1,164 @@
+/**
+ * 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 builder
+
+import (
+	"fmt"
+	"path/filepath"
+	"strconv"
+
+	"mynewt.apache.org/newt/newt/pkg"
+	"mynewt.apache.org/newt/newt/project"
+)
+
+const BUILD_NAME_APP = "app"
+const BUILD_NAME_LOADER = "loader"
+
+func BinRoot() string {
+	return project.GetProject().Path() + "/bin"
+}
+
+func TargetBinDir(targetName string) string {
+	return BinRoot() + "/" + targetName
+}
+
+func GeneratedBaseDir(targetName string) string {
+	return BinRoot() + "/" + targetName + "/generated"
+}
+
+func GeneratedSrcDir(targetName string) string {
+	return GeneratedBaseDir(targetName) + "/src"
+}
+
+func GeneratedIncludeDir(targetName string) string {
+	return GeneratedBaseDir(targetName) + "/include"
+}
+
+func GeneratedBinDir(targetName string) string {
+	return GeneratedBaseDir(targetName) + "/bin"
+}
+
+func SysinitArchivePath(targetName string) string {
+	return GeneratedBinDir(targetName) + "/sysinit.a"
+}
+
+func BinDir(targetName string, buildName string) string {
+	return BinRoot() + "/" + targetName + "/" + buildName
+}
+
+func FileBinDir(targetName string, buildName string, pkgName string) string {
+	return BinDir(targetName, buildName) + "/" + pkgName
+}
+
+func AppElfPath(targetName string, buildName string, appName string) string {
+	return FileBinDir(targetName, buildName, appName) + "/" +
+		filepath.Base(appName) + ".elf"
+}
+
+func AppBinPath(targetName string, buildName string, appName string) string {
+	return AppElfPath(targetName, buildName, appName) + ".bin"
+}
+
+func ManifestPath(targetName string, buildName string, pkgName string) string {
+	return FileBinDir(targetName, buildName, pkgName) + "/manifest.json"
+}
+
+func AppImgPath(targetName string, buildName string, appName string) string {
+	return FileBinDir(targetName, buildName, appName) + "/" +
+		filepath.Base(appName) + ".img"
+}
+
+func MfgBinDir(mfgPkgName string) string {
+	return BinRoot() + "/" + mfgPkgName
+}
+
+func MfgBinBootDir(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 (b *Builder) BinDir() string {
+	return BinDir(b.targetPkg.Name(), b.buildName)
+}
+
+func (b *Builder) FileBinDir(pkgName string) string {
+	return FileBinDir(b.targetPkg.Name(), b.buildName, pkgName)
+}
+
+func (b *Builder) PkgBinDir(bpkg *BuildPackage) string {
+	switch bpkg.Type() {
+	case pkg.PACKAGE_TYPE_GENERATED:
+		return GeneratedBinDir(b.targetPkg.Name())
+	default:
+		return b.FileBinDir(bpkg.Name())
+	}
+}
+
+// Generates the path+filename of the specified package's .a file.
+func (b *Builder) ArchivePath(bpkg *BuildPackage) string {
+	return b.PkgBinDir(bpkg) + "/" + filepath.Base(bpkg.Name()) + ".a"
+}
+
+func (b *Builder) AppTempElfPath() string {
+	return b.PkgBinDir(b.appPkg) + "/" + filepath.Base(b.appPkg.Name()) +
+		"_tmp.elf"
+}
+
+func (b *Builder) AppElfPath() string {
+	return AppElfPath(b.targetPkg.Name(), b.buildName, b.appPkg.Name())
+}
+
+func (b *Builder) AppLinkerElfPath() string {
+	return b.PkgBinDir(b.appPkg) + "/" + filepath.Base(b.appPkg.Name()) +
+		"linker.elf"
+}
+
+func (b *Builder) AppImgPath() string {
+	return b.PkgBinDir(b.appPkg) + "/" + filepath.Base(b.appPkg.Name()) +
+		".img"
+}
+
+func (b *Builder) AppBinPath() string {
+	return b.AppElfPath() + ".bin"
+}
+
+func (b *Builder) AppPath() string {
+	return b.PkgBinDir(b.appPkg) + "/"
+}
+
+func (b *Builder) ManifestPath() string {
+	return ManifestPath(b.targetPkg.Name(), b.buildName, b.appPkg.Name())
+}
+
+func (b *Builder) AppBinBasePath() string {
+	return b.PkgBinDir(b.appPkg) + "/" + filepath.Base(b.appPkg.Name())
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/3e7b198e/newt/builder/targetbuild.go
----------------------------------------------------------------------
diff --git a/newt/builder/targetbuild.go b/newt/builder/targetbuild.go
index 37bae38..cbfb7f9 100644
--- a/newt/builder/targetbuild.go
+++ b/newt/builder/targetbuild.go
@@ -250,7 +250,7 @@ func (t *TargetBuilder) PrepBuild() error {
 	}
 
 	if loaderPkgs != nil {
-		t.LoaderBuilder, err = NewBuilder(t, "loader", loaderPkgs,
+		t.LoaderBuilder, err = NewBuilder(t, BUILD_NAME_LOADER, loaderPkgs,
 			cfgResolution.ApiMap, cfgResolution.Cfg)
 		if err != nil {
 			return err
@@ -266,7 +266,7 @@ func (t *TargetBuilder) PrepBuild() error {
 		t.LoaderList = project.ResetDeps(nil)
 	}
 
-	t.AppBuilder, err = NewBuilder(t, "app", appPkgs,
+	t.AppBuilder, err = NewBuilder(t, BUILD_NAME_APP, appPkgs,
 		cfgResolution.ApiMap, cfgResolution.Cfg)
 	if err != nil {
 		return err

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/3e7b198e/newt/cli/build_cmds.go
----------------------------------------------------------------------
diff --git a/newt/cli/build_cmds.go b/newt/cli/build_cmds.go
index 56c83a9..21ab145 100644
--- a/newt/cli/build_cmds.go
+++ b/newt/cli/build_cmds.go
@@ -196,7 +196,7 @@ func cleanRunCmd(cmd *cobra.Command, args []string) {
 		cleanDir(builder.BinRoot())
 	} else {
 		for _, t := range targets {
-			cleanDir(builder.TargetBinDir(t))
+			cleanDir(builder.TargetBinDir(t.Name()))
 		}
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/3e7b198e/newt/cli/mfg_cmds.go
----------------------------------------------------------------------
diff --git a/newt/cli/mfg_cmds.go b/newt/cli/mfg_cmds.go
index 54eb1bd..ee9d731 100644
--- a/newt/cli/mfg_cmds.go
+++ b/newt/cli/mfg_cmds.go
@@ -54,13 +54,19 @@ func resolveMfgPkg(pkgName string) (*pkg.LocalPackage, error) {
 }
 
 func mfgCreate(mi *mfg.MfgImage) {
-	binPath, sectionPaths, err := mi.CreateMfgImage()
-	if err != nil {
-		NewtUsage(nil, err)
+	pathStr := ""
+	for _, path := range mi.SrcPaths() {
+		pathStr += "    * " + path + "\n"
 	}
 
 	util.StatusMessage(util.VERBOSITY_DEFAULT,
-		"Created manufacturing image: %s\n", binPath)
+		"Creating a manufacturing image from the following files:\n%s",
+		pathStr)
+
+	sectionPaths, err := mi.CreateMfgImage()
+	if err != nil {
+		NewtUsage(nil, err)
+	}
 
 	for _, sectionPath := range sectionPaths {
 		util.StatusMessage(util.VERBOSITY_DEFAULT,
@@ -151,31 +157,25 @@ func AddMfgCommands(cmd *cobra.Command) {
 
 	cmd.AddCommand(mfgCmd)
 
-	mfgCreateHelpText := "TBD"
 	mfgCreateCmd := &cobra.Command{
 		Use:       "create <mfg-package-name>",
 		Short:     "Create a manufacturing flash image",
-		Long:      mfgCreateHelpText,
 		Run:       mfgCreateRunCmd,
 		ValidArgs: mfgList(),
 	}
 	mfgCmd.AddCommand(mfgCreateCmd)
 
-	mfgLoadHelpText := "TBD"
 	mfgLoadCmd := &cobra.Command{
 		Use:       "load <mfg-package-name>",
 		Short:     "Load a manufacturing flash image onto a device",
-		Long:      mfgLoadHelpText,
 		Run:       mfgLoadRunCmd,
 		ValidArgs: mfgList(),
 	}
 	mfgCmd.AddCommand(mfgLoadCmd)
 
-	mfgDeployHelpText := "TBD"
 	mfgDeployCmd := &cobra.Command{
 		Use:       "deploy <mfg-package-name>",
 		Short:     "Builds and uploads a manufacturing image (build + load)",
-		Long:      mfgDeployHelpText,
 		Run:       mfgDeployRunCmd,
 		ValidArgs: mfgList(),
 	}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/3e7b198e/newt/mfg/create.go
----------------------------------------------------------------------
diff --git a/newt/mfg/create.go b/newt/mfg/create.go
index ac6595d..55e7364 100644
--- a/newt/mfg/create.go
+++ b/newt/mfg/create.go
@@ -22,18 +22,25 @@ package mfg
 import (
 	"bytes"
 	"encoding/binary"
+	"encoding/json"
 	"fmt"
 	"io/ioutil"
 	"os"
 	"path/filepath"
+	"time"
 
 	"mynewt.apache.org/newt/newt/builder"
 	"mynewt.apache.org/newt/newt/flash"
-	"mynewt.apache.org/newt/newt/project"
+	"mynewt.apache.org/newt/newt/pkg"
 	"mynewt.apache.org/newt/newt/target"
 	"mynewt.apache.org/newt/util"
 )
 
+type mfgManifest struct {
+	BuildTime string `json:"build_time"`
+	MfgHash   string `json:"mfg_hash"`
+}
+
 func insertPartIntoBlob(blob []byte, part mfgPart) {
 	partEnd := part.offset + len(part.data)
 
@@ -153,180 +160,301 @@ func createSectionHeader(deviceId int, offset int, size int) ([]byte, error) {
 	return buf.Bytes(), nil
 }
 
-func (mi *MfgImage) createBlob(parts []mfgPart) ([]byte, error) {
-	section0Data, hashSubOff, err := mi.section0Data(parts)
-	if err != nil {
-		return nil, err
-	}
-
-	hashOff := MFG_IMAGE_HEADER_SIZE + MFG_IMAGE_SECTION_HEADER_SIZE +
-		hashSubOff
+// @return						[section0blob, section1blob,...], hash, err
+func (mi *MfgImage) createDeviceSections(parts []mfgPart) (
+	[][]byte, []byte, error) {
 
-	imageHdr, err := createImageHeader(hashOff)
+	section0Data, hashOff, err := mi.section0Data(parts)
 	if err != nil {
-		return nil, err
+		return nil, nil, err
 	}
 
-	section0Hdr, err := createSectionHeader(0, 0, len(section0Data))
-	if err != nil {
-		return nil, err
-	}
+	// XXX: Append additional flash device sections.
 
-	blob := append(imageHdr, section0Hdr...)
-	blob = append(blob, section0Data...)
+	// Calculate manufacturing has.
+	sections := [][]byte{section0Data}
+	hash := calcMetaHash(sections)
 
-	fillMetaHash(blob, hashOff)
+	// Write hash to meta region in section 0.
+	copy(section0Data[hashOff:hashOff+META_HASH_SZ], hash)
 
-	return blob, nil
+	return sections, hash, nil
 }
 
-// @return                      bin-path, error
-func (mi *MfgImage) buildBoot() (string, error) {
-	t, err := builder.NewTargetBuilder(mi.boot)
-	if err != nil {
-		return "", err
+func areaNameFromImgIdx(imgIdx int) (string, error) {
+	switch imgIdx {
+	case 0:
+		return flash.FLASH_AREA_NAME_IMAGE_0, nil
+	case 1:
+		return flash.FLASH_AREA_NAME_IMAGE_1, nil
+	default:
+		return "", util.FmtNewtError("invalid image index: %d", imgIdx)
 	}
+}
 
-	if err := t.Build(); err != nil {
-		return "", err
+func (mi *MfgImage) rawSectionParts() []mfgPart {
+	parts := make([]mfgPart, len(mi.rawSections))
+	for i, section := range mi.rawSections {
+		parts[i].name = fmt.Sprintf("section-%d (%s)", i, section.filename)
+		parts[i].offset = section.offset
+		parts[i].data = section.data
 	}
 
-	binPath := t.AppBuilder.AppBinPath()
-	project.ResetProject()
+	return parts
+}
+
+func bootLoaderBinPaths(t *target.Target) []string {
+	return []string{
+		/* boot.elf */
+		builder.AppElfPath(t.Name(), builder.BUILD_NAME_APP, t.App().Name()),
+
+		/* boot.elf.bin */
+		builder.AppBinPath(t.Name(), builder.BUILD_NAME_APP, t.App().Name()),
 
-	return binPath, nil
+		/* manifest.json */
+		builder.ManifestPath(t.Name(), builder.BUILD_NAME_APP, t.App().Name()),
+	}
 }
 
-// @return                      [[loader-path], app-path], error
-func (mi *MfgImage) buildTarget(target *target.Target) ([]string, error) {
-	t, err := builder.NewTargetBuilder(target)
-	if err != nil {
-		return nil, err
+func loaderBinPaths(t *target.Target) []string {
+	if t.LoaderName == "" {
+		return nil
 	}
 
-	// XXX: Currently using made up version and key values.
-	appImg, loaderImg, err := t.CreateImages("99.0.99.0", "", 0)
-	if err != nil {
-		return nil, err
+	return []string{
+		/* <loader>.elf */
+		builder.AppElfPath(t.Name(), builder.BUILD_NAME_LOADER,
+			t.Loader().Name()),
 	}
+}
 
-	paths := []string{}
+func appBinPaths(t *target.Target) []string {
+	return []string{
+		/* <app>.elf */
+		builder.AppElfPath(t.Name(), builder.BUILD_NAME_APP, t.App().Name()),
+
+		/* <app>.img */
+		builder.AppImgPath(t.Name(), builder.BUILD_NAME_APP, t.App().Name()),
 
-	if loaderImg != nil {
-		paths = append(paths, loaderImg.TargetImg)
+		/* manifest.json */
+		builder.ManifestPath(t.Name(), builder.BUILD_NAME_APP, t.App().Name()),
 	}
+}
 
-	paths = append(paths, appImg.TargetImg)
+func imageBinPaths(t *target.Target) []string {
+	paths := loaderBinPaths(t)
+	paths = append(paths, appBinPaths(t)...)
+	return paths
+}
 
-	project.ResetProject()
+func (mi *MfgImage) copyBinFile(srcPath string, dstDir string) error {
+	dstPath := dstDir + "/" + filepath.Base(srcPath)
 
-	return paths, nil
-}
+	util.StatusMessage(util.VERBOSITY_VERBOSE, "copying file %s --> %s\n",
+		srcPath, dstPath)
 
-func areaNameFromImgIdx(imgIdx int) (string, error) {
-	switch imgIdx {
-	case 0:
-		return flash.FLASH_AREA_NAME_IMAGE_0, nil
-	case 1:
-		return flash.FLASH_AREA_NAME_IMAGE_1, nil
-	default:
-		return "", util.FmtNewtError("invalid image index: %d", imgIdx)
+	if err := util.CopyFile(srcPath, dstPath); err != nil {
+		return err
 	}
+
+	return nil
 }
 
-func (mi *MfgImage) rawSectionParts() []mfgPart {
-	parts := make([]mfgPart, len(mi.rawSections))
-	for i, section := range mi.rawSections {
-		parts[i].name = fmt.Sprintf("section-%d (%s)", i, section.filename)
-		parts[i].offset = section.offset
-		parts[i].data = section.data
+func (mi *MfgImage) copyBinFiles() error {
+	dstPath := builder.MfgBinDir(mi.basePkg.Name())
+	if err := os.MkdirAll(filepath.Dir(dstPath), 0755); err != nil {
+		return util.ChildNewtError(err)
 	}
 
-	return parts
+	bootPaths := bootLoaderBinPaths(mi.boot)
+	for _, path := range bootPaths {
+		dstDir := builder.MfgBinBootDir(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)
+		for _, path := range imgPaths {
+			if err := mi.copyBinFile(path, dstDir); err != nil {
+				return err
+			}
+		}
+	}
+
+	return nil
 }
 
-func (mi *MfgImage) build() ([]byte, error) {
-	bootPath, err := mi.buildBoot()
-	if err != nil {
-		return nil, err
+func (mi *MfgImage) dstBootBinPath() string {
+	if mi.boot == nil {
+		return ""
 	}
 
-	paths := []string{bootPath}
+	return fmt.Sprintf("%s/%s.elf.bin",
+		builder.MfgBinBootDir(mi.basePkg.Name()),
+		pkg.ShortName(mi.boot.App()))
+}
 
-	bootPart, err := mi.partFromImage(
-		paths[0],
-		flash.FLASH_AREA_NAME_BOOTLOADER)
-	if err != nil {
-		return nil, err
+func (mi *MfgImage) dstImgPath(imgIdx int) string {
+	var pack *pkg.LocalPackage
+
+	if len(mi.images) >= 1 {
+		switch imgIdx {
+		case 0:
+			if mi.images[0].LoaderName != "" {
+				pack = mi.images[0].Loader()
+			} else {
+				pack = mi.images[0].App()
+			}
+
+		case 1:
+			if mi.images[0].LoaderName != "" {
+				pack = mi.images[0].App()
+			} else {
+				if len(mi.images) >= 2 {
+					pack = mi.images[1].App()
+				}
+			}
+
+		default:
+			panic(fmt.Sprintf("invalid image index: %d", imgIdx))
+		}
 	}
 
-	imgParts := []mfgPart{}
-	for _, img := range mi.images {
-		paths, err := mi.buildTarget(img)
+	if pack == nil {
+		return ""
+	}
+
+	return fmt.Sprintf("%s/%s.img",
+		builder.MfgBinImageDir(mi.basePkg.Name(), imgIdx), pkg.ShortName(pack))
+}
+
+func (mi *MfgImage) targetParts() ([]mfgPart, error) {
+	parts := []mfgPart{}
+
+	bootPath := mi.dstBootBinPath()
+	if bootPath != "" {
+		bootPart, err := mi.partFromImage(
+			bootPath, flash.FLASH_AREA_NAME_BOOTLOADER)
 		if err != nil {
 			return nil, err
 		}
 
-		for _, path := range paths {
-			areaName, err := areaNameFromImgIdx(len(imgParts))
+		parts = append(parts, bootPart)
+	}
+
+	for i := 0; i < 2; i++ {
+		imgPath := mi.dstImgPath(i)
+		if imgPath != "" {
+			areaName, err := areaNameFromImgIdx(i)
 			if err != nil {
 				return nil, err
 			}
 
-			part, err := mi.partFromImage(path, areaName)
+			part, err := mi.partFromImage(imgPath, areaName)
 			if err != nil {
 				return nil, err
 			}
-			imgParts = append(imgParts, part)
+			parts = append(parts, part)
 		}
 	}
 
-	sectionParts := mi.rawSectionParts()
+	return parts, nil
+}
 
-	parts := []mfgPart{bootPart}
-	parts = append(parts, imgParts...)
-	parts = append(parts, sectionParts...)
+// Returns a slice containing the path of each file required to build the
+// manufacturing image.
+func (mi *MfgImage) SrcPaths() []string {
+	paths := []string{}
 
-	sortParts(parts)
+	if mi.boot != nil {
+		paths = append(paths, bootLoaderBinPaths(mi.boot)...)
+	}
+	if len(mi.images) >= 1 {
+		paths = append(paths, imageBinPaths(mi.images[0])...)
+	}
+	if len(mi.images) >= 2 {
+		paths = append(paths, imageBinPaths(mi.images[1])...)
+	}
 
-	blob, err := mi.createBlob(parts)
-	if err != nil {
-		return nil, err
+	for _, raw := range mi.rawSections {
+		paths = append(paths, raw.filename)
 	}
 
-	return blob, nil
+	return paths
 }
 
-// @return                      path-of-image, [paths-of-sections], error
-func (mi *MfgImage) CreateMfgImage() (string, []string, error) {
-	blob, err := mi.build()
+// @return						[section0blob, section1blob,...], hash, err
+func (mi *MfgImage) build() ([][]byte, []byte, error) {
+	if err := mi.copyBinFiles(); err != nil {
+		return nil, nil, err
+	}
+
+	targetParts, err := mi.targetParts()
 	if err != nil {
-		return "", nil, err
+		return nil, nil, err
 	}
 
-	dstPath := builder.MfgBinPath(mi.basePkg.Name())
+	rawParts := mi.rawSectionParts()
 
-	if err := os.MkdirAll(filepath.Dir(dstPath), 0755); err != nil {
-		return "", nil, util.ChildNewtError(err)
+	parts := append(targetParts, rawParts...)
+	sortParts(parts)
+
+	deviceSections, hash, err := mi.createDeviceSections(parts)
+	if err != nil {
+		return nil, nil, err
 	}
 
-	if err := ioutil.WriteFile(dstPath, blob, 0644); err != nil {
-		return "", nil, util.ChildNewtError(err)
+	return deviceSections, hash, nil
+}
+
+func (mi *MfgImage) createManifest(hash []byte) ([]byte, error) {
+	manifest := mfgManifest{
+		BuildTime: time.Now().Format(time.RFC3339),
+		MfgHash:   fmt.Sprintf("%x", hash),
 	}
+	buffer, err := json.MarshalIndent(manifest, "", "  ")
+	if err != nil {
+		return nil, util.FmtNewtError("Failed to encode mfg manifest: %s",
+			err.Error())
+	}
+
+	return buffer, nil
+}
 
-	sections, err := mi.ExtractSections()
+// @return                      [paths-of-sections], error
+func (mi *MfgImage) CreateMfgImage() ([]string, error) {
+	sections, hash, err := mi.build()
 	if err != nil {
-		return "", nil, err
+		return nil, err
+	}
+
+	sectionDir := builder.MfgSectionDir(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)
 		if err := ioutil.WriteFile(sectionPath, section, 0644); err != nil {
-			return "", nil, util.ChildNewtError(err)
+			return nil, util.ChildNewtError(err)
 		}
 		sectionPaths[i] = sectionPath
 	}
 
-	return dstPath, sectionPaths, nil
+	manifest, err := mi.createManifest(hash)
+	if err != nil {
+		return nil, err
+	}
+
+	manifestPath := builder.MfgManifestPath(mi.basePkg.Name())
+	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
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/3e7b198e/newt/mfg/meta.go
----------------------------------------------------------------------
diff --git a/newt/mfg/meta.go b/newt/mfg/meta.go
index 3e3b1bd..d617369 100644
--- a/newt/mfg/meta.go
+++ b/newt/mfg/meta.go
@@ -180,25 +180,15 @@ func insertMeta(section0Data []byte, flashMap flash.FlashMap) (int, error) {
 	return metaOff + hashSubOff, nil
 }
 
-func calcMetaHash(mfgImageBlob []byte, hashOffset int) []byte {
-	// Temporarily zero-out old contents for hash calculation.
-	oldContents := make([]byte, META_HASH_SZ)
-	copy(oldContents, mfgImageBlob[hashOffset:hashOffset+META_HASH_SZ])
-
-	for i := 0; i < META_HASH_SZ; i++ {
-		mfgImageBlob[hashOffset+i] = 0
+func calcMetaHash(deviceSections [][]byte) []byte {
+	// Concatenate all device sections.
+	blob := []byte{}
+	for _, section := range deviceSections {
+		blob = append(blob, section...)
 	}
 
 	// Calculate hash.
-	hash := sha256.Sum256(mfgImageBlob)
-
-	// Restore old contents.
-	copy(mfgImageBlob[hashOffset:hashOffset+META_HASH_SZ], oldContents)
+	hash := sha256.Sum256(blob)
 
 	return hash[:]
 }
-
-func fillMetaHash(mfgImageBlob []byte, hashOffset int) {
-	hash := calcMetaHash(mfgImageBlob, hashOffset)
-	copy(mfgImageBlob[hashOffset:hashOffset+META_HASH_SZ], hash)
-}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/3e7b198e/newt/mfg/read.go
----------------------------------------------------------------------
diff --git a/newt/mfg/read.go b/newt/mfg/read.go
index f73e81e..a947494 100644
--- a/newt/mfg/read.go
+++ b/newt/mfg/read.go
@@ -20,124 +20,11 @@
 package mfg
 
 import (
-	"bytes"
-	"encoding/binary"
-	"fmt"
-	"io/ioutil"
 	"strings"
 
 	"mynewt.apache.org/newt/newt/builder"
-	"mynewt.apache.org/newt/util"
 )
 
-func (mi *MfgImage) Validate() error {
-	binPath := builder.MfgBinPath(mi.basePkg.Name())
-
-	blob, err := ioutil.ReadFile(binPath)
-	if err != nil {
-		return util.ChildNewtError(err)
-	}
-
-	buf := bytes.NewReader(blob)
-	var hdr mfgImageHeader
-	if err := binary.Read(buf, binary.BigEndian, &hdr); err != nil {
-		return util.ChildNewtError(err)
-	}
-
-	if hdr.Version != MFG_IMAGE_VERSION {
-		return util.FmtNewtError(
-			"Manufacturing image \"%s\" specifies unrecognized version: %d",
-			binPath, hdr.Version)
-	}
-
-	if int(hdr.HashOffset)+META_HASH_SZ > len(blob) {
-		return util.FmtNewtError(
-			"Manufacturing image \"%s\" specifies hash offset beyond end of "+
-				"file: %d",
-			binPath, hdr.HashOffset)
-	}
-
-	writtenHash := blob[hdr.HashOffset : hdr.HashOffset+META_HASH_SZ]
-	calcHash := calcMetaHash(blob, int(hdr.HashOffset))
-	if bytes.Compare(writtenHash, calcHash) != 0 {
-		return util.FmtNewtError(
-			"Manufacturing image \"%s\" contains incorrect hash; "+
-				"expected=%x actual=%x",
-			binPath, calcHash, writtenHash)
-	}
-
-	return nil
-}
-
-func extractSection(mfgImageBlob []byte, sectionOff int) (int, []byte, error) {
-	var hdr mfgImageSectionHeader
-
-	buf := bytes.NewReader(mfgImageBlob)
-	if _, err := buf.Seek(int64(MFG_IMAGE_HEADER_SIZE), 0); err != nil {
-		return 0, nil, util.ChildNewtError(err)
-	}
-
-	if err := binary.Read(buf, binary.BigEndian, &hdr); err != nil {
-		return 0, nil, util.ChildNewtError(err)
-	}
-
-	fmt.Printf("off=%d SECTIONHDR=%+v\n", sectionOff, hdr)
-
-	dataOff := sectionOff + MFG_IMAGE_SECTION_HEADER_SIZE
-	dataEnd := dataOff + int(hdr.Size)
-	if dataEnd > len(mfgImageBlob) {
-		return 0, nil, util.FmtNewtError(
-			"invalid mfg image; section %d (off=%d len=%d) extends beyond "+
-				"dataEnd of image (len=%d)",
-			hdr.DeviceId, sectionOff, hdr.Size, len(mfgImageBlob))
-	}
-
-	// 0xff-fill the pre-data portion of the section.
-	sectionData := make([]byte, hdr.Offset+hdr.Size)
-	for i := 0; i < int(hdr.Offset); i++ {
-		sectionData[i] = 0xff
-	}
-
-	// Copy data into section.
-	src := mfgImageBlob[dataOff:dataEnd]
-	dst := sectionData[hdr.Offset : hdr.Offset+hdr.Size]
-	copy(dst, src)
-
-	return int(hdr.DeviceId), sectionData, nil
-}
-
-func (mi *MfgImage) ExtractSections() ([][]byte, error) {
-	if err := mi.Validate(); err != nil {
-		return nil, err
-	}
-
-	binPath := builder.MfgBinPath(mi.basePkg.Name())
-
-	data, err := ioutil.ReadFile(binPath)
-	if err != nil {
-		return nil, util.ChildNewtError(err)
-	}
-
-	sections := [][]byte{}
-	off := MFG_IMAGE_HEADER_SIZE
-	for off < len(data) {
-		sectionIdx, sectionData, err := extractSection(data, off)
-		if err != nil {
-			return nil, err
-		}
-
-		for len(sections) <= sectionIdx {
-			sections = append(sections, nil)
-		}
-
-		sections[sectionIdx] = sectionData
-
-		off += MFG_IMAGE_SECTION_HEADER_SIZE + len(sectionData)
-	}
-
-	return sections, nil
-}
-
 // @return						mfg-image-path, error
 func (mi *MfgImage) Upload() (string, error) {
 	// For now, we always upload section 0 only.


[2/3] incubator-mynewt-newt git commit: newt - Create manifests at build-time

Posted by cc...@apache.org.
newt - Create manifests at build-time

Previously, newt only created a manifest when creating an image.  This
had the potential to be misleading, as the list of git commits didn't
necessarily reflect what went into the build.

Now, manifest creation is done in two steps:

1. Create manifest at build time ("newt build").

This initial manifest contains the following fields:
    * build_time
    * pkgs
    * loader_pkgs
    * target
    * repos

2. Augment manifest at image creation time.

The following fields are added to the existing manifest:
    * build_version
    * id
    * image
    * image_hash
    * loader
    * loader_hash

An "added bonus" is that boot loaders now have manifests.


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

Branch: refs/heads/develop
Commit: 5c047acd8c314a406a5dd3e0630ce4df54b628fa
Parents: 3e7b198
Author: Christopher Collins <cc...@apache.org>
Authored: Tue Oct 25 19:32:45 2016 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Tue Oct 25 20:33:51 2016 -0700

----------------------------------------------------------------------
 newt/builder/targetbuild.go | 188 ++++++++++++++++++++++++++-------------
 1 file changed, 124 insertions(+), 64 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/5c047acd/newt/builder/targetbuild.go
----------------------------------------------------------------------
diff --git a/newt/builder/targetbuild.go b/newt/builder/targetbuild.go
index cbfb7f9..7d1dce3 100644
--- a/newt/builder/targetbuild.go
+++ b/newt/builder/targetbuild.go
@@ -22,6 +22,7 @@ package builder
 import (
 	"encoding/json"
 	"fmt"
+	"io/ioutil"
 	"os"
 	"path/filepath"
 	"sort"
@@ -290,56 +291,25 @@ func (t *TargetBuilder) PrepBuild() error {
 	return nil
 }
 
-func (t *TargetBuilder) Build() error {
-	var err error
-	var linkerScript string
-
-	if err = t.PrepBuild(); err != nil {
-		return err
-	}
-
-	/* Build the Apps */
-	project.ResetDeps(t.AppList)
-
-	if err := t.bspPkg.Reload(t.AppBuilder.cfg.Features()); err != nil {
-		return err
-	}
-
-	err = t.AppBuilder.Build()
-	if err != nil {
-		return err
-	}
-
-	/* if we have no loader, we are done here.  All of the rest of this
-	 * function is for split images */
-	if t.LoaderBuilder == nil {
-		err = t.AppBuilder.Link(t.bspPkg.LinkerScript)
-		return err
-	}
-
+func (t *TargetBuilder) buildLoader() error {
 	/* Link the app as a test (using the normal single image linker script) */
-	err = t.AppBuilder.TestLink(t.bspPkg.LinkerScript)
-	if err != nil {
+	if err := t.AppBuilder.TestLink(t.bspPkg.LinkerScript); err != nil {
 		return err
 	}
 
 	/* rebuild the loader */
 	project.ResetDeps(t.LoaderList)
 
-	if err = t.bspPkg.Reload(t.LoaderBuilder.cfg.Features()); err != nil {
+	if err := t.bspPkg.Reload(t.LoaderBuilder.cfg.Features()); err != nil {
 		return err
 	}
 
-	err = t.LoaderBuilder.Build()
-
-	if err != nil {
+	if err := t.LoaderBuilder.Build(); err != nil {
 		return err
 	}
 
 	/* perform a test link of the loader */
-	err = t.LoaderBuilder.TestLink(t.bspPkg.LinkerScript)
-
-	if err != nil {
+	if err := t.LoaderBuilder.TestLink(t.bspPkg.LinkerScript); err != nil {
 		return err
 	}
 
@@ -362,15 +332,57 @@ func (t *TargetBuilder) Build() error {
 
 	/* set up the linker elf and linker script for the app */
 	t.AppBuilder.linkElf = t.LoaderBuilder.AppLinkerElfPath()
-	linkerScript = t.bspPkg.Part2LinkerScript
+	linkerScript := t.bspPkg.Part2LinkerScript
 
 	if linkerScript == "" {
 		return util.NewNewtError("BSP must specify linker script ")
 	}
 
-	/* link the app */
-	err = t.AppBuilder.Link(linkerScript)
-	if err != nil {
+	return nil
+
+}
+
+func (t *TargetBuilder) Build() error {
+	if err := t.PrepBuild(); err != nil {
+		return err
+	}
+
+	/* Build the Apps */
+	project.ResetDeps(t.AppList)
+
+	if err := t.bspPkg.Reload(t.AppBuilder.cfg.Features()); err != nil {
+		return err
+	}
+
+	if err := t.AppBuilder.Build(); err != nil {
+		return err
+	}
+
+	linkerScript := ""
+	if t.LoaderBuilder == nil {
+		linkerScript = t.bspPkg.LinkerScript
+		if linkerScript == "" {
+			return util.NewNewtError("BSP does not specify linker script")
+		}
+	} else {
+		if err := t.buildLoader(); err != nil {
+			return err
+		}
+
+		linkerScript = t.bspPkg.Part2LinkerScript
+		if linkerScript == "" {
+			return util.NewNewtError(
+				"BSP does not specify part 2 linker script for split image")
+		}
+	}
+
+	/* Link the app. */
+	if err := t.AppBuilder.Link(linkerScript); err != nil {
+		return err
+	}
+
+	/* Create manifest. */
+	if err := t.createManifest(); err != nil {
 		return err
 	}
 
@@ -554,42 +566,40 @@ func (t *TargetBuilder) GetTarget() *target.Target {
 	return t.target
 }
 
-func (t *TargetBuilder) createManifest(
-	appImg *image.Image,
-	loaderImg *image.Image,
-	buildId []byte) error {
+func readManifest(path string) (*image.ImageManifest, error) {
+	content, err := ioutil.ReadFile(path)
+	if err != nil {
+		return nil, util.ChildNewtError(err)
+	}
 
-	versionStr := fmt.Sprintf("%d.%d.%d.%d",
-		appImg.Version.Major, appImg.Version.Minor,
-		appImg.Version.Rev, appImg.Version.BuildNum)
-	hashStr := fmt.Sprintf("%x", appImg.Hash)
-	timeStr := time.Now().Format(time.RFC3339)
+	manifest := &image.ImageManifest{}
+	if err := json.Unmarshal(content, &manifest); err != nil {
+		return nil, util.FmtNewtError(
+			"Failure decoding manifest with path \"%s\": %s", err.Error())
+	}
 
+	return manifest, nil
+}
+
+func (t *TargetBuilder) createManifest() error {
 	manifest := &image.ImageManifest{
-		Version:   versionStr,
-		ImageHash: hashStr,
-		Image:     filepath.Base(appImg.TargetImg),
-		Date:      timeStr,
+		Date: time.Now().Format(time.RFC3339),
 	}
 
 	rm := image.NewRepoManager()
-	for _, builtPkg := range t.AppBuilder.PkgMap {
+	for _, lpkg := range t.AppBuilder.sortedLocalPackages() {
 		manifest.Pkgs = append(manifest.Pkgs,
-			rm.GetImageManifestPkg(builtPkg.LocalPackage))
+			rm.GetImageManifestPkg(lpkg))
 	}
 
-	if loaderImg != nil {
-		manifest.Loader = filepath.Base(loaderImg.TargetImg)
-		manifest.LoaderHash = fmt.Sprintf("%x", loaderImg.Hash)
-
-		for _, builtPkg := range t.LoaderBuilder.PkgMap {
+	if t.LoaderBuilder != nil {
+		for _, lpkg := range t.LoaderBuilder.sortedLocalPackages() {
 			manifest.LoaderPkgs = append(manifest.LoaderPkgs,
-				rm.GetImageManifestPkg(builtPkg.LocalPackage))
+				rm.GetImageManifestPkg(lpkg))
 		}
 	}
-	manifest.Repos = rm.AllRepos()
 
-	manifest.BuildID = fmt.Sprintf("%x", buildId)
+	manifest.Repos = rm.AllRepos()
 
 	vars := t.GetTarget().Vars
 	keys := make([]string, 0, len(vars))
@@ -620,6 +630,56 @@ func (t *TargetBuilder) createManifest(
 	return nil
 }
 
+// Reads an existing manifest file and augments it with image fields:
+//     * Image version
+//     * App image path
+//     * App image hash
+//     * Loader image path
+//     * Loader image hash
+//     * Build ID
+func (t *TargetBuilder) augmentManifest(
+	appImg *image.Image,
+	loaderImg *image.Image,
+	buildId []byte) error {
+
+	manifest, err := readManifest(t.AppBuilder.ManifestPath())
+	if err != nil {
+		return err
+	}
+
+	manifest.Version = fmt.Sprintf("%d.%d.%d.%d",
+		appImg.Version.Major, appImg.Version.Minor,
+		appImg.Version.Rev, appImg.Version.BuildNum)
+	manifest.ImageHash = fmt.Sprintf("%x", appImg.Hash)
+	manifest.Image = filepath.Base(appImg.TargetImg)
+
+	if loaderImg != nil {
+		manifest.Loader = filepath.Base(loaderImg.TargetImg)
+		manifest.LoaderHash = fmt.Sprintf("%x", loaderImg.Hash)
+	}
+
+	manifest.BuildID = fmt.Sprintf("%x", buildId)
+
+	file, err := os.Create(t.AppBuilder.ManifestPath())
+	if err != nil {
+		return util.FmtNewtError("Cannot create manifest file %s: %s",
+			t.AppBuilder.ManifestPath(), err.Error())
+	}
+	defer file.Close()
+
+	buffer, err := json.MarshalIndent(manifest, "", "  ")
+	if err != nil {
+		return util.FmtNewtError("Cannot encode manifest: %s", err.Error())
+	}
+	_, err = file.Write(buffer)
+	if err != nil {
+		return util.FmtNewtError("Cannot write manifest file: %s",
+			err.Error())
+	}
+
+	return nil
+}
+
 // @return                      app-image, loader-image, error
 func (t *TargetBuilder) CreateImages(version string,
 	keystr string, keyId uint8) (*image.Image, *image.Image, error) {
@@ -646,7 +706,7 @@ func (t *TargetBuilder) CreateImages(version string,
 	}
 
 	buildId := image.CreateBuildId(appImg, loaderImg)
-	if err := t.createManifest(appImg, loaderImg, buildId); err != nil {
+	if err := t.augmentManifest(appImg, loaderImg, buildId); err != nil {
 		return nil, nil, err
 	}
 


[3/3] incubator-mynewt-newt git commit: newt - Create manifest for manufacturing image.

Posted by cc...@apache.org.
newt - Create manifest for manufacturing image.

This manifest currently only contains two fields:
    * build_date
    * mfg_hash


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

Branch: refs/heads/develop
Commit: fa889a748382f82ebc3c6ad2f8278a4a8afcd7a6
Parents: 5c047ac
Author: Christopher Collins <cc...@apache.org>
Authored: Tue Oct 25 19:38:51 2016 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Tue Oct 25 20:33:51 2016 -0700

----------------------------------------------------------------------
 newt/builder/paths.go | 5 +++++
 1 file changed, 5 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/fa889a74/newt/builder/paths.go
----------------------------------------------------------------------
diff --git a/newt/builder/paths.go b/newt/builder/paths.go
index 9a27b80..3f84a62 100644
--- a/newt/builder/paths.go
+++ b/newt/builder/paths.go
@@ -101,11 +101,16 @@ func MfgBinImageDir(mfgPkgName string, imageIdx int) string {
 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)
 }