11#include " FlashIAP.h"
2+ #include " QSPIFBlockDevice.h"
3+ #include " MBRBlockDevice.h"
4+ #include " LittleFileSystem.h"
5+ #include " FATFileSystem.h"
26#if defined(ARDUINO_PORTENTA_H7_M7)
37#include " portenta_bootloader.h"
48#include " portenta_lite_bootloader.h"
59#include " portenta_lite_connected_bootloader.h"
10+ #include " mcuboot_bootloader.h"
11+ #include " ecdsa-p256-encrypt-key.h"
12+ #include " ecdsa-p256-signing-key.h"
613#elif defined(ARDUINO_NICLA_VISION)
714#include " nicla_vision_bootloader.h"
815#endif
916
10- #ifndef CORE_CM7
17+ #ifndef CORE_CM7
1118 #error Update the bootloader by uploading the sketch to the M7 core instead of the M4 core.
1219#endif
1320
1421#define BOOTLOADER_ADDR (0x8000000 )
22+ #define SIGNING_KEY_ADDR (0x8000300 )
23+ #define ENCRYPT_KEY_ADDR (0x8000400 )
24+ #define ENCRYPT_KEY_SIZE (0x0000100 )
25+ #define SIGNING_KEY_SIZE (0x0000100 )
26+
1527mbed::FlashIAP flash;
28+ QSPIFBlockDevice root (QSPI_SO0, QSPI_SO1, QSPI_SO2, QSPI_SO3, QSPI_SCK, QSPI_CS, QSPIF_POLARITY_MODE_1, 40000000 );
29+
30+ bool writeLoader = false ;
31+ bool writeKeys = false ;
32+ bool video_available = false ;
33+ bool wifi_available = false ;
34+ bool MCUboot = false ;
1635
1736uint32_t bootloader_data_offset = 0x1F000 ;
1837uint8_t * bootloader_data = (uint8_t *)(BOOTLOADER_ADDR + bootloader_data_offset);
1938
20- bool video_available = false ;
21- bool wifi_available = false ;
39+ uint32_t bootloader_identification_offset = 0x2F0 ;
40+ uint8_t * bootloader_identification = ( uint8_t *)(BOOTLOADER_ADDR + bootloader_identification_offset) ;
2241
23- void setup () {
42+ const unsigned char * bootloader_ptr = &bootloader_mbed_bin[0 ];
43+ long bootloader_len = bootloader_mbed_bin_len;
44+
45+ void setup () {
2446 Serial.begin (115200 );
2547 while (!Serial) {}
2648
2749 uint8_t currentBootloaderVersion = bootloader_data[1 ];
28- uint8_t availableBootloaderVersion = (bootloader_mbed_bin + bootloader_data_offset)[1 ];
50+ String currentBootloaderIdentifier = String (bootloader_identification, 15 );
51+
52+ if (!currentBootloaderIdentifier.equals (" MCUboot Arduino" )) {
53+ currentBootloaderIdentifier = " Arduino loader" ;
54+ }
2955
56+ Serial.println (currentBootloaderIdentifier);
3057 Serial.println (" Magic Number (validation): " + String (bootloader_data[0 ], HEX));
3158 Serial.println (" Bootloader version: " + String (currentBootloaderVersion));
3259 Serial.println (" Clock source: " + getClockSource (bootloader_data[2 ]));
@@ -41,36 +68,62 @@ void setup() {
4168 video_available = bootloader_data[8 ];
4269 wifi_available = bootloader_data[5 ];
4370
44- if (availableBootloaderVersion > currentBootloaderVersion) {
45- Serial.print (" \n A new bootloader version is available: v" + String (availableBootloaderVersion));
46- Serial.println (" (Your version: v" + String (currentBootloaderVersion) + " )" );
47- Serial.println (" Do you want to update the bootloader? Y/[n]" );
48- } else if (availableBootloaderVersion < currentBootloaderVersion){
49- Serial.println (" \n A newer bootloader version is already installed: v" + String (currentBootloaderVersion));
50- Serial.println (" Do you want to downgrade the bootloader to v" + String (availableBootloaderVersion) + " ? Y/[n]" );
71+ #if defined(ARDUINO_PORTENTA_H7_M7)
72+ Serial.println (" \n Do you want to update the default Arduino bootloader? Y/[n]" );
73+ Serial.println (" If No, MCUBoot bootloader will be updated." );
74+ if (waitResponse ()) {
75+ bootloader_ptr = &bootloader_mbed_bin[0 ];
76+ bootloader_len = bootloader_mbed_bin_len;
77+ if (!video_available) {
78+ if (wifi_available) {
79+ bootloader_ptr = &bootloader_mbed_lite_connected_bin[0 ];
80+ bootloader_len = bootloader_mbed_lite_connected_bin_len;
81+ } else {
82+ bootloader_ptr = &bootloader_mbed_lite_bin[0 ];
83+ bootloader_len = bootloader_mbed_lite_bin_len;
84+ }
85+ }
5186 } else {
52- Serial. println ( " \n The latest version of the bootloader is already installed (v " + String (currentBootloaderVersion) + " ). " ) ;
53- Serial. println ( " Do you want to update the bootloader anyway? Y/[n] " ) ;
87+ bootloader_ptr = &mcuboot_bin[ 0 ] ;
88+ bootloader_len = mcuboot_bin_len ;
5489 }
55-
56- bool confirmation = false ;
57- while (confirmation == false ) {
58- if (Serial.available ()) {
59- char choice = Serial.read ();
60- switch (choice) {
61- case ' y' :
62- case ' Y' :
63- applyUpdate (BOOTLOADER_ADDR);
64- confirmation = true ;
65- break ;
66- case ' n' :
67- case ' N' :
68- confirmation = true ;
69- break ;
70- default :
71- continue ;
72- }
90+ #endif
91+
92+ uint8_t availableBootloaderVersion = (bootloader_ptr + bootloader_data_offset)[1 ];
93+ String availableBootloaderIdentifier = String (bootloader_ptr + bootloader_identification_offset, 15 );
94+
95+ if (!availableBootloaderIdentifier.equals (" MCUboot Arduino" )) {
96+ availableBootloaderIdentifier = " Arduino loader" ;
97+ }
98+
99+ if (currentBootloaderIdentifier == availableBootloaderIdentifier) {
100+ if (availableBootloaderVersion > currentBootloaderVersion) {
101+ Serial.print (" \n A new bootloader version is available: v" + String (availableBootloaderVersion));
102+ Serial.println (" (Your version: v" + String (currentBootloaderVersion) + " )" );
103+ Serial.println (" Do you want to update the bootloader? Y/[n]" );
104+ } else if (availableBootloaderVersion < currentBootloaderVersion) {
105+ Serial.println (" \n A newer bootloader version is already installed: v" + String (currentBootloaderVersion));
106+ Serial.println (" Do you want to downgrade the bootloader to v" + String (availableBootloaderVersion) + " ? Y/[n]" );
107+ } else {
108+ Serial.println (" \n The latest version of the bootloader is already installed (v" + String (currentBootloaderVersion) + " )." );
109+ Serial.println (" Do you want to update the bootloader anyway? Y/[n]" );
73110 }
111+ } else {
112+ Serial.println (" \n A different bootloader type is available: v" + String (availableBootloaderVersion));
113+ Serial.println (" Do you want to update the bootloader? Y/[n]" );
114+ }
115+ writeLoader = waitResponse ();
116+
117+ if (writeLoader) {
118+ if (availableBootloaderIdentifier.equals (" MCUboot Arduino" )) {
119+ setupMCUBootOTAData ();
120+ Serial.println (" \n The bootloader comes with a set of default keys to evaluate signing and encryption process" );
121+ Serial.println (" Do you want to load default keys? Y/[n]" );
122+ writeKeys = waitResponse ();
123+ }
124+ applyUpdate (BOOTLOADER_ADDR);
125+ } else {
126+ Serial.println (" It's now safe to reboot or disconnect your board." );
74127 }
75128}
76129
@@ -98,17 +151,91 @@ String getClockSource(uint8_t flag) {
98151 }
99152}
100153
101- void applyUpdate (uint32_t address) {
102- long len = bootloader_mbed_bin_len;
103- #if defined(ARDUINO_PORTENTA_H7_M7)
104- if (!video_available) {
105- if (wifi_available) {
106- len = bootloader_mbed_lite_connected_bin_len;
107- } else {
108- len = bootloader_mbed_lite_bin_len;
154+ void printProgress (uint32_t offset, uint32_t size, uint32_t threshold, bool reset) {
155+ static int percent_done = 0 ;
156+ if (reset == true ) {
157+ percent_done = 0 ;
158+ Serial.println (" Flashed " + String (percent_done) + " %" );
159+ } else {
160+ uint32_t percent_done_new = offset * 100 / size;
161+ if (percent_done_new >= percent_done + threshold) {
162+ percent_done = percent_done_new;
163+ Serial.println (" Flashed " + String (percent_done) + " %" );
109164 }
110165 }
111- #endif
166+ }
167+
168+ bool waitResponse () {
169+ bool confirmation = false ;
170+ while (confirmation == false ) {
171+ if (Serial.available ()) {
172+ char choice = Serial.read ();
173+ switch (choice) {
174+ case ' y' :
175+ case ' Y' :
176+ confirmation = true ;
177+ return true ;
178+ break ;
179+ case ' n' :
180+ case ' N' :
181+ confirmation = true ;
182+ return false ;
183+ break ;
184+ default :
185+ continue ;
186+ }
187+ }
188+ }
189+ }
190+
191+ void setupMCUBootOTAData () {
192+ mbed::MBRBlockDevice ota_data (&root, 2 );
193+ mbed::FATFileSystem ota_data_fs (" fs" );
194+
195+ int err = ota_data_fs.reformat (&ota_data);
196+ if (err) {
197+ Serial.println (" Error creating MCUBoot files in OTA partition" );
198+ }
199+
200+ FILE* fp = fopen (" /fs/scratch.bin" , " wb" );
201+ const int scratch_file_size = 128 * 1024 ;
202+ const char buffer[128 ] = {0xFF };
203+ int size = 0 ;
204+
205+ Serial.println (" \n Creating scratch file" );
206+ printProgress (size, scratch_file_size, 10 , true );
207+ while (size < scratch_file_size) {
208+ int ret = fwrite (buffer, sizeof (buffer), 1 , fp);
209+ if (ret != 1 ) {
210+ Serial.println (" Error writing scratch file" );
211+ break ;
212+ }
213+ size += sizeof (buffer);
214+ printProgress (size, scratch_file_size, 10 , false );
215+ }
216+ fclose (fp);
217+
218+ fp = fopen (" /fs/update.bin" , " wb" );
219+ const int update_file_size = 15 * 128 * 1024 ;
220+ size = 0 ;
221+
222+ Serial.println (" \n Creating update file" );
223+ printProgress (size, update_file_size, 10 , true );
224+ while (size < update_file_size) {
225+ int ret = fwrite (buffer, sizeof (buffer), 1 , fp);
226+ if (ret != 1 ) {
227+ Serial.println (" Error writing scratch file" );
228+ break ;
229+ }
230+ size += sizeof (buffer);
231+ printProgress (size, update_file_size, 5 , false );
232+ }
233+
234+ fclose (fp);
235+ }
236+
237+ void applyUpdate (uint32_t address) {
238+ long len = bootloader_len;
112239
113240 flash.init ();
114241
@@ -133,19 +260,7 @@ void applyUpdate(uint32_t address) {
133260 }
134261
135262 // Program page
136- #if defined(ARDUINO_PORTENTA_H7_M7)
137- if (video_available) {
138- flash.program (&bootloader_mbed_bin[page_size * pages_flashed], addr, page_size);
139- } else {
140- if (wifi_available) {
141- flash.program (&bootloader_mbed_lite_connected_bin[page_size * pages_flashed], addr, page_size);
142- } else {
143- flash.program (&bootloader_mbed_lite_bin[page_size * pages_flashed], addr, page_size);
144- }
145- }
146- #else
147- flash.program (&bootloader_mbed_bin[page_size * pages_flashed], addr, page_size);
148- #endif
263+ flash.program (&bootloader_ptr[page_size * pages_flashed], addr, page_size);
149264
150265 addr += page_size;
151266 if (addr >= next_sector) {
@@ -161,12 +276,20 @@ void applyUpdate(uint32_t address) {
161276 }
162277 }
163278 }
279+
280+ #if defined(ARDUINO_PORTENTA_H7_M7)
281+ if (writeKeys) {
282+ flash.program (&enc_priv_key, ENCRYPT_KEY_ADDR, ENCRYPT_KEY_SIZE);
283+ flash.program (&ecdsa_pub_key, SIGNING_KEY_ADDR, SIGNING_KEY_SIZE);
284+ }
285+ #endif
286+
164287 Serial.println (" Flashed 100%" );
165288
166289 delete[] page_buffer;
167290
168291 flash.deinit ();
169- Serial.println (" Bootloader update complete. You may now disconnect the board." );
292+ Serial.println (" \n Bootloader update complete. It's now safe to reboot or disconnect your board." );
170293}
171294
172295void loop () {
0 commit comments