1 /*
2 * Copyright (c) 2017 Nordic Semiconductor ASA
3 * Copyright (c) 2016-2017 Linaro Limited
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <stddef.h>
9 #include <errno.h>
10 #include <string.h>
11 #include <drivers/flash.h>
12 #include <storage/flash_map.h>
13 #include <zephyr.h>
14 #include <init.h>
15
16 #include <sys/__assert.h>
17 #include <sys/byteorder.h>
18
19 #include "bootutil/bootutil_public.h"
20 #include <dfu/mcuboot.h>
21
22 #include "mcuboot_priv.h"
23
24 /*
25 * Helpers for image headers and trailers, as defined by mcuboot.
26 */
27
28 /*
29 * Strict defines: the definitions in the following block contain
30 * values which are MCUboot implementation requirements.
31 */
32
33 /* Header: */
34 #define BOOT_HEADER_MAGIC_V1 0x96f3b83d
35 #define BOOT_HEADER_SIZE_V1 32
36
37 /*
38 * Raw (on-flash) representation of the v1 image header.
39 */
40 struct mcuboot_v1_raw_header {
41 uint32_t header_magic;
42 uint32_t image_load_address;
43 uint16_t header_size;
44 uint16_t pad;
45 uint32_t image_size;
46 uint32_t image_flags;
47 struct {
48 uint8_t major;
49 uint8_t minor;
50 uint16_t revision;
51 uint32_t build_num;
52 } version;
53 uint32_t pad2;
54 } __packed;
55
56 /*
57 * End of strict defines
58 */
59
boot_read_v1_header(uint8_t area_id,struct mcuboot_v1_raw_header * v1_raw)60 static int boot_read_v1_header(uint8_t area_id,
61 struct mcuboot_v1_raw_header *v1_raw)
62 {
63 const struct flash_area *fa;
64 int rc;
65
66 rc = flash_area_open(area_id, &fa);
67 if (rc) {
68 return rc;
69 }
70
71 /*
72 * Read and sanity-check the raw header.
73 */
74 rc = flash_area_read(fa, 0, v1_raw, sizeof(*v1_raw));
75 flash_area_close(fa);
76 if (rc) {
77 return rc;
78 }
79
80 v1_raw->header_magic = sys_le32_to_cpu(v1_raw->header_magic);
81 v1_raw->image_load_address =
82 sys_le32_to_cpu(v1_raw->image_load_address);
83 v1_raw->header_size = sys_le16_to_cpu(v1_raw->header_size);
84 v1_raw->image_size = sys_le32_to_cpu(v1_raw->image_size);
85 v1_raw->image_flags = sys_le32_to_cpu(v1_raw->image_flags);
86 v1_raw->version.revision =
87 sys_le16_to_cpu(v1_raw->version.revision);
88 v1_raw->version.build_num =
89 sys_le32_to_cpu(v1_raw->version.build_num);
90
91 /*
92 * Sanity checks.
93 *
94 * Larger values in header_size than BOOT_HEADER_SIZE_V1 are
95 * possible, e.g. if Zephyr was linked with
96 * CONFIG_ROM_START_OFFSET > BOOT_HEADER_SIZE_V1.
97 */
98 if ((v1_raw->header_magic != BOOT_HEADER_MAGIC_V1) ||
99 (v1_raw->header_size < BOOT_HEADER_SIZE_V1)) {
100 return -EIO;
101 }
102
103 return 0;
104 }
105
boot_read_bank_header(uint8_t area_id,struct mcuboot_img_header * header,size_t header_size)106 int boot_read_bank_header(uint8_t area_id,
107 struct mcuboot_img_header *header,
108 size_t header_size)
109 {
110 int rc;
111 struct mcuboot_v1_raw_header v1_raw;
112 struct mcuboot_img_sem_ver *sem_ver;
113 size_t v1_min_size = (sizeof(uint32_t) +
114 sizeof(struct mcuboot_img_header_v1));
115
116 /*
117 * Only version 1 image headers are supported.
118 */
119 if (header_size < v1_min_size) {
120 return -ENOMEM;
121 }
122 rc = boot_read_v1_header(area_id, &v1_raw);
123 if (rc) {
124 return rc;
125 }
126
127 /*
128 * Copy just the fields we care about into the return parameter.
129 *
130 * - header_magic: skip (only used to check format)
131 * - image_load_address: skip (only matters for PIC code)
132 * - header_size: skip (only used to check format)
133 * - image_size: include
134 * - image_flags: skip (all unsupported or not relevant)
135 * - version: include
136 */
137 header->mcuboot_version = 1U;
138 header->h.v1.image_size = v1_raw.image_size;
139 sem_ver = &header->h.v1.sem_ver;
140 sem_ver->major = v1_raw.version.major;
141 sem_ver->minor = v1_raw.version.minor;
142 sem_ver->revision = v1_raw.version.revision;
143 sem_ver->build_num = v1_raw.version.build_num;
144 return 0;
145 }
146
mcuboot_swap_type_multi(int image_index)147 int mcuboot_swap_type_multi(int image_index)
148 {
149 return boot_swap_type_multi(image_index);
150 }
151
mcuboot_swap_type(void)152 int mcuboot_swap_type(void)
153 {
154 #ifdef FLASH_AREA_IMAGE_SECONDARY
155 return boot_swap_type();
156 #else
157 return BOOT_SWAP_TYPE_NONE;
158 #endif
159
160 }
161
boot_request_upgrade(int permanent)162 int boot_request_upgrade(int permanent)
163 {
164 #ifdef FLASH_AREA_IMAGE_SECONDARY
165 int rc;
166
167 rc = boot_set_pending(permanent);
168 if (rc) {
169 return -EFAULT;
170 }
171 #endif /* FLASH_AREA_IMAGE_SECONDARY */
172 return 0;
173 }
174
boot_request_upgrade_multi(int image_index,int permanent)175 int boot_request_upgrade_multi(int image_index, int permanent)
176 {
177 int rc;
178
179 rc = boot_set_pending_multi(image_index, permanent);
180 if (rc) {
181 return -EFAULT;
182 }
183 return 0;
184 }
185
boot_is_img_confirmed(void)186 bool boot_is_img_confirmed(void)
187 {
188 const struct flash_area *fa;
189 int rc;
190 uint8_t flag_val;
191
192 rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY, &fa);
193 if (rc) {
194 return false;
195 }
196
197 rc = boot_read_image_ok(fa, &flag_val);
198 if (rc) {
199 return false;
200 }
201
202 return flag_val == BOOT_FLAG_SET;
203 }
204
boot_write_img_confirmed(void)205 int boot_write_img_confirmed(void)
206 {
207 int rc;
208
209 rc = boot_set_confirmed();
210 if (rc) {
211 return -EIO;
212 }
213
214 return 0;
215 }
216
boot_write_img_confirmed_multi(int image_index)217 int boot_write_img_confirmed_multi(int image_index)
218 {
219 int rc;
220
221 rc = boot_set_confirmed_multi(image_index);
222 if (rc) {
223 return -EIO;
224 }
225
226 return 0;
227 }
228
boot_erase_img_bank(uint8_t area_id)229 int boot_erase_img_bank(uint8_t area_id)
230 {
231 const struct flash_area *fa;
232 int rc;
233
234 rc = flash_area_open(area_id, &fa);
235 if (rc) {
236 return rc;
237 }
238
239 rc = flash_area_erase(fa, 0, fa->fa_size);
240
241 flash_area_close(fa);
242
243 return rc;
244 }
245