1 /*
2 * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7 #include <string.h>
8 #include "psa/crypto.h"
9 #include "tfm_sp_log.h"
10 #include "bootutil_priv.h"
11 #include "bootutil/bootutil.h"
12 #include "bootutil/image.h"
13 #include "flash_map_backend/flash_map_backend.h"
14 #include "sysflash/sysflash.h"
15 #include "tfm_api.h"
16 #include "tfm_bootloader_fwu_abstraction.h"
17 #include "tfm_boot_status.h"
18 #include "service_api.h"
19
20 #if (FWU_COMPONENT_NUMBER != MCUBOOT_IMAGE_NUMBER)
21 #error "FWU_COMPONENT_NUMBER mismatch with MCUBOOT_IMAGE_NUMBER"
22 #endif
23
24 #if (MCUBOOT_IMAGE_NUMBER == 1)
25 #define MAX_IMAGE_INFO_LENGTH (sizeof(struct image_version) + \
26 SHARED_DATA_ENTRY_HEADER_SIZE)
27 #else
28 #define MAX_IMAGE_INFO_LENGTH 2 * (sizeof(struct image_version) + \
29 SHARED_DATA_ENTRY_HEADER_SIZE)
30 #endif
31
32 /*
33 * \struct fwu_image_info_data
34 *
35 * \brief Contains the received boot status information from bootloader
36 *
37 * \details This is a redefinition of \ref tfm_boot_data to allocate the
38 * appropriate, service dependent size of \ref boot_data.
39 */
40 typedef struct fwu_image_info_data_s {
41 struct shared_data_tlv_header header;
42 uint8_t data[MAX_IMAGE_INFO_LENGTH];
43 } fwu_image_info_data_t;
44
45 typedef struct tfm_fwu_mcuboot_ctx_s {
46 /* The flash area corresponding to component. */
47 const struct flash_area *fap;
48
49 /* The size of the downloaded data in the FWU process. */
50 size_t loaded_size;
51 } tfm_fwu_mcuboot_ctx_t;
52
53 static tfm_fwu_mcuboot_ctx_t mcuboot_ctx[FWU_COMPONENT_NUMBER];
54 static fwu_image_info_data_t __attribute__((aligned(4))) boot_shared_data;
55
fwu_bootloader_get_shared_data(void)56 static int fwu_bootloader_get_shared_data(void)
57 {
58 return tfm_core_get_boot_data(TLV_MAJOR_FWU,
59 (struct tfm_boot_data *)&boot_shared_data,
60 sizeof(boot_shared_data));
61 }
62
get_active_image_version(psa_fwu_component_t component,struct image_version * image_ver)63 static psa_status_t get_active_image_version(psa_fwu_component_t component,
64 struct image_version *image_ver)
65 {
66 struct shared_data_tlv_entry tlv_entry;
67 uint8_t *tlv_end;
68 uint8_t *tlv_curr;
69
70 /* The bootloader writes the image version information into the memory which
71 * is shared between MCUboot and TF-M. Read the shared memory.
72 */
73 if (boot_shared_data.header.tlv_magic != SHARED_DATA_TLV_INFO_MAGIC) {
74 return PSA_ERROR_DATA_CORRUPT;
75 }
76
77 tlv_end = (uint8_t *)&boot_shared_data +
78 boot_shared_data.header.tlv_tot_len;
79 tlv_curr = boot_shared_data.data;
80
81 while (tlv_curr < tlv_end) {
82 (void)memcpy(&tlv_entry, tlv_curr, SHARED_DATA_ENTRY_HEADER_SIZE);
83 if ((GET_FWU_CLAIM(tlv_entry.tlv_type) == SW_VERSION) &&
84 (GET_FWU_MODULE(tlv_entry.tlv_type) == component)) {
85 if (tlv_entry.tlv_len != sizeof(struct image_version)) {
86 return PSA_ERROR_DATA_CORRUPT;
87 }
88 memcpy(image_ver,
89 tlv_curr + SHARED_DATA_ENTRY_HEADER_SIZE,
90 tlv_entry.tlv_len);
91 return PSA_SUCCESS;
92 }
93 tlv_curr += SHARED_DATA_ENTRY_HEADER_SIZE + tlv_entry.tlv_len;
94 }
95
96 return PSA_ERROR_DATA_CORRUPT;
97 }
98
fwu_bootloader_init(void)99 psa_status_t fwu_bootloader_init(void)
100 {
101 if (fwu_bootloader_get_shared_data() != TFM_SUCCESS) {
102 return PSA_ERROR_STORAGE_FAILURE;
103 }
104 /* add Init of specific flash driver */
105 flash_area_driver_init();
106 return PSA_SUCCESS;
107 }
108
fwu_bootloader_staging_area_init(psa_fwu_component_t component,const void * manifest,size_t manifest_size)109 psa_status_t fwu_bootloader_staging_area_init(psa_fwu_component_t component,
110 const void *manifest,
111 size_t manifest_size)
112 {
113 const struct flash_area *fap;
114
115 /* MCUboot uses bundled manifest. */
116 if ((manifest_size != 0) || (component >= FWU_COMPONENT_NUMBER)) {
117 return PSA_ERROR_INVALID_ARGUMENT;
118 }
119
120 if (flash_area_open(FLASH_AREA_IMAGE_SECONDARY(component),
121 &fap) != 0) {
122 LOG_ERRFMT("TFM FWU: opening flash failed.\r\n");
123 return PSA_ERROR_STORAGE_FAILURE;
124 }
125
126 if (flash_area_erase(fap, 0, fap->fa_size) != 0) {
127 LOG_ERRFMT("TFM FWU: erasing flash failed.\r\n");
128 return PSA_ERROR_GENERIC_ERROR;
129 }
130
131 mcuboot_ctx[component].fap = fap;
132
133 /* Reset the loaded_size. */
134 mcuboot_ctx[component].loaded_size = 0;
135
136 return PSA_SUCCESS;
137 }
138
fwu_bootloader_load_image(psa_fwu_component_t component,size_t block_offset,const void * block,size_t block_size)139 psa_status_t fwu_bootloader_load_image(psa_fwu_component_t component,
140 size_t block_offset,
141 const void *block,
142 size_t block_size)
143 {
144 const struct flash_area *fap;
145
146 if (block == NULL || component >= FWU_COMPONENT_NUMBER) {
147 return PSA_ERROR_INVALID_ARGUMENT;
148 }
149
150 /* The component should already be added into the mcuboot_ctx. */
151 if (mcuboot_ctx[component].fap != NULL) {
152 fap = mcuboot_ctx[component].fap;
153 } else {
154 return PSA_ERROR_BAD_STATE;
155 }
156
157 if (flash_area_write(fap, block_offset, block, block_size) != 0) {
158 LOG_ERRFMT("TFM FWU: write flash failed.\r\n");
159 return PSA_ERROR_STORAGE_FAILURE;
160 }
161
162 /* The overflow check has been done in flash_area_write. */
163 mcuboot_ctx[component].loaded_size += block_size;
164 return PSA_SUCCESS;
165 }
166
167 #if (MCUBOOT_IMAGE_NUMBER > 1)
168 /**
169 * \brief Compare image version numbers not including the build number.
170 *
171 * \param[in] image_ver_1 The first image version to compare.
172 *
173 * \param[in] image_ver_2 The second image version to compare.
174 *
175 * \return true image_ver_1 is greater or equal than image_ver_2.
176 * \return false image_ver_1 is less than image_ver_2.
177 */
is_version_greater_or_equal(const struct image_version * image_ver_1,const struct image_version * image_ver_2)178 static bool is_version_greater_or_equal(const struct image_version *image_ver_1,
179 const struct image_version *image_ver_2)
180 {
181 if (image_ver_1->iv_major > image_ver_2->iv_major) {
182 return true;
183 }
184 if (image_ver_1->iv_major < image_ver_2->iv_major) {
185 return false;
186 }
187 /* The major version numbers are equal, continue comparison. */
188 if (image_ver_1->iv_minor > image_ver_2->iv_minor) {
189 return true;
190 }
191 if (image_ver_1->iv_minor < image_ver_2->iv_minor) {
192 return false;
193 }
194 /* The minor version numbers are equal, continue comparison. */
195 if (image_ver_1->iv_revision >= image_ver_2->iv_revision) {
196 return true;
197 }
198 return false;
199 }
200 #endif
201
fwu_bootloader_install_image(const psa_fwu_component_t * candidates,uint8_t number)202 psa_status_t fwu_bootloader_install_image(const psa_fwu_component_t *candidates, uint8_t number)
203 {
204 uint8_t index_i, cand_index;
205 #if (MCUBOOT_IMAGE_NUMBER > 1)
206 psa_fwu_component_t component;
207 const struct flash_area *fap;
208 struct image_tlv_iter it;
209 struct image_header hdr;
210 int rc;
211 uint32_t off;
212 uint16_t len;
213 struct image_dependency dep;
214 struct image_version image_ver = { 0 };
215 const struct flash_area *fap_secondary;
216 struct image_header hdr_secondary;
217 bool check_pass = true;
218 #endif
219
220 if (candidates == NULL) {
221 return PSA_ERROR_INVALID_ARGUMENT;
222 }
223
224 #if (MCUBOOT_IMAGE_NUMBER > 1)
225 for (cand_index = 0; cand_index < number; cand_index++) {
226 component = candidates[cand_index];
227 /* The image should already be added into the mcuboot_ctx. */
228 if ((component >= FWU_COMPONENT_NUMBER) ||
229 (mcuboot_ctx[component].fap == NULL)) {
230 return PSA_ERROR_INVALID_ARGUMENT;
231 }
232 fap = mcuboot_ctx[component].fap;
233 /* Read the image header. */
234 if (flash_area_read(fap, 0, &hdr, sizeof(hdr)) != 0) {
235 return PSA_ERROR_STORAGE_FAILURE;
236 }
237
238 /* Return PSA_ERROR_DATA_CORRUPT if the image header is invalid. */
239 if (hdr.ih_magic != IMAGE_MAGIC) {
240 return PSA_ERROR_DATA_CORRUPT;
241 }
242
243 /* Initialize the iterator. */
244 if (bootutil_tlv_iter_begin(&it, &hdr, fap, IMAGE_TLV_DEPENDENCY, true)) {
245 return PSA_ERROR_STORAGE_FAILURE;
246 }
247 /* Check dependencies. */
248 while (true) {
249 rc = bootutil_tlv_iter_next(&it, &off, &len, NULL);
250 if (rc < 0) {
251 return PSA_ERROR_STORAGE_FAILURE;
252 } else if (rc > 0) {
253 /* No more dependency found. */
254 rc = 0;
255 break;
256 }
257
258 /* A dependency requirement is found. Set check_pass to false. */
259 check_pass = false;
260 if (flash_area_read(fap, off, &dep, len) != 0) {
261 return PSA_ERROR_STORAGE_FAILURE;
262 }
263
264 if (dep.image_id > MCUBOOT_IMAGE_NUMBER) {
265 return PSA_ERROR_DATA_CORRUPT;
266 }
267
268 /* As this partition does not validate the image in the secondary slot,
269 * so it has no information of which image will be chosen to run after
270 * reboot. So if the dependency image in the primary slot or that in the
271 * secondary slot can meet the dependency requirement, then the
272 * dependency check pass.
273 */
274 /* Check the dependency image in the primary slot. */
275 if (get_active_image_version(dep.image_id,
276 &image_ver) != PSA_SUCCESS) {
277 return PSA_ERROR_STORAGE_FAILURE;
278 }
279
280 /* Check whether the version of the running image can meet the
281 * dependency requirement.
282 */
283 if (is_version_greater_or_equal(&image_ver,
284 &dep.image_min_version)) {
285 check_pass = true;
286 } else {
287 /* Check whether the CANDIDATE image can meet this image's dependency
288 * requirement.
289 */
290 for (index_i = 0; index_i < number; index_i++) {
291 if (candidates[index_i] == dep.image_id)
292 break;
293 }
294 if ((index_i < number) && (mcuboot_ctx[dep.image_id].fap != NULL)) {
295 /* The running image cannot meet the dependency requirement. Check
296 * the dependency image in the secondary slot.
297 */
298 fap_secondary = mcuboot_ctx[dep.image_id].fap;
299 if (flash_area_read(fap_secondary,
300 0,
301 &hdr_secondary,
302 sizeof(hdr_secondary)) != 0) {
303 return PSA_ERROR_STORAGE_FAILURE;
304 }
305
306 /* Check the version of the dependency image in the secondary slot
307 * only if the image header is good.
308 */
309 if (hdr_secondary.ih_magic == IMAGE_MAGIC &&
310 (is_version_greater_or_equal(&hdr_secondary.ih_ver,
311 &dep.image_min_version))) {
312 /* The dependency image in the secondary slot meet the
313 * dependency requirement.
314 */
315 check_pass = true;
316 }
317 }
318 }
319
320 /* Return directly if dependency check fails. */
321 if (!check_pass) {
322 return PSA_ERROR_DEPENDENCY_NEEDED;
323 }
324 }
325 }
326 #endif
327
328 /* Write the boot magic in image trailer so that these images will be
329 * taken as candidates.
330 */
331 for (cand_index = 0; cand_index < number; cand_index++) {
332 if (boot_set_pending_multi(candidates[cand_index], false) != 0) {
333 /* If failure happens, reject candidates have been installed successfully. */
334 for (index_i = 0; index_i < cand_index; index_i++) {
335 if (fwu_bootloader_reject_staged_image(candidates[index_i]) != PSA_SUCCESS) {
336 break;
337 }
338 }
339 return PSA_ERROR_STORAGE_FAILURE;
340 }
341 }
342 return PSA_SUCCESS_REBOOT;
343 }
344
345 static inline uint32_t
boot_magic_off(const struct flash_area * fap)346 boot_magic_off(const struct flash_area *fap)
347 {
348 return flash_area_get_size(fap) - BOOT_MAGIC_SZ;
349 }
350
351 #if (defined(MCUBOOT_DIRECT_XIP) && defined(MCUBOOT_DIRECT_XIP_REVERT)) || \
352 defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE)
353 static inline uint32_t
boot_image_ok_off(const struct flash_area * fap)354 boot_image_ok_off(const struct flash_area *fap)
355 {
356 return ALIGN_DOWN(boot_magic_off(fap) - BOOT_MAX_ALIGN, BOOT_MAX_ALIGN);
357 }
358
erase_image_ok(const struct flash_area * fap)359 static psa_status_t erase_image_ok(const struct flash_area *fap)
360 {
361 uint32_t off;
362 uint8_t buf[BOOT_MAX_ALIGN];
363 uint8_t erased_val;
364 uint32_t align;
365
366 /* off of image OK flag is already BOOT_MAX_ALIGN aligned. */
367 off = boot_image_ok_off(fap);
368
369 /* Clear the image ok trailer. */
370 align = flash_area_align(fap);
371 align = ALIGN_UP(BOOT_MAX_ALIGN, align);
372 if (align > BOOT_MAX_ALIGN) {
373 return PSA_ERROR_STORAGE_FAILURE;
374 }
375 erased_val = flash_area_erased_val(fap);
376 memset(buf, erased_val, align);
377 if (flash_area_write(fap, off, buf, align) != 0) {
378 return PSA_ERROR_STORAGE_FAILURE;
379 }
380
381 return PSA_SUCCESS;
382 }
383 #endif
384
fwu_bootloader_mark_image_accepted(const psa_fwu_component_t * trials,uint8_t number)385 psa_status_t fwu_bootloader_mark_image_accepted(const psa_fwu_component_t *trials,
386 uint8_t number)
387 {
388 /* As RAM_LOAD and OVERWRITE_ONLY do not support image revert, the image
389 * does not need to be confirmed explicitly in these two upgrade strategies.
390 * Image revert is supported in SWAP upgrade strategy and DIRECT_XIP upgrade
391 * strategy when MCUBOOT_DIRECT_XIP_REVERT is true. In these cases, the
392 * image needs to be set as a permanent image explicitly. Then the accpeted
393 * image can still be selected as the running image during next time reboot
394 * up. Otherwise, the image will be reverted and the previous one will be
395 * chosen as the running image.
396 */
397 #if (defined(MCUBOOT_DIRECT_XIP) && defined(MCUBOOT_DIRECT_XIP_REVERT)) || \
398 defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE)
399 uint8_t trial_index, i;
400 psa_fwu_component_t component;
401 const struct flash_area *fap;
402
403 if (trials == NULL) {
404 return PSA_ERROR_INVALID_ARGUMENT;
405 }
406 for (trial_index = 0; trial_index < number; trial_index++) {
407 component = trials[trial_index];
408 if (component >= FWU_COMPONENT_NUMBER) {
409 return PSA_ERROR_INVALID_ARGUMENT;
410 }
411 if (flash_area_open(FLASH_AREA_IMAGE_SECONDARY(component),
412 &fap) != 0) {
413 return PSA_ERROR_STORAGE_FAILURE;
414 }
415 if (fap == NULL) {
416 return PSA_ERROR_INVALID_ARGUMENT;
417 }
418 mcuboot_ctx[component].fap = fap;
419 }
420 for (trial_index = 0; trial_index < number; trial_index++) {
421 component = trials[trial_index];
422 if (boot_set_confirmed_multi(component) != 0) {
423 for (i = 0; i < trial_index; i++) {
424 if (erase_image_ok(mcuboot_ctx[component].fap) != 0) {
425 break;
426 }
427 }
428 return PSA_ERROR_STORAGE_FAILURE;
429 }
430 }
431 #else
432 (void)trials;
433 (void)number;
434 #endif
435 return PSA_SUCCESS;
436 }
437
erase_boot_magic(const struct flash_area * fap)438 static psa_status_t erase_boot_magic(const struct flash_area *fap)
439 {
440 uint32_t off, pad_off;
441 uint8_t magic[BOOT_MAGIC_ALIGN_SIZE];
442 uint8_t erased_val;
443
444 off = boot_magic_off(fap);
445 pad_off = ALIGN_DOWN(off, BOOT_MAX_ALIGN);
446 erased_val = flash_area_erased_val(fap);
447 memset(&magic[0], erased_val, sizeof(magic));
448
449 /* Clear the boot magic trailer. */
450 if (flash_area_write(fap, pad_off, &magic[0], BOOT_MAGIC_ALIGN_SIZE)) {
451 return PSA_ERROR_STORAGE_FAILURE;
452 }
453 return PSA_SUCCESS;
454 }
455
456 /* Reject the staged image. */
fwu_bootloader_reject_staged_image(psa_fwu_component_t component)457 psa_status_t fwu_bootloader_reject_staged_image(psa_fwu_component_t component)
458 {
459 if (component >= FWU_COMPONENT_NUMBER) {
460 return PSA_ERROR_INVALID_ARGUMENT;
461 }
462
463 /* The image should already be added into the mcuboot_ctx. */
464 if (mcuboot_ctx[component].fap != NULL) {
465 return erase_boot_magic(mcuboot_ctx[component].fap);
466 }
467
468 /* The component is not in FWU process. */
469 return PSA_ERROR_DOES_NOT_EXIST;
470 }
471
472 /* Reject the running image in trial state. */
fwu_bootloader_reject_trial_image(psa_fwu_component_t component)473 psa_status_t fwu_bootloader_reject_trial_image(psa_fwu_component_t component)
474 {
475 if (component >= FWU_COMPONENT_NUMBER) {
476 return PSA_ERROR_INVALID_ARGUMENT;
477 }
478
479 /* The image will be reverted if it is not accepted explicitly. */
480 return PSA_SUCCESS_REBOOT;
481 }
482
fwu_bootloader_abort(psa_fwu_component_t component)483 psa_status_t fwu_bootloader_abort(psa_fwu_component_t component)
484 {
485 const struct flash_area *fap;
486
487 if (component >= FWU_COMPONENT_NUMBER) {
488 return PSA_ERROR_INVALID_ARGUMENT;
489 }
490
491 /* The image should already be added into the mcuboot_ctx. */
492 if (mcuboot_ctx[component].fap != NULL) {
493 fap = mcuboot_ctx[component].fap;
494 } else {
495 return PSA_ERROR_INVALID_ARGUMENT;
496 }
497
498 flash_area_erase(fap, 0, fap->fa_size);
499 flash_area_close(fap);
500 mcuboot_ctx[component].fap = NULL;
501 mcuboot_ctx[component].loaded_size = 0;
502 return PSA_SUCCESS;
503 }
504
505
util_img_hash(const struct flash_area * fap,size_t data_size,uint8_t * hash_result,size_t buf_size,size_t * hash_size)506 static psa_status_t util_img_hash(const struct flash_area *fap,
507 size_t data_size,
508 uint8_t *hash_result,
509 size_t buf_size,
510 size_t *hash_size)
511 {
512 psa_hash_operation_t handle = psa_hash_operation_init();
513 psa_status_t status;
514 uint8_t tmpbuf[BOOT_TMPBUF_SZ];
515 uint32_t tmp_buf_sz = BOOT_TMPBUF_SZ;
516 uint32_t blk_sz;
517 uint32_t off;
518
519 /* Setup the hash object for the desired hash. */
520 status = psa_hash_setup(&handle, PSA_ALG_SHA_256);
521 if (status != PSA_SUCCESS) {
522 return status;
523 }
524
525 for (off = 0; off < data_size; off += blk_sz) {
526 blk_sz = data_size - off;
527 if (blk_sz > tmp_buf_sz) {
528 blk_sz = tmp_buf_sz;
529 }
530
531 if (flash_area_read(fap, off, tmpbuf, blk_sz)) {
532 return PSA_ERROR_STORAGE_FAILURE;
533 }
534 status = psa_hash_update(&handle, tmpbuf, blk_sz);
535 if (status != PSA_SUCCESS) {
536 return status;
537 }
538 }
539
540 status = psa_hash_finish(&handle, hash_result, buf_size, hash_size);
541
542 return status;
543 }
544
get_second_image_digest(psa_fwu_component_t component,psa_fwu_component_info_t * info)545 static psa_status_t get_second_image_digest(psa_fwu_component_t component,
546 psa_fwu_component_info_t *info)
547 {
548 const struct flash_area *fap = NULL;
549 uint8_t hash[TFM_FWU_MAX_DIGEST_SIZE] = {0};
550 size_t hash_size = 0;
551 psa_status_t ret = PSA_SUCCESS;
552 size_t data_size;
553
554 if (component >= FWU_COMPONENT_NUMBER) {
555 return PSA_ERROR_INVALID_ARGUMENT;
556 }
557
558 /* Check if the image is in a FWU process. */
559 if (mcuboot_ctx[component].fap != NULL) {
560 /* Calculate hash on the downloaded data. */
561 data_size = mcuboot_ctx[component].loaded_size;
562 } else {
563 return PSA_ERROR_INVALID_ARGUMENT;
564 }
565 if ((flash_area_open(FLASH_AREA_IMAGE_SECONDARY(component),
566 &fap)) != 0) {
567 LOG_ERRFMT("TFM FWU: opening flash failed.\r\n");
568 return PSA_ERROR_STORAGE_FAILURE;
569 }
570
571 if (util_img_hash(fap, data_size, hash, (size_t)TFM_FWU_MAX_DIGEST_SIZE,
572 &hash_size) == PSA_SUCCESS) {
573 memcpy(info->impl.candidate_digest, hash, hash_size);
574 } else {
575 ret = PSA_ERROR_STORAGE_FAILURE;
576 }
577
578 flash_area_close(fap);
579 return ret;
580 }
581
fwu_bootloader_get_image_info(psa_fwu_component_t component,bool query_state,bool query_impl_info,psa_fwu_component_info_t * info)582 psa_status_t fwu_bootloader_get_image_info(psa_fwu_component_t component,
583 bool query_state,
584 bool query_impl_info,
585 psa_fwu_component_info_t *info)
586 {
587 #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) && \
588 !defined(MCUBOOT_OVERWRITE_ONLY)
589 uint8_t image_ok = BOOT_FLAG_UNSET;
590 #endif
591 const struct flash_area *fap = NULL;
592 struct image_version image_version;
593 psa_status_t ret = PSA_SUCCESS;
594
595 if (info == NULL) {
596 return PSA_ERROR_INVALID_ARGUMENT;
597 }
598
599 if (component >= FWU_COMPONENT_NUMBER) {
600 return PSA_ERROR_INVALID_ARGUMENT;
601 }
602
603 if ((flash_area_open(FLASH_AREA_IMAGE_PRIMARY(component),
604 &fap)) != 0) {
605 LOG_ERRFMT("TFM FWU: opening flash failed.\r\n");
606 return PSA_ERROR_STORAGE_FAILURE;
607 }
608 info->max_size = fap->fa_size;
609 info->location = fap->fa_id;
610 info->flags = PSA_FWU_FLAG_VOLATILE_STAGING;
611
612 if (query_state) {
613 /* As DIRECT_XIP, RAM_LOAD and OVERWRITE_ONLY do not support image revert.
614 * So the running image is in INSTALLED state in these three upgrade
615 * strategies. In the SWAP case, the image_ok flag should be read to check
616 * whether the running image has been confirmed as a pernament image.
617 */
618 #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) && \
619 !defined(MCUBOOT_OVERWRITE_ONLY)
620 /* Get value of image-ok flag of the image to check whether application
621 * itself is already confirmed.
622 */
623 if (boot_read_image_ok(fap, &image_ok) != 0) {
624 ret = PSA_ERROR_STORAGE_FAILURE;
625 goto close_return;
626 }
627 if (image_ok == BOOT_FLAG_SET) {
628 info->state = PSA_FWU_READY;
629 } else {
630 info->state = PSA_FWU_TRIAL;
631 }
632 #else
633 info->state = PSA_FWU_READY;
634 #endif
635 }
636 if (get_active_image_version(component,
637 &image_version) == PSA_SUCCESS) {
638 info->version.major = image_version.iv_major;
639 info->version.minor = image_version.iv_minor;
640 info->version.patch = image_version.iv_revision;
641 info->version.build = image_version.iv_build_num;
642 } else {
643 ret = PSA_ERROR_STORAGE_FAILURE;
644 goto close_return;
645 }
646 if (query_impl_info) {
647 ret = get_second_image_digest(component, info);
648 }
649
650 close_return:
651 flash_area_close(fap);
652 return ret;
653 }
654
fwu_bootloader_clean_component(psa_fwu_component_t component)655 psa_status_t fwu_bootloader_clean_component(psa_fwu_component_t component)
656 {
657 const struct flash_area *fap = NULL;
658
659 if (component >= FWU_COMPONENT_NUMBER) {
660 return PSA_ERROR_INVALID_ARGUMENT;
661 }
662
663 /* Check if the image is in a FWU process. */
664 if (mcuboot_ctx[component].fap != NULL) {
665 fap = mcuboot_ctx[component].fap;
666 if (flash_area_erase(fap, 0, fap->fa_size) != 0) {
667 return PSA_ERROR_STORAGE_FAILURE;
668 }
669 mcuboot_ctx[component].fap = NULL;
670 } else {
671 return PSA_ERROR_DOES_NOT_EXIST;
672 }
673
674 return PSA_SUCCESS;
675 }
676