Skip to content

Commit 4994615

Browse files
committed
compileopts: add support for custom binary formats
Some chips (like the ESP family) have a particular image format that is more complex than simply dumping everything in a raw image.
1 parent 258a466 commit 4994615

File tree

4 files changed

+49
-16
lines changed

4 files changed

+49
-16
lines changed

builder/build.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -232,19 +232,27 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(stri
232232
}
233233

234234
// Get an Intel .hex file or .bin file from the .elf file.
235-
if outext == ".hex" || outext == ".bin" || outext == ".gba" {
235+
outputBinaryFormat := config.BinaryFormat(outext)
236+
switch outputBinaryFormat {
237+
case "elf":
238+
// do nothing, file is already in ELF format
239+
case "hex", "bin":
240+
// Extract raw binary, either encoding it as a hex file or as a raw
241+
// firmware file.
236242
tmppath = filepath.Join(dir, "main"+outext)
237-
err := objcopy(executable, tmppath)
243+
err := objcopy(executable, tmppath, outputBinaryFormat)
238244
if err != nil {
239245
return err
240246
}
241-
} else if outext == ".uf2" {
247+
case "uf2":
242248
// Get UF2 from the .elf file.
243249
tmppath = filepath.Join(dir, "main"+outext)
244250
err := convertELFFileToUF2File(executable, tmppath, config.Target.UF2FamilyID)
245251
if err != nil {
246252
return err
247253
}
254+
default:
255+
return fmt.Errorf("unknown output binary format: %s", outputBinaryFormat)
248256
}
249257
return action(tmppath)
250258
}

builder/objcopy.go

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"debug/elf"
55
"io/ioutil"
66
"os"
7-
"path/filepath"
87
"sort"
98

109
"github.com/marcinbor85/gohex"
@@ -93,7 +92,7 @@ func extractROM(path string) (uint64, []byte, error) {
9392

9493
// objcopy converts an ELF file to a different (simpler) output file format:
9594
// .bin or .hex. It extracts only the .text section.
96-
func objcopy(infile, outfile string) error {
95+
func objcopy(infile, outfile, binaryFormat string) error {
9796
f, err := os.OpenFile(outfile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
9897
if err != nil {
9998
return err
@@ -107,23 +106,20 @@ func objcopy(infile, outfile string) error {
107106
}
108107

109108
// Write to the file, in the correct format.
110-
switch filepath.Ext(outfile) {
111-
case ".gba":
112-
// The address is not stored in a .gba file.
113-
_, err := f.Write(data)
114-
return err
115-
case ".bin":
116-
// The address is not stored in a .bin file (therefore you
117-
// should use .hex files in most cases).
118-
_, err := f.Write(data)
119-
return err
120-
case ".hex":
109+
switch binaryFormat {
110+
case "hex":
111+
// Intel hex file, includes the firmware start address.
121112
mem := gohex.NewMemory()
122113
err := mem.AddBinary(uint32(addr), data)
123114
if err != nil {
124115
return objcopyError{"failed to create .hex file", err}
125116
}
126117
return mem.DumpIntelHex(f, 16)
118+
case "bin":
119+
// The start address is not stored in raw firmware files (therefore you
120+
// should use .hex files in most cases).
121+
_, err := f.Write(data)
122+
return err
127123
default:
128124
panic("unreachable")
129125
}

compileopts/config.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,31 @@ func (c *Config) Debug() bool {
229229
return c.Options.Debug
230230
}
231231

232+
// BinaryFormat returns an appropriate binary format, based on the file
233+
// extension and the configured binary format in the target JSON file.
234+
func (c *Config) BinaryFormat(ext string) string {
235+
switch ext {
236+
case ".bin", ".gba":
237+
// The simplest format possible: dump everything in a raw binary file.
238+
if c.Target.BinaryFormat != "" {
239+
return c.Target.BinaryFormat
240+
}
241+
return "bin"
242+
case ".hex":
243+
// Similar to bin, but includes the start address and is thus usually a
244+
// better format.
245+
return "hex"
246+
case ".uf2":
247+
// Special purpose firmware format, mainly used on Adafruit boards.
248+
// More information:
249+
// https://github.com/Microsoft/uf2
250+
return "uf2"
251+
default:
252+
// Use the ELF format for unrecognized file formats.
253+
return "elf"
254+
}
255+
}
256+
232257
// Programmer returns the flash method and OpenOCD interface name given a
233258
// particular configuration. It may either be all configured in the target JSON
234259
// file or be modified using the -programmmer command-line option.

compileopts/target.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ type TargetSpec struct {
4545
FlashVolume string `json:"msd-volume-name"`
4646
FlashFilename string `json:"msd-firmware-name"`
4747
UF2FamilyID string `json:"uf2-family-id"`
48+
BinaryFormat string `json:"binary-format"`
4849
OpenOCDInterface string `json:"openocd-interface"`
4950
OpenOCDTarget string `json:"openocd-target"`
5051
OpenOCDTransport string `json:"openocd-transport"`
@@ -120,6 +121,9 @@ func (spec *TargetSpec) copyProperties(spec2 *TargetSpec) {
120121
if spec2.UF2FamilyID != "" {
121122
spec.UF2FamilyID = spec2.UF2FamilyID
122123
}
124+
if spec2.BinaryFormat != "" {
125+
spec.BinaryFormat = spec2.BinaryFormat
126+
}
123127
if spec2.OpenOCDInterface != "" {
124128
spec.OpenOCDInterface = spec2.OpenOCDInterface
125129
}

0 commit comments

Comments
 (0)