Skip to content

Commit d50e0ee

Browse files
authoredApr 26, 2023
Merge pull request #640 from pennam/mcuboot-src
MCUboot library update
2 parents 77830b0 + da11900 commit d50e0ee

26 files changed

+3796
-26
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
This example shows how to enable/disable bootloader debug
3+
using MCUboot library. The used debug output is Serial1
4+
5+
Circuit:
6+
- Arduino Portenta H7 board
7+
8+
This example code is in the public domain.
9+
*/
10+
11+
#include <MCUboot.h>
12+
13+
// the setup function runs once when you press reset or power the board
14+
void setup() {
15+
// set RTC register DR7
16+
MCUboot::bootDebug(true);
17+
}
18+
19+
// the loop function runs over and over again forever
20+
void loop() {
21+
22+
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
/*
2+
This example shows how to perform an OTA with MCUboot
3+
using MCUboot library.
4+
5+
WARNING: The ota binary is signed and encrypted with default keys.
6+
The example will work only if default keys are flashed within the
7+
bootloader otherwise MCUboot will refuse to boot the OTA binary
8+
9+
Circuit:
10+
- Arduino Portenta H7 board
11+
12+
This example code is in the public domain.
13+
*/
14+
15+
#include "BlockDevice.h"
16+
#include "MBRBlockDevice.h"
17+
#include "FATFileSystem.h"
18+
#include <MCUboot.h>
19+
#include <WiFi.h>
20+
21+
static char const SSID[] = "SECRET_SSID"; /* your network SSID (name) */
22+
static char const PASS[] = "SECRET_PASS"; /* your network password (use for WPA, or use as key for WEP) */
23+
24+
static char const OTA_FILE_LOCATION[] = "https://downloads.arduino.cc/ota/OTA_Usage_Portenta.ino.PORTENTA_H7_M7.MCUboot.slot";
25+
26+
static const int MCUBOOT_SLOT_SIZE = 0x1E0000;
27+
28+
bool applyUpdate = false;
29+
bool confirmUpdate = false;
30+
31+
// the setup function runs once when you press reset or power the board
32+
void setup() {
33+
Serial.begin(9600);
34+
while(!Serial);
35+
36+
if (WiFi.status() == WL_NO_SHIELD)
37+
return;
38+
39+
int status = WL_IDLE_STATUS;
40+
while (status != WL_CONNECTED)
41+
{
42+
Serial.print("Attempting to connect to SSID: ");
43+
Serial.println(SSID);
44+
status = WiFi.begin(SSID, PASS);
45+
delay(3000);
46+
}
47+
Serial.println("Connected to wifi");
48+
49+
Serial.println("Are you ready to apply a new update? Y/[n]");
50+
applyUpdate = waitResponse();
51+
52+
if (applyUpdate) {
53+
54+
// Mount filesystem and download the OTA file
55+
mbed::BlockDevice * raw = mbed::BlockDevice::get_default_instance();
56+
mbed::MBRBlockDevice * mbr = new mbed::MBRBlockDevice(raw, 2);
57+
int err = mbr->init();
58+
if (err < 0) {
59+
Serial.print("Error initializing Block Device ");
60+
Serial.println(err);
61+
return;
62+
}
63+
64+
mbed::FATFileSystem * fs = new mbed::FATFileSystem("ota");
65+
err = fs->mount(mbr);
66+
if (err < 0) {
67+
Serial.print("Error mounting filesystem ");
68+
Serial.println(err);
69+
return;
70+
}
71+
72+
Serial.println("Downloading update file");
73+
err = WiFi.download((char*)OTA_FILE_LOCATION, "/ota/update.bin", true);
74+
if (err < 0) {
75+
Serial.print("Error downloading file ");
76+
Serial.println(err);
77+
return;
78+
}
79+
80+
// OTA file is not padded to reduce download time,
81+
// but MCUboot needs update file to be padded
82+
FILE* update_file = fopen("/ota/update.bin", "rb+");
83+
fseek(update_file, 0, SEEK_END);
84+
int fsize = ftell(update_file);
85+
86+
Serial.print("File update.bin size ");
87+
Serial.println( fsize );
88+
89+
if (fsize < MCUBOOT_SLOT_SIZE) {
90+
const char buffer[1] = {0xFF};
91+
92+
Serial.println("Padding update file");
93+
printProgress(fsize, MCUBOOT_SLOT_SIZE, 10, true);
94+
while (fsize < MCUBOOT_SLOT_SIZE) {
95+
int ret = fwrite(buffer, 1, 1, update_file);
96+
if (ret != 1) {
97+
Serial.println("Error writing update file");
98+
break;
99+
}
100+
fsize += 1;
101+
printProgress(fsize, MCUBOOT_SLOT_SIZE, 10, false);
102+
}
103+
}
104+
Serial.println("Flashed 100%");
105+
106+
fseek(update_file, 0, SEEK_END);
107+
Serial.print("File update.bin size ");
108+
Serial.println( fsize );
109+
110+
if(fsize != 0x1E0000) {
111+
Serial.print("Error padding file ");
112+
return;
113+
}
114+
115+
fclose(update_file);
116+
fs->unmount();
117+
118+
// Is it possible to pre-confirm padded OTA file to prevent rollback
119+
Serial.println("Do you want to make the update permanent? Y/[n]");
120+
confirmUpdate = waitResponse();
121+
122+
// Set update pending and image OK flags
123+
MCUboot::applyUpdate(confirmUpdate);
124+
Serial.println("Done, waiting reset");
125+
} else {
126+
Serial.println("No update pending. It's now safe to reboot or disconnect your board.");
127+
}
128+
}
129+
130+
bool waitResponse() {
131+
bool confirmation = false;
132+
while (confirmation == false) {
133+
if (Serial.available()) {
134+
char choice = Serial.read();
135+
switch (choice) {
136+
case 'y':
137+
case 'Y':
138+
confirmation = true;
139+
return true;
140+
break;
141+
case 'n':
142+
case 'N':
143+
confirmation = true;
144+
return false;
145+
break;
146+
default:
147+
continue;
148+
}
149+
}
150+
}
151+
}
152+
153+
void printProgress(uint32_t offset, uint32_t size, uint32_t threshold, bool reset) {
154+
static int percent_done = 0;
155+
if (reset == true) {
156+
percent_done = 0;
157+
Serial.println("Flashed " + String(percent_done) + "%");
158+
} else {
159+
uint32_t percent_done_new = offset * 100 / size;
160+
if (percent_done_new >= percent_done + threshold) {
161+
percent_done = percent_done_new;
162+
Serial.println("Flashed " + String(percent_done) + "%");
163+
}
164+
}
165+
}
166+
167+
// the loop function runs over and over again forever
168+
void loop() {
169+
// wait 100ms
170+
delay(100);
171+
}

‎libraries/MCUboot/library.properties

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
name=MCUboot
2-
version=0.0.1
2+
version=0.1.0
33
author=Arduino
44
maintainer=Arduino <info@arduino.cc>
55
sentence=Wrapper library for MCUboot
66
paragraph=
77
category=Other
88
url=
99
architectures=mbed,mbed_portenta
10-
precompiled=true
11-
ldflags=-lbootutil

‎libraries/MCUboot/src/MCUboot.cpp

+15-5
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,27 @@
11
#include "MCUboot.h"
2-
#include "bootutil.h"
2+
#include "bootutil/bootutil_public.h"
3+
#include "STM32H747_System.h"
4+
35

46
void MCUboot::confirmSketch()
57
{
68
boot_set_confirmed();
79
}
810

9-
void MCUboot::applyUpdate(int permanent)
11+
void MCUboot::applyUpdate(bool permanent)
1012
{
11-
boot_set_pending(permanent);
13+
boot_set_pending(permanent == true ? 1 : 0);
1214
}
1315

14-
void MCUboot::bootDebug(int enable)
16+
void MCUboot::bootDebug(bool enable)
1517
{
16-
boot_set_debug(enable);
18+
unsigned int rtc_reg = STM32H747::readBackupRegister(RTCBackup::DR7);
19+
20+
if(enable) {
21+
rtc_reg |= 0x00000001;
22+
} else {
23+
rtc_reg &= ~0x00000001;
24+
}
25+
26+
return STM32H747::writeBackupRegister(RTCBackup::DR7, rtc_reg);
1727
}

‎libraries/MCUboot/src/MCUboot.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ class MCUboot
66

77
public:
88
static void confirmSketch(void);
9-
static void applyUpdate(int permanent);
10-
static void bootDebug(int enable);
9+
static void applyUpdate(bool permanent);
10+
static void bootDebug(bool enable);
1111

1212
};
1313

‎libraries/MCUboot/src/bootutil.h

-16
This file was deleted.
+160
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* Copyright (c) 2021 Nordic Semiconductor ASA
5+
*
6+
* Original license:
7+
*
8+
* Licensed to the Apache Software Foundation (ASF) under one
9+
* or more contributor license agreements. See the NOTICE file
10+
* distributed with this work for additional information
11+
* regarding copyright ownership. The ASF licenses this file
12+
* to you under the Apache License, Version 2.0 (the
13+
* "License"); you may not use this file except in compliance
14+
* with the License. You may obtain a copy of the License at
15+
*
16+
* http://www.apache.org/licenses/LICENSE-2.0
17+
*
18+
* Unless required by applicable law or agreed to in writing,
19+
* software distributed under the License is distributed on an
20+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21+
* KIND, either express or implied. See the License for the
22+
* specific language governing permissions and limitations
23+
* under the License.
24+
*/
25+
26+
/**
27+
* @file
28+
* @brief Hooks definition implementation API
29+
*
30+
* This file contains API interface definition for hooks which can be
31+
* implemented to overide or to amend some of MCUboot's native routines.
32+
*/
33+
34+
#ifndef H_BOOTUTIL_HOOKS
35+
#define H_BOOTUTIL_HOOKS
36+
37+
#ifdef MCUBOOT_IMAGE_ACCESS_HOOKS
38+
39+
#define BOOT_HOOK_CALL(f, ret_default, ...) f(__VA_ARGS__)
40+
41+
#define BOOT_HOOK_CALL_FIH(f, fih_ret_default, fih_rc, ...) \
42+
do { \
43+
FIH_CALL(f, fih_rc, __VA_ARGS__); \
44+
} while(0);
45+
46+
#else
47+
48+
#define BOOT_HOOK_CALL(f, ret_default, ...) ret_default
49+
50+
#define BOOT_HOOK_CALL_FIH(f, fih_ret_default, fih_rc, ...) \
51+
do { \
52+
fih_rc = fih_ret_default; \
53+
} while(0);
54+
55+
#endif
56+
57+
/** Hook for provide image header data.
58+
*
59+
* This Hook may be used to overide image header read implementation or doing
60+
* a custom action before.
61+
*
62+
* @param img_index the index of the image pair
63+
* @param slot slot number
64+
* @param img_head image header structure to be populated
65+
*
66+
* @retval 0: header was read/populated, skip direct header data read
67+
* BOOT_HOOK_REGULAR: follow the normal execution path,
68+
* otherwise an error-code value.
69+
*/
70+
int boot_read_image_header_hook(int img_index, int slot,
71+
struct image_header *img_head);
72+
73+
/** Hook for Validate image hash/signature
74+
*
75+
* This Hook may be used to overide image validation procedure or doing
76+
* a custom action before.
77+
*
78+
* @param img_index the index of the image pair
79+
* @param slot slot number
80+
*
81+
* @retval FIH_SUCCESS: image is valid, skip direct validation
82+
* FIH_FAILURE: image is invalid, skip direct validation
83+
* fih encoded BOOT_HOOK_REGULAR: follow the normal execution path.
84+
*/
85+
fih_int boot_image_check_hook(int img_index, int slot);
86+
87+
/** Hook for implement image update
88+
*
89+
* This hook is for for implementing an alternative mechanism of image update or
90+
* doing a custom action before.
91+
*
92+
* @param img_index the index of the image pair
93+
* @param img_head the image header of the secondary image
94+
* @param area the flash area of the secondary image.
95+
*
96+
* @retval 0: update was done, skip performing the update
97+
* BOOT_HOOK_REGULAR: follow the normal execution path,
98+
* otherwise an error-code value.
99+
*/
100+
int boot_perform_update_hook(int img_index, struct image_header *img_head,
101+
const struct flash_area *area);
102+
103+
/** Hook for implement image's post copying action
104+
*
105+
* This hook is for implement action which might be done right after image was
106+
* copied to the primary slot. This hook is called in MCUBOOT_OVERWRITE_ONLY
107+
* mode only.
108+
*
109+
* @param img_index the index of the image pair
110+
* @param area the flash area of the primary image.
111+
* @param size size of copied image.
112+
*
113+
* @retval 0: success, mcuboot will follow normal code execution flow after
114+
* execution of this call.
115+
* non-zero: an error, mcuboot will return from
116+
* boot_copy_image() with error.
117+
* Update will be undone so might be resume on the next boot.
118+
*/
119+
int boot_copy_region_post_hook(int img_index, const struct flash_area *area,
120+
size_t size);
121+
122+
/** Hook for implement image's post recovery upload action
123+
*
124+
* This hook is for implement action which might be done right after image was
125+
* copied to the primary slot. This hook is called in serial recovery upload
126+
* operation.
127+
*
128+
* @param img_index the index of the image pair
129+
* @param area the flash area of the primary image.
130+
* @param size size of copied image.
131+
*
132+
* @retval 0: success, mcuboot will follow normal code execution flow after
133+
* execution of this call.
134+
* non-zero: an error, will be transferred as part of comand response
135+
* as "rc" entry.
136+
*/
137+
int boot_serial_uploaded_hook(int img_index, const struct flash_area *area,
138+
size_t size);
139+
140+
/** Hook for implement the image's slot installation status fetch operation for
141+
* the MGMT custom command.
142+
*
143+
* The image's slot installation status is custom property. It's detailed
144+
* definition depends on user implementation. It is only defined that the status
145+
* will be set to 0 if this hook not provides another value.
146+
*
147+
* @param img_index the index of the image pair
148+
* @param slot slot number
149+
* @param img_install_stat the image installation status to be populated
150+
*
151+
* @retval 0: the installaton status was fetched successfully,
152+
* BOOT_HOOK_REGULAR: follow the normal execution path, status will be
153+
* set to 0
154+
* otherwise an error-code value. Error-code is ignored, but it is up to
155+
* the implementation to reflect this error in img_install_stat.
156+
*/
157+
int boot_img_install_stat_hook(int image_index, int slot,
158+
int *img_install_stat);
159+
160+
#endif /*H_BOOTUTIL_HOOKS*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* Copyright (c) 2021 Nordic Semiconductor ASA
5+
*
6+
* Original license:
7+
*
8+
* Licensed to the Apache Software Foundation (ASF) under one
9+
* or more contributor license agreements. See the NOTICE file
10+
* distributed with this work for additional information
11+
* regarding copyright ownership. The ASF licenses this file
12+
* to you under the Apache License, Version 2.0 (the
13+
* "License"); you may not use this file except in compliance
14+
* with the License. You may obtain a copy of the License at
15+
*
16+
* http://www.apache.org/licenses/LICENSE-2.0
17+
*
18+
* Unless required by applicable law or agreed to in writing,
19+
* software distributed under the License is distributed on an
20+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21+
* KIND, either express or implied. See the License for the
22+
* specific language governing permissions and limitations
23+
* under the License.
24+
*/
25+
26+
/**
27+
* @file
28+
* @brief Hooks definition implementation API
29+
*
30+
* This file contains API interface definition for hooks which can be
31+
* implemented for overide some of MCUboot's native routines.
32+
*/
33+
34+
#ifndef H_BOOTUTIL_PUBLIC_HOOKS
35+
#define H_BOOTUTIL_PUBLIC_HOOKS
36+
37+
#include "bootutil/boot_hooks.h"
38+
39+
/** Hook for provide primary image swap state.
40+
*
41+
* @param img_index the index of the image pair
42+
* @param state image swap state structure to be populated
43+
*
44+
* @retval 0: header was read/populated
45+
* FIH_FAILURE: image is invalid,
46+
* BOOT_HOOK_REGULAR if hook not implemented for the image-slot,
47+
* othervise an error-code value.
48+
*/
49+
int boot_read_swap_state_primary_slot_hook(int image_index,
50+
struct boot_swap_state *state);
51+
52+
#endif /*H_BOOTUTIL_PUBLIC_HOOKS*/
+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* Copyright (c) 2017-2019 Linaro LTD
5+
* Copyright (c) 2016-2019 JUUL Labs
6+
* Copyright (c) 2019-2020 Arm Limited
7+
*
8+
* Original license:
9+
*
10+
* Licensed to the Apache Software Foundation (ASF) under one
11+
* or more contributor license agreements. See the NOTICE file
12+
* distributed with this work for additional information
13+
* regarding copyright ownership. The ASF licenses this file
14+
* to you under the Apache License, Version 2.0 (the
15+
* "License"); you may not use this file except in compliance
16+
* with the License. You may obtain a copy of the License at
17+
*
18+
* http://www.apache.org/licenses/LICENSE-2.0
19+
*
20+
* Unless required by applicable law or agreed to in writing,
21+
* software distributed under the License is distributed on an
22+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
23+
* KIND, either express or implied. See the License for the
24+
* specific language governing permissions and limitations
25+
* under the License.
26+
*/
27+
28+
#ifndef H_BOOTUTIL_
29+
#define H_BOOTUTIL_
30+
31+
#include <inttypes.h>
32+
#include "bootutil/fault_injection_hardening.h"
33+
#include "bootutil/bootutil_public.h"
34+
35+
#ifdef __cplusplus
36+
extern "C" {
37+
#endif
38+
39+
struct image_header;
40+
/**
41+
* A response object provided by the boot loader code; indicates where to jump
42+
* to execute the main image.
43+
*/
44+
struct boot_rsp {
45+
/** A pointer to the header of the image to be executed. */
46+
const struct image_header *br_hdr;
47+
48+
/**
49+
* The flash offset of the image to execute. Indicates the position of
50+
* the image header within its flash device.
51+
*/
52+
uint8_t br_flash_dev_id;
53+
uint32_t br_image_off;
54+
};
55+
56+
/* This is not actually used by mcuboot's code but can be used by apps
57+
* when attempting to read/write a trailer.
58+
*/
59+
struct image_trailer {
60+
uint8_t swap_type;
61+
uint8_t pad1[BOOT_MAX_ALIGN - 1];
62+
uint8_t copy_done;
63+
uint8_t pad2[BOOT_MAX_ALIGN - 1];
64+
uint8_t image_ok;
65+
uint8_t pad3[BOOT_MAX_ALIGN - 1];
66+
#if BOOT_MAX_ALIGN > BOOT_MAGIC_SZ
67+
uint8_t pad4[BOOT_MAGIC_ALIGN_SIZE - BOOT_MAGIC_SZ];
68+
#endif
69+
uint8_t magic[BOOT_MAGIC_SZ];
70+
};
71+
72+
/* you must have pre-allocated all the entries within this structure */
73+
fih_int boot_go(struct boot_rsp *rsp);
74+
75+
struct boot_loader_state;
76+
fih_int context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp);
77+
78+
#define SPLIT_GO_OK (0)
79+
#define SPLIT_GO_NON_MATCHING (-1)
80+
#define SPLIT_GO_ERR (-2)
81+
82+
fih_int split_go(int loader_slot, int split_slot, void **entry);
83+
84+
#ifdef __cplusplus
85+
}
86+
#endif
87+
88+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* Copyright (c) 2017 Linaro Limited
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
#ifndef H_BOOTUTIL_LOG_H_
20+
#define H_BOOTUTIL_LOG_H_
21+
22+
#include "ignore.h"
23+
24+
#ifdef __cplusplus
25+
extern "C" {
26+
#endif
27+
28+
#include <mcuboot_config/mcuboot_config.h>
29+
30+
#ifdef MCUBOOT_HAVE_LOGGING
31+
#include <mcuboot_config/mcuboot_logging.h>
32+
33+
#define BOOT_LOG_ERR(...) MCUBOOT_LOG_ERR(__VA_ARGS__)
34+
#define BOOT_LOG_WRN(...) MCUBOOT_LOG_WRN(__VA_ARGS__)
35+
#define BOOT_LOG_INF(...) MCUBOOT_LOG_INF(__VA_ARGS__)
36+
#define BOOT_LOG_DBG(...) MCUBOOT_LOG_DBG(__VA_ARGS__)
37+
#define BOOT_LOG_SIM(...) MCUBOOT_LOG_SIM(__VA_ARGS__)
38+
39+
#define BOOT_LOG_MODULE_DECLARE(module) MCUBOOT_LOG_MODULE_DECLARE(module)
40+
#define BOOT_LOG_MODULE_REGISTER(module) MCUBOOT_LOG_MODULE_REGISTER(module)
41+
42+
#else
43+
44+
#define BOOT_LOG_ERR(...) IGNORE(__VA_ARGS__)
45+
#define BOOT_LOG_WRN(...) IGNORE(__VA_ARGS__)
46+
#define BOOT_LOG_INF(...) IGNORE(__VA_ARGS__)
47+
#define BOOT_LOG_DBG(...) IGNORE(__VA_ARGS__)
48+
#define BOOT_LOG_SIM(...) IGNORE(__VA_ARGS__)
49+
50+
#define BOOT_LOG_MODULE_DECLARE(module)
51+
#define BOOT_LOG_MODULE_REGISTER(module)
52+
53+
#endif /* MCUBOOT_HAVE_LOGGING */
54+
55+
#ifdef __cplusplus
56+
}
57+
#endif
58+
59+
#endif

‎libraries/MCUboot/src/bootutil/bootutil_priv.h

+442
Large diffs are not rendered by default.

‎libraries/MCUboot/src/bootutil/bootutil_public.c

+659
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* Copyright (c) 2017-2019 Linaro LTD
5+
* Copyright (c) 2016-2019 JUUL Labs
6+
* Copyright (c) 2019-2021 Arm Limited
7+
* Copyright (c) 2020-2021 Nordic Semiconductor ASA
8+
*
9+
* Original license:
10+
*
11+
* Licensed to the Apache Software Foundation (ASF) under one
12+
* or more contributor license agreements. See the NOTICE file
13+
* distributed with this work for additional information
14+
* regarding copyright ownership. The ASF licenses this file
15+
* to you under the Apache License, Version 2.0 (the
16+
* "License"); you may not use this file except in compliance
17+
* with the License. You may obtain a copy of the License at
18+
*
19+
* http://www.apache.org/licenses/LICENSE-2.0
20+
*
21+
* Unless required by applicable law or agreed to in writing,
22+
* software distributed under the License is distributed on an
23+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
24+
* KIND, either express or implied. See the License for the
25+
* specific language governing permissions and limitations
26+
* under the License.
27+
*/
28+
29+
/**
30+
* @file
31+
* @brief Public MCUBoot interface API
32+
*
33+
* This file contains API which can be combined with the application in order
34+
* to interact with the MCUBoot bootloader. This API are shared code-base betwen
35+
* MCUBoot and the application which controls DFU process.
36+
*/
37+
38+
#ifndef H_BOOTUTIL_PUBLIC
39+
#define H_BOOTUTIL_PUBLIC
40+
41+
#include <inttypes.h>
42+
#include <string.h>
43+
#include <flash_map_backend/flash_map_backend.h>
44+
#include <mcuboot_config/mcuboot_config.h>
45+
46+
#ifdef __cplusplus
47+
extern "C" {
48+
#endif
49+
50+
/** Attempt to boot the contents of the primary slot. */
51+
#define BOOT_SWAP_TYPE_NONE 1
52+
53+
/**
54+
* Swap to the secondary slot.
55+
* Absent a confirm command, revert back on next boot.
56+
*/
57+
#define BOOT_SWAP_TYPE_TEST 2
58+
59+
/**
60+
* Swap to the secondary slot,
61+
* and permanently switch to booting its contents.
62+
*/
63+
#define BOOT_SWAP_TYPE_PERM 3
64+
65+
/** Swap back to alternate slot. A confirm changes this state to NONE. */
66+
#define BOOT_SWAP_TYPE_REVERT 4
67+
68+
/** Swap failed because image to be run is not valid */
69+
#define BOOT_SWAP_TYPE_FAIL 5
70+
71+
/** Swapping encountered an unrecoverable error */
72+
#define BOOT_SWAP_TYPE_PANIC 0xff
73+
74+
#define BOOT_MAGIC_SZ 16
75+
76+
#ifdef MCUBOOT_BOOT_MAX_ALIGN
77+
#define BOOT_MAX_ALIGN MCUBOOT_BOOT_MAX_ALIGN
78+
#define BOOT_MAGIC_ALIGN_SIZE \
79+
((((BOOT_MAGIC_SZ - 1) / BOOT_MAX_ALIGN) + 1) * BOOT_MAX_ALIGN)
80+
#else
81+
#define BOOT_MAX_ALIGN 8
82+
#define BOOT_MAGIC_ALIGN_SIZE BOOT_MAGIC_SZ
83+
#endif
84+
85+
#ifdef MCUBOOT_SWAP_BUF_SIZE
86+
#define BOOT_SWAP_BUF_SIZE MCUBOOT_SWAP_BUF_SIZE
87+
#elif BOOT_MAX_ALIGN > 1024
88+
#define BOOT_SWAP_BUF_SIZE BOOT_MAX_ALIGN
89+
#else
90+
#define BOOT_SWAP_BUF_SIZE 1024
91+
#endif
92+
93+
#define BOOT_MAGIC_GOOD 1
94+
#define BOOT_MAGIC_BAD 2
95+
#define BOOT_MAGIC_UNSET 3
96+
#define BOOT_MAGIC_ANY 4 /* NOTE: control only, not dependent on sector */
97+
#define BOOT_MAGIC_NOTGOOD 5 /* NOTE: control only, not dependent on sector */
98+
99+
/*
100+
* NOTE: leave BOOT_FLAG_SET equal to one, this is written to flash!
101+
*/
102+
#define BOOT_FLAG_SET 1
103+
#define BOOT_FLAG_BAD 2
104+
#define BOOT_FLAG_UNSET 3
105+
#define BOOT_FLAG_ANY 4 /* NOTE: control only, not dependent on sector */
106+
107+
#define BOOT_EFLASH 1
108+
#define BOOT_EFILE 2
109+
#define BOOT_EBADIMAGE 3
110+
#define BOOT_EBADVECT 4
111+
#define BOOT_EBADSTATUS 5
112+
#define BOOT_ENOMEM 6
113+
#define BOOT_EBADARGS 7
114+
#define BOOT_EBADVERSION 8
115+
#define BOOT_EFLASH_SEC 9
116+
117+
#define BOOT_HOOK_REGULAR 1
118+
/*
119+
* Extract the swap type and image number from image trailers's swap_info
120+
* filed.
121+
*/
122+
#define BOOT_GET_SWAP_TYPE(swap_info) ((swap_info) & 0x0F)
123+
#define BOOT_GET_IMAGE_NUM(swap_info) ((swap_info) >> 4)
124+
125+
/* Construct the swap_info field from swap type and image number */
126+
#define BOOT_SET_SWAP_INFO(swap_info, image, type) { \
127+
assert((image) < 0xF); \
128+
assert((type) < 0xF); \
129+
(swap_info) = (image) << 4 \
130+
| (type); \
131+
}
132+
#ifdef MCUBOOT_HAVE_ASSERT_H
133+
#include "mcuboot_config/mcuboot_assert.h"
134+
#else
135+
#include <assert.h>
136+
#ifndef ASSERT
137+
#define ASSERT assert
138+
#endif
139+
#endif
140+
141+
struct boot_swap_state {
142+
uint8_t magic; /* One of the BOOT_MAGIC_[...] values. */
143+
uint8_t swap_type; /* One of the BOOT_SWAP_TYPE_[...] values. */
144+
uint8_t copy_done; /* One of the BOOT_FLAG_[...] values. */
145+
uint8_t image_ok; /* One of the BOOT_FLAG_[...] values. */
146+
uint8_t image_num; /* Boot status belongs to this image */
147+
};
148+
149+
/**
150+
* @brief Determines the action, if any, that mcuboot will take on a image pair.
151+
*
152+
* @param image_index Image pair index.
153+
*
154+
* @return a BOOT_SWAP_TYPE_[...] constant on success, negative errno code on
155+
* fail.
156+
*/
157+
int boot_swap_type_multi(int image_index);
158+
159+
/**
160+
* @brief Determines the action, if any, that mcuboot will take.
161+
*
162+
* Works the same as a boot_swap_type_multi(0) call;
163+
*
164+
* @return a BOOT_SWAP_TYPE_[...] constant on success, negative errno code on
165+
* fail.
166+
*/
167+
int boot_swap_type(void);
168+
169+
/**
170+
* Marks the image with the given index in the secondary slot as pending. On the
171+
* next reboot, the system will perform a one-time boot of the the secondary
172+
* slot image.
173+
*
174+
* @param image_index Image pair index.
175+
*
176+
* @param permanent Whether the image should be used permanently or
177+
* only tested once:
178+
* 0=run image once, then confirm or revert.
179+
* 1=run image forever.
180+
*
181+
* @return 0 on success; nonzero on failure.
182+
*/
183+
int boot_set_pending_multi(int image_index, int permanent);
184+
185+
/**
186+
* Marks the image with index 0 in the secondary slot as pending. On the next
187+
* reboot, the system will perform a one-time boot of the the secondary slot
188+
* image. Note that this API is kept for compatibility. The
189+
* boot_set_pending_multi() API is recommended.
190+
*
191+
* @param permanent Whether the image should be used permanently or
192+
* only tested once:
193+
* 0=run image once, then confirm or revert.
194+
* 1=run image forever.
195+
*
196+
* @return 0 on success; nonzero on failure.
197+
*/
198+
int boot_set_pending(int permanent);
199+
200+
/**
201+
* Marks the image with the given index in the primary slot as confirmed. The
202+
* system will continue booting into the image in the primary slot until told to
203+
* boot from a different slot.
204+
*
205+
* @param image_index Image pair index.
206+
*
207+
* @return 0 on success; nonzero on failure.
208+
*/
209+
int boot_set_confirmed_multi(int image_index);
210+
211+
/**
212+
* Marks the image with index 0 in the primary slot as confirmed. The system
213+
* will continue booting into the image in the primary slot until told to boot
214+
* from a different slot. Note that this API is kept for compatibility. The
215+
* boot_set_confirmed_multi() API is recommended.
216+
*
217+
* @return 0 on success; nonzero on failure.
218+
*/
219+
int boot_set_confirmed(void);
220+
221+
/**
222+
* @brief Get offset of the swap info field in the image trailer.
223+
*
224+
* @param fap Flash are for which offset is determined.
225+
*
226+
* @retval offset of the swap info field.
227+
*/
228+
uint32_t boot_swap_info_off(const struct flash_area *fap);
229+
230+
/**
231+
* @brief Get value of image-ok flag of the image.
232+
*
233+
* If called from chin-loaded image the image-ok flag value can be used to check
234+
* whether application itself is already confirmed.
235+
*
236+
* @param fap Flash area of the image.
237+
* @param image_ok[out] image-ok value.
238+
*
239+
* @return 0 on success; nonzero on failure.
240+
*/
241+
int boot_read_image_ok(const struct flash_area *fap, uint8_t *image_ok);
242+
243+
/**
244+
* @brief Read the image swap state
245+
*
246+
* @param flash_area_id id of flash partition from which state will be read;
247+
* @param state pointer to structure for storing swap state.
248+
*
249+
* @return 0 on success; non-zero error code on failure;
250+
*/
251+
int
252+
boot_read_swap_state_by_id(int flash_area_id, struct boot_swap_state *state);
253+
254+
/**
255+
* @brief Read the image swap state
256+
*
257+
* @param fa pointer to flash_area object;
258+
* @param state pointer to structure for storing swap state.
259+
*
260+
* @return 0 on success; non-zero error code on failure.
261+
*/
262+
int
263+
boot_read_swap_state(const struct flash_area *fa,
264+
struct boot_swap_state *state);
265+
266+
/**
267+
* Populates the version information of the
268+
* currently installed primary application
269+
*
270+
* @param[in] version Destination version structure buffer
271+
* @return 0 on success; nonzero on failure.
272+
*/
273+
int boot_get_current_version(struct image_version *version);
274+
275+
#define BOOT_MAGIC_ARR_SZ \
276+
(sizeof boot_img_magic / sizeof boot_img_magic[0])
277+
278+
extern const uint32_t boot_img_magic[4];
279+
280+
#ifdef __cplusplus
281+
}
282+
#endif
283+
284+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,377 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* Copyright (c) 2020 Arm Limited
5+
*/
6+
7+
#ifndef __FAULT_INJECTION_HARDENING_H__
8+
#define __FAULT_INJECTION_HARDENING_H__
9+
10+
/* Fault injection mitigation library.
11+
*
12+
* Has support for different measures, which can either be enabled/disabled
13+
* separately or by defining one of the MCUBOOT_FIH_PROFILEs.
14+
*
15+
* NOTE: These constructs against fault injection attacks are not guaranteed to
16+
* be secure for all compilers, but execution is going to be correct and
17+
* including them will certainly help to harden the code.
18+
*
19+
* FIH_ENABLE_DOUBLE_VARS makes critical variables into a tuple (x, x ^ msk).
20+
* Then the correctness of x can be checked by XORing the two tuple values
21+
* together. This also means that comparisons between fih_ints can be verified
22+
* by doing x == y && x_msk == y_msk.
23+
*
24+
* FIH_ENABLE_GLOBAL_FAIL makes all while(1) failure loops redirect to a global
25+
* failure loop. This loop has mitigations against loop escapes / unlooping.
26+
* This also means that any unlooping won't immediately continue executing the
27+
* function that was executing before the failure.
28+
*
29+
* FIH_ENABLE_CFI (Control Flow Integrity) creates a global counter that is
30+
* incremented before every FIH_CALL of vulnerable functions. On the function
31+
* return the counter is decremented, and after the return it is verified that
32+
* the counter has the same value as before this process. This can be used to
33+
* verify that the function has actually been called. This protection is
34+
* intended to discover that important functions are called in an expected
35+
* sequence and neither of them is missed due to an instruction skip which could
36+
* be a result of glitching attack. It does not provide protection against ROP
37+
* or JOP attacks.
38+
*
39+
* FIH_ENABLE_DELAY causes random delays. This makes it hard to cause faults
40+
* precisely. It requires an RNG. An mbedtls integration is provided in
41+
* fault_injection_hardening_delay_mbedtls.h, but any RNG that has an entropy
42+
* source can be used by implementing the fih_delay_random_uchar function.
43+
*
44+
* The basic call pattern is:
45+
*
46+
* fih_int fih_rc = FIH_FAILURE;
47+
* FIH_CALL(vulnerable_function, fih_rc, arg1, arg2);
48+
* if (fih_not_eq(fih_rc, FIH_SUCCESS)) {
49+
* FIH_PANIC;
50+
* }
51+
*
52+
* Note that any function called by FIH_CALL must only return using FIH_RETURN,
53+
* as otherwise the CFI counter will not be decremented and the CFI check will
54+
* fail causing a panic.
55+
*/
56+
57+
#include "mcuboot_config/mcuboot_config.h"
58+
59+
#if defined(MCUBOOT_FIH_PROFILE_HIGH)
60+
61+
#define FIH_ENABLE_DELAY /* Requires an entropy source */
62+
#define FIH_ENABLE_DOUBLE_VARS
63+
#define FIH_ENABLE_GLOBAL_FAIL
64+
#define FIH_ENABLE_CFI
65+
66+
#elif defined(MCUBOOT_FIH_PROFILE_MEDIUM)
67+
68+
#define FIH_ENABLE_DOUBLE_VARS
69+
#define FIH_ENABLE_GLOBAL_FAIL
70+
#define FIH_ENABLE_CFI
71+
72+
#elif defined(MCUBOOT_FIH_PROFILE_LOW)
73+
74+
#define FIH_ENABLE_GLOBAL_FAIL
75+
#define FIH_ENABLE_CFI
76+
77+
#elif !defined(MCUBOOT_FIH_PROFILE_OFF)
78+
#define MCUBOOT_FIH_PROFILE_OFF
79+
#endif /* MCUBOOT_FIH_PROFILE */
80+
81+
#ifdef FIH_ENABLE_DELAY
82+
#include "fault_injection_hardening_delay_rng.h"
83+
#endif /* FIH_ENABLE_DELAY */
84+
85+
86+
#ifdef __cplusplus
87+
extern "C" {
88+
#endif /* __cplusplus */
89+
90+
/* Non-zero success value to defend against register resets. Zero is the most
91+
* common value for a corrupted register so complex bit-patterns are used
92+
*/
93+
#ifndef MCUBOOT_FIH_PROFILE_OFF
94+
#define FIH_POSITIVE_VALUE 0x1AAAAAAA
95+
#define FIH_NEGATIVE_VALUE 0x15555555
96+
#else
97+
#define FIH_POSITIVE_VALUE 0
98+
#define FIH_NEGATIVE_VALUE -1
99+
#endif
100+
101+
/* A volatile mask is used to prevent compiler optimization - the mask is xored
102+
* with the variable to create the backup and the integrity can be checked with
103+
* another xor. The mask value doesn't _really_ matter that much, as long as
104+
* it has reasonably high hamming weight.
105+
*/
106+
#define _FIH_MASK_VALUE 0xBEEF
107+
108+
#ifdef FIH_ENABLE_DOUBLE_VARS
109+
110+
/* All ints are replaced with two int - the normal one and a backup which is
111+
* XORed with the mask.
112+
*/
113+
extern volatile int _fih_mask;
114+
typedef volatile struct {
115+
volatile int val;
116+
volatile int msk;
117+
} fih_int;
118+
119+
#else
120+
121+
typedef int fih_int;
122+
123+
#endif /* FIH_ENABLE_DOUBLE_VARS */
124+
125+
extern fih_int FIH_SUCCESS;
126+
extern fih_int FIH_FAILURE;
127+
128+
#ifdef FIH_ENABLE_GLOBAL_FAIL
129+
/* Global failure handler - more resistant to unlooping. noinline and used are
130+
* used to prevent optimization
131+
*/
132+
__attribute__((noinline)) __attribute__((used))
133+
void fih_panic_loop(void);
134+
#define FIH_PANIC fih_panic_loop()
135+
#else
136+
#define FIH_PANIC while (1) {}
137+
#endif /* FIH_ENABLE_GLOBAL_FAIL */
138+
139+
/* NOTE: For functions to be inlined outside their compilation unit they have to
140+
* have the body in the header file. This is required as function calls are easy
141+
* to skip.
142+
*/
143+
#ifdef FIH_ENABLE_DELAY
144+
145+
/* Delaying logic, with randomness from a CSPRNG */
146+
__attribute__((always_inline)) inline
147+
int fih_delay(void)
148+
{
149+
unsigned char delay;
150+
int foo = 0;
151+
volatile int rc;
152+
153+
delay = fih_delay_random_uchar();
154+
155+
for (volatile int i = 0; i < delay; i++) {
156+
foo++;
157+
}
158+
159+
rc = 1;
160+
161+
/* rc is volatile so if it is the return value then the function cannot be
162+
* optimized
163+
*/
164+
return rc;
165+
}
166+
167+
#else
168+
169+
__attribute__((always_inline)) inline
170+
int fih_delay_init(void)
171+
{
172+
return 1;
173+
}
174+
175+
__attribute__((always_inline)) inline
176+
int fih_delay(void)
177+
{
178+
return 1;
179+
}
180+
#endif /* FIH_ENABLE_DELAY */
181+
182+
#ifdef FIH_ENABLE_DOUBLE_VARS
183+
184+
__attribute__((always_inline)) inline
185+
void fih_int_validate(fih_int x)
186+
{
187+
if (x.val != (x.msk ^ _fih_mask)) {
188+
FIH_PANIC;
189+
}
190+
}
191+
192+
/* Convert a fih_int to an int. Validate for tampering. */
193+
__attribute__((always_inline)) inline
194+
int fih_int_decode(fih_int x)
195+
{
196+
fih_int_validate(x);
197+
return x.val;
198+
}
199+
200+
/* Convert an int to a fih_int, can be used to encode specific error codes. */
201+
__attribute__((always_inline)) inline
202+
fih_int fih_int_encode(int x)
203+
{
204+
fih_int ret = {x, x ^ _fih_mask};
205+
return ret;
206+
}
207+
208+
/* Standard equality. If A == B then 1, else 0 */
209+
__attribute__((always_inline)) inline
210+
int fih_eq(fih_int x, fih_int y)
211+
{
212+
fih_int_validate(x);
213+
fih_int_validate(y);
214+
return (x.val == y.val) && fih_delay() && (x.msk == y.msk);
215+
}
216+
217+
__attribute__((always_inline)) inline
218+
int fih_not_eq(fih_int x, fih_int y)
219+
{
220+
fih_int_validate(x);
221+
fih_int_validate(y);
222+
return (x.val != y.val) && fih_delay() && (x.msk != y.msk);
223+
}
224+
225+
#else
226+
227+
/* NOOP */
228+
__attribute__((always_inline)) inline
229+
void fih_int_validate(fih_int x)
230+
{
231+
(void) x;
232+
return;
233+
}
234+
235+
/* NOOP */
236+
__attribute__((always_inline)) inline
237+
int fih_int_decode(fih_int x)
238+
{
239+
return x;
240+
}
241+
242+
/* NOOP */
243+
__attribute__((always_inline)) inline
244+
fih_int fih_int_encode(int x)
245+
{
246+
return x;
247+
}
248+
249+
__attribute__((always_inline)) inline
250+
int fih_eq(fih_int x, fih_int y)
251+
{
252+
return x == y;
253+
}
254+
255+
__attribute__((always_inline)) inline
256+
int fih_not_eq(fih_int x, fih_int y)
257+
{
258+
return x != y;
259+
}
260+
#endif /* FIH_ENABLE_DOUBLE_VARS */
261+
262+
/* C has a common return pattern where 0 is a correct value and all others are
263+
* errors. This function converts 0 to FIH_SUCCESS and any other number to a
264+
* value that is not FIH_SUCCESS
265+
*/
266+
__attribute__((always_inline)) inline
267+
fih_int fih_int_encode_zero_equality(int x)
268+
{
269+
if (x) {
270+
return FIH_FAILURE;
271+
} else {
272+
return FIH_SUCCESS;
273+
}
274+
}
275+
276+
#ifdef FIH_ENABLE_CFI
277+
extern fih_int _fih_cfi_ctr;
278+
#endif /* FIH_ENABLE_CFI */
279+
280+
fih_int fih_cfi_get_and_increment(void);
281+
void fih_cfi_validate(fih_int saved);
282+
void fih_cfi_decrement(void);
283+
284+
/* Label for interacting with FIH testing tool. Can be parsed from the elf file
285+
* after compilation. Does not require debug symbols.
286+
*/
287+
#if defined(__ICCARM__)
288+
#define FIH_LABEL(str, lin, cnt) __asm volatile ("FIH_LABEL_" str "_" #lin "_" #cnt "::" ::);
289+
#else
290+
#define FIH_LABEL(str) __asm volatile ("FIH_LABEL_" str "_%=:" ::);
291+
#endif
292+
293+
/* Main FIH calling macro. return variable is second argument. Does some setup
294+
* before and validation afterwards. Inserts labels for use with testing script.
295+
*
296+
* First perform the precall step - this gets the current value of the CFI
297+
* counter and saves it to a local variable, and then increments the counter.
298+
*
299+
* Then set the return variable to FIH_FAILURE as a base case.
300+
*
301+
* Then perform the function call. As part of the funtion FIH_RET must be called
302+
* which will decrement the counter.
303+
*
304+
* The postcall step gets the value of the counter and compares it to the
305+
* previously saved value. If this is equal then the function call and all child
306+
* function calls were performed.
307+
*/
308+
#if defined(__ICCARM__)
309+
#define FIH_CALL(f, ret, ...) FIH_CALL2(f, ret, __LINE__, __COUNTER__, __VA_ARGS__)
310+
311+
#define FIH_CALL2(f, ret, l, c, ...) \
312+
do { \
313+
FIH_LABEL("FIH_CALL_START", l, c); \
314+
FIH_CFI_PRECALL_BLOCK; \
315+
ret = FIH_FAILURE; \
316+
if (fih_delay()) { \
317+
ret = f(__VA_ARGS__); \
318+
} \
319+
FIH_CFI_POSTCALL_BLOCK; \
320+
FIH_LABEL("FIH_CALL_END", l, c); \
321+
} while (0)
322+
323+
#else
324+
325+
#define FIH_CALL(f, ret, ...) \
326+
do { \
327+
FIH_LABEL("FIH_CALL_START"); \
328+
FIH_CFI_PRECALL_BLOCK; \
329+
ret = FIH_FAILURE; \
330+
if (fih_delay()) { \
331+
ret = f(__VA_ARGS__); \
332+
} \
333+
FIH_CFI_POSTCALL_BLOCK; \
334+
FIH_LABEL("FIH_CALL_END"); \
335+
} while (0)
336+
#endif
337+
338+
/* FIH return changes the state of the internal state machine. If you do a
339+
* FIH_CALL then you need to do a FIH_RET else the state machine will detect
340+
* tampering and panic.
341+
*/
342+
#define FIH_RET(ret) \
343+
do { \
344+
FIH_CFI_PRERET; \
345+
return ret; \
346+
} while (0)
347+
348+
349+
#ifdef FIH_ENABLE_CFI
350+
/* Macro wrappers for functions - Even when the functions have zero body this
351+
* saves a few bytes on noop functions as it doesn't generate the call/ret
352+
*
353+
* CFI precall function saves the CFI counter and then increments it - the
354+
* postcall then checks if the counter is equal to the saved value. In order for
355+
* this to be the case a FIH_RET must have been performed inside the called
356+
* function in order to decrement the counter, so the function must have been
357+
* called.
358+
*/
359+
#define FIH_CFI_PRECALL_BLOCK \
360+
fih_int _fih_cfi_saved_value = fih_cfi_get_and_increment()
361+
362+
#define FIH_CFI_POSTCALL_BLOCK \
363+
fih_cfi_validate(_fih_cfi_saved_value)
364+
365+
#define FIH_CFI_PRERET \
366+
fih_cfi_decrement()
367+
#else
368+
#define FIH_CFI_PRECALL_BLOCK
369+
#define FIH_CFI_POSTCALL_BLOCK
370+
#define FIH_CFI_PRERET
371+
#endif /* FIH_ENABLE_CFI */
372+
373+
#ifdef __cplusplus
374+
}
375+
#endif /* __cplusplus */
376+
377+
#endif /* __FAULT_INJECTION_HARDENING_H__ */
+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* Copyright (c) 2017 Nordic Semiconductor ASA
5+
*
6+
* Original license:
7+
*
8+
* Licensed to the Apache Software Foundation (ASF) under one
9+
* or more contributor license agreements. See the NOTICE file
10+
* distributed with this work for additional information
11+
* regarding copyright ownership. The ASF licenses this file
12+
* to you under the Apache License, Version 2.0 (the
13+
* "License"); you may not use this file except in compliance
14+
* with the License. You may obtain a copy of the License at
15+
*
16+
* http://www.apache.org/licenses/LICENSE-2.0
17+
*
18+
* Unless required by applicable law or agreed to in writing,
19+
* software distributed under the License is distributed on an
20+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21+
* KIND, either express or implied. See the License for the
22+
* specific language governing permissions and limitations
23+
* under the License.
24+
*/
25+
26+
#ifndef H_IGNORE_
27+
#define H_IGNORE_
28+
29+
#ifdef __cplusplus
30+
extern "C" {
31+
#endif
32+
33+
/**
34+
* These macros prevent the "set but not used" warnings for log writes below
35+
* the log level.
36+
*/
37+
38+
#define IGN_1(X) ((void)(X))
39+
#define IGN_2(X, ...) ((void)(X));IGN_1(__VA_ARGS__)
40+
#define IGN_3(X, ...) ((void)(X));IGN_2(__VA_ARGS__)
41+
#define IGN_4(X, ...) ((void)(X));IGN_3(__VA_ARGS__)
42+
#define IGN_5(X, ...) ((void)(X));IGN_4(__VA_ARGS__)
43+
#define IGN_6(X, ...) ((void)(X));IGN_5(__VA_ARGS__)
44+
#define IGN_7(X, ...) ((void)(X));IGN_6(__VA_ARGS__)
45+
#define IGN_8(X, ...) ((void)(X));IGN_7(__VA_ARGS__)
46+
#define IGN_9(X, ...) ((void)(X));IGN_8(__VA_ARGS__)
47+
#define IGN_10(X, ...) ((void)(X));IGN_9(__VA_ARGS__)
48+
#define IGN_11(X, ...) ((void)(X));IGN_10(__VA_ARGS__)
49+
#define IGN_12(X, ...) ((void)(X));IGN_11(__VA_ARGS__)
50+
#define IGN_13(X, ...) ((void)(X));IGN_12(__VA_ARGS__)
51+
#define IGN_14(X, ...) ((void)(X));IGN_13(__VA_ARGS__)
52+
#define IGN_15(X, ...) ((void)(X));IGN_14(__VA_ARGS__)
53+
#define IGN_16(X, ...) ((void)(X));IGN_15(__VA_ARGS__)
54+
#define IGN_17(X, ...) ((void)(X));IGN_16(__VA_ARGS__)
55+
#define IGN_18(X, ...) ((void)(X));IGN_17(__VA_ARGS__)
56+
#define IGN_19(X, ...) ((void)(X));IGN_18(__VA_ARGS__)
57+
#define IGN_20(X, ...) ((void)(X));IGN_19(__VA_ARGS__)
58+
59+
#define GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, \
60+
_13, _14, _15, _16, _17, _18, _19, _20, NAME, ...) NAME
61+
#define IGNORE(...) \
62+
GET_MACRO(__VA_ARGS__, IGN_20, IGN_19, IGN_18, IGN_17, IGN_16, IGN_15, \
63+
IGN_14, IGN_13, IGN_12, IGN_11, IGN_10, IGN_9, IGN_8, IGN_7, \
64+
IGN_6, IGN_5, IGN_4, IGN_3, IGN_2, IGN_1)(__VA_ARGS__)
65+
66+
#ifdef __cplusplus
67+
}
68+
#endif
69+
70+
#endif
+191
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* Copyright (c) 2016-2019 Linaro LTD
5+
* Copyright (c) 2016-2019 JUUL Labs
6+
* Copyright (c) 2019-2021 Arm Limited
7+
*
8+
* Original license:
9+
*
10+
* Licensed to the Apache Software Foundation (ASF) under one
11+
* or more contributor license agreements. See the NOTICE file
12+
* distributed with this work for additional information
13+
* regarding copyright ownership. The ASF licenses this file
14+
* to you under the Apache License, Version 2.0 (the
15+
* "License"); you may not use this file except in compliance
16+
* with the License. You may obtain a copy of the License at
17+
*
18+
* http://www.apache.org/licenses/LICENSE-2.0
19+
*
20+
* Unless required by applicable law or agreed to in writing,
21+
* software distributed under the License is distributed on an
22+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
23+
* KIND, either express or implied. See the License for the
24+
* specific language governing permissions and limitations
25+
* under the License.
26+
*/
27+
28+
#ifndef H_IMAGE_
29+
#define H_IMAGE_
30+
31+
#include <inttypes.h>
32+
#include <stdbool.h>
33+
#include "bootutil/fault_injection_hardening.h"
34+
35+
#ifdef __cplusplus
36+
extern "C" {
37+
#endif
38+
39+
struct flash_area;
40+
41+
#define IMAGE_MAGIC 0x96f3b83d
42+
#define IMAGE_MAGIC_V1 0x96f3b83c
43+
#define IMAGE_MAGIC_NONE 0xffffffff
44+
#define IMAGE_TLV_INFO_MAGIC 0x6907
45+
#define IMAGE_TLV_PROT_INFO_MAGIC 0x6908
46+
47+
#define IMAGE_HEADER_SIZE 32
48+
49+
/*
50+
* Image header flags.
51+
*/
52+
#define IMAGE_F_PIC 0x00000001 /* Not supported. */
53+
#define IMAGE_F_ENCRYPTED_AES128 0x00000004 /* Encrypted using AES128. */
54+
#define IMAGE_F_ENCRYPTED_AES256 0x00000008 /* Encrypted using AES256. */
55+
#define IMAGE_F_NON_BOOTABLE 0x00000010 /* Split image app. */
56+
/*
57+
* Indicates that this image should be loaded into RAM instead of run
58+
* directly from flash. The address to load should be in the
59+
* ih_load_addr field of the header.
60+
*/
61+
#define IMAGE_F_RAM_LOAD 0x00000020
62+
63+
/*
64+
* Indicates that ih_load_addr stores information on flash/ROM address the
65+
* image has been built for.
66+
*/
67+
#define IMAGE_F_ROM_FIXED 0x00000100
68+
69+
/*
70+
* ECSDA224 is with NIST P-224
71+
* ECSDA256 is with NIST P-256
72+
*/
73+
74+
/*
75+
* Image trailer TLV types.
76+
*
77+
* Signature is generated by computing signature over the image hash.
78+
* Currently the only image hash type is SHA256.
79+
*
80+
* Signature comes in the form of 2 TLVs.
81+
* 1st on identifies the public key which should be used to verify it.
82+
* 2nd one is the actual signature.
83+
*/
84+
#define IMAGE_TLV_KEYHASH 0x01 /* hash of the public key */
85+
#define IMAGE_TLV_PUBKEY 0x02 /* public key */
86+
#define IMAGE_TLV_SHA256 0x10 /* SHA256 of image hdr and body */
87+
#define IMAGE_TLV_RSA2048_PSS 0x20 /* RSA2048 of hash output */
88+
#define IMAGE_TLV_ECDSA224 0x21 /* ECDSA of hash output */
89+
#define IMAGE_TLV_ECDSA256 0x22 /* ECDSA of hash output */
90+
#define IMAGE_TLV_RSA3072_PSS 0x23 /* RSA3072 of hash output */
91+
#define IMAGE_TLV_ED25519 0x24 /* ed25519 of hash output */
92+
#define IMAGE_TLV_ENC_RSA2048 0x30 /* Key encrypted with RSA-OAEP-2048 */
93+
#define IMAGE_TLV_ENC_KW 0x31 /* Key encrypted with AES-KW 128 or 256*/
94+
#define IMAGE_TLV_ENC_EC256 0x32 /* Key encrypted with ECIES-EC256 */
95+
#define IMAGE_TLV_ENC_X25519 0x33 /* Key encrypted with ECIES-X25519 */
96+
#define IMAGE_TLV_DEPENDENCY 0x40 /* Image depends on other image */
97+
#define IMAGE_TLV_SEC_CNT 0x50 /* security counter */
98+
#define IMAGE_TLV_BOOT_RECORD 0x60 /* measured boot record */
99+
/*
100+
* vendor reserved TLVs at xxA0-xxFF,
101+
* where xx denotes the upper byte
102+
* range. Examples:
103+
* 0x00a0 - 0x00ff
104+
* 0x01a0 - 0x01ff
105+
* 0x02a0 - 0x02ff
106+
* ...
107+
* 0xffa0 - 0xfffe
108+
*/
109+
#define IMAGE_TLV_ANY 0xffff /* Used to iterate over all TLV */
110+
111+
struct image_version {
112+
uint8_t iv_major;
113+
uint8_t iv_minor;
114+
uint16_t iv_revision;
115+
uint32_t iv_build_num;
116+
};
117+
118+
struct image_dependency {
119+
uint8_t image_id; /* Image index (from 0) */
120+
uint8_t _pad1;
121+
uint16_t _pad2;
122+
struct image_version image_min_version; /* Indicates at minimum which
123+
* version of firmware must be
124+
* available to satisfy compliance
125+
*/
126+
};
127+
128+
/** Image header. All fields are in little endian byte order. */
129+
struct image_header {
130+
uint32_t ih_magic;
131+
uint32_t ih_load_addr;
132+
uint32_t ih_hdr_size; /* Size of image header (bytes). */
133+
uint32_t ih_protect_tlv_size; /* Size of protected TLV area (bytes). */
134+
uint32_t ih_img_size; /* Does not include header. */
135+
uint32_t ih_flags; /* IMAGE_F_[...]. */
136+
struct image_version ih_ver;
137+
};
138+
139+
/** Image TLV header. All fields in little endian. */
140+
struct image_tlv_info {
141+
uint16_t it_magic;
142+
uint16_t it_tlv_tot; /* size of TLV area (including tlv_info header) */
143+
};
144+
145+
/** Image trailer TLV format. All fields in little endian. */
146+
struct image_tlv {
147+
uint16_t it_type; /* IMAGE_TLV_[...]. */
148+
uint16_t it_len; /* Data length (not including TLV header). */
149+
};
150+
151+
#define IS_ENCRYPTED(hdr) (((hdr)->ih_flags & IMAGE_F_ENCRYPTED_AES128) \
152+
|| ((hdr)->ih_flags & IMAGE_F_ENCRYPTED_AES256))
153+
#define MUST_DECRYPT(fap, idx, hdr) \
154+
(flash_area_get_id(fap) == FLASH_AREA_IMAGE_SECONDARY(idx) && IS_ENCRYPTED(hdr))
155+
156+
_Static_assert(sizeof(struct image_header) == IMAGE_HEADER_SIZE,
157+
"struct image_header not required size");
158+
159+
struct enc_key_data;
160+
fih_int bootutil_img_validate(struct enc_key_data *enc_state, int image_index,
161+
struct image_header *hdr,
162+
const struct flash_area *fap,
163+
uint8_t *tmp_buf, uint32_t tmp_buf_sz,
164+
uint8_t *seed, int seed_len, uint8_t *out_hash);
165+
166+
struct image_tlv_iter {
167+
const struct image_header *hdr;
168+
const struct flash_area *fap;
169+
uint16_t type;
170+
bool prot;
171+
uint32_t prot_end;
172+
uint32_t tlv_off;
173+
uint32_t tlv_end;
174+
};
175+
176+
int bootutil_tlv_iter_begin(struct image_tlv_iter *it,
177+
const struct image_header *hdr,
178+
const struct flash_area *fap, uint16_t type,
179+
bool prot);
180+
int bootutil_tlv_iter_next(struct image_tlv_iter *it, uint32_t *off,
181+
uint16_t *len, uint16_t *type);
182+
183+
int32_t bootutil_get_img_security_cnt(struct image_header *hdr,
184+
const struct flash_area *fap,
185+
uint32_t *security_cnt);
186+
187+
#ifdef __cplusplus
188+
}
189+
#endif
190+
191+
#endif
-45.1 KB
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
/*
2+
Copyright (c) 2022 Arduino SA. All right reserved.
3+
4+
This library is free software; you can redistribute it and/or
5+
modify it under the terms of the GNU Lesser General Public
6+
License as published by the Free Software Foundation; either
7+
version 2.1 of the License, or (at your option) any later version.
8+
9+
This library is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
Lesser General Public License for more details.
13+
14+
You should have received a copy of the GNU Lesser General Public
15+
License along with this library; if not, write to the Free Software
16+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17+
*/
18+
19+
#include "FileBlockDevice.h"
20+
#include "platform/mbed_assert.h"
21+
#include "mcuboot_config/mcuboot_logging.h"
22+
#include "stddef.h"
23+
#include <stdio.h>
24+
25+
#ifndef MBED_CONF_MBED_TRACE_ENABLE
26+
#define MBED_CONF_MBED_TRACE_ENABLE 0
27+
#endif
28+
29+
#include "mbed_trace.h"
30+
#define TRACE_GROUP "FILEBD"
31+
32+
namespace mbed {
33+
34+
FileBlockDevice::FileBlockDevice(const char *path, const char *flags, bd_size_t bd_size, bd_size_t r_size, bd_size_t w_size, bd_size_t e_size)
35+
:_path(path), _oflag(flags), _bd_size(bd_size), _r_size(r_size), _w_size(w_size), _e_size(e_size)
36+
{
37+
38+
}
39+
40+
int FileBlockDevice::init()
41+
{
42+
tr_debug("Opening file block device %s", _path);
43+
44+
_file[0] = fopen(_path, _oflag);
45+
if (_file[0] == NULL) {
46+
MCUBOOT_LOG_ERR("Cannot open file block device %s %s", _path, _oflag);
47+
return BD_ERROR_DEVICE_ERROR;
48+
}
49+
50+
int err = fseek (_file[0] , 0 , SEEK_END);
51+
if (err) {
52+
MCUBOOT_LOG_ERR("Init:fseek");
53+
return BD_ERROR_DEVICE_ERROR;
54+
}
55+
56+
uint32_t f_size = ftell (_file[0]);
57+
if (f_size != _bd_size) {
58+
MCUBOOT_LOG_WRN("File %s size (0x%zx) should be the same of underlying block device (0x%zx)", _path, f_size, _bd_size);
59+
}
60+
61+
tr_debug("Opened file block device handle %d file size 0x%zx", _file[0], f_size);
62+
63+
_is_initialized = true;
64+
65+
return BD_ERROR_OK;
66+
}
67+
68+
int FileBlockDevice::deinit()
69+
{
70+
tr_debug("Closing file block handle %d", _file[0]);
71+
fclose(_file[0]);
72+
return BD_ERROR_OK;
73+
}
74+
75+
int FileBlockDevice::sync()
76+
{
77+
return BD_ERROR_OK;
78+
}
79+
80+
int FileBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
81+
{
82+
if (_file[0] == NULL) {
83+
MCUBOOT_LOG_ERR("Read:invalid handle");
84+
return BD_ERROR_DEVICE_ERROR;
85+
}
86+
87+
tr_debug("reading addr 0x%x", (long)addr);
88+
tr_debug("reading size %d", (int)size);
89+
int err = fseek(_file[0], addr, SEEK_SET);
90+
if (err) {
91+
MCUBOOT_LOG_ERR("Read:fseek");
92+
return BD_ERROR_DEVICE_ERROR;
93+
}
94+
size_t count = fread(buffer, 1u, size, _file[0]);
95+
tr_debug("reading count %d", (int)count);
96+
if (count != size) {
97+
MCUBOOT_LOG_ERR("Read:handle %d count 0x%zx", _file[0], count);
98+
return BD_ERROR_DEVICE_ERROR;
99+
}
100+
101+
return BD_ERROR_OK;
102+
}
103+
104+
int FileBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size)
105+
{
106+
if (_file[0] == NULL) {
107+
MCUBOOT_LOG_ERR("Program:invalid handle");
108+
return BD_ERROR_DEVICE_ERROR;
109+
}
110+
111+
tr_debug("program addr 0x%x", (long)addr);
112+
tr_debug("program size %d", (int)size);
113+
int err = fseek(_file[0], addr, SEEK_SET);
114+
if (err) {
115+
MCUBOOT_LOG_ERR("Program:fseek");
116+
return BD_ERROR_DEVICE_ERROR;
117+
}
118+
119+
int count = fwrite(buffer, size, 1u, _file[0]);
120+
if (count != 1u) {
121+
MCUBOOT_LOG_ERR("Program:handle %d count 0x%zx", _file[0], count);
122+
return BD_ERROR_DEVICE_ERROR;
123+
}
124+
125+
err = fflush(_file[0]);
126+
if (err != 0u) {
127+
MCUBOOT_LOG_ERR("Program:flush");
128+
return BD_ERROR_DEVICE_ERROR;
129+
}
130+
131+
return BD_ERROR_OK;
132+
}
133+
134+
int FileBlockDevice::erase(bd_addr_t addr, bd_size_t size)
135+
{
136+
if (_file[0] == NULL) {
137+
MCUBOOT_LOG_ERR("Erase:invalid handle");
138+
return BD_ERROR_DEVICE_ERROR;
139+
}
140+
141+
tr_debug("program addr 0x%x", (long)addr);
142+
tr_debug("program size %d", (int)size);
143+
bd_size_t len;
144+
for (len = 0; len < size; len++) {
145+
int err = fseek(_file[0], addr + len, SEEK_SET);
146+
if (err) {
147+
MCUBOOT_LOG_ERR("Erase:fseek");
148+
return BD_ERROR_DEVICE_ERROR;
149+
}
150+
uint8_t erase_val = 0xFF;
151+
int count = fwrite(&erase_val, 1u, 1u, _file[0]);
152+
if (count != 1u) {
153+
MCUBOOT_LOG_ERR("Erase:handle %d count 0x%zx", _file[0], count);
154+
return BD_ERROR_DEVICE_ERROR;
155+
}
156+
}
157+
158+
int err = fflush(_file[0]);
159+
if (err != 0u) {
160+
MCUBOOT_LOG_ERR("Erase:flush");
161+
return BD_ERROR_DEVICE_ERROR;
162+
}
163+
164+
return BD_ERROR_OK;
165+
}
166+
167+
bool FileBlockDevice::is_valid_read(bd_addr_t addr, bd_size_t size) const
168+
{
169+
return ((addr + size) <= _bd_size);
170+
}
171+
172+
bool FileBlockDevice::is_valid_program(bd_addr_t addr, bd_size_t size) const
173+
{
174+
return ((addr + size) <= _bd_size);
175+
}
176+
177+
bool FileBlockDevice::is_valid_erase(bd_addr_t addr, bd_size_t size) const
178+
{
179+
return ((addr + size) <= _bd_size);
180+
}
181+
182+
bd_size_t FileBlockDevice::get_read_size() const
183+
{
184+
// Return minimum read size in bytes for the device
185+
return _r_size;
186+
}
187+
188+
bd_size_t FileBlockDevice::get_program_size() const
189+
{
190+
// Return minimum program/write size in bytes for the device
191+
return _w_size;
192+
}
193+
194+
bd_size_t FileBlockDevice::get_erase_size() const
195+
{
196+
// return minimal erase size supported by all regions (0 if none exists)
197+
return _e_size;
198+
}
199+
200+
bd_size_t FileBlockDevice::get_erase_size(bd_addr_t addr) const
201+
{
202+
return _e_size;
203+
}
204+
205+
int FileBlockDevice::get_erase_value() const
206+
{
207+
return 0xFF;
208+
}
209+
210+
bd_size_t FileBlockDevice::size() const
211+
{
212+
return _bd_size;
213+
}
214+
215+
const char *FileBlockDevice::get_type() const
216+
{
217+
return "FILEBD";
218+
}
219+
220+
} // namespace mbed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
/*
2+
Copyright (c) 2022 Arduino SA. All right reserved.
3+
4+
This library is free software; you can redistribute it and/or
5+
modify it under the terms of the GNU Lesser General Public
6+
License as published by the Free Software Foundation; either
7+
version 2.1 of the License, or (at your option) any later version.
8+
9+
This library is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
Lesser General Public License for more details.
13+
14+
You should have received a copy of the GNU Lesser General Public
15+
License along with this library; if not, write to the Free Software
16+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17+
*/
18+
19+
/** \addtogroup storage */
20+
/** @{*/
21+
22+
#ifndef MBED_FILE_BLOCK_DEVICE_H
23+
#define MBED_FILE_BLOCK_DEVICE_H
24+
25+
#include "mbed.h"
26+
#include "BlockDevice.h"
27+
#include "platform/mbed_assert.h"
28+
#include <stdio.h>
29+
30+
namespace mbed {
31+
32+
/** BlockDevice for mapping a file into a Blockdevice
33+
*
34+
*/
35+
class FileBlockDevice : public BlockDevice {
36+
public:
37+
/** Create FileBlockDevice - An SFDP based Flash Block Device over QSPI bus
38+
*
39+
*/
40+
FileBlockDevice(const char *path, const char * flags, bd_size_t bd_size, bd_size_t r_size, bd_size_t w_size, bd_size_t e_size);
41+
42+
/** Lifetime of a block device
43+
*/
44+
~FileBlockDevice() {};
45+
46+
/** Initialize a block device
47+
*
48+
* @return QSPIF_BD_ERROR_OK(0) - success
49+
* QSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
50+
* QSPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timedout
51+
* QSPIF_BD_ERROR_PARSING_FAILED - unexpected format or values in one of the SFDP tables
52+
*/
53+
virtual int init();
54+
55+
/** Deinitialize a block device
56+
*
57+
* @return QSPIF_BD_ERROR_OK(0) - success
58+
* QSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
59+
*/
60+
virtual int deinit();
61+
62+
/** Ensure data on storage is in sync with the driver
63+
*
64+
* @return 0 on success or a negative error code on failure
65+
*/
66+
virtual int sync();
67+
68+
/** Read blocks from a block device
69+
*
70+
* @param buffer Buffer to write blocks to
71+
* @param addr Address of block to begin reading from
72+
* @param size Size to read in bytes, must be a multiple of read block size
73+
* @return QSPIF_BD_ERROR_OK(0) - success
74+
* QSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
75+
*/
76+
virtual int read(void *buffer, bd_addr_t addr, bd_size_t size);
77+
78+
/** Program blocks to a block device
79+
*
80+
* The blocks must have been erased prior to being programmed
81+
*
82+
* @param buffer Buffer of data to write to blocks
83+
* @param addr Address of block to begin writing to
84+
* @param size Size to write in bytes, must be a multiple of program block size
85+
* @return QSPIF_BD_ERROR_OK(0) - success
86+
* QSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
87+
* QSPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out
88+
* QSPIF_BD_ERROR_WREN_FAILED - Write Enable failed
89+
* QSPIF_BD_ERROR_PARSING_FAILED - unexpected format or values in one of the SFDP tables
90+
*/
91+
virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size);
92+
93+
/** Erase blocks on a block device
94+
*
95+
* The state of an erased block is undefined until it has been programmed
96+
*
97+
* @param addr Address of block to begin erasing
98+
* @param size Size to erase in bytes, must be a multiple of erase block size
99+
* @return QSPIF_BD_ERROR_OK(0) - success
100+
* QSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
101+
* QSPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out
102+
* QSPIF_BD_ERROR_WREN_FAILED - Write Enable failed
103+
* QSPIF_BD_ERROR_PARSING_FAILED - unexpected format or values in one of the SFDP tables
104+
* QSPIF_BD_ERROR_INVALID_ERASE_PARAMS - Trying to erase unaligned address or size
105+
*/
106+
virtual int erase(bd_addr_t addr, bd_size_t size);
107+
108+
/** Get the size of a readable block
109+
*
110+
* @return Size of a readable block in bytes
111+
*/
112+
virtual bd_size_t get_read_size() const;
113+
114+
/** Get the size of a programable block
115+
*
116+
* @return Size of a program block size in bytes
117+
* @note Must be a multiple of the read size
118+
*/
119+
virtual bd_size_t get_program_size() const;
120+
121+
/** Get the size of a eraseable block
122+
*
123+
* @return Size of a minimal erase block, common to all regions, in bytes
124+
* @note Must be a multiple of the program size
125+
*/
126+
virtual bd_size_t get_erase_size() const;
127+
128+
/** Get the size of minimal eraseable sector size of given address
129+
*
130+
* @param addr Any address within block queried for erase sector size (can be any address within flash size offset)
131+
* @return Size of minimal erase sector size, in given address region, in bytes
132+
* @note Must be a multiple of the program size
133+
*/
134+
virtual bd_size_t get_erase_size(bd_addr_t addr) const;
135+
136+
/** Get the value of storage byte after it was erased
137+
*
138+
* If get_erase_value returns a non-negative byte value, the underlying
139+
* storage is set to that value when erased, and storage containing
140+
* that value can be programmed without another erase.
141+
*
142+
* @return The value of storage when erased, or -1 if you can't
143+
* rely on the value of erased storage
144+
*/
145+
virtual int get_erase_value() const;
146+
147+
/** Get the total size of the underlying device
148+
*
149+
* @return Size of the underlying device in bytes
150+
*/
151+
virtual mbed::bd_size_t size() const;
152+
153+
/** Get the BlockDevice class type.
154+
*
155+
* @return A string represent the BlockDevice class type.
156+
*/
157+
virtual const char *get_type() const;
158+
159+
/** Convenience function for checking block program validity
160+
*
161+
* @param addr Address of block to begin writing to
162+
* @param size Size to write in bytes
163+
* @return True if program is valid for underlying block device
164+
*/
165+
virtual bool is_valid_program(bd_addr_t addr, bd_size_t size) const;
166+
167+
/** Convenience function for checking block read validity
168+
*
169+
* @param addr Address of block to begin reading from
170+
* @param size Size to read in bytes
171+
* @return True if read is valid for underlying block device
172+
*/
173+
virtual bool is_valid_read(bd_addr_t addr, bd_size_t size) const;
174+
175+
/** Convenience function for checking block erase validity
176+
*
177+
* @param addr Address of block to begin erasing
178+
* @param size Size to erase in bytes
179+
* @return True if erase is valid for underlying block device
180+
*/
181+
virtual bool is_valid_erase(bd_addr_t addr, bd_size_t size) const;
182+
183+
private:
184+
FILE *_file[1];
185+
const char *_path;
186+
const char *_oflag;
187+
bd_size_t _bd_size;
188+
bd_size_t _r_size;
189+
bd_size_t _w_size;
190+
bd_size_t _e_size;
191+
bool _is_initialized;
192+
};
193+
194+
} // namespace mbed
195+
196+
// Added "using" for backwards compatibility
197+
#ifndef MBED_NO_GLOBAL_USING_DIRECTIVE
198+
using mbed::FileBlockDevice;
199+
#endif
200+
201+
#endif
202+
203+
/** @}*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
/*
2+
* Copyright (c) 2020 Embedded Planet
3+
* Copyright (c) 2020 ARM Limited
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License
17+
*/
18+
19+
#include <assert.h>
20+
#include <cstring>
21+
#include "flash_map_backend/flash_map_backend.h"
22+
#include "flash_map_backend/secondary_bd.h"
23+
#include "sysflash/sysflash.h"
24+
25+
#include "mbed.h"
26+
#include "blockdevice/BlockDevice.h"
27+
#include "FlashIAP/FlashIAPBlockDevice.h"
28+
29+
#include "mcuboot_config/mcuboot_logging.h"
30+
31+
#include "bootutil/bootutil_priv.h"
32+
33+
#define FLASH_DEVICE_INTERNAL_FLASH 0
34+
#define FLASH_AREAS 3
35+
36+
/** Application defined secondary block device */
37+
mbed::BlockDevice* mcuboot_secondary_bd = get_secondary_bd();
38+
39+
/** Internal application block device */
40+
static FlashIAPBlockDevice mcuboot_primary_bd(MCUBOOT_PRIMARY_SLOT_START_ADDR, MCUBOOT_SLOT_SIZE);
41+
42+
#if MCUBOOT_SWAP_USING_SCRATCH
43+
mbed::BlockDevice* mcuboot_scratch_bd = get_scratch_bd();
44+
#endif
45+
46+
static mbed::BlockDevice* flash_map_bd[FLASH_AREAS] = {
47+
(mbed::BlockDevice*) &mcuboot_primary_bd, /** Primary (loadable) image area */
48+
mcuboot_secondary_bd, /** Secondary (update candidate) image area */
49+
#if MCUBOOT_SWAP_USING_SCRATCH
50+
mcuboot_scratch_bd /** Scratch space for swapping images */
51+
#else
52+
nullptr
53+
#endif
54+
};
55+
56+
static struct flash_area flash_areas[FLASH_AREAS];
57+
58+
static unsigned int open_count[FLASH_AREAS] = {0};
59+
60+
int flash_area_open(uint8_t id, const struct flash_area** fapp) {
61+
62+
*fapp = &flash_areas[id];
63+
struct flash_area* fap = (struct flash_area*)*fapp;
64+
65+
// The offset of the slot is from the beginning of the flash device.
66+
switch (id) {
67+
case PRIMARY_ID:
68+
fap->fa_off = MCUBOOT_PRIMARY_SLOT_START_ADDR;
69+
break;
70+
case SECONDARY_ID:
71+
#if MCUBOOT_DIRECT_XIP
72+
fap->fa_off = MBED_CONF_MCUBOOT_XIP_SECONDARY_SLOT_ADDRESS;
73+
#else
74+
fap->fa_off = 0;
75+
#endif
76+
break;
77+
#if MCUBOOT_SWAP_USING_SCRATCH
78+
case SCRATCH_ID:
79+
fap->fa_off = MCUBOOT_SCRATCH_START_ADDR;
80+
break;
81+
#endif
82+
default:
83+
MCUBOOT_LOG_ERR("flash_area_open, unknown id %d", id);
84+
return -1;
85+
}
86+
87+
open_count[id]++;
88+
MCUBOOT_LOG_DBG("flash area %d open count: %d (+)", id, open_count[id]);
89+
90+
fap->fa_id = id;
91+
fap->fa_device_id = 0; // not relevant
92+
93+
mbed::BlockDevice* bd = flash_map_bd[id];
94+
fap->fa_size = (uint32_t) bd->size();
95+
96+
/* Only initialize if this isn't a nested call to open the flash area */
97+
if (open_count[id] == 1) {
98+
MCUBOOT_LOG_DBG("initializing flash area %d...", id);
99+
return bd->init();
100+
} else {
101+
return 0;
102+
}
103+
}
104+
105+
void flash_area_close(const struct flash_area* fap) {
106+
uint8_t id = fap->fa_id;
107+
/* No need to close an unopened flash area, avoid an overflow of the counter */
108+
if (!open_count[id]) {
109+
return;
110+
}
111+
112+
open_count[id]--;
113+
MCUBOOT_LOG_DBG("flash area %d open count: %d (-)", id, open_count[id]);
114+
if (!open_count[id]) {
115+
/* mcuboot is not currently consistent in opening/closing flash areas only once at a time
116+
* so only deinitialize the BlockDevice if all callers have closed the flash area. */
117+
MCUBOOT_LOG_DBG("deinitializing flash area block device %d...", id);
118+
mbed::BlockDevice* bd = flash_map_bd[id];
119+
bd->deinit();
120+
}
121+
}
122+
123+
/*
124+
* Read/write/erase. Offset is relative from beginning of flash area.
125+
*/
126+
int flash_area_read(const struct flash_area* fap, uint32_t off, void* dst, uint32_t len) {
127+
mbed::BlockDevice* bd = flash_map_bd[fap->fa_id];
128+
129+
/* Note: The address must be aligned to bd->get_read_size(). If MCUBOOT_READ_GRANULARITY
130+
is defined, the length does not need to be aligned. */
131+
#ifdef MCUBOOT_READ_GRANULARITY
132+
uint32_t read_size = bd->get_read_size();
133+
if (read_size == 0) {
134+
MCUBOOT_LOG_ERR("Invalid read size: must be non-zero");
135+
return -1;
136+
}
137+
if (MCUBOOT_READ_GRANULARITY < read_size) {
138+
MCUBOOT_LOG_ERR("Please increase MCUBOOT_READ_GRANULARITY (currently %u) to be at least %u",
139+
MCUBOOT_READ_GRANULARITY, read_size);
140+
return -1;
141+
}
142+
143+
uint32_t remainder = len % read_size;
144+
len -= remainder;
145+
if (len != 0) {
146+
#endif
147+
if (!bd->is_valid_read(off, len)) {
148+
MCUBOOT_LOG_ERR("Invalid read: fa_id %d offset 0x%x len 0x%x", fap->fa_id,
149+
(unsigned int) off, (unsigned int) len);
150+
return -1;
151+
}
152+
else {
153+
int ret = bd->read(dst, off, len);
154+
if (ret != 0) {
155+
MCUBOOT_LOG_ERR("Read failed: fa_id %d offset 0x%x len 0x%x", fap->fa_id,
156+
(unsigned int) off, (unsigned int) len);
157+
return ret;
158+
}
159+
}
160+
#ifdef MCUBOOT_READ_GRANULARITY
161+
}
162+
163+
if (remainder) {
164+
if (!bd->is_valid_read(off + len, read_size)) {
165+
MCUBOOT_LOG_ERR("Invalid read: fa_id %d offset 0x%x len 0x%x", fap->fa_id,
166+
(unsigned int) (off + len), (unsigned int) read_size);
167+
return -1;
168+
}
169+
else {
170+
uint8_t buffer[MCUBOOT_READ_GRANULARITY];
171+
int ret = bd->read(buffer, off + len, read_size);
172+
if (ret != 0) {
173+
MCUBOOT_LOG_ERR("Read failed: %d", ret);
174+
return ret;
175+
}
176+
memcpy((uint8_t *)dst + len, buffer, remainder);
177+
}
178+
}
179+
#endif
180+
181+
return 0;
182+
}
183+
184+
int flash_area_write(const struct flash_area* fap, uint32_t off, const void* src, uint32_t len) {
185+
mbed::BlockDevice* bd = flash_map_bd[fap->fa_id];
186+
return bd->program(src, off, len);
187+
}
188+
189+
int flash_area_erase(const struct flash_area* fap, uint32_t off, uint32_t len) {
190+
mbed::BlockDevice* bd = flash_map_bd[fap->fa_id];
191+
return bd->erase(off, len);
192+
}
193+
194+
uint8_t flash_area_align(const struct flash_area* fap) {
195+
mbed::BlockDevice* bd = flash_map_bd[fap->fa_id];
196+
return bd->get_program_size();
197+
}
198+
199+
uint8_t flash_area_erased_val(const struct flash_area* fap) {
200+
mbed::BlockDevice* bd = flash_map_bd[fap->fa_id];
201+
return bd->get_erase_value();
202+
}
203+
204+
int flash_area_get_sectors(int fa_id, uint32_t* count, struct flash_sector* sectors) {
205+
mbed::BlockDevice* bd = flash_map_bd[fa_id];
206+
207+
/* Loop through sectors and collect information on them */
208+
mbed::bd_addr_t offset = 0;
209+
*count = 0;
210+
while (*count < MCUBOOT_MAX_IMG_SECTORS && bd->is_valid_read(offset, bd->get_read_size())) {
211+
212+
sectors[*count].fs_off = offset;
213+
mbed::bd_size_t erase_size = bd->get_erase_size(offset);
214+
sectors[*count].fs_size = erase_size;
215+
216+
offset += erase_size;
217+
*count += 1;
218+
}
219+
220+
return 0;
221+
}
222+
223+
int flash_area_id_from_image_slot(int slot) {
224+
return slot;
225+
}
226+
227+
int flash_area_id_to_image_slot(int area_id) {
228+
return area_id;
229+
}
230+
231+
/**
232+
* Multi images support not implemented yet
233+
*/
234+
int flash_area_id_from_multi_image_slot(int image_index, int slot)
235+
{
236+
assert(image_index == 0);
237+
return slot;
238+
}
239+
240+
int flash_area_id_to_multi_image_slot(int image_index, int area_id)
241+
{
242+
assert(image_index == 0);
243+
return area_id;
244+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
/*
2+
* Copyright (c) 2018 Nordic Semiconductor ASA
3+
* Copyright (c) 2015 Runtime Inc
4+
* Copyright (c) 2020 Embedded Planet
5+
* SPDX-License-Identifier: Apache-2.0
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the Licens
18+
*/
19+
20+
#ifndef H_UTIL_FLASH_MAP_
21+
#define H_UTIL_FLASH_MAP_
22+
23+
#ifdef __cplusplus
24+
extern "C" {
25+
#endif
26+
27+
/**
28+
*
29+
* Provides abstraction of flash regions for type of use.
30+
* I.e. dude where's my image?
31+
*
32+
* System will contain a map which contains flash areas. Every
33+
* region will contain flash identifier, offset within flash and length.
34+
*
35+
* 1. This system map could be in a file within filesystem (Initializer
36+
* must know/figure out where the filesystem is at).
37+
* 2. Map could be at fixed location for project (compiled to code)
38+
* 3. Map could be at specific place in flash (put in place at mfg time).
39+
*
40+
* Note that the map you use must be valid for BSP it's for,
41+
* match the linker scripts when platform executes from flash,
42+
* and match the target offset specified in download script.
43+
*/
44+
#include <inttypes.h>
45+
46+
/**
47+
* @brief Structure describing an area on a flash device.
48+
*
49+
* Multiple flash devices may be available in the system, each of
50+
* which may have its own areas. For this reason, flash areas track
51+
* which flash device they are part of.
52+
*/
53+
struct flash_area {
54+
/**
55+
* This flash area's ID; unique in the system.
56+
*/
57+
uint8_t fa_id;
58+
59+
/**
60+
* ID of the flash device this area is a part of.
61+
*/
62+
uint8_t fa_device_id;
63+
64+
uint16_t pad16;
65+
66+
/**
67+
* This area's offset, relative to the beginning of its flash
68+
* device's storage.
69+
*/
70+
uint32_t fa_off;
71+
72+
/**
73+
* This area's size, in bytes.
74+
*/
75+
uint32_t fa_size;
76+
};
77+
78+
static inline uint8_t flash_area_get_id(const struct flash_area *fa)
79+
{
80+
return fa->fa_id;
81+
}
82+
83+
static inline uint8_t flash_area_get_device_id(const struct flash_area *fa)
84+
{
85+
return fa->fa_device_id;
86+
}
87+
88+
static inline uint32_t flash_area_get_off(const struct flash_area *fa)
89+
{
90+
return fa->fa_off;
91+
}
92+
93+
static inline uint32_t flash_area_get_size(const struct flash_area *fa)
94+
{
95+
return fa->fa_size;
96+
}
97+
98+
/**
99+
* @brief Structure describing a sector within a flash area.
100+
*
101+
* Each sector has an offset relative to the start of its flash area
102+
* (NOT relative to the start of its flash device), and a size. A
103+
* flash area may contain sectors with different sizes.
104+
*/
105+
struct flash_sector {
106+
/**
107+
* Offset of this sector, from the start of its flash area (not device).
108+
*/
109+
uint32_t fs_off;
110+
111+
/**
112+
* Size of this sector, in bytes.
113+
*/
114+
uint32_t fs_size;
115+
};
116+
117+
static inline uint32_t flash_sector_get_off(const struct flash_sector *fs)
118+
{
119+
return fs->fs_off;
120+
}
121+
122+
static inline uint32_t flash_sector_get_size(const struct flash_sector *fs)
123+
{
124+
return fs->fs_size;
125+
}
126+
127+
/*
128+
* Start using flash area.
129+
*/
130+
int flash_area_open(uint8_t id, const struct flash_area ** fapp);
131+
132+
void flash_area_close(const struct flash_area * fap);
133+
134+
/*
135+
* Read/write/erase. Offset is relative from beginning of flash area.
136+
*/
137+
int flash_area_read(const struct flash_area * fap, uint32_t off, void *dst,
138+
uint32_t len);
139+
int flash_area_write(const struct flash_area * fap, uint32_t off, const void *src,
140+
uint32_t len);
141+
int flash_area_erase(const struct flash_area * fap, uint32_t off, uint32_t len);
142+
143+
/*
144+
* Alignment restriction for flash writes.
145+
*/
146+
uint8_t flash_area_align(const struct flash_area * fap);
147+
148+
/*
149+
* What is value is read from erased flash bytes.
150+
*/
151+
uint8_t flash_area_erased_val(const struct flash_area * fap);
152+
153+
/*
154+
* Given flash area ID, return info about sectors within the area.
155+
*/
156+
int flash_area_get_sectors(int fa_id, uint32_t *count,
157+
struct flash_sector *sectors);
158+
159+
160+
int flash_area_id_from_image_slot(int slot);
161+
int flash_area_id_from_multi_image_slot(int image_index, int slot);
162+
163+
164+
int flash_area_id_to_image_slot(int area_id);
165+
/**
166+
* Converts the specified flash area ID and image index (in multi-image setup)
167+
* to an image slot index.
168+
*
169+
* Returns image slot index (0 or 1), or -1 if ID doesn't correspond to an image
170+
* slot.
171+
*/
172+
int flash_area_id_to_multi_image_slot(int image_index, int area_id);
173+
174+
#ifdef __cplusplus
175+
}
176+
#endif
177+
178+
#endif /* H_UTIL_FLASH_MAP_ */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Mbed-OS Microcontroller Library
3+
* Copyright (c) 2020 Embedded Planet
4+
* Copyright (c) 2020 ARM Limited
5+
* SPDX-License-Identifier: Apache-2.0
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License
18+
*/
19+
20+
#include "flash_map_backend/secondary_bd.h"
21+
#include "mcuboot_config/mcuboot_logging.h"
22+
#include "platform/mbed_toolchain.h"
23+
#include "MBRBlockDevice.h"
24+
#include "fileblockdevice/FileBlockDevice.h"
25+
#include "FATFileSystem.h"
26+
#include "bootutil/bootutil_priv.h"
27+
28+
mbed::FATFileSystem* get_filesystem(void) {
29+
mbed::BlockDevice* raw = mbed::BlockDevice::get_default_instance();
30+
static mbed::MBRBlockDevice mbr = mbed::MBRBlockDevice(raw, 2);
31+
static mbed::FATFileSystem fs("fs");
32+
33+
int err = mbr.init();
34+
if(err) {
35+
MCUBOOT_LOG_ERR("Cannot initialize Block Device");
36+
return nullptr;
37+
}
38+
39+
// Mount can fail if filerystem already mounted
40+
fs.mount(&mbr);
41+
return &fs;
42+
}
43+
44+
mbed::BlockDevice* get_secondary_bd(void) {
45+
mbed::FATFileSystem* fs = get_filesystem();
46+
if(fs == nullptr) {
47+
MCUBOOT_LOG_ERR("Cannot initialize secondary fs");
48+
}
49+
50+
// TODO: This is the default configuration, check RTC registers to allow custom settings
51+
static mbed::FileBlockDevice secondary_bd = mbed::FileBlockDevice("/fs/update.bin", "rb+", MCUBOOT_SLOT_SIZE, 0x01, 0x01, 0x1000);
52+
return &secondary_bd;
53+
}
54+
55+
mbed::BlockDevice* get_scratch_bd(void) {
56+
mbed::FATFileSystem* fs = get_filesystem();
57+
if(fs == nullptr) {
58+
MCUBOOT_LOG_ERR("Cannot initialize scratch fs");
59+
}
60+
61+
// TODO: This is the default configuration, check RTC registers to allow custom settings
62+
static mbed::FileBlockDevice scratch_bd = mbed::FileBlockDevice("/fs/scratch.bin", "rb+", MCUBOOT_SCRATCH_SIZE, 0x01, 0x01, 0x1000);
63+
return &scratch_bd;
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright (c) 2020 Embedded Planet
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the Licens
16+
*
17+
* Created on: Jul 30, 2020
18+
* Author: gdbeckstein
19+
*/
20+
21+
#ifndef MCUBOOT_BOOT_MBED_INCLUDE_FLASH_MAP_BACKEND_SECONDARY_BD_H_
22+
#define MCUBOOT_BOOT_MBED_INCLUDE_FLASH_MAP_BACKEND_SECONDARY_BD_H_
23+
24+
#include "blockdevice/BlockDevice.h"
25+
26+
/**
27+
* This is implemented as a weak function and may be redefined
28+
* by the application. The default case is to return the
29+
* BlockDevice object returned by BlockDevice::get_default_instance();
30+
*
31+
* For an XIP build, the secondary BD is provided by mcuboot by default.
32+
*
33+
* This is implemented as a weak symbol so the user can override it.
34+
*
35+
* @retval secondary_bd Secondary BlockDevice where update candidates are stored
36+
*/
37+
mbed::BlockDevice* get_secondary_bd(void);
38+
39+
/**
40+
* This is implemented as a weak function and may be redefined
41+
* by the application. By default, scratch space is at the end of
42+
* internal flash, after the main application.
43+
*
44+
* This is implemented as a weak symbol so the user can override it.
45+
*
46+
* Security warning: Using an external scratch memory might compromise
47+
* the security of encrypted images. In this case, the scratch and
48+
* slot 0 are encrypted. If the swap is moved to external memory,
49+
* it could be read if the swap were interrupted. Done enough
50+
* times, this could be used to extract the plaintext image.
51+
*
52+
* @retval scratch_bd BlockDevice containing the scratch region
53+
*/
54+
mbed::BlockDevice* get_scratch_bd(void);
55+
56+
#endif /* MCUBOOT_BOOT_MBED_INCLUDE_FLASH_MAP_BACKEND_SECONDARY_BD_H_ */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
* Copyright (c) 2018 Open Source Foundries Limited
3+
* Copyright (c) 2019-2020 Arm Limited
4+
* Copyright (c) 2019-2020 Linaro Limited
5+
* Copyright (c) 2020 Embedded Planet
6+
*
7+
* SPDX-License-Identifier: Apache-2.0
8+
*/
9+
10+
#ifndef __MCUBOOT_CONFIG_H__
11+
#define __MCUBOOT_CONFIG_H__
12+
13+
/*
14+
* Primary slot start address (Internal flash)
15+
*/
16+
#define MCUBOOT_PRIMARY_SLOT_START_ADDR 0x8020000
17+
18+
/*
19+
* Primary/Secondary slot size
20+
*/
21+
#define MCUBOOT_SLOT_SIZE 0x1E0000
22+
23+
/*
24+
* Scratch slot start address (QSPI flash FS "virtual" address)
25+
*/
26+
#define MCUBOOT_SCRATCH_START_ADDR 0x9000000
27+
28+
/*
29+
* Scratch slot size
30+
*/
31+
#define MCUBOOT_SCRATCH_SIZE 0x20000
32+
33+
/*
34+
* Maximum number of flash sector per slot
35+
*/
36+
#define MCUBOOT_MAX_IMG_SECTORS 0x3C0
37+
38+
/*
39+
* STM32H7 flash read alignment
40+
*/
41+
#define MCUBOOT_BOOT_MAX_ALIGN 32
42+
43+
/*
44+
* MCUboot swaps slots using scratch partition
45+
*/
46+
#define MCUBOOT_SWAP_USING_SCRATCH 1
47+
48+
/*
49+
* LOG level: 0 OFF, 1 ERROR, 2 WARNING, 3 DEBUG, 4 INFO
50+
*/
51+
#define MCUBOOT_LOG_LEVEL 4
52+
53+
/*
54+
* Signature algorithm
55+
*/
56+
#define MCUBOOT_SIGN_EC256
57+
58+
/*
59+
* Crypto backend
60+
*/
61+
#define MCUBOOT_USE_MBED_TLS
62+
63+
/*
64+
* Only one image (two slots) supported for now
65+
*/
66+
#define MCUBOOT_IMAGE_NUMBER 1
67+
68+
/*
69+
* Currently there is no configuration option, for this platform,
70+
* that enables the system specific mcumgr commands in mcuboot
71+
*/
72+
#define MCUBOOT_PERUSER_MGMT_GROUP_ENABLED 0
73+
74+
/*
75+
* Encrypted Images
76+
*/
77+
#if defined(MCUBOOT_ENCRYPT_RSA) || defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
78+
#define MCUBOOT_ENC_IMAGES
79+
#endif
80+
81+
/*
82+
* Enabling this option uses newer flash map APIs. This saves RAM and
83+
* avoids deprecated API usage.
84+
*/
85+
#define MCUBOOT_USE_FLASH_AREA_GET_SECTORS
86+
87+
/*
88+
* No watchdog integration for now
89+
*/
90+
#define MCUBOOT_WATCHDOG_FEED() \
91+
do { \
92+
} while (0)
93+
94+
/*
95+
* No direct idle call implemented
96+
*/
97+
#define MCUBOOT_CPU_IDLE() \
98+
do { \
99+
} while (0)
100+
101+
/*
102+
* Enable MCUBoot logging
103+
*/
104+
#define MCUBOOT_HAVE_LOGGING
105+
106+
#endif /* __MCUBOOT_CONFIG_H__ */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
* Copyright (c) 2018 Nordic Semiconductor ASA
3+
* Copyright (c) 2015 Runtime Inc
4+
* Copyright (c) 2020 Cypress Semiconductor Corporation
5+
* Copyright (c) 2020 Embedded Planet
6+
* Copyright (c) 2020 ARM Limited
7+
* SPDX-License-Identifier: Apache-2.0
8+
*
9+
* Licensed under the Apache License, Version 2.0 (the "License");
10+
* you may not use this file except in compliance with the License.
11+
* You may obtain a copy of the License at
12+
*
13+
* http://www.apache.org/licenses/LICENSE-2.0
14+
*
15+
* Unless required by applicable law or agreed to in writing, software
16+
* distributed under the License is distributed on an "AS IS" BASIS,
17+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
* See the License for the specific language governing permissions and
19+
* limitations under the Licens.
20+
*/
21+
22+
#ifndef __MCUBOOT_LOGGING_H__
23+
#define __MCUBOOT_LOGGING_H__
24+
25+
#include <stdio.h>
26+
27+
#define MCUBOOT_LOG_LEVEL_OFF 0
28+
#define MCUBOOT_LOG_LEVEL_ERROR 1
29+
#define MCUBOOT_LOG_LEVEL_WARNING 2
30+
#define MCUBOOT_LOG_LEVEL_INFO 3
31+
#define MCUBOOT_LOG_LEVEL_DEBUG 4
32+
33+
/*
34+
* The compiled log level determines the maximum level that can be
35+
* printed.
36+
*/
37+
#ifndef MCUBOOT_LOG_LEVEL
38+
#define MCUBOOT_LOG_LEVEL MCUBOOT_LOG_LEVEL_OFF
39+
#endif
40+
41+
#if MCUBOOT_LOG_LEVEL == MCUBOOT_LOG_LEVEL_OFF
42+
#define MBED_CONF_MBED_TRACE_ENABLE 0
43+
#else
44+
#define MCUBOOT_HAVE_LOGGING
45+
#endif
46+
47+
#if MCUBOOT_LOG_LEVEL == MCUBOOT_LOG_LEVEL_ERROR
48+
#define MBED_TRACE_MAX_LEVEL TRACE_LEVEL_ERROR
49+
#elif MCUBOOT_LOG_LEVEL == MCUBOOT_LOG_LEVEL_WARNING
50+
#define MBED_TRACE_MAX_LEVEL TRACE_LEVEL_WARN
51+
#elif MCUBOOT_LOG_LEVEL == MCUBOOT_LOG_LEVEL_INFO
52+
#define MBED_TRACE_MAX_LEVEL TRACE_LEVEL_INFO
53+
#elif MCUBOOT_LOG_LEVEL == MCUBOOT_LOG_LEVEL_DEBUG
54+
#define MBED_TRACE_MAX_LEVEL TRACE_LEVEL_DEBUG
55+
#endif
56+
57+
#define TRACE_GROUP "MCUb"
58+
#include "mbed_trace.h"
59+
#include "bootutil/ignore.h"
60+
#include "mcuboot_config/mcuboot_config.h"
61+
62+
#define MCUBOOT_LOG_MODULE_DECLARE(domain) /* ignore */
63+
#define MCUBOOT_LOG_MODULE_REGISTER(domain) /* ignore */
64+
65+
#if MCUBOOT_LOG_LEVEL >= MCUBOOT_LOG_LEVEL_ERROR
66+
#if MBED_CONF_MBED_TRACE_ENABLE
67+
#define MCUBOOT_LOG_ERR tr_error
68+
#else
69+
#define MCUBOOT_LOG_ERR(_fmt, ...) \
70+
do { \
71+
printf( "E-" _fmt "\n", ##__VA_ARGS__); \
72+
} while (0)
73+
#endif
74+
#else
75+
#define MCUBOOT_LOG_ERR(...) IGNORE(__VA_ARGS__)
76+
#endif
77+
78+
#if MCUBOOT_LOG_LEVEL >= MCUBOOT_LOG_LEVEL_WARNING
79+
#if MBED_CONF_MBED_TRACE_ENABLE
80+
#define MCUBOOT_LOG_WRN tr_warn
81+
#else
82+
#define MCUBOOT_LOG_WRN(_fmt, ...) \
83+
do { \
84+
printf("W-" _fmt "\n", ##__VA_ARGS__); \
85+
} while (0)
86+
#endif
87+
#else
88+
#define MCUBOOT_LOG_WRN(...) IGNORE(__VA_ARGS__)
89+
#endif
90+
91+
#if MCUBOOT_LOG_LEVEL >= MCUBOOT_LOG_LEVEL_INFO
92+
#if MBED_CONF_MBED_TRACE_ENABLE
93+
#define MCUBOOT_LOG_INF tr_info
94+
#else
95+
#define MCUBOOT_LOG_INF(_fmt, ...) \
96+
do { \
97+
printf( "I-" _fmt "\n", ##__VA_ARGS__); \
98+
} while (0)
99+
#endif
100+
#else
101+
#define MCUBOOT_LOG_INF(...) IGNORE(__VA_ARGS__)
102+
#endif
103+
104+
#if MCUBOOT_LOG_LEVEL >= MCUBOOT_LOG_LEVEL_DEBUG
105+
#if MBED_CONF_MBED_TRACE_ENABLE
106+
#define MCUBOOT_LOG_DBG tr_debug
107+
#else
108+
#define MCUBOOT_LOG_DBG(_fmt, ...) \
109+
do { \
110+
printf( "D-" _fmt "\n", ##__VA_ARGS__); \
111+
} while (0)
112+
#endif
113+
#else
114+
#define MCUBOOT_LOG_DBG(...) IGNORE(__VA_ARGS__)
115+
#endif
116+
117+
#endif /* __MCUBOOT_LOGGING_H__ */
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/* Manual version of auto-generated version. */
2+
3+
#ifndef __SYSFLASH_H__
4+
#define __SYSFLASH_H__
5+
6+
#define PRIMARY_ID 0
7+
#define SECONDARY_ID 1
8+
#define SCRATCH_ID 2
9+
10+
#define FLASH_AREA_IMAGE_PRIMARY(x) PRIMARY_ID
11+
#define FLASH_AREA_IMAGE_SECONDARY(x) SECONDARY_ID
12+
#define FLASH_AREA_IMAGE_SCRATCH SCRATCH_ID
13+
14+
#endif /* __SYSFLASH_H__ */

0 commit comments

Comments
 (0)
Please sign in to comment.