1 /*
2 * Copyright (c) 2020 Grinn
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "bootutil/bootutil_public.h"
8 #include <zephyr/dfu/mcuboot.h>
9 #include <zephyr/init.h>
10 #include <zephyr/shell/shell.h>
11 #include <stdlib.h>
12
13 #include "mcuboot_priv.h"
14
15 #ifdef CONFIG_RETENTION_BOOT_MODE
16 #include <zephyr/retention/bootmode.h>
17 #ifdef CONFIG_REBOOT
18 #include <zephyr/sys/reboot.h>
19 #endif
20 #endif
21
22 struct area_desc {
23 const char *name;
24 unsigned int id;
25 };
26
27 static const struct area_desc areas[] = {
28 {"primary", FLASH_AREA_IMAGE_PRIMARY},
29 #ifdef FLASH_AREA_IMAGE_SECONDARY
30 {"secondary", FLASH_AREA_IMAGE_SECONDARY},
31 #endif
32 };
33
swap_state_magic_str(uint8_t magic)34 static const char *swap_state_magic_str(uint8_t magic)
35 {
36 switch (magic) {
37 case BOOT_MAGIC_GOOD:
38 return "good";
39 case BOOT_MAGIC_BAD:
40 return "bad";
41 case BOOT_MAGIC_UNSET:
42 return "unset";
43 case BOOT_MAGIC_ANY:
44 return "any";
45 case BOOT_MAGIC_NOTGOOD:
46 return "notgood";
47 }
48
49 return "unknown";
50 }
51
swap_type_str(uint8_t type)52 static const char *swap_type_str(uint8_t type)
53 {
54 switch (type) {
55 case BOOT_SWAP_TYPE_NONE:
56 return "none";
57 case BOOT_SWAP_TYPE_TEST:
58 return "test";
59 case BOOT_SWAP_TYPE_PERM:
60 return "perm";
61 case BOOT_SWAP_TYPE_REVERT:
62 return "revert";
63 case BOOT_SWAP_TYPE_FAIL:
64 return "fail";
65 }
66
67 return "unknown";
68 }
69
swap_state_flag_str(uint8_t flag)70 static const char *swap_state_flag_str(uint8_t flag)
71 {
72 switch (flag) {
73 case BOOT_FLAG_SET:
74 return "set";
75 case BOOT_FLAG_BAD:
76 return "bad";
77 case BOOT_FLAG_UNSET:
78 return "unset";
79 case BOOT_FLAG_ANY:
80 return "any";
81 }
82
83 return "unknown";
84 }
85
cmd_mcuboot_erase(const struct shell * sh,size_t argc,char ** argv)86 static int cmd_mcuboot_erase(const struct shell *sh, size_t argc,
87 char **argv)
88 {
89 unsigned int id;
90 int err;
91
92 id = strtoul(argv[1], NULL, 0);
93
94 err = boot_erase_img_bank(id);
95 if (err) {
96 shell_error(sh, "failed to erase bank %u", id);
97 return err;
98 }
99
100 return 0;
101 }
102
cmd_mcuboot_confirm(const struct shell * sh,size_t argc,char ** argv)103 static int cmd_mcuboot_confirm(const struct shell *sh, size_t argc,
104 char **argv)
105 {
106 int err;
107
108 err = boot_write_img_confirmed();
109 if (err) {
110 shell_error(sh, "failed to confirm: %d", err);
111 }
112
113 return err;
114 }
115
cmd_mcuboot_request_upgrade(const struct shell * sh,size_t argc,char ** argv)116 static int cmd_mcuboot_request_upgrade(const struct shell *sh, size_t argc,
117 char **argv)
118 {
119 int permanent = 0;
120 int err;
121
122 if (argc > 1) {
123 if (!strcmp(argv[1], "permanent")) {
124 permanent = 1;
125 } else {
126 shell_warn(sh, "invalid argument!");
127 return -EINVAL;
128 }
129 }
130
131 err = boot_request_upgrade(permanent);
132 if (err) {
133 shell_error(sh, "failed to request upgrade: %d", err);
134 }
135
136 return err;
137 }
138
139 #ifdef CONFIG_RETENTION_BOOT_MODE
cmd_mcuboot_serial_recovery(const struct shell * sh,size_t argc,char ** argv)140 static int cmd_mcuboot_serial_recovery(const struct shell *sh, size_t argc,
141 char **argv)
142 {
143 int rc;
144
145 rc = bootmode_set(BOOT_MODE_TYPE_BOOTLOADER);
146
147 if (rc) {
148 shell_error(sh, "Failed to set serial recovery mode: %d", rc);
149
150 return rc;
151 }
152
153 #ifdef CONFIG_REBOOT
154 sys_reboot(SYS_REBOOT_COLD);
155 #else
156 shell_error(sh, "mcuboot serial recovery mode set, please reboot your device");
157 #endif
158
159 return rc;
160 }
161 #endif
162
cmd_mcuboot_info_area(const struct shell * sh,const struct area_desc * area)163 static int cmd_mcuboot_info_area(const struct shell *sh,
164 const struct area_desc *area)
165 {
166 struct mcuboot_img_header hdr;
167 struct boot_swap_state swap_state;
168 int err;
169
170 err = boot_read_bank_header(area->id, &hdr, sizeof(hdr));
171 if (err) {
172 shell_error(sh, "failed to read %s area (%u) %s: %d",
173 area->name, area->id, "header", err);
174 return err;
175 }
176
177 shell_print(sh, "%s area (%u):", area->name, area->id);
178 shell_print(sh, " version: %u.%u.%u+%u",
179 (unsigned int) hdr.h.v1.sem_ver.major,
180 (unsigned int) hdr.h.v1.sem_ver.minor,
181 (unsigned int) hdr.h.v1.sem_ver.revision,
182 (unsigned int) hdr.h.v1.sem_ver.build_num);
183 shell_print(sh, " image size: %u",
184 (unsigned int) hdr.h.v1.image_size);
185
186 err = boot_read_swap_state_by_id(area->id, &swap_state);
187 if (err) {
188 shell_error(sh, "failed to read %s area (%u) %s: %d",
189 area->name, area->id, "swap state", err);
190 return err;
191 }
192
193 shell_print(sh, " magic: %s",
194 swap_state_magic_str(swap_state.magic));
195
196 if (IS_ENABLED(CONFIG_MCUBOOT_TRAILER_SWAP_TYPE)) {
197 shell_print(sh, " swap type: %s",
198 swap_type_str(swap_state.swap_type));
199 }
200
201 shell_print(sh, " copy done: %s",
202 swap_state_flag_str(swap_state.copy_done));
203 shell_print(sh, " image ok: %s",
204 swap_state_flag_str(swap_state.image_ok));
205
206 return 0;
207 }
208
cmd_mcuboot_info(const struct shell * sh,size_t argc,char ** argv)209 static int cmd_mcuboot_info(const struct shell *sh, size_t argc,
210 char **argv)
211 {
212 int i;
213
214 shell_print(sh, "swap type: %s", swap_type_str(mcuboot_swap_type()));
215 shell_print(sh, "confirmed: %d", boot_is_img_confirmed());
216
217 for (i = 0; i < ARRAY_SIZE(areas); i++) {
218 shell_print(sh, "");
219 cmd_mcuboot_info_area(sh, &areas[i]);
220 }
221
222 return 0;
223 }
224
225 SHELL_STATIC_SUBCMD_SET_CREATE(mcuboot_cmds,
226 SHELL_CMD_ARG(confirm, NULL, "confirm", cmd_mcuboot_confirm, 1, 0),
227 SHELL_CMD_ARG(erase, NULL, "erase <area_id>", cmd_mcuboot_erase, 2, 0),
228 SHELL_CMD_ARG(request_upgrade, NULL, "request_upgrade [permanent]",
229 cmd_mcuboot_request_upgrade, 1, 1),
230 #ifdef CONFIG_RETENTION_BOOT_MODE
231 SHELL_CMD_ARG(serial_recovery, NULL, "serial_recovery", cmd_mcuboot_serial_recovery, 1, 0),
232 #endif
233 SHELL_SUBCMD_SET_END /* Array terminated. */
234 );
235
236 SHELL_CMD_REGISTER(mcuboot, &mcuboot_cmds, "MCUboot commands",
237 cmd_mcuboot_info);
238