Skip to content

Commit 66c90bf

Browse files
committed
mfg split: Don't discard trailing 0xff bytes
The `mfg split` command separates an mfgimg binary into several files, one for each flash area. Prior to this commit, imgmod would strip all trailing erase-val bytes (0xff) from each file. Usually this was the correct behavior, but if the contents of a flash area legitimately ended with an erase-val byte, then the file would be corrupted during this step. The problem is that `newt` was throwing away information when it created mfgimages. It embedded the specified binaries into a single mfgimage and filled in the gaps with erase-val bytes, and it did this without leaving any indication of the sizes of the binaries used as input. Newt was recently changed to include the sizes of these binaries in the `manifest.json` file that accompanies an mfgimage. This commit changes imgmod to read these sizes from the manifest file so that it knows how many erase-val bytes it can safely strip. If the manifest does not contain size information (backwards compatibility), imgmod falls back to the old behavior or stripping all trailing erase-val bytes.
1 parent fa5c279 commit 66c90bf

File tree

2 files changed

+71
-5
lines changed

2 files changed

+71
-5
lines changed

cli/mfg_cmds.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ func runSplitCmd(cmd *cobra.Command, args []string) {
184184
ImgmodUsage(nil, err)
185185
}
186186

187-
nbmap, err := imfg.Split(bin, man.Device, areas, man.EraseVal)
187+
nbmap, err := imfg.Split(bin, man, areas)
188188
if err != nil {
189189
ImgmodUsage(nil, err)
190190
}

imfg/imfg.go

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828

2929
"github.com/apache/mynewt-artifact/errors"
3030
"github.com/apache/mynewt-artifact/flash"
31+
"github.com/apache/mynewt-artifact/manifest"
3132
"github.com/apache/mynewt-artifact/mfg"
3233
"mynewt.apache.org/imgmod/iutil"
3334
)
@@ -78,8 +79,63 @@ func VerifyAreas(areas []flash.FlashArea) error {
7879
return nil
7980
}
8081

81-
func Split(mfgBin []byte, deviceNum int,
82-
areas []flash.FlashArea, eraseVal byte) (NameBlobMap, error) {
82+
// areaDataEnd calculates the end offset of valid data in a flash area. "Valid
83+
// data" includes all target binaries and raw sections. If it cannot determine
84+
// the end of any constituent part, it returns an error.
85+
func areaDataEnd(area flash.FlashArea, man manifest.MfgManifest) (int, error) {
86+
end := 0
87+
88+
// Updates `end` if the specified region extends beyond our current concept
89+
// of "the end".
90+
checkOne := func(offset int, size int) error {
91+
a := man.FindWithinFlashAreaDevOff(man.Device, offset)
92+
if a.Id != area.Id {
93+
// Data belongs to a different area.
94+
return nil
95+
}
96+
97+
// Older manifests do not contain target size information.
98+
if size <= 0 {
99+
return errors.Errorf(
100+
"failed to calculate end offset of data at %d: "+
101+
"manifest lacks size",
102+
offset)
103+
}
104+
105+
subEnd := offset - a.Offset + size
106+
if subEnd > end {
107+
end = subEnd
108+
}
109+
110+
return nil
111+
}
112+
113+
for _, t := range man.Targets {
114+
err := checkOne(t.Offset, t.Size)
115+
if err != nil {
116+
return 0, err
117+
}
118+
}
119+
120+
for _, r := range man.Raws {
121+
err := checkOne(r.Offset, r.Size)
122+
if err != nil {
123+
return 0, err
124+
}
125+
}
126+
127+
if man.Meta != nil {
128+
err := checkOne(man.Meta.EndOffset-1, 1)
129+
if err != nil {
130+
return 0, err
131+
}
132+
}
133+
134+
return end, nil
135+
}
136+
137+
func Split(mfgBin []byte, man manifest.MfgManifest,
138+
areas []flash.FlashArea) (NameBlobMap, error) {
83139

84140
mm := NameBlobMap{}
85141

@@ -89,7 +145,7 @@ func Split(mfgBin []byte, deviceNum int,
89145
"two or more flash areas with same name: \"%s\"", area.Name)
90146
}
91147

92-
if area.Device == deviceNum {
148+
if area.Device == man.Device {
93149
var areaBin []byte
94150
if area.Offset < len(mfgBin) {
95151
end := area.Offset + area.Size
@@ -100,7 +156,17 @@ func Split(mfgBin []byte, deviceNum int,
100156
areaBin = mfgBin[area.Offset:end]
101157
}
102158

103-
mm[area.Name] = StripPadding(areaBin, eraseVal)
159+
dataEnd, err := areaDataEnd(area, man)
160+
if err != nil {
161+
// Failed to determine the data end offset. Just strip all
162+
// trailing erase-val bytes.
163+
areaBin = StripPadding(areaBin, man.EraseVal)
164+
} else {
165+
areaBin = areaBin[:dataEnd]
166+
}
167+
if len(areaBin) > 0 {
168+
mm[area.Name] = areaBin
169+
}
104170
}
105171
}
106172

0 commit comments

Comments
 (0)