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