Skip to content

Commit 1b4be75

Browse files
committed
bootutil: Move update-independent code
Move functions from loader.c that are independent from the update type into a dedicated file. That way it will be easier to provide alternative loader type without massive code duplication. This file is intended to be used by loader-like files instead and should not be included in the bootutil/_priv.h headers. Signed-off-by: Tomasz Chyrowicz <[email protected]>
1 parent 4c1fa52 commit 1b4be75

File tree

7 files changed

+574
-398
lines changed

7 files changed

+574
-398
lines changed

boot/bootutil/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ target_sources(bootutil
2222
src/bootutil_img_security_cnt.c
2323
src/bootutil_misc.c
2424
src/bootutil_area.c
25+
src/bootutil_loader.c
2526
src/bootutil_public.c
2627
src/caps.c
2728
src/encrypted.c
Lines changed: 383 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,383 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* Copyright (c) 2016-2020 Linaro LTD
5+
* Copyright (c) 2016-2019 JUUL Labs
6+
* Copyright (c) 2019-2023 Arm Limited
7+
* Copyright (c) 2024-2025 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+
* This file provides an interface to the manifest-based boot loader.
31+
* Functions defined in this file should only be called while the boot loader is
32+
* running.
33+
*/
34+
35+
#include "bootutil_loader.h"
36+
#include "bootutil/boot_record.h"
37+
#include "bootutil/boot_hooks.h"
38+
#ifdef MCUBOOT_ENC_IMAGES
39+
#include "bootutil/enc_key.h"
40+
#endif
41+
#ifdef MCUBOOT_HW_ROLLBACK_PROT
42+
#include "bootutil/security_cnt.h"
43+
#endif
44+
#if defined(MCUBOOT_SWAP_USING_MOVE) || defined(MCUBOOT_SWAP_USING_OFFSET) || \
45+
defined(MCUBOOT_SWAP_USING_SCRATCH)
46+
#include "swap_priv.h"
47+
#endif
48+
#include "bootutil/bootutil_log.h"
49+
50+
BOOT_LOG_MODULE_DECLARE(mcuboot);
51+
52+
bool
53+
boot_check_header_erased(struct boot_loader_state *state, int slot)
54+
{
55+
const struct flash_area *fap = NULL;
56+
struct image_header *hdr;
57+
58+
fap = BOOT_IMG_AREA(state, slot);
59+
assert(fap != NULL);
60+
61+
hdr = boot_img_hdr(state, slot);
62+
if (bootutil_buffer_is_erased(fap, &hdr->ih_magic, sizeof(hdr->ih_magic))) {
63+
return true;
64+
}
65+
66+
return false;
67+
}
68+
69+
bool
70+
boot_check_header_valid(struct boot_loader_state *state, int slot)
71+
{
72+
const struct flash_area *fap = NULL;
73+
struct image_header *hdr;
74+
uint32_t size;
75+
76+
fap = BOOT_IMG_AREA(state, slot);
77+
assert(fap != NULL);
78+
79+
hdr = boot_img_hdr(state, slot);
80+
if (hdr->ih_magic != IMAGE_MAGIC) {
81+
return false;
82+
}
83+
84+
if (!boot_u32_safe_add(&size, hdr->ih_img_size, hdr->ih_hdr_size)) {
85+
return false;
86+
}
87+
88+
#ifdef MCUBOOT_DECOMPRESS_IMAGES
89+
if (!MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), hdr)) {
90+
#else
91+
if (1) {
92+
#endif
93+
if (!boot_u32_safe_add(&size, size, hdr->ih_protect_tlv_size)) {
94+
return false;
95+
}
96+
}
97+
98+
if (size >= flash_area_get_size(fap)) {
99+
return false;
100+
}
101+
102+
#if !defined(MCUBOOT_ENC_IMAGES)
103+
if (IS_ENCRYPTED(hdr)) {
104+
return false;
105+
}
106+
#else
107+
if ((hdr->ih_flags & IMAGE_F_ENCRYPTED_AES128) &&
108+
(hdr->ih_flags & IMAGE_F_ENCRYPTED_AES256))
109+
{
110+
return false;
111+
}
112+
#endif
113+
114+
#if !defined(MCUBOOT_DECOMPRESS_IMAGES)
115+
if (IS_COMPRESSED(hdr)) {
116+
return false;
117+
}
118+
#else
119+
if ((hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1) &&
120+
(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2))
121+
{
122+
return false;
123+
}
124+
#endif
125+
126+
return true;
127+
}
128+
129+
int
130+
boot_read_image_headers(struct boot_loader_state *state, bool require_all, struct boot_status *bs)
131+
{
132+
int rc;
133+
int i;
134+
135+
for (i = 0; i < BOOT_NUM_SLOTS; i++) {
136+
rc = BOOT_HOOK_CALL(boot_read_image_header_hook, BOOT_HOOK_REGULAR,
137+
BOOT_CURR_IMG(state), i, boot_img_hdr(state, i));
138+
if (rc == BOOT_HOOK_REGULAR)
139+
{
140+
rc = boot_read_image_header(state, i, boot_img_hdr(state, i), bs);
141+
}
142+
if (rc != 0) {
143+
/* If `require_all` is set, fail on any single fail, otherwise
144+
* if at least the first slot's header was read successfully,
145+
* then the boot loader can attempt a boot.
146+
*
147+
* Failure to read any headers is a fatal error.
148+
*/
149+
if (i > 0 && !require_all) {
150+
return 0;
151+
} else {
152+
return rc;
153+
}
154+
}
155+
}
156+
157+
return 0;
158+
}
159+
160+
fih_ret
161+
boot_check_image(struct boot_loader_state *state, struct boot_status *bs, int slot)
162+
{
163+
TARGET_STATIC uint8_t tmpbuf[BOOT_TMPBUF_SZ];
164+
int rc;
165+
FIH_DECLARE(fih_rc, FIH_FAILURE);
166+
const struct flash_area *fap = NULL;
167+
struct image_header *hdr;
168+
169+
fap = BOOT_IMG_AREA(state, slot);
170+
assert(fap != NULL);
171+
172+
hdr = boot_img_hdr(state, slot);
173+
174+
(void)bs;
175+
(void)rc;
176+
177+
/* In the case of ram loading the image has already been decrypted as it is
178+
* decrypted when copied in ram
179+
*/
180+
#if defined(MCUBOOT_ENC_IMAGES) && !defined(MCUBOOT_RAM_LOAD)
181+
if (MUST_DECRYPT(fap, BOOT_CURR_IMG(state), hdr)) {
182+
rc = boot_enc_load(state, BOOT_SLOT_SECONDARY, hdr, fap, bs);
183+
if (rc < 0) {
184+
FIH_RET(fih_rc);
185+
}
186+
if (rc == 0 && boot_enc_set_key(BOOT_CURR_ENC_SLOT(state, BOOT_SLOT_SECONDARY),
187+
bs->enckey[BOOT_SLOT_SECONDARY])) {
188+
FIH_RET(fih_rc);
189+
}
190+
}
191+
#endif
192+
193+
FIH_CALL(bootutil_img_validate, fih_rc, state, hdr, fap, tmpbuf, BOOT_TMPBUF_SZ,
194+
NULL, 0, NULL);
195+
196+
FIH_RET(fih_rc);
197+
}
198+
199+
int
200+
boot_compare_version(const struct image_version *ver1, const struct image_version *ver2)
201+
{
202+
#if !defined(MCUBOOT_VERSION_CMP_USE_BUILD_NUMBER)
203+
BOOT_LOG_DBG("boot_version_cmp: ver1 %u.%u.%u vs ver2 %u.%u.%u",
204+
(unsigned)ver1->iv_major, (unsigned)ver1->iv_minor,
205+
(unsigned)ver1->iv_revision, (unsigned)ver2->iv_major,
206+
(unsigned)ver2->iv_minor, (unsigned)ver2->iv_revision);
207+
#else
208+
BOOT_LOG_DBG("boot_version_cmp: ver1 %u.%u.%u.%u vs ver2 %u.%u.%u.%u",
209+
(unsigned)ver1->iv_major, (unsigned)ver1->iv_minor,
210+
(unsigned)ver1->iv_revision, (unsigned)ver1->iv_build_num,
211+
(unsigned)ver2->iv_major, (unsigned)ver2->iv_minor,
212+
(unsigned)ver2->iv_revision, (unsigned)ver2->iv_build_num);
213+
#endif
214+
215+
if (ver1->iv_major > ver2->iv_major) {
216+
return 1;
217+
}
218+
if (ver1->iv_major < ver2->iv_major) {
219+
return -1;
220+
}
221+
/* The major version numbers are equal, continue comparison. */
222+
if (ver1->iv_minor > ver2->iv_minor) {
223+
return 1;
224+
}
225+
if (ver1->iv_minor < ver2->iv_minor) {
226+
return -1;
227+
}
228+
/* The minor version numbers are equal, continue comparison. */
229+
if (ver1->iv_revision > ver2->iv_revision) {
230+
return 1;
231+
}
232+
if (ver1->iv_revision < ver2->iv_revision) {
233+
return -1;
234+
}
235+
236+
#if defined(MCUBOOT_VERSION_CMP_USE_BUILD_NUMBER)
237+
/* The revisions are equal, continue comparison. */
238+
if (ver1->iv_build_num > ver2->iv_build_num) {
239+
return 1;
240+
}
241+
if (ver1->iv_build_num < ver2->iv_build_num) {
242+
return -1;
243+
}
244+
#endif
245+
246+
return 0;
247+
}
248+
249+
#ifdef MCUBOOT_HW_ROLLBACK_PROT
250+
int
251+
boot_update_security_counter(struct boot_loader_state *state, int slot, int hdr_slot_idx)
252+
{
253+
const struct flash_area *fap = NULL;
254+
uint32_t img_security_cnt;
255+
int rc;
256+
257+
fap = BOOT_IMG_AREA(state, slot);
258+
assert(fap != NULL);
259+
260+
rc = bootutil_get_img_security_cnt(state, hdr_slot_idx, fap, &img_security_cnt);
261+
if (rc != 0) {
262+
goto done;
263+
}
264+
265+
rc = boot_nv_security_counter_update(BOOT_CURR_IMG(state), img_security_cnt);
266+
if (rc != 0) {
267+
goto done;
268+
}
269+
270+
done:
271+
return rc;
272+
}
273+
#endif /* MCUBOOT_HW_ROLLBACK_PROT */
274+
275+
int
276+
boot_add_shared_data(struct boot_loader_state *state, uint8_t active_slot)
277+
{
278+
#if defined(MCUBOOT_MEASURED_BOOT) || defined(MCUBOOT_DATA_SHARING)
279+
int rc;
280+
281+
#ifdef MCUBOOT_MEASURED_BOOT
282+
rc = boot_save_boot_status(BOOT_CURR_IMG(state),
283+
boot_img_hdr(state, active_slot),
284+
BOOT_IMG_AREA(state, active_slot));
285+
if (rc != 0) {
286+
BOOT_LOG_ERR("Failed to add image data to shared area");
287+
return rc;
288+
}
289+
#endif /* MCUBOOT_MEASURED_BOOT */
290+
291+
#ifdef MCUBOOT_DATA_SHARING
292+
rc = boot_save_shared_data(boot_img_hdr(state, active_slot),
293+
BOOT_IMG_AREA(state, active_slot),
294+
active_slot, boot_get_image_max_sizes());
295+
if (rc != 0) {
296+
BOOT_LOG_ERR("Failed to add data to shared memory area.");
297+
return rc;
298+
}
299+
#endif /* MCUBOOT_DATA_SHARING */
300+
301+
return 0;
302+
303+
#else /* MCUBOOT_MEASURED_BOOT || MCUBOOT_DATA_SHARING */
304+
(void) (state);
305+
(void) (active_slot);
306+
307+
return 0;
308+
#endif
309+
}
310+
311+
#if !defined(MCUBOOT_SINGLE_APPLICATION_SLOT_RAM_LOAD) && !defined(MCUBOOT_SINGLE_APPLICATION_SLOT)
312+
int
313+
boot_open_all_flash_areas(struct boot_loader_state *state)
314+
{
315+
size_t slot;
316+
int rc = 0;
317+
int fa_id;
318+
int image_index;
319+
320+
IMAGES_ITER(BOOT_CURR_IMG(state)) {
321+
#if BOOT_IMAGE_NUMBER > 1
322+
if (state->img_mask[BOOT_CURR_IMG(state)]) {
323+
continue;
324+
}
325+
#endif
326+
image_index = BOOT_CURR_IMG(state);
327+
328+
for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
329+
fa_id = flash_area_id_from_multi_image_slot(image_index, slot);
330+
rc = flash_area_open(fa_id, &BOOT_IMG_AREA(state, slot));
331+
assert(rc == 0);
332+
333+
if (rc != 0) {
334+
BOOT_LOG_ERR("Failed to open flash area ID %d (image %d slot %zu): %d",
335+
fa_id, image_index, slot, rc);
336+
goto out;
337+
}
338+
}
339+
}
340+
341+
#if MCUBOOT_SWAP_USING_SCRATCH
342+
rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, &BOOT_SCRATCH_AREA(state));
343+
assert(rc == 0);
344+
345+
if (rc != 0) {
346+
BOOT_LOG_ERR("Failed to open scratch flash area: %d", rc);
347+
goto out;
348+
}
349+
#endif
350+
351+
out:
352+
if (rc != 0) {
353+
boot_close_all_flash_areas(state);
354+
}
355+
356+
return rc;
357+
}
358+
359+
void
360+
boot_close_all_flash_areas(struct boot_loader_state *state)
361+
{
362+
uint32_t slot;
363+
364+
#if MCUBOOT_SWAP_USING_SCRATCH
365+
if (BOOT_SCRATCH_AREA(state) != NULL) {
366+
flash_area_close(BOOT_SCRATCH_AREA(state));
367+
}
368+
#endif
369+
370+
IMAGES_ITER(BOOT_CURR_IMG(state)) {
371+
#if BOOT_IMAGE_NUMBER > 1
372+
if (state->img_mask[BOOT_CURR_IMG(state)]) {
373+
continue;
374+
}
375+
#endif
376+
for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
377+
if (BOOT_IMG_AREA(state, BOOT_NUM_SLOTS - 1 - slot) != NULL) {
378+
flash_area_close(BOOT_IMG_AREA(state, BOOT_NUM_SLOTS - 1 - slot));
379+
}
380+
}
381+
}
382+
}
383+
#endif /* !MCUBOOT_SINGLE_APPLICATION_SLOT_RAM_LOAD && !MCUBOOT_SINGLE_APPLICATION_SLOT */

0 commit comments

Comments
 (0)