Skip to content

Commit a98a593

Browse files
pennamgiulcioffi
authored andcommitted
Update STM32H747_updateBootloader sketch to support MCUBoot upload.
Add MCUBoot v2 binary Add default keys to be flashed updating the loader
1 parent 539473b commit a98a593

File tree

4 files changed

+10885
-55
lines changed

4 files changed

+10885
-55
lines changed

libraries/STM32H747_System/examples/STM32H747_updateBootloader/STM32H747_updateBootloader.ino

Lines changed: 178 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,59 @@
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+
1527
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;
1635

1736
uint32_t bootloader_data_offset = 0x1F000;
1837
uint8_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("\nA 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("\nA 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("\nDo 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("\nThe 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("\nA 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("\nA 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("\nThe 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("\nA 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("\nThe 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("\nCreating 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("\nCreating 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("\nBootloader update complete. It's now safe to reboot or disconnect your board.");
170293
}
171294

172295
void loop() {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const unsigned char enc_priv_key[] {
2+
0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13,
3+
0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
4+
0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
5+
0x03, 0x01, 0x07, 0x04, 0x6d, 0x30, 0x6b, 0x02,
6+
0x01, 0x01, 0x04, 0x20, 0x79, 0x72, 0xb6, 0xf3,
7+
0x62, 0x91, 0x09, 0xbb, 0x35, 0x22, 0xb8, 0x54,
8+
0x32, 0x3b, 0xfe, 0x1c, 0x9f, 0xa7, 0x10, 0x6f,
9+
0xba, 0xaf, 0x73, 0x64, 0xd3, 0xf5, 0x31, 0xbc,
10+
0x28, 0xe7, 0xc9, 0x72, 0xa1, 0x44, 0x03, 0x42,
11+
0x00, 0x04, 0x6a, 0xc9, 0x20, 0x4c, 0x96, 0xd6,
12+
0x89, 0xe8, 0xd1, 0x6e, 0x51, 0x04, 0x02, 0x86,
13+
0xe8, 0x95, 0x0b, 0x22, 0xc4, 0xc9, 0x95, 0x06,
14+
0x4f, 0xf5, 0x1b, 0xf6, 0xd0, 0xe3, 0x83, 0xd9,
15+
0xd1, 0x81, 0x66, 0x6e, 0xf2, 0x07, 0x3b, 0x03,
16+
0xdb, 0xe4, 0xd1, 0xde, 0x7c, 0x43, 0x70, 0x8d,
17+
0xa2, 0x89, 0xeb, 0x1b, 0xfa, 0xbe, 0x02, 0x5e,
18+
0x5c, 0xa0, 0x12, 0xdc, 0x23, 0x31, 0xc1, 0xe0,
19+
0x37, 0xb0,
20+
};
21+
const unsigned int enc_priv_key_len = 138;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
const unsigned char ecdsa_pub_key[] {
2+
0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
3+
0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
4+
0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
5+
0x42, 0x00, 0x04, 0xd5, 0x16, 0x35, 0x26, 0xc3,
6+
0x3b, 0xad, 0x4d, 0x67, 0x8e, 0x43, 0x24, 0xc4,
7+
0x98, 0xe9, 0x6b, 0x2e, 0xbe, 0x0d, 0xa3, 0xf1,
8+
0xf4, 0x97, 0x80, 0x7b, 0x31, 0x32, 0x07, 0xd9,
9+
0x95, 0xa7, 0x17, 0x57, 0x69, 0x43, 0x7b, 0xe9,
10+
0xc8, 0xaa, 0xd0, 0x0a, 0x0c, 0x86, 0x0b, 0xe3,
11+
0x7f, 0x99, 0x88, 0x51, 0xc4, 0xf9, 0x22, 0x98,
12+
0xbe, 0x5e, 0xaa, 0xfd, 0x90, 0x3c, 0xa2, 0x74,
13+
0x18, 0x49, 0x05,
14+
};
15+
const unsigned int ecdsa_pub_key_len = 91;

0 commit comments

Comments
 (0)