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