11package main
22
33import (
4+ "bytes"
5+ "encoding/binary"
46 "flag"
57 "fmt"
68 "os"
@@ -10,6 +12,8 @@ func main() {
1012 var output = flag .String ("output" , "" , "Output to a specific file (default: add .dfu suffix)" )
1113 var debug = flag .Bool ("debug" , false , "Enable debugging mode" )
1214 var linked = flag .Bool ("prelinked" , false , "Provided file has already been linked to Zephyr" )
15+ var force = flag .Bool ("force" , false , "Ignore safety checks and overwrite the header" )
16+ var add_header = flag .Bool ("add_header" , false , "Add space for the header to the file" )
1317
1418 flag .Parse ()
1519 if flag .NArg () != 1 {
@@ -26,16 +30,57 @@ func main() {
2630 return
2731 }
2832
29- // Get the length of the file content
30- length := len (content )
33+ var ELF_HEADER = []byte { 0x7f , 0x45 , 0x4c , 0x46 }
34+ var elf_header_found = bytes .Compare (ELF_HEADER , content [0 :4 ]) == 0
35+ if * add_header || (! * force && ! elf_header_found ) {
36+ fmt .Printf ("File does not have an ELF header, adding empty space\n " )
3137
32- // Create the new content with the length in front
33- len_str := fmt .Sprintf ("%d" , length )
34- newContent := append ([]byte (len_str ), 0 , byte (* debug ), byte (* linked ))
35- // make newContent 16 bytes
36- tmp := make ([]byte , 16 - len (newContent ))
37- newContent = append (newContent , tmp ... )
38- newContent = append (newContent , content ... )
38+ var newContent = make ([]byte , len (content )+ 16 )
39+ copy (newContent [16 :], content )
40+ content = newContent
41+ }
42+
43+ // Create and fill custom header
44+ var header struct {
45+ ver uint8 // @ 0x07
46+ len uint32 // @ 0x08
47+ magic uint16 // @ 0x0c
48+ flags uint8 // @ 0x0e
49+ }
50+
51+ header .ver = 1
52+ header .magic = 0x2341 // Arduino USB VID
53+ header .len = uint32 (len (content ))
54+
55+ header .flags = 0
56+ if * debug {
57+ header .flags |= 0x01
58+ }
59+ if * linked {
60+ header .flags |= 0x02
61+ }
62+
63+ var bytes = make ([]byte , 9 )
64+ _ , err = binary .Encode (bytes , binary .LittleEndian , header )
65+ if err != nil {
66+ fmt .Printf ("Error encoding header: %v\n " , err )
67+ return
68+ }
69+
70+ // Bytes 7 to 15 are free to use in current ELF specification. We will
71+ // use them to store the debug and linked flags.
72+ // Check if the target area is empty
73+ if ! * force {
74+ for i := 7 ; i < 16 ; i ++ {
75+ if content [i ] != 0 {
76+ fmt .Printf ("Target ELF header area is not empty. Use --force to overwrite\n " )
77+ return
78+ }
79+ }
80+ }
81+
82+ // Change the header bytes in the content
83+ copy (content [7 :16 ], bytes )
3984
4085 // Create a new filename for the copy
4186 newFilename := * output
@@ -44,13 +89,7 @@ func main() {
4489 }
4590
4691 // Write the new content to the new file
47- err = os .WriteFile (newFilename , []byte (newContent ), 0644 )
48- if err != nil {
49- fmt .Printf ("Error writing to file: %v\n " , err )
50- return
51- }
52- // Copy in .bin
53- err = os .WriteFile (newFilename + ".bin" , []byte (newContent ), 0644 )
92+ err = os .WriteFile (newFilename , content , 0644 )
5493 if err != nil {
5594 fmt .Printf ("Error writing to file: %v\n " , err )
5695 return
0 commit comments