Implement new swap scheme for devices with large erase size using scratch with status area
diff --git a/boot/bootutil/src/swap_status.h b/boot/bootutil/src/swap_status.h
new file mode 100644
index 0000000..dc27d64
--- /dev/null
+++ b/boot/bootutil/src/swap_status.h
@@ -0,0 +1,167 @@
+/*
+ * 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"), \
+ (state)->swap_type, \
+ (state)->copy_done, \
+ (state)->image_ok)
+
+#define BOOT_SET_SWAP_INFO_M(swap_info, image, type) { \
+ assert((int)((image) < 0xFu)); \
+ assert((int)((type) < 0xFu)); \
+ (swap_info) = (image) << 4u \
+ | (type); \
+ }
+
+#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 (0xDEADBEAFu)
+
+#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 CY_FLASH_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)
+
+int32_t swap_status_init_offset(uint32_t area_id);
+int swap_status_update(uint32_t target_area_id, uint32_t offs, const void *data, uint32_t len);
+int swap_status_retrieve(uint32_t target_area_id, uint32_t offs, void *data, uint32_t len);
+
+int boot_write_trailer(const struct flash_area *fap, uint32_t off,
+ const uint8_t *inbuf, uint8_t inlen);
+
+#endif /* MCUBOOT_SWAP_USING_STATUS */
+
+#endif /* H_SWAP_STATUS_H_ */