Merge pull request #74 from ccollins476ad/syscfg-override-self

syscfg - Allow a package to override its own setting
diff --git a/newt/builder/paths.go b/newt/builder/paths.go
index 5beb6b3..43d4744 100644
--- a/newt/builder/paths.go
+++ b/newt/builder/paths.go
@@ -161,6 +161,11 @@
 		".img"
 }
 
+func (b *Builder) AppHexPath() string {
+	return b.PkgBinDir(b.appPkg) + "/" + filepath.Base(b.appPkg.rpkg.Lpkg.Name()) +
+		".hex"
+}
+
 func (b *Builder) AppBinPath() string {
 	return b.AppElfPath() + ".bin"
 }
diff --git a/newt/builder/targetbuild.go b/newt/builder/targetbuild.go
index 9c5dc1e..8acb276 100644
--- a/newt/builder/targetbuild.go
+++ b/newt/builder/targetbuild.go
@@ -776,12 +776,27 @@
 	var appImg *image.Image
 	var loaderImg *image.Image
 
+	c, err := t.NewCompiler("")
+	if err != nil {
+		return nil, nil, err
+	}
+
 	if t.LoaderBuilder != nil {
 		loaderImg, err = t.LoaderBuilder.CreateImage(version, keystr, keyId,
 			nil)
 		if err != nil {
 			return nil, nil, err
 		}
+		tgtArea := t.bspPkg.FlashMap.Areas[flash.FLASH_AREA_NAME_IMAGE_0]
+		log.Debugf("Convert %s -> %s at offset 0x%x",
+			t.LoaderBuilder.AppImgPath(),
+			t.LoaderBuilder.AppHexPath(),
+			tgtArea.Offset)
+		err = c.ConvertBinToHex(t.LoaderBuilder.AppImgPath(),
+				t.LoaderBuilder.AppHexPath(), tgtArea.Offset)
+		if err != nil {
+			log.Errorf("Can't convert to hexfile %s\n", err.Error())
+		}
 	}
 
 	appImg, err = t.AppBuilder.CreateImage(version, keystr, keyId, loaderImg)
@@ -789,6 +804,24 @@
 		return nil, nil, err
 	}
 
+	flashTargetArea := ""
+	if t.LoaderBuilder == nil {
+		flashTargetArea = flash.FLASH_AREA_NAME_IMAGE_0
+	} else  {
+		flashTargetArea = flash.FLASH_AREA_NAME_IMAGE_1
+	}
+	tgtArea := t.bspPkg.FlashMap.Areas[flashTargetArea]
+	if tgtArea.Name != "" {
+		log.Debugf("Convert %s -> %s at offset 0x%x",
+			t.AppBuilder.AppImgPath(),
+			t.AppBuilder.AppHexPath(),
+			tgtArea.Offset)
+		err = c.ConvertBinToHex(t.AppBuilder.AppImgPath(),
+				t.AppBuilder.AppHexPath(), tgtArea.Offset)
+		if err != nil {
+			log.Errorf("Can't convert to hexfile %s\n", err.Error())
+		}
+	}
 	buildId := image.CreateBuildId(appImg, loaderImg)
 	if err := t.augmentManifest(appImg, loaderImg, buildId); err != nil {
 		return nil, nil, err
diff --git a/newt/mfg/create.go b/newt/mfg/create.go
index 08614e0..2ee9f07 100644
--- a/newt/mfg/create.go
+++ b/newt/mfg/create.go
@@ -43,22 +43,27 @@
 	MetaOffset  int    `json:"meta_offset"`
 }
 
+type mfgSection struct {
+	offset     int
+	blob       []byte
+}
+
 type createState struct {
-	// {0:[section0blob], 1:[section1blob], ...}
-	dsMap      map[int][]byte
+	// {0:[section0], 1:[section1], ...}
+	dsMap      map[int]mfgSection
 	metaOffset int
 	hashOffset int
 	hash       []byte
 }
 
-func insertPartIntoBlob(blob []byte, part mfgPart) {
+func insertPartIntoBlob(section mfgSection, part mfgPart) {
 	partEnd := part.offset + len(part.data)
 
-	if len(blob) < partEnd {
+	if len(section.blob) < partEnd {
 		panic("internal error; mfg blob too small")
 	}
 
-	copy(blob[part.offset:partEnd], part.data)
+	copy(section.blob[part.offset:partEnd], part.data)
 }
 
 func (mi *MfgImage) partFromImage(
@@ -146,24 +151,35 @@
 	return parts, nil
 }
 
-func sectionSize(parts []mfgPart) int {
+func sectionSize(parts []mfgPart) (int, int) {
 	greatest := 0
-
+	lowest := 0
+	if len(parts) > 0 {
+		lowest = parts[0].offset
+	}
+	for _, part := range parts {
+		lowest = util.IntMin(lowest, part.offset)
+	}
 	for _, part := range parts {
 		end := part.offset + len(part.data)
 		greatest = util.IntMax(greatest, end)
 	}
 
-	return greatest
+	return lowest, greatest
 }
 
-func sectionFromParts(parts []mfgPart) []byte {
-	sectionSize := sectionSize(parts)
-	section := make([]byte, sectionSize)
+func sectionFromParts(parts []mfgPart) mfgSection {
+	offset, sectionSize := sectionSize(parts)
+	blob := make([]byte, sectionSize)
+
+	section := mfgSection{
+		offset: offset,
+		blob:   blob,
+	}
 
 	// Initialize section 0's data as unwritten flash (0xff).
-	for i, _ := range section {
-		section[i] = 0xff
+	for i, _ := range blob {
+		blob[i] = 0xff
 	}
 
 	for _, part := range parts {
@@ -197,14 +213,14 @@
 	return dpMap, nil
 }
 
-func (mi *MfgImage) deviceSectionMap() (map[int][]byte, error) {
+func (mi *MfgImage) deviceSectionMap() (map[int]mfgSection, error) {
 	dpMap, err := mi.devicePartMap()
 	if err != nil {
 		return nil, err
 	}
 
-	// Convert each part slice into a section (byte slice).
-	dsMap := map[int][]byte{}
+	// Convert each part slice into a section.
+	dsMap := map[int]mfgSection{}
 	for device, parts := range dpMap {
 		dsMap[device] = sectionFromParts(parts)
 	}
@@ -226,11 +242,11 @@
 		return cs, err
 	}
 
-	if cs.dsMap[0] == nil {
+	if len(cs.dsMap) < 1 {
 		panic("Invalid state; no section 0")
 	}
 
-	cs.metaOffset, cs.hashOffset, err = insertMeta(cs.dsMap[0],
+	cs.metaOffset, cs.hashOffset, err = insertMeta(cs.dsMap[0].blob,
 		mi.bsp.FlashMap)
 	if err != nil {
 		return cs, err
@@ -245,10 +261,10 @@
 
 	sections := make([][]byte, len(devices))
 	for i, device := range devices {
-		sections[i] = cs.dsMap[device]
+		sections[i] = cs.dsMap[device].blob
 	}
 	cs.hash = calcMetaHash(sections)
-	copy(cs.dsMap[0][cs.hashOffset:cs.hashOffset+META_HASH_SZ], cs.hash)
+	copy(cs.dsMap[0].blob[cs.hashOffset:cs.hashOffset+META_HASH_SZ], cs.hash)
 
 	return cs, nil
 }
@@ -476,6 +492,7 @@
 	}
 
 	paths = append(paths, mi.SectionBinPaths()...)
+	paths = append(paths, mi.SectionHexPaths()...)
 	paths = append(paths, mi.ManifestPath())
 
 	return paths
@@ -495,9 +512,12 @@
 
 	for device, section := range cs.dsMap {
 		sectionPath := MfgSectionBinPath(mi.basePkg.Name(), device)
-		if err := ioutil.WriteFile(sectionPath, section, 0644); err != nil {
+		err := ioutil.WriteFile(sectionPath, section.blob[section.offset:], 0644)
+		if err != nil {
 			return nil, util.ChildNewtError(err)
 		}
+		hexPath := MfgSectionHexPath(mi.basePkg.Name(), device)
+		mi.compiler.ConvertBinToHex(sectionPath, hexPath, section.offset)
 	}
 
 	manifest, err := mi.createManifest(cs)
diff --git a/newt/mfg/load.go b/newt/mfg/load.go
index 4370cda..b2250ed 100644
--- a/newt/mfg/load.go
+++ b/newt/mfg/load.go
@@ -31,6 +31,7 @@
 	"mynewt.apache.org/newt/newt/pkg"
 	"mynewt.apache.org/newt/newt/project"
 	"mynewt.apache.org/newt/newt/target"
+	"mynewt.apache.org/newt/newt/toolchain"
 	"mynewt.apache.org/newt/util"
 )
 
@@ -283,6 +284,16 @@
 		return nil, mi.loadError(err.Error())
 	}
 
+	compilerPkg, err := proj.ResolvePackage(mi.bsp.Repo(), mi.bsp.CompilerName)
+	if err != nil {
+		return nil, mi.loadError(err.Error())
+	}
+	mi.compiler, err = toolchain.NewCompiler(compilerPkg.BasePath(), "",
+							target.DEFAULT_BUILD_PROFILE)
+	if err != nil {
+		return nil, mi.loadError(err.Error())
+	}
+
 	for _, imgTarget := range mi.images {
 		if len(mi.images) > 1 && imgTarget.LoaderName != "" {
 			return nil, mi.loadError("only one image allowed in "+
diff --git a/newt/mfg/mfg.go b/newt/mfg/mfg.go
index 98fbc37..51d6e6d 100644
--- a/newt/mfg/mfg.go
+++ b/newt/mfg/mfg.go
@@ -25,6 +25,7 @@
 	"mynewt.apache.org/newt/newt/image"
 	"mynewt.apache.org/newt/newt/pkg"
 	"mynewt.apache.org/newt/newt/target"
+	"mynewt.apache.org/newt/newt/toolchain"
 )
 
 type MfgRawEntry struct {
@@ -46,7 +47,8 @@
 type MfgImage struct {
 	basePkg *pkg.LocalPackage
 
-	bsp *pkg.BspPackage
+	bsp      *pkg.BspPackage
+	compiler *toolchain.Compiler
 
 	boot       *target.Target
 	images     []*target.Target
diff --git a/newt/mfg/paths.go b/newt/mfg/paths.go
index f05abb3..04cf448 100644
--- a/newt/mfg/paths.go
+++ b/newt/mfg/paths.go
@@ -78,6 +78,11 @@
 		filepath.Base(mfgPkgName), sectionNum)
 }
 
+func MfgSectionHexPath(mfgPkgName string, sectionNum int) string {
+	return fmt.Sprintf("%s/%s-s%d.hex", MfgSectionBinDir(mfgPkgName),
+		filepath.Base(mfgPkgName), sectionNum)
+}
+
 func MfgManifestPath(mfgPkgName string) string {
 	return MfgBinDir(mfgPkgName) + "/manifest.json"
 }
@@ -165,3 +170,13 @@
 	}
 	return paths
 }
+
+func (mi *MfgImage) SectionHexPaths() []string {
+	sectionIds := mi.sectionIds()
+
+	paths := make([]string, len(sectionIds))
+	for i, sectionId := range sectionIds {
+		paths[i] = MfgSectionHexPath(mi.basePkg.Name(), sectionId)
+	}
+	return paths
+}
diff --git a/newt/syscfg/syscfg.go b/newt/syscfg/syscfg.go
index 54d96a3..db2ad29 100644
--- a/newt/syscfg/syscfg.go
+++ b/newt/syscfg/syscfg.go
@@ -322,8 +322,10 @@
 	v := lpkg.SyscfgV
 
 	lfeatures := cfg.FeaturesForLpkg(lpkg)
-	for k, _ := range features {
-		lfeatures[k] = true
+	for k, v := range features {
+		if v {
+			lfeatures[k] = true
+		}
 	}
 
 	settings := newtutil.GetStringMapFeatures(v, lfeatures, "syscfg.defs")
@@ -360,8 +362,10 @@
 	v := lpkg.SyscfgV
 
 	lfeatures := cfg.FeaturesForLpkg(lpkg)
-	for k, _ := range features {
-		lfeatures[k] = true
+	for k, v := range features {
+		if v {
+			lfeatures[k] = true
+		}
 	}
 
 	values := newtutil.GetStringMapFeatures(v, lfeatures, "syscfg.vals")
diff --git a/newt/toolchain/compiler.go b/newt/toolchain/compiler.go
index b846ee2..65b76fb 100644
--- a/newt/toolchain/compiler.go
+++ b/newt/toolchain/compiler.go
@@ -1285,3 +1285,22 @@
 	}
 	return err
 }
+
+func (c *Compiler) ConvertBinToHex(inFile string, outFile string, baseAddr int) error {
+	cmd := []string{
+		c.ocPath,
+		"-I",
+		"binary",
+		"-O",
+		"ihex",
+		"--adjust-vma",
+		"0x" + strconv.FormatInt(int64(baseAddr), 16),
+		inFile,
+		outFile,
+	}
+	_, err := util.ShellCommand(cmd, nil)
+	if err != nil {
+		return err
+	}
+	return nil
+}