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