blob: 9cc83626e8716b1a16e3004b49ce52c8c8508fde [file] [log] [blame]
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2017-2019 Linaro LTD
* Copyright (c) 2016-2019 JUUL Labs
* Copyright (c) 2019-2020 Arm Limited
* Copyright (c) 2020 Cypress Semiconductors
*
* Original license:
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef H_SWAP_STATUS_H_
#define H_SWAP_STATUS_H_
#include <stdint.h>
#include "sysflash/sysflash.h"
#include "bootutil_priv.h"
#include "mcuboot_config/mcuboot_config.h"
#ifdef MCUBOOT_SWAP_USING_STATUS
#define BOOT_LOG_SWAP_STATE_M(area, state) \
BOOT_LOG_DBG("%s: magic=%s, swap_type=0x%x, copy_done=0x%x, image_ok=0x%x", \
(area), \
((state)->magic == (uint8_t)BOOT_MAGIC_GOOD ? "good" : \
(state)->magic == (uint8_t)BOOT_MAGIC_UNSET ? "unset" : \
"bad"), \
(unsigned)(state)->swap_type, \
(unsigned)(state)->copy_done, \
(unsigned)(state)->image_ok)
#define BOOT_SET_SWAP_INFO_M(swap_info, image, type) do { \
assert((image) < 0xFu); \
assert((type) < 0xFu); \
(swap_info) = (image) << 4u \
| (type); \
} while (false)
#define BOOT_GET_SWAP_TYPE_M(swap_info) ((swap_info) & 0x0Fu)
#define BOOT_GET_IMAGE_NUM_M(swap_info) ((swap_info) >> 4u)
extern const uint32_t stat_part_magic[1];
#define BOOT_SWAP_STATUS_MAGIC (0xDEADBEEFu)
#define BOOT_SWAP_STATUS_ENCK1_SZ 16UL
#define BOOT_SWAP_STATUS_ENCK2_SZ 16UL
struct image_status_trailer {
uint8_t enc_key1[BOOT_SWAP_STATUS_ENCK1_SZ];
uint8_t enc_key2[BOOT_SWAP_STATUS_ENCK2_SZ];
uint32_t swap_size;
uint8_t swap_type;
uint8_t copy_done;
uint8_t image_ok;
uint8_t magic[BOOT_MAGIC_SZ];
};
#define BOOT_SWAP_STATUS_SWAPSZ_SZ 4UL
#define BOOT_SWAP_STATUS_SWAPINF_SZ 1UL
#define BOOT_SWAP_STATUS_COPY_DONE_SZ 1UL
#define BOOT_SWAP_STATUS_IMG_OK_SZ 1UL
#define BOOT_SWAP_STATUS_MAGIC_SZ BOOT_MAGIC_SZ
#define BOOT_SWAP_STATUS_MGCREC_SZ 4UL
#define BOOT_SWAP_STATUS_CNT_SZ 4UL
#define BOOT_SWAP_STATUS_CRC_SZ 4UL
#define BOOT_SWAP_STATUS_ROW_SZ MEMORY_ALIGN
/* agreed to name it "a record" */
#define BOOT_SWAP_STATUS_PAYLD_SZ (BOOT_SWAP_STATUS_ROW_SZ -\
BOOT_SWAP_STATUS_MGCREC_SZ - \
BOOT_SWAP_STATUS_CNT_SZ - \
BOOT_SWAP_STATUS_CRC_SZ)
#define BOOT_SWAP_STATUS_ROW_SZ_MIN 16UL
/* INFO: defining record structure for better understanding */
struct status_part_record{
uint8_t payload[BOOT_SWAP_STATUS_PAYLD_SZ];
uint8_t magic[BOOT_SWAP_STATUS_MGCREC_SZ];
uint8_t counter[BOOT_SWAP_STATUS_CNT_SZ];
uint8_t crc[BOOT_SWAP_STATUS_CRC_SZ];
};
#if (BOOT_SWAP_STATUS_ROW_SZ % BOOT_SWAP_STATUS_ROW_SZ_MIN != 0)
#error "BOOT_SWAP_STATUS_ROW_SZ size is less then min value of 16 bytes"
#endif
/* number of rows sector-status area should fit into */
#define BOOT_SWAP_STATUS_SECT_ROWS_NUM (((BOOT_MAX_IMG_SECTORS-1u)/BOOT_SWAP_STATUS_PAYLD_SZ) + 1u)
/*
Number of flash rows used to store swap info. It consists
of following fields. 16 bytes is a minimum required row size,
thus 64 bytes required at minimum size of swap info size.
16 bytes - uint8_t enc_key1[BOOT_SWAP_STATUS_ENCK1_SZ];
16 bytes - uint8_t enc_key2[BOOT_SWAP_STATUS_ENCK2_SZ];
4 bytes - uint32_t swap_size;
1 byte - uint8_t swap_type;
1 byte - uint8_t copy_done;
1 byte - uint8_t image_ok;
16 bytes - uint8_t magic[BOOT_MAGIC_SZ];
= 55 bytes
*/
#define BOOT_SWAP_STATUS_TRAILER_SIZE 64UL
// TODO: check if min write size is 64 or larger
// TODO: small-magic, coutner and crc aren't coutned here
/* number of rows trailer data should fit into */
#define BOOT_SWAP_STATUS_TRAIL_ROWS_NUM (((BOOT_SWAP_STATUS_TRAILER_SIZE - 1u)/BOOT_SWAP_STATUS_PAYLD_SZ) + 1u)
/* the size of one copy of status area */
#define BOOT_SWAP_STATUS_D_SIZE (BOOT_SWAP_STATUS_ROW_SZ * \
(BOOT_SWAP_STATUS_SECT_ROWS_NUM + \
BOOT_SWAP_STATUS_TRAIL_ROWS_NUM))
/* the size of one copy of status area without cnt and crc fields */
#define BOOT_SWAP_STATUS_D_SIZE_RAW (BOOT_SWAP_STATUS_PAYLD_SZ * \
(BOOT_SWAP_STATUS_SECT_ROWS_NUM + \
BOOT_SWAP_STATUS_TRAIL_ROWS_NUM))
/* multiplier which defines how many blocks will be used to reduce Flash wear
* 1 is for single write wear, 2 - twice less wear, 3 - three times less wear, etc */
#define BOOT_SWAP_STATUS_MULT 2UL
#define BOOT_SWAP_STATUS_SIZE (BOOT_SWAP_STATUS_MULT * BOOT_SWAP_STATUS_D_SIZE)
#define BOOT_SWAP_STATUS_SZ_PRIM BOOT_SWAP_STATUS_SIZE
#define BOOT_SWAP_STATUS_SZ_SEC BOOT_SWAP_STATUS_SIZE
#define BOOT_SWAP_STATUS_SZ_SCRATCH BOOT_SWAP_STATUS_SIZE
#define BOOT_SWAP_STATUS_OFFS_PRIM 0UL
#define BOOT_SWAP_STATUS_OFFS_SEC (BOOT_SWAP_STATUS_OFFS_PRIM + \
BOOT_SWAP_STATUS_SZ_PRIM)
/* size Limit for primary slot trailer buffer */
#define MAX_TRAILER_BUF_SIZE PLATFORM_MAX_TRAILER_PAGE_SIZE
int32_t swap_status_init_offset(uint8_t area_id);
int swap_status_update(uint8_t target_area_id, uint32_t offs, const void *data, uint32_t len);
int swap_status_retrieve(uint8_t target_area_id, uint32_t offs, void *data, uint32_t len);
int swap_status_to_image_trailer(const struct flash_area *fap);
#endif /* MCUBOOT_SWAP_USING_STATUS */
#endif /* H_SWAP_STATUS_H_ */