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/02 15:12:14 UTC

incubator-mynewt-newt git commit: newt - clean up mfg image code

Repository: incubator-mynewt-newt
Updated Branches:
  refs/heads/develop a1cb7024e -> cc1c2dd81


newt - clean up mfg image code

This code had gone through a few changes in requirements.  This commit
rewrites parts of it without changing its behavior.


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

Branch: refs/heads/develop
Commit: cc1c2dd81204baf9235a7377c0d0814f1f35da3d
Parents: a1cb702
Author: Christopher Collins <cc...@apache.org>
Authored: Wed Nov 2 08:12:44 2016 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Wed Nov 2 08:13:49 2016 -0700

----------------------------------------------------------------------
 newt/mfg/create.go | 216 +++++++++++++++++++++++++++---------------------
 newt/mfg/load.go   |  83 +++++++------------
 newt/mfg/mfg.go    |   3 +-
 3 files changed, 153 insertions(+), 149 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/cc1c2dd8/newt/mfg/create.go
----------------------------------------------------------------------
diff --git a/newt/mfg/create.go b/newt/mfg/create.go
index 2a7f36f..fc11f75 100644
--- a/newt/mfg/create.go
+++ b/newt/mfg/create.go
@@ -25,6 +25,7 @@ import (
 	"io/ioutil"
 	"os"
 	"path/filepath"
+	"sort"
 	"time"
 
 	"mynewt.apache.org/newt/newt/builder"
@@ -52,7 +53,10 @@ func insertPartIntoBlob(blob []byte, part mfgPart) {
 func (mi *MfgImage) partFromImage(
 	imgPath string, flashAreaName string) (mfgPart, error) {
 
-	part := mfgPart{}
+	part := mfgPart{
+		// Boot loader and images always go in device 0.
+		device: 0,
+	}
 
 	area, ok := mi.bsp.FlashMap.Areas[flashAreaName]
 	if !ok {
@@ -79,75 +83,155 @@ func (mi *MfgImage) partFromImage(
 			imgPath, flashAreaName, len(part.data), area.Size, overflow)
 	}
 
+	// If an image slot is used, the entire flash area is unwritable.  This
+	// restriction comes from the boot loader's need to write status at the end
+	// of an area.  Pad out part with unwriten flash (0xff).  This probably
+	// isn't terribly efficient...
+	for i := 0; i < -overflow; i++ {
+		part.data = append(part.data, 0xff)
+	}
+
 	return part, nil
 }
 
-func (mi *MfgImage) section0Size() int {
-	greatest := 0
+func partFromRawEntry(entry MfgRawEntry, entryIdx int) mfgPart {
+	return mfgPart{
+		name:   fmt.Sprintf("entry-%d (%s)", entryIdx, entry.filename),
+		offset: entry.offset,
+		data:   entry.data,
+	}
+}
 
-	bootArea := mi.bsp.FlashMap.Areas[flash.FLASH_AREA_NAME_BOOTLOADER]
-	image0Area := mi.bsp.FlashMap.Areas[flash.FLASH_AREA_NAME_IMAGE_0]
-	image1Area := mi.bsp.FlashMap.Areas[flash.FLASH_AREA_NAME_IMAGE_1]
+func (mi *MfgImage) targetParts() ([]mfgPart, error) {
+	parts := []mfgPart{}
 
-	if mi.boot != nil {
-		greatest = util.IntMax(greatest, bootArea.Offset+bootArea.Size)
-	}
-	if len(mi.images) >= 1 {
-		greatest = util.IntMax(greatest, image0Area.Offset+image0Area.Size)
+	bootPath := mi.dstBootBinPath()
+	if bootPath != "" {
+		bootPart, err := mi.partFromImage(
+			bootPath, flash.FLASH_AREA_NAME_BOOTLOADER)
+		if err != nil {
+			return nil, err
+		}
+
+		parts = append(parts, bootPart)
 	}
-	if len(mi.images) >= 2 {
-		greatest = util.IntMax(greatest, image1Area.Offset+image1Area.Size)
+
+	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(imgPath, areaName)
+			if err != nil {
+				return nil, err
+			}
+			parts = append(parts, part)
+		}
 	}
 
-	for _, entry := range mi.rawEntries {
-		greatest = util.IntMax(greatest, entry.offset+len(entry.data))
+	return parts, nil
+}
+
+func sectionSize(parts []mfgPart) int {
+	greatest := 0
+
+	for _, part := range parts {
+		end := part.offset + len(part.data)
+		greatest = util.IntMax(greatest, end)
 	}
 
 	return greatest
 }
 
-// @return						section-0-blob, hash-offset, error
-func (mi *MfgImage) section0Data(parts []mfgPart) ([]byte, int, error) {
-	blobSize := mi.section0Size()
-	blob := make([]byte, blobSize)
+func sectionFromParts(parts []mfgPart) []byte {
+	sectionSize := sectionSize(parts)
+	section := make([]byte, sectionSize)
 
 	// Initialize section 0's data as unwritten flash (0xff).
-	for i, _ := range blob {
-		blob[i] = 0xff
+	for i, _ := range section {
+		section[i] = 0xff
 	}
 
 	for _, part := range parts {
-		insertPartIntoBlob(blob, part)
+		insertPartIntoBlob(section, part)
+	}
+
+	return section
+}
+
+func (mi *MfgImage) devicePartMap() (map[int][]mfgPart, error) {
+	dpMap := map[int][]mfgPart{}
+
+	// Create parts from the raw entries.
+	for i, entry := range mi.rawEntries {
+		part := partFromRawEntry(entry, i)
+		dpMap[entry.device] = append(dpMap[entry.device], part)
 	}
 
-	hashOffset, err := insertMeta(blob, mi.bsp.FlashMap)
+	// Insert the boot loader and image parts into section 0.
+	targetParts, err := mi.targetParts()
 	if err != nil {
-		return nil, 0, err
+		return nil, err
 	}
+	dpMap[0] = append(dpMap[0], targetParts...)
 
-	return blob, hashOffset, nil
+	// Sort each part slice by offset.
+	for device, _ := range dpMap {
+		sortParts(dpMap[device])
+	}
 
+	return dpMap, nil
+}
+
+func (mi *MfgImage) deviceSectionMap() (map[int][]byte, error) {
+	dpMap, err := mi.devicePartMap()
+	if err != nil {
+		return nil, err
+	}
+
+	// Convert each part slice into a section (byte slice).
+	dsMap := map[int][]byte{}
+	for device, parts := range dpMap {
+		dsMap[device] = sectionFromParts(parts)
+	}
+
+	return dsMap, nil
 }
 
 // @return						[section0blob, section1blob,...], hash, err
-func (mi *MfgImage) createSections(parts []mfgPart) (
-	[][]byte, []byte, error) {
+func (mi *MfgImage) createSections() (map[int][]byte, []byte, error) {
+	dsMap, err := mi.deviceSectionMap()
+	if err != nil {
+		return nil, nil, err
+	}
+
+	if dsMap[0] == nil {
+		panic("Invalid state; no section 0")
+	}
 
-	section0Data, hashOff, err := mi.section0Data(parts)
+	hashOffset, err := insertMeta(dsMap[0], mi.bsp.FlashMap)
 	if err != nil {
 		return nil, nil, err
 	}
 
-	// XXX: Append additional sections.
+	// Calculate manufacturing hash.
+	devices := make([]int, 0, len(dsMap))
+	for device, _ := range dsMap {
+		devices = append(devices, device)
+	}
+	sort.Ints(devices)
 
-	// Calculate manufacturing has.
-	sections := [][]byte{section0Data}
+	sections := make([][]byte, len(devices))
+	for i, device := range devices {
+		sections[i] = dsMap[device]
+	}
 	hash := calcMetaHash(sections)
+	copy(dsMap[0][hashOffset:hashOffset+META_HASH_SZ], hash)
 
-	// Write hash to meta region in section 0.
-	copy(section0Data[hashOff:hashOff+META_HASH_SZ], hash)
-
-	return sections, hash, nil
+	return dsMap, hash, nil
 }
 
 func areaNameFromImgIdx(imgIdx int) (string, error) {
@@ -161,17 +245,6 @@ func areaNameFromImgIdx(imgIdx int) (string, error) {
 	}
 }
 
-func (mi *MfgImage) rawEntryParts() []mfgPart {
-	parts := make([]mfgPart, len(mi.rawEntries))
-	for i, entry := range mi.rawEntries {
-		parts[i].name = fmt.Sprintf("entry-%d (%s)", i, entry.filename)
-		parts[i].offset = entry.offset
-		parts[i].data = entry.data
-	}
-
-	return parts
-}
-
 func bootLoaderFromPaths(t *target.Target) []string {
 	return []string{
 		/* boot.elf */
@@ -308,39 +381,6 @@ func (mi *MfgImage) dstImgPath(slotIdx int) string {
 		MfgImageBinDir(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
-		}
-
-		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(imgPath, areaName)
-			if err != nil {
-				return nil, err
-			}
-			parts = append(parts, part)
-		}
-	}
-
-	return parts, nil
-}
-
 // Returns a slice containing the path of each file required to build the
 // manufacturing image.
 func (mi *MfgImage) FromPaths() []string {
@@ -364,22 +404,12 @@ func (mi *MfgImage) FromPaths() []string {
 }
 
 // @return						[section0blob, section1blob,...], hash, err
-func (mi *MfgImage) build() ([][]byte, []byte, error) {
+func (mi *MfgImage) build() (map[int][]byte, []byte, error) {
 	if err := mi.copyBinFiles(); err != nil {
 		return nil, nil, err
 	}
 
-	targetParts, err := mi.targetParts()
-	if err != nil {
-		return nil, nil, err
-	}
-
-	rawParts := mi.rawEntryParts()
-
-	parts := append(targetParts, rawParts...)
-	sortParts(parts)
-
-	sections, hash, err := mi.createSections(parts)
+	sections, hash, err := mi.createSections()
 	if err != nil {
 		return nil, nil, err
 	}
@@ -442,8 +472,8 @@ func (mi *MfgImage) CreateMfgImage() ([]string, error) {
 		return nil, util.ChildNewtError(err)
 	}
 
-	for i, section := range sections {
-		sectionPath := MfgSectionBinPath(mi.basePkg.Name(), i)
+	for device, section := range sections {
+		sectionPath := MfgSectionBinPath(mi.basePkg.Name(), device)
 		if err := ioutil.WriteFile(sectionPath, section, 0644); err != nil {
 			return nil, util.ChildNewtError(err)
 		}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/cc1c2dd8/newt/mfg/load.go
----------------------------------------------------------------------
diff --git a/newt/mfg/load.go b/newt/mfg/load.go
index 6e986ae..ef75d4d 100644
--- a/newt/mfg/load.go
+++ b/newt/mfg/load.go
@@ -28,13 +28,14 @@ import (
 
 	"github.com/spf13/cast"
 
-	"mynewt.apache.org/newt/newt/flash"
 	"mynewt.apache.org/newt/newt/pkg"
 	"mynewt.apache.org/newt/newt/project"
 	"mynewt.apache.org/newt/newt/target"
 	"mynewt.apache.org/newt/util"
 )
 
+const MFG_YAML_FILENAME string = "mfg.yml"
+
 type partSorter struct {
 	parts []mfgPart
 }
@@ -129,21 +130,6 @@ func (mi *MfgImage) loadRawEntry(
 	return raw, nil
 }
 
-func (mi *MfgImage) areaNameToPart(areaName string) (mfgPart, bool) {
-	part := mfgPart{}
-
-	area, ok := mi.bsp.FlashMap.Areas[areaName]
-	if !ok {
-		return part, false
-	}
-
-	part.offset = area.Offset
-	part.data = make([]byte, area.Size)
-	part.name = area.Name
-
-	return part, true
-}
-
 func (mi *MfgImage) detectInvalidDevices() error {
 	sectionIds := mi.sectionIds()
 	deviceIds := mi.bsp.FlashMap.DeviceIds()
@@ -183,45 +169,33 @@ func (mi *MfgImage) detectOverlaps() error {
 		part1 mfgPart
 	}
 
-	parts := []mfgPart{}
-
-	// If an image slot is used, the entire flash area is unwritable.  This
-	// restriction comes from the boot loader's need to write status at the end
-	// of an area.
-	if mi.boot != nil {
-		part, ok := mi.areaNameToPart(flash.FLASH_AREA_NAME_BOOTLOADER)
-		if ok {
-			parts = append(parts, part)
-		}
-	}
-	if len(mi.images) >= 1 {
-		part, ok := mi.areaNameToPart(flash.FLASH_AREA_NAME_IMAGE_0)
-		if ok {
-			parts = append(parts, part)
-		}
-	}
-	if len(mi.images) >= 2 {
-		part, ok := mi.areaNameToPart(flash.FLASH_AREA_NAME_IMAGE_1)
-		if ok {
-			parts = append(parts, part)
-		}
-	}
-
-	parts = append(parts, mi.rawEntryParts()...)
-	sortParts(parts)
-
 	overlaps := []overlap{}
 
-	for i, part0 := range parts[:len(parts)-1] {
-		part0End := part0.offset + len(part0.data)
-		for _, part1 := range parts[i+1:] {
-			// Parts are sorted by offset, so only one comparison is necessary
-			// to detect overlap.
-			if part1.offset < part0End {
-				overlaps = append(overlaps, overlap{
-					part0: part0,
-					part1: part1,
-				})
+	dpMap, err := mi.devicePartMap()
+	if err != nil {
+		return err
+	}
+
+	// Iterate flash devices in order.
+	devices := make([]int, 0, len(dpMap))
+	for device, _ := range dpMap {
+		devices = append(devices, device)
+	}
+	sort.Ints(devices)
+
+	for _, device := range devices {
+		parts := dpMap[device]
+		for i, part0 := range parts[:len(parts)-1] {
+			part0End := part0.offset + len(part0.data)
+			for _, part1 := range parts[i+1:] {
+				// Parts are sorted by offset, so only one comparison is
+				// necessary to detect overlap.
+				if part1.offset < part0End {
+					overlaps = append(overlaps, overlap{
+						part0: part0,
+						part1: part1,
+					})
+				}
 			}
 		}
 	}
@@ -232,7 +206,8 @@ func (mi *MfgImage) detectOverlaps() error {
 
 			part0End := overlap.part0.offset + len(overlap.part0.data)
 			part1End := overlap.part1.offset + len(overlap.part1.data)
-			str += fmt.Sprintf("\n    * [%s] (%d - %d) <=> [%s] (%d - %d)",
+			str += fmt.Sprintf("\n    * s%d [%s] (%d - %d) <=> [%s] (%d - %d)",
+				overlap.part0.device,
 				overlap.part0.name, overlap.part0.offset, part0End,
 				overlap.part1.name, overlap.part1.offset, part1End)
 		}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/cc1c2dd8/newt/mfg/mfg.go
----------------------------------------------------------------------
diff --git a/newt/mfg/mfg.go b/newt/mfg/mfg.go
index ea31f85..999c00f 100644
--- a/newt/mfg/mfg.go
+++ b/newt/mfg/mfg.go
@@ -26,8 +26,6 @@ import (
 	"mynewt.apache.org/newt/newt/target"
 )
 
-const MFG_YAML_FILENAME string = "mfg.yml"
-
 type MfgRawEntry struct {
 	device   int
 	offset   int
@@ -38,6 +36,7 @@ type MfgRawEntry struct {
 // A chunk of data in the manufacturing image.  Can be a firmware image or a
 // raw entry (contents of a data file).
 type mfgPart struct {
+	device int
 	offset int
 	data   []byte
 	name   string