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