Dominik Ermel | 3d51e43 | 2021-06-25 17:29:50 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2021 Nordic Semiconductor ASA |
| 3 | * |
| 4 | * SPDX-License-Identifier: Apache-2.0 |
| 5 | */ |
| 6 | |
Jamie McCrae | e188dbb | 2023-08-29 07:43:16 +0100 | [diff] [blame] | 7 | #include <stdio.h> |
Gerard Marull-Paretas | 34dd9e7 | 2022-05-09 12:13:12 +0200 | [diff] [blame] | 8 | #include <zephyr/kernel.h> |
Gerard Marull-Paretas | 3cd2cec | 2022-05-09 12:10:05 +0200 | [diff] [blame] | 9 | #include <zephyr/drivers/flash.h> |
Jamie McCrae | e188dbb | 2023-08-29 07:43:16 +0100 | [diff] [blame] | 10 | #include <zephyr/mgmt/mcumgr/mgmt/mgmt_defines.h> |
| 11 | #include <zephyr/mgmt/mcumgr/grp/zephyr/zephyr_basic.h> |
| 12 | #include <../subsys/mgmt/mcumgr/transport/include/mgmt/mcumgr/transport/smp_internal.h> |
Dominik Ermel | 3d51e43 | 2021-06-25 17:29:50 +0000 | [diff] [blame] | 13 | |
| 14 | #include <flash_map_backend/flash_map_backend.h> |
| 15 | #include <sysflash/sysflash.h> |
| 16 | |
| 17 | #include "bootutil/bootutil_log.h" |
| 18 | #include "../boot_serial/src/boot_serial_priv.h" |
Dominik Ermel | e6e4801 | 2023-06-19 11:37:20 +0000 | [diff] [blame] | 19 | #include <zcbor_encode.h> |
Dominik Ermel | 3d51e43 | 2021-06-25 17:29:50 +0000 | [diff] [blame] | 20 | |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 21 | #include "bootutil/image.h" |
Andrzej Puzdrowski | 2a29f5d | 2021-07-30 16:22:22 +0200 | [diff] [blame] | 22 | #include "bootutil/bootutil_public.h" |
| 23 | #include "bootutil/boot_hooks.h" |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 24 | |
Andrzej Puzdrowski | d16598f | 2022-01-10 10:49:09 +0100 | [diff] [blame] | 25 | BOOT_LOG_MODULE_DECLARE(mcuboot); |
Dominik Ermel | 3d51e43 | 2021-06-25 17:29:50 +0000 | [diff] [blame] | 26 | |
Dominik Ermel | 0435d5d | 2021-08-16 15:58:15 +0000 | [diff] [blame] | 27 | #ifdef CONFIG_BOOT_MGMT_CUSTOM_STORAGE_ERASE |
Dominik Ermel | 864d104 | 2022-07-12 12:41:39 +0000 | [diff] [blame] | 28 | static int bs_custom_storage_erase(zcbor_state_t *cs) |
Dominik Ermel | 3d51e43 | 2021-06-25 17:29:50 +0000 | [diff] [blame] | 29 | { |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 30 | int rc; |
Dominik Ermel | 3d51e43 | 2021-06-25 17:29:50 +0000 | [diff] [blame] | 31 | |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 32 | const struct flash_area *fa; |
Dominik Ermel | 97b4c79 | 2021-06-25 17:32:38 +0000 | [diff] [blame] | 33 | |
Dominik Ermel | 2c53934 | 2022-08-24 14:37:11 +0000 | [diff] [blame] | 34 | rc = flash_area_open(FIXED_PARTITION_ID(storage_partition), &fa); |
Dominik Ermel | 97b4c79 | 2021-06-25 17:32:38 +0000 | [diff] [blame] | 35 | |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 36 | if (rc < 0) { |
Andrzej Puzdrowski | d16598f | 2022-01-10 10:49:09 +0100 | [diff] [blame] | 37 | BOOT_LOG_ERR("failed to open flash area"); |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 38 | } else { |
Dominik Ermel | 2c53934 | 2022-08-24 14:37:11 +0000 | [diff] [blame] | 39 | rc = flash_area_erase(fa, 0, flash_area_get_size(fa)); |
Dominik Ermel | 97b4c79 | 2021-06-25 17:32:38 +0000 | [diff] [blame] | 40 | if (rc < 0) { |
Andrzej Puzdrowski | d16598f | 2022-01-10 10:49:09 +0100 | [diff] [blame] | 41 | BOOT_LOG_ERR("failed to erase flash area"); |
Dominik Ermel | 97b4c79 | 2021-06-25 17:32:38 +0000 | [diff] [blame] | 42 | } |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 43 | flash_area_close(fa); |
| 44 | } |
| 45 | if (rc == 0) { |
| 46 | rc = MGMT_ERR_OK; |
| 47 | } else { |
| 48 | rc = MGMT_ERR_EUNKNOWN; |
Dominik Ermel | 3d51e43 | 2021-06-25 17:29:50 +0000 | [diff] [blame] | 49 | } |
| 50 | |
Dominik Ermel | 864d104 | 2022-07-12 12:41:39 +0000 | [diff] [blame] | 51 | zcbor_map_start_encode(cs, 10); |
| 52 | zcbor_tstr_put_lit(cs, "rc"); |
| 53 | zcbor_uint32_put(cs, rc); |
| 54 | zcbor_map_end_encode(cs, 10); |
Dominik Ermel | 3d51e43 | 2021-06-25 17:29:50 +0000 | [diff] [blame] | 55 | |
| 56 | return rc; |
| 57 | } |
Dominik Ermel | 0435d5d | 2021-08-16 15:58:15 +0000 | [diff] [blame] | 58 | #endif |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 59 | |
Andrzej Puzdrowski | 420ad9a | 2021-07-29 16:22:52 +0200 | [diff] [blame] | 60 | #ifdef MCUBOOT_MGMT_CUSTOM_IMG_LIST |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 61 | static int custom_img_status(int image_index, uint32_t slot,char *buffer, |
| 62 | ssize_t len) |
| 63 | { |
| 64 | uint32_t area_id; |
| 65 | struct flash_area const *fap; |
| 66 | struct image_header hdr; |
| 67 | int rc; |
Andrzej Puzdrowski | 2a29f5d | 2021-07-30 16:22:22 +0200 | [diff] [blame] | 68 | int img_install_stat; |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 69 | |
Andrzej Puzdrowski | 2a29f5d | 2021-07-30 16:22:22 +0200 | [diff] [blame] | 70 | rc = BOOT_HOOK_CALL(boot_img_install_stat_hook, BOOT_HOOK_REGULAR, |
| 71 | image_index, slot, &img_install_stat); |
| 72 | if (rc == BOOT_HOOK_REGULAR) |
| 73 | { |
| 74 | img_install_stat = 0; |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 75 | } |
| 76 | |
Andrzej Puzdrowski | 2a29f5d | 2021-07-30 16:22:22 +0200 | [diff] [blame] | 77 | rc = BOOT_HOOK_CALL(boot_read_image_header_hook, BOOT_HOOK_REGULAR, |
| 78 | image_index, slot, &hdr); |
| 79 | if (rc == BOOT_HOOK_REGULAR) |
| 80 | { |
| 81 | area_id = flash_area_id_from_multi_image_slot(image_index, slot); |
| 82 | |
| 83 | rc = flash_area_open(area_id, &fap); |
| 84 | if (rc) { |
| 85 | return rc; |
| 86 | } |
| 87 | |
| 88 | rc = flash_area_read(fap, 0, &hdr, sizeof(hdr)); |
| 89 | |
| 90 | flash_area_close(fap); |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 91 | } |
| 92 | |
Andrzej Puzdrowski | 2a29f5d | 2021-07-30 16:22:22 +0200 | [diff] [blame] | 93 | if (rc == 0) { |
| 94 | if (hdr.ih_magic == IMAGE_MAGIC) { |
| 95 | snprintf(buffer, len, "ver=%d.%d.%d.%d,install_stat=%d", |
| 96 | hdr.ih_ver.iv_major, |
| 97 | hdr.ih_ver.iv_minor, |
| 98 | hdr.ih_ver.iv_revision, |
| 99 | hdr.ih_ver.iv_build_num, |
| 100 | img_install_stat); |
| 101 | } else { |
| 102 | rc = 1; |
| 103 | } |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 104 | } |
| 105 | |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 106 | return rc; |
| 107 | } |
| 108 | |
Dominik Ermel | 864d104 | 2022-07-12 12:41:39 +0000 | [diff] [blame] | 109 | static int bs_custom_img_list(zcbor_state_t *cs) |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 110 | { |
| 111 | int rc = 0; |
| 112 | char tmpbuf[64]; /* Buffer should fit version and flags */ |
| 113 | |
Dominik Ermel | 864d104 | 2022-07-12 12:41:39 +0000 | [diff] [blame] | 114 | zcbor_map_start_encode(cs, 10); |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 115 | |
| 116 | for (int img = 0; img < MCUBOOT_IMAGE_NUMBER; img++) { |
| 117 | for (int slot = 0; slot < 2; slot++) { |
| 118 | rc = custom_img_status(img, slot, tmpbuf, sizeof(tmpbuf)); |
| 119 | |
Dominik Ermel | 864d104 | 2022-07-12 12:41:39 +0000 | [diff] [blame] | 120 | zcbor_int32_put(cs, img * 2 + slot + 1); |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 121 | if (rc == 0) { |
Dominik Ermel | 864d104 | 2022-07-12 12:41:39 +0000 | [diff] [blame] | 122 | zcbor_tstr_put_term(cs, tmpbuf); |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 123 | } else { |
Dominik Ermel | 864d104 | 2022-07-12 12:41:39 +0000 | [diff] [blame] | 124 | zcbor_tstr_put_lit(cs, ""); |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 125 | } |
| 126 | } |
| 127 | } |
| 128 | |
Dominik Ermel | 864d104 | 2022-07-12 12:41:39 +0000 | [diff] [blame] | 129 | zcbor_tstr_put_lit(cs, "rc"); |
| 130 | zcbor_uint32_put(cs, MGMT_ERR_OK); |
| 131 | zcbor_map_end_encode(cs, 10); |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 132 | |
| 133 | return rc; |
| 134 | } |
| 135 | |
| 136 | #ifndef ZEPHYR_MGMT_GRP_BASIC_CMD_IMAGE_LIST |
| 137 | #define ZEPHYR_MGMT_GRP_BASIC_CMD_IMAGE_LIST 1 |
| 138 | #endif |
Andrzej Puzdrowski | 420ad9a | 2021-07-29 16:22:52 +0200 | [diff] [blame] | 139 | #endif /*MCUBOOT_MGMT_CUSTOM_IMG_LIST*/ |
| 140 | |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 141 | int bs_peruser_system_specific(const struct nmgr_hdr *hdr, const char *buffer, |
Dominik Ermel | 864d104 | 2022-07-12 12:41:39 +0000 | [diff] [blame] | 142 | int len, zcbor_state_t *cs) |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 143 | { |
| 144 | int mgmt_rc = MGMT_ERR_ENOTSUP; |
| 145 | |
Jamie McCrae | e188dbb | 2023-08-29 07:43:16 +0100 | [diff] [blame] | 146 | if (hdr->nh_group == ZEPHYR_MGMT_GRP_BASIC) { |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 147 | if (hdr->nh_op == NMGR_OP_WRITE) { |
Dominik Ermel | 0435d5d | 2021-08-16 15:58:15 +0000 | [diff] [blame] | 148 | #ifdef CONFIG_BOOT_MGMT_CUSTOM_STORAGE_ERASE |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 149 | if (hdr->nh_id == ZEPHYR_MGMT_GRP_BASIC_CMD_ERASE_STORAGE) { |
| 150 | mgmt_rc = bs_custom_storage_erase(cs); |
| 151 | } |
Dominik Ermel | 0435d5d | 2021-08-16 15:58:15 +0000 | [diff] [blame] | 152 | #endif |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 153 | } else if (hdr->nh_op == NMGR_OP_READ) { |
Andrzej Puzdrowski | 420ad9a | 2021-07-29 16:22:52 +0200 | [diff] [blame] | 154 | #ifdef MCUBOOT_MGMT_CUSTOM_IMG_LIST |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 155 | if (hdr->nh_id == ZEPHYR_MGMT_GRP_BASIC_CMD_IMAGE_LIST) { |
| 156 | mgmt_rc = bs_custom_img_list(cs); |
| 157 | } |
Andrzej Puzdrowski | 420ad9a | 2021-07-29 16:22:52 +0200 | [diff] [blame] | 158 | #endif |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 159 | } |
| 160 | } |
| 161 | |
| 162 | if (mgmt_rc == MGMT_ERR_ENOTSUP) { |
Dominik Ermel | 864d104 | 2022-07-12 12:41:39 +0000 | [diff] [blame] | 163 | zcbor_map_start_encode(cs, 10); |
| 164 | zcbor_tstr_put_lit(cs, "rc"); |
| 165 | zcbor_uint32_put(cs, mgmt_rc); |
| 166 | zcbor_map_end_encode(cs, 10); |
Andrzej Puzdrowski | 1b62cf2 | 2021-07-28 17:21:19 +0200 | [diff] [blame] | 167 | } |
| 168 | |
| 169 | return MGMT_ERR_OK; |
| 170 | } |