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