2626logger = logging .getLogger (__name__ )
2727
2828
29- def update_hub_name (firmware , metadata , name ):
30- """Changes the hub name in the firmware blob."""
31-
32- if not name :
33- return
34-
35- if semver .compare (metadata ["metadata-version" ], "1.1.0" ) < 0 :
36- raise ValueError ("this firmware image does not support setting the hub name" )
37-
38- name = name .encode () + b"\0 "
39-
40- max_size = metadata ["max-hub-name-size" ]
41- if len (name ) > max_size :
42- raise ValueError (
43- f"name is too big - must be < { metadata ['max-hub-name-size' ]} UTF-8 bytes"
44- )
45-
46- offset = metadata ["hub-name-offset" ]
47- firmware [offset : offset + len (name )] = name
48-
49-
5029async def create_firmware (
5130 firmware_zip : Union [str , os .PathLike , BinaryIO ], name : Optional [str ] = None
5231) -> Tuple [bytes , dict ]:
@@ -72,55 +51,64 @@ async def create_firmware(
7251 archive = zipfile .ZipFile (firmware_zip )
7352 metadata = json .load (archive .open ("firmware.metadata.json" ))
7453
75- # For SPIKE Hubs, we can use the firmware without appending anything.
76- if metadata ["device-id" ] in (HubKind .TECHNIC_SMALL , HubKind .TECHNIC_LARGE ):
77- firmware = bytearray (archive .open ("firmware.bin" ).read ())
78- update_hub_name (firmware , metadata , name )
79- return firmware , metadata
54+ # Check if there's a complete firmware already
55+ if "firmware.bin" in archive .namelist ():
56+ # If so, use it as-is, with the final checksum stripped off.
57+ # We'll add an updated checksum later on.
58+ firmware = bytearray (archive .open ("firmware.bin" ).read ()[:- 4 ])
59+ else :
60+ # Otherwise, we have to take a base firmware and extend it.
61+ base = archive .open ("firmware-base.bin" ).read ()
62+ main_py = io .TextIOWrapper (archive .open ("main.py" ))
63+
64+ mpy = await compile_file (
65+ save_script (main_py .read ()),
66+ metadata ["mpy-cross-options" ],
67+ metadata ["mpy-abi-version" ],
68+ )
69+
70+ # start with base firmware binary blob
71+ firmware = bytearray (base )
72+ # pad with 0s until user-mpy-offset
73+ firmware .extend (0 for _ in range (metadata ["user-mpy-offset" ] - len (firmware )))
74+ # append 32-bit little-endian main.mpy file size
75+ firmware .extend (struct .pack ("<I" , len (mpy )))
76+ # append main.mpy file
77+ firmware .extend (mpy )
78+ # pad with 0s to align to 4-byte boundary
79+ firmware .extend (0 for _ in range (- len (firmware ) % 4 ))
80+
81+ # Update hub name if given
82+ if name :
83+
84+ if semver .compare (metadata ["metadata-version" ], "1.1.0" ) < 0 :
85+ raise ValueError (
86+ "this firmware image does not support setting the hub name"
87+ )
8088
81- # For Powered Up hubs, we append a script and checksum to a base firmware.
82- base = archive .open ("firmware-base.bin" ).read ()
83- main_py = io .TextIOWrapper (archive .open ("main.py" ))
89+ name = name .encode () + b"\0 "
8490
85- mpy = await compile_file (
86- save_script (main_py .read ()),
87- metadata ["mpy-cross-options" ],
88- metadata ["mpy-abi-version" ],
89- )
91+ max_size = metadata ["max-hub-name-size" ]
92+ if len (name ) > max_size :
93+ raise ValueError (
94+ f"name is too big - must be < { metadata ['max-hub-name-size' ]} UTF-8 bytes"
95+ )
96+
97+ offset = metadata ["hub-name-offset" ]
98+ firmware [offset : offset + len (name )] = name
9099
91- # start with base firmware binary blob
92- firmware = bytearray (base )
93- # pad with 0s until user-mpy-offset
94- firmware .extend (0 for _ in range (metadata ["user-mpy-offset" ] - len (firmware )))
95- # append 32-bit little-endian main.mpy file size
96- firmware .extend (struct .pack ("<I" , len (mpy )))
97- # append main.mpy file
98- firmware .extend (mpy )
99- # pad with 0s to align to 4-byte boundary
100- firmware .extend (0 for _ in range (- len (firmware ) % 4 ))
101-
102- # Update hub name
103- update_hub_name (firmware , metadata , name )
104-
105- # append 32-bit little-endian checksum
100+ # Get checksum for this firmware
106101 if metadata ["checksum-type" ] == "sum" :
107- firmware .extend (
108- struct .pack (
109- "<I" ,
110- sum_complement (io .BytesIO (firmware ), metadata ["max-firmware-size" ] - 4 ),
111- )
112- )
102+ checksum = sum_complement (io .BytesIO (firmware ), metadata ["max-firmware-size" ])
113103 elif metadata ["checksum-type" ] == "crc32" :
114- firmware .extend (
115- struct .pack (
116- "<I" ,
117- crc32_checksum (io .BytesIO (firmware ), metadata ["max-firmware-size" ] - 4 ),
118- )
119- )
104+ checksum = crc32_checksum (io .BytesIO (firmware ), metadata ["max-firmware-size" ])
120105 else :
121106 print (f'Unknown checksum type "{ metadata ["checksum-type" ]} "' , file = sys .stderr )
122107 exit (1 )
123108
109+ # Append checksum to the firmware
110+ firmware .extend (struct .pack ("<I" , checksum ))
111+
124112 return firmware , metadata
125113
126114
0 commit comments