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