@@ -38,7 +38,7 @@ def get_pybricks_reset_vector():
3838 """Gets the boot vector of the pybricks firmware."""
3939
4040 # Extract reset vector from dual boot firmware.
41- with open ("_pybricks/firmware.bin" ) as pybricks_bin_file :
41+ with open ("_pybricks/firmware.bin" , "rb" ) as pybricks_bin_file :
4242 pybricks_bin_file .seek (4 )
4343 return pybricks_bin_file .read (4 )
4444
@@ -84,6 +84,34 @@ def get_lego_firmware(size, reset_vector):
8484 yield block
8585
8686
87+ def get_pybricks_firmware (reset_vector ):
88+ """Gets the Pybricks firmware with an updated reset vector."""
89+
90+ # Open the file and get it chunk by chunk
91+ with open ("_pybricks/firmware.bin" , "rb" ) as pybricks_bin_file :
92+
93+ # Read first chunk and override boot vector
94+ block = bytearray (pybricks_bin_file .read (BLOCK_WRITE_SIZE ))
95+ block [4 :8 ] = reset_vector
96+ yield bytes (block )
97+
98+ # Yield remaining blocks
99+ while len (block ) > 0 :
100+ block = pybricks_bin_file .read (BLOCK_WRITE_SIZE )
101+ yield block
102+
103+
104+ def get_padding (padding_length ):
105+ """Gets empty padding blocks with extra information put in at the end."""
106+
107+ # Pad whole blocks as far as we can.
108+ for _ in range (padding_length // BLOCK_WRITE_SIZE ):
109+ yield FF * BLOCK_WRITE_SIZE
110+
111+ # Pad remaining FF as a partial block.
112+ yield FF * (padding_length % BLOCK_WRITE_SIZE )
113+
114+
87115def install (pybricks_hash ):
88116 """Main installation routine."""
89117
@@ -93,7 +121,7 @@ def install(pybricks_hash):
93121 pybricks_hash_calc = uhashlib .sha256 ()
94122 pybricks_size = 0
95123
96- with open ("_pybricks/firmware.bin" ) as pybricks_bin_file :
124+ with open ("_pybricks/firmware.bin" , "rb" ) as pybricks_bin_file :
97125 data = b'START'
98126 while len (data ) > 0 :
99127 data = pybricks_bin_file .read (128 )
@@ -121,9 +149,36 @@ def install(pybricks_hash):
121149 print ("LEGO firmware too big." )
122150 return
123151
124- if FLASH_PYBRICKS_START + pybricks_size >= FLASH_END :
152+ # Total size of combined firmwares, including checksum
153+ total_size = FLASH_PYBRICKS_START - FLASH_LEGO_START + pybricks_size + 4
154+ if total_size >= FLASH_END :
125155 print ("Pybricks firmware too big." )
126156 return
127157
158+ # Initialize flash
159+ print ("Initializing flash for {0} bytes." .format (total_size ))
160+ if not firmware .appl_image_initialise (total_size ):
161+ print ("Failed to initialize external flash." )
162+ return
163+
164+ # Copy original firmware to external flash
165+ print ("Copying LEGO firmware." )
128166 for block in get_lego_firmware (lego_size , get_pybricks_reset_vector ()):
129- pass
167+ firmware .appl_image_store (block )
168+
169+ # Add padding to external flash
170+ print ("Copying padding." )
171+ for block in get_padding (FLASH_PYBRICKS_START - FLASH_LEGO_START - lego_size ):
172+ firmware .appl_image_store (block )
173+
174+ # Copy pybricks firmware to external flash
175+ print ("Copying Pybricks firmware." )
176+ for block in get_pybricks_firmware (get_lego_reset_vector ()):
177+ firmware .appl_image_store (block )
178+
179+ # Get the combined checksum and store it.
180+ overall_checksum = firmware .info ()['new_appl_image_calc_checksum' ]
181+ firmware .appl_image_store (overall_checksum .to_bytes (4 , 'little' ))
182+
183+ # Check result
184+ print (firmware .info ())
0 commit comments