blob: 6b9d33b9193afae1b0845b4007f81b046f82cb57 [file] [log] [blame]
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +02001/*
2 * SPDX-License-Identifier: Apache-2.0
3 *
4 * Copyright (c) 2017-2019 Linaro LTD
5 * Copyright (c) 2016-2019 JUUL Labs
6 * Copyright (c) 2019-2020 Arm Limited
7 * Copyright (c) 2020 Cypress Semiconductors
8 *
9 * Original license:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one
12 * or more contributor license agreements. See the NOTICE file
13 * distributed with this work for additional information
14 * regarding copyright ownership. The ASF licenses this file
15 * to you under the Apache License, Version 2.0 (the
16 * "License"); you may not use this file except in compliance
17 * with the License. You may obtain a copy of the License at
18 *
19 * http://www.apache.org/licenses/LICENSE-2.0
20 *
21 * Unless required by applicable law or agreed to in writing,
22 * software distributed under the License is distributed on an
23 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
24 * KIND, either express or implied. See the License for the
25 * specific language governing permissions and limitations
26 * under the License.
27 */
28
29#include <assert.h>
30#include <stddef.h>
31#include <stdbool.h>
32#include <inttypes.h>
33#include <stdlib.h>
34#include <string.h>
35#include "bootutil/bootutil.h"
36#include "bootutil_priv.h"
37#include "swap_priv.h"
38#include "swap_status.h"
39#include "bootutil/bootutil_log.h"
40
41#include "mcuboot_config/mcuboot_config.h"
42
43MCUBOOT_LOG_MODULE_DECLARE(mcuboot);
44
45#ifdef MCUBOOT_SWAP_USING_STATUS
46
47#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)
48int
49swap_read_status_bytes(const struct flash_area *fap,
50 struct boot_loader_state *state, struct boot_status *bs)
51{
52 uint32_t off;
53 uint8_t status = 0;
54 uint8_t last_status = 0xff;
55 int max_entries;
56 int32_t found_idx;
57 bool found;
58 bool invalid;
59 int rc;
60 int i;
61 (void)state;
62
63 BOOT_LOG_DBG("> STATUS: swap_read_status_bytes: fa_id = %d", fap->fa_id);
64
65 if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
66 max_entries = 1;
67 } else {
68 max_entries = BOOT_STATUS_MAX_ENTRIES;
69 }
70
71 off = boot_status_off(fap);
72
73 found = false;
74 found_idx = -1;
75 invalid = false;
76
77 for (i = 0; i < max_entries; i++) {
78 rc = swap_status_retrieve(fap->fa_id, off + i, &status, 1);
79 if (rc < 0) {
80 return BOOT_EFLASH;
81 }
82
83 // if (status != flash_area_erased_val(fap)) { // TODO: fixup for external memory fap's
84 if (status == 0) {
85 if (found && (found_idx == -1)) {
86 found_idx = i;
87 }
88 } else {
89 last_status = status;
90
91 if (!found) {
92 found = true;
93 } else if (found_idx > 0) {
94 invalid = true;
95 break;
96 }
97 }
98 }
99
100 if (invalid) {
101 /* This means there was an error writing status on the last
102 * swap. Tell user and move on to validation!
103 */
104#if !defined(__BOOTSIM__)
105 BOOT_LOG_ERR("Detected inconsistent status!");
106#endif
107
108#if !defined(MCUBOOT_VALIDATE_PRIMARY_SLOT)
109 /* With validation of the primary slot disabled, there is no way
110 * to be sure the swapped primary slot is OK, so abort!
111 */
112 assert(0);
113#endif
114 }
115
116 if (found_idx == -1) {
117 /* no swap status found; nothing to do */
118 }
119 else {
120 uint8_t image_index = BOOT_CURR_IMG(state);
121 rc = boot_read_swap_size((int32_t)image_index, &bs->swap_size);
122 if (rc < 0) {
123 return BOOT_EFLASH;
124 }
125
126#ifdef MCUBOOT_SWAP_USING_MOVE
127 /* get image size in blocks */
128 uint32_t move_entries = bs->swap_size / state->write_sz + (uint32_t)(bs->swap_size % state->write_sz != 0u);
129
130 if (found_idx < (int32_t)move_entries) {
131 /* continue move sector up operation */
132 bs->op = (uint8_t)BOOT_STATUS_OP_MOVE;
133 bs->idx = (uint32_t)found_idx;
134 bs->state = (uint8_t)last_status;
135 } else
136#endif /* MCUBOOT_SWAP_USING_MOVE */
137 {
138 /* resume swap sectors operation */
139 last_status++;
140 if (last_status > BOOT_STATUS_STATE_COUNT) {
141 last_status = BOOT_STATUS_STATE_0;
142 found_idx++;
143 }
144
145 bs->op = (uint8_t)BOOT_STATUS_OP_SWAP;
146 bs->idx = (uint32_t)found_idx;
147 bs->state = (uint8_t)last_status;
148 }
149 }
150
151 return 0;
152}
153
154/* this is internal offset in swap status area */
155uint32_t
156boot_status_internal_off(const struct boot_status *bs, int elem_sz)
157{
158 uint32_t off = (bs->idx - BOOT_STATUS_IDX_0) * (uint32_t)elem_sz;
159
160 return off;
161}
162#endif /* !MCUBOOT_DIRECT_XIP && !MCUBOOT_RAM_LOAD */
163
164#endif /* MCUBOOT_SWAP_USING_STATUS */