blob: 4c19d56ba167760fe94fd1750c10eb9c4f5a0f07 [file] [log] [blame]
Fabio Utzig12d59162019-11-28 10:01:59 -03001/*
David Brownaac71112020-02-03 16:13:42 -07002 * SPDX-License-Identifier: Apache-2.0
3 *
Fabio Utzig12d59162019-11-28 10:01:59 -03004 * Copyright (c) 2019 JUUL Labs
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19#include <assert.h>
20#include <stddef.h>
21#include <stdbool.h>
22#include <inttypes.h>
23#include <stdlib.h>
24#include <string.h>
25#include "bootutil/bootutil.h"
26#include "bootutil_priv.h"
27#include "swap_priv.h"
28#include "bootutil/bootutil_log.h"
29
30#include "mcuboot_config/mcuboot_config.h"
31
32MCUBOOT_LOG_MODULE_DECLARE(mcuboot);
33
34#if defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE)
35
36int
37swap_erase_trailer_sectors(const struct boot_loader_state *state,
38 const struct flash_area *fap)
39{
40 uint8_t slot;
41 uint32_t sector;
42 uint32_t trailer_sz;
43 uint32_t total_sz;
44 uint32_t off;
45 uint32_t sz;
46 int fa_id_primary;
47 int fa_id_secondary;
48 uint8_t image_index;
49 int rc;
50
51 BOOT_LOG_DBG("erasing trailer; fa_id=%d", fap->fa_id);
52
53 image_index = BOOT_CURR_IMG(state);
54 fa_id_primary = flash_area_id_from_multi_image_slot(image_index,
55 BOOT_PRIMARY_SLOT);
56 fa_id_secondary = flash_area_id_from_multi_image_slot(image_index,
57 BOOT_SECONDARY_SLOT);
58
59 if (fap->fa_id == fa_id_primary) {
60 slot = BOOT_PRIMARY_SLOT;
61 } else if (fap->fa_id == fa_id_secondary) {
62 slot = BOOT_SECONDARY_SLOT;
63 } else {
64 return BOOT_EFLASH;
65 }
66
67 /* delete starting from last sector and moving to beginning */
68 sector = boot_img_num_sectors(state, slot) - 1;
69 trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state));
70 total_sz = 0;
71 do {
72 sz = boot_img_sector_size(state, slot, sector);
73 off = boot_img_sector_off(state, slot, sector);
74 rc = boot_erase_region(fap, off, sz);
75 assert(rc == 0);
76
77 sector--;
78 total_sz += sz;
79 } while (total_sz < trailer_sz);
80
81 return rc;
82}
83
84int
85swap_status_init(const struct boot_loader_state *state,
86 const struct flash_area *fap,
87 const struct boot_status *bs)
88{
89 struct boot_swap_state swap_state;
90 uint8_t image_index;
91 int rc;
92
93#if (BOOT_IMAGE_NUMBER == 1)
94 (void)state;
95#endif
96
97 image_index = BOOT_CURR_IMG(state);
98
99 BOOT_LOG_DBG("initializing status; fa_id=%d", fap->fa_id);
100
101 rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_SECONDARY(image_index),
102 &swap_state);
103 assert(rc == 0);
104
105 if (bs->swap_type != BOOT_SWAP_TYPE_NONE) {
106 rc = boot_write_swap_info(fap, bs->swap_type, image_index);
107 assert(rc == 0);
108 }
109
110 if (swap_state.image_ok == BOOT_FLAG_SET) {
111 rc = boot_write_image_ok(fap);
112 assert(rc == 0);
113 }
114
115 rc = boot_write_swap_size(fap, bs->swap_size);
116 assert(rc == 0);
117
118#ifdef MCUBOOT_ENC_IMAGES
Fabio Utzig4741c452019-12-19 15:32:41 -0300119 rc = boot_write_enc_key(fap, 0, bs);
Fabio Utzig12d59162019-11-28 10:01:59 -0300120 assert(rc == 0);
121
Fabio Utzig4741c452019-12-19 15:32:41 -0300122 rc = boot_write_enc_key(fap, 1, bs);
Fabio Utzig12d59162019-11-28 10:01:59 -0300123 assert(rc == 0);
124#endif
125
126 rc = boot_write_magic(fap);
127 assert(rc == 0);
128
129 return 0;
130}
131
132int
133swap_read_status(struct boot_loader_state *state, struct boot_status *bs)
134{
135 const struct flash_area *fap;
136 uint32_t off;
137 uint8_t swap_info;
Fabio Utzig12d59162019-11-28 10:01:59 -0300138 int area_id;
139 int rc;
140
Fabio Utzigb86e6882019-12-10 09:51:17 -0300141 bs->source = swap_status_source(state);
142 switch (bs->source) {
Fabio Utzig12d59162019-11-28 10:01:59 -0300143 case BOOT_STATUS_SOURCE_NONE:
144 return 0;
145
146#if MCUBOOT_SWAP_USING_SCRATCH
147 case BOOT_STATUS_SOURCE_SCRATCH:
148 area_id = FLASH_AREA_IMAGE_SCRATCH;
149 break;
150#endif
151
152 case BOOT_STATUS_SOURCE_PRIMARY_SLOT:
153 area_id = FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state));
154 break;
155
156 default:
157 assert(0);
158 return BOOT_EBADARGS;
159 }
160
161 rc = flash_area_open(area_id, &fap);
162 if (rc != 0) {
163 return BOOT_EFLASH;
164 }
165
166 rc = swap_read_status_bytes(fap, state, bs);
167 if (rc == 0) {
168 off = boot_swap_info_off(fap);
169 rc = flash_area_read_is_empty(fap, off, &swap_info, sizeof swap_info);
170 if (rc == 1) {
171 BOOT_SET_SWAP_INFO(swap_info, 0, BOOT_SWAP_TYPE_NONE);
172 rc = 0;
173 }
174
175 /* Extract the swap type info */
176 bs->swap_type = BOOT_GET_SWAP_TYPE(swap_info);
177 }
178
179 flash_area_close(fap);
180
181 return rc;
182}
183
184int
185swap_set_copy_done(uint8_t image_index)
186{
187 const struct flash_area *fap;
188 int rc;
189
190 rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(image_index),
191 &fap);
192 if (rc != 0) {
193 return BOOT_EFLASH;
194 }
195
196 rc = boot_write_copy_done(fap);
197 flash_area_close(fap);
198 return rc;
199}
200
201int
202swap_set_image_ok(uint8_t image_index)
203{
204 const struct flash_area *fap;
205 struct boot_swap_state state;
206 int rc;
207
208 rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(image_index),
209 &fap);
210 if (rc != 0) {
211 return BOOT_EFLASH;
212 }
213
214 rc = boot_read_swap_state(fap, &state);
215 if (rc != 0) {
216 rc = BOOT_EFLASH;
217 goto out;
218 }
219
220 if (state.image_ok == BOOT_FLAG_UNSET) {
221 rc = boot_write_image_ok(fap);
222 }
223
224out:
225 flash_area_close(fap);
226 return rc;
227}
228
229
230#endif /* defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE) */