1515#include <pbio/main.h>
1616#include <pbio/protocol.h>
1717#include <pbsys/main.h>
18+ #include <pbsys/program_load.h>
1819#include <pbsys/status.h>
1920
2021#include "core.h"
2122
22- // Sanity check that application RAM is enough to load ROM and still do something useful
23- #if PBSYS_CONFIG_PROGRAM_LOAD_RAM_SIZE < PBSYS_CONFIG_PROGRAM_LOAD_ROM_SIZE + 2048
24- #error "Application RAM must be at least ROM size + 2K."
25- #endif
26-
2723/**
28- * Map of loaded data. All data types are little-endian.
24+ * Map of loaded data.
2925 */
3026typedef struct {
3127 /**
32- * How much to write on shutdown. This is reset to 0 on load, and should be
33- * set whenever any data is updated. This must always remain the first
34- * element of this structure.
35- */
36- uint32_t write_size ;
37- #if PBSYS_CONFIG_PROGRAM_LOAD_OVERLAPS_BOOTLOADER_CHECKSUM
38- /**
39- * Checksum complement to satisfy bootloader requirements. This ensures
40- * that words in the scanned area still add up to precisely 0 after user
41- * data was written.
42- */
43- volatile uint32_t checksum_complement ;
44- #endif
45- /**
46- * Size of the application program (size of code only).
28+ * User data header.
4729 */
48- uint32_t program_size ;
30+ pbsys_program_load_data_header_t header ;
4931 /**
5032 * Data of the application program (code + heap).
5133 */
52- uint8_t program_data [PBSYS_CONFIG_PROGRAM_LOAD_RAM_SIZE ] __attribute__((aligned (sizeof (void * ))));
34+ uint8_t program_data [PBSYS_CONFIG_PROGRAM_LOAD_RAM_SIZE - sizeof ( pbsys_program_load_data_header_t ) ] __attribute__((aligned (sizeof (void * ))));
5335} data_map_t ;
5436
5537// The data map sits at the start of user RAM.
@@ -59,16 +41,14 @@ static data_map_t *map = &pbsys_user_ram_data_map;
5941static bool pbsys_program_load_start_user_program_requested ;
6042static bool pbsys_program_load_start_repl_requested ;
6143
62- #define MAP_HEADER_SIZE (sizeof(*map) - sizeof(map->program_data))
63-
6444#if PBSYS_CONFIG_PROGRAM_LOAD_OVERLAPS_BOOTLOADER_CHECKSUM
6545// Updates checksum in data map to satisfy bootloader requirements.
6646static void pbsys_program_load_update_checksum (void ) {
6747
6848 // Align writable data by a double word, to simplify checksum
6949 // computation and storage drivers that write double words.
70- while (map -> write_size % 8 ) {
71- * ((uint8_t * )map + map -> write_size ++ ) = 0 ;
50+ while (map -> header . write_size % 8 ) {
51+ * ((uint8_t * )map + map -> header . write_size ++ ) = 0 ;
7252 }
7353
7454 // The area scanned by the bootloader adds up to 0 when all user data
@@ -79,25 +59,20 @@ static void pbsys_program_load_update_checksum(void) {
7959 uint32_t checksum = checksize / sizeof (uint32_t );
8060
8161 // Don't count existing value.
82- map -> checksum_complement = 0 ;
62+ map -> header . checksum_complement = 0 ;
8363
8464 // Add checksum for each word in the written data and empty checked size.
8565 for (uint32_t offset = 0 ; offset < checksize ; offset += sizeof (uint32_t )) {
8666 uint32_t * word = (uint32_t * )((uint8_t * )map + offset );
8767 // Assume that everything after written data is erased.
88- checksum += offset < map -> write_size ? * word : 0xFFFFFFFF ;
68+ checksum += offset < map -> header . write_size ? * word : 0xFFFFFFFF ;
8969 }
9070
9171 // Set the checksum complement to cancel out user data checksum.
92- map -> checksum_complement = 0xFFFFFFFF - checksum + 1 ;
72+ map -> header . checksum_complement = 0xFFFFFFFF - checksum + 1 ;
9373}
9474#endif // PBSYS_CONFIG_PROGRAM_LOAD_OVERLAPS_BOOTLOADER_CHECKSUM
9575
96- // Gets the (constant) maximum program size.
97- static inline uint32_t pbsys_program_load_get_max_program_size () {
98- return PBSYS_CONFIG_PROGRAM_LOAD_ROM_SIZE - MAP_HEADER_SIZE ;
99- }
100-
10176/**
10277 * Writes the user program metadata.
10378 *
@@ -112,9 +87,9 @@ pbio_error_t pbsys_program_load_set_program_size(uint32_t size) {
11287 return PBIO_ERROR_BUSY ;
11388 }
11489
115- map -> program_size = size ;
90+ map -> header . program_size = size ;
11691 // Data was updated, so set the write size.
117- map -> write_size = size + MAP_HEADER_SIZE ;
92+ map -> header . write_size = size + sizeof ( pbsys_program_load_data_header_t ) ;
11893
11994 return PBIO_SUCCESS ;
12095}
@@ -162,7 +137,7 @@ pbio_error_t pbsys_program_load_start_user_program(void) {
162137 }
163138
164139 // Don't run invalid programs.
165- if (map -> program_size == 0 || map -> program_size > pbsys_program_load_get_max_program_size () ) {
140+ if (map -> header . program_size == 0 || map -> header . program_size > PBSYS_PROGRAM_LOAD_MAX_PROGRAM_SIZE ) {
166141 // TODO: Validate the data beyond just size.
167142 return PBIO_ERROR_INVALID_ARG ;
168143 }
@@ -218,16 +193,16 @@ PROCESS_THREAD(pbsys_program_load_process, ev, data) {
218193 PROCESS_BEGIN ();
219194
220195 // Read size of stored data.
221- PROCESS_PT_SPAWN (& pt , pbdrv_block_device_read (& pt , 0 , (uint8_t * )map , sizeof (map -> write_size ), & err ));
196+ PROCESS_PT_SPAWN (& pt , pbdrv_block_device_read (& pt , 0 , (uint8_t * )map , sizeof (map -> header . write_size ), & err ));
222197
223198 // Read the available data into RAM.
224- PROCESS_PT_SPAWN (& pt , pbdrv_block_device_read (& pt , 0 , (uint8_t * )map , map -> write_size , & err ));
199+ PROCESS_PT_SPAWN (& pt , pbdrv_block_device_read (& pt , 0 , (uint8_t * )map , map -> header . write_size , & err ));
225200 if (err != PBIO_SUCCESS ) {
226- map -> program_size = 0 ;
201+ map -> header . program_size = 0 ;
227202 }
228203
229204 // Reset write size, so we don't write data if nothing changed.
230- map -> write_size = 0 ;
205+ map -> header . write_size = 0 ;
231206
232207 // Initialization done.
233208 pbsys_init_busy_down ();
@@ -236,14 +211,14 @@ PROCESS_THREAD(pbsys_program_load_process, ev, data) {
236211 PROCESS_WAIT_EVENT_UNTIL (ev == PROCESS_EVENT_CONTINUE );
237212
238213 // Write data to storage if it was updated.
239- if (map -> write_size ) {
214+ if (map -> header . write_size ) {
240215
241216 #if PBSYS_CONFIG_PROGRAM_LOAD_OVERLAPS_BOOTLOADER_CHECKSUM
242217 pbsys_program_load_update_checksum ();
243218 #endif
244219
245220 // Write the data.
246- PROCESS_PT_SPAWN (& pt , pbdrv_block_device_store (& pt , (uint8_t * )map , map -> write_size , & err ));
221+ PROCESS_PT_SPAWN (& pt , pbdrv_block_device_store (& pt , (uint8_t * )map , map -> header . write_size , & err ));
247222 }
248223
249224 // Deinitialization done.
@@ -288,7 +263,7 @@ pbio_error_t pbsys_program_load_wait_command(pbsys_main_program_t *program) {
288263
289264 // REPL can also use user program (e.g. in MicroPython, import user modules)
290265 program -> code_start = map -> program_data ;
291- program -> code_end = map -> program_data + map -> program_size ;
266+ program -> code_end = map -> program_data + map -> header . program_size ;
292267 program -> data_end = map -> program_data + sizeof (map -> program_data );
293268
294269 return PBIO_SUCCESS ;
0 commit comments