1
1
#include " FlashIAP.h"
2
+ #include " QSPIFBlockDevice.h"
3
+ #include " MBRBlockDevice.h"
4
+ #include " LittleFileSystem.h"
5
+ #include " FATFileSystem.h"
2
6
#if defined(ARDUINO_PORTENTA_H7_M7)
3
7
#include " portenta_bootloader.h"
4
8
#include " portenta_lite_bootloader.h"
5
9
#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"
6
13
#elif defined(ARDUINO_NICLA_VISION)
7
14
#include " nicla_vision_bootloader.h"
8
15
#endif
9
16
10
- #ifndef CORE_CM7
17
+ #ifndef CORE_CM7
11
18
#error Update the bootloader by uploading the sketch to the M7 core instead of the M4 core.
12
19
#endif
13
20
14
21
#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
+
15
27
mbed::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 ;
16
35
17
36
uint32_t bootloader_data_offset = 0x1F000 ;
18
37
uint8_t * bootloader_data = (uint8_t *)(BOOTLOADER_ADDR + bootloader_data_offset);
19
38
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) ;
22
41
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 () {
24
46
Serial.begin (115200 );
25
47
while (!Serial) {}
26
48
27
49
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
+ }
29
55
56
+ Serial.println (currentBootloaderIdentifier);
30
57
Serial.println (" Magic Number (validation): " + String (bootloader_data[0 ], HEX));
31
58
Serial.println (" Bootloader version: " + String (currentBootloaderVersion));
32
59
Serial.println (" Clock source: " + getClockSource (bootloader_data[2 ]));
@@ -41,36 +68,62 @@ void setup() {
41
68
video_available = bootloader_data[8 ];
42
69
wifi_available = bootloader_data[5 ];
43
70
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
+ }
51
86
} 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 ;
54
89
}
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]" );
73
110
}
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." );
74
127
}
75
128
}
76
129
@@ -98,17 +151,91 @@ String getClockSource(uint8_t flag) {
98
151
}
99
152
}
100
153
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) + " %" );
109
164
}
110
165
}
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;
112
239
113
240
flash.init ();
114
241
@@ -133,19 +260,7 @@ void applyUpdate(uint32_t address) {
133
260
}
134
261
135
262
// 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);
149
264
150
265
addr += page_size;
151
266
if (addr >= next_sector) {
@@ -161,12 +276,20 @@ void applyUpdate(uint32_t address) {
161
276
}
162
277
}
163
278
}
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
+
164
287
Serial.println (" Flashed 100%" );
165
288
166
289
delete[] page_buffer;
167
290
168
291
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." );
170
293
}
171
294
172
295
void loop () {
0 commit comments