Implement new swap scheme for devices with large erase size using scratch with status area
diff --git a/boot/bootutil/include/bootutil/bootutil.h b/boot/bootutil/include/bootutil/bootutil.h
index b45334a..cf08a59 100644
--- a/boot/bootutil/include/bootutil/bootutil.h
+++ b/boot/bootutil/include/bootutil/bootutil.h
@@ -72,6 +72,12 @@
struct boot_loader_state;
fih_int context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp);
+int boot_swap_type_multi(int image_index);
+int boot_swap_type(void);
+
+int boot_set_pending(int permanent);
+int boot_set_confirmed(void);
+
#define SPLIT_GO_OK (0)
#define SPLIT_GO_NON_MATCHING (-1)
#define SPLIT_GO_ERR (-2)
diff --git a/boot/bootutil/include/bootutil/caps.h b/boot/bootutil/include/bootutil/caps.h
index 8ead3be..77182a1 100644
--- a/boot/bootutil/include/bootutil/caps.h
+++ b/boot/bootutil/include/bootutil/caps.h
@@ -47,6 +47,7 @@
#define BOOTUTIL_CAP_DOWNGRADE_PREVENTION (1<<12)
#define BOOTUTIL_CAP_ENC_X25519 (1<<13)
#define BOOTUTIL_CAP_BOOTSTRAP (1<<14)
+#define BOOTUTIL_CAP_SWAP_USING_STATUS (1<<15)
/*
* Query the number of images this bootloader is configured for. This
diff --git a/boot/bootutil/include/bootutil/enc_key.h b/boot/bootutil/include/bootutil/enc_key.h
index 779b0d4..1de6f81 100644
--- a/boot/bootutil/include/bootutil/enc_key.h
+++ b/boot/bootutil/include/bootutil/enc_key.h
@@ -45,6 +45,7 @@
struct enc_key_data {
uint8_t valid;
+ uint8_t aes_iv[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE];
bootutil_aes_ctr_context aes_ctr;
};
@@ -58,7 +59,7 @@
int boot_enc_load(struct enc_key_data *enc_state, int image_index,
const struct image_header *hdr, const struct flash_area *fap,
struct boot_status *bs);
-int boot_enc_decrypt(const uint8_t *buf, uint8_t *enckey);
+int boot_enc_decrypt(const uint8_t *buf, uint8_t *enckey, uint32_t sz, uint8_t *enciv);
bool boot_enc_valid(struct enc_key_data *enc_state, int image_index,
const struct flash_area *fap);
void boot_encrypt(struct enc_key_data *enc_state, int image_index,
diff --git a/boot/bootutil/src/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c
index 9ee317f..221d8a6 100644
--- a/boot/bootutil/src/bootutil_misc.c
+++ b/boot/bootutil/src/bootutil_misc.c
@@ -41,6 +41,12 @@
#include "bootutil/enc_key.h"
#endif
+#ifdef MCUBOOT_SWAP_USING_STATUS
+#include "swap_status.h"
+#endif
+
+#include "mcuboot_config/mcuboot_config.h"
+
MCUBOOT_LOG_MODULE_DECLARE(mcuboot);
/* Currently only used by imgmgr */
@@ -134,6 +140,7 @@
return -1;
}
+#ifndef MCUBOOT_SWAP_USING_STATUS
uint32_t
boot_status_off(const struct flash_area *fap)
{
@@ -147,6 +154,7 @@
assert(off_from_end <= fap->fa_size);
return fap->fa_size - off_from_end;
}
+#endif
static inline uint32_t
boot_magic_off(const struct flash_area *fap)
@@ -154,6 +162,8 @@
return fap->fa_size - BOOT_MAGIC_SZ;
}
+#ifndef MCUBOOT_SWAP_USING_STATUS
+
static inline uint32_t
boot_image_ok_off(const struct flash_area *fap)
{
@@ -171,6 +181,7 @@
{
return boot_swap_info_off(fap) - BOOT_MAX_ALIGN;
}
+#endif /* !MCUBOOT_SWAP_USING_STATUS */
#ifdef MCUBOOT_ENC_IMAGES
static inline uint32_t
@@ -185,6 +196,7 @@
}
#endif
+#ifndef MCUBOOT_SWAP_USING_STATUS
/**
* This functions tries to locate the status area after an aborted swap,
* by looking for the magic in the possible locations.
@@ -272,6 +284,8 @@
if (rc == 0) {
off = boot_enc_key_off(fap, slot);
#if MCUBOOT_SWAP_SAVE_ENCTLV
+ uint8_t aes_iv[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE];
+
rc = flash_area_read(fap, off, bs->enctlv[slot], BOOT_ENC_TLV_ALIGN_SIZE);
if (rc == 0) {
for (i = 0; i < BOOT_ENC_TLV_ALIGN_SIZE; i++) {
@@ -281,7 +295,7 @@
}
/* Only try to decrypt non-erased TLV metadata */
if (i != BOOT_ENC_TLV_ALIGN_SIZE) {
- rc = boot_enc_decrypt(bs->enctlv[slot], bs->enckey[slot]);
+ rc = boot_enc_decrypt(bs->enctlv[slot], bs->enckey[slot], 0, aes_iv);
}
}
#else
@@ -294,6 +308,8 @@
}
#endif
+#endif /* !MCUBOOT_SWAP_USING_STATUS */
+
int
boot_write_copy_done(const struct flash_area *fap)
{
@@ -318,6 +334,8 @@
return boot_write_trailer(fap, off, (const uint8_t *) &swap_size, 4);
}
+#ifndef MCUBOOT_SWAP_USING_STATUS
+
#ifdef MCUBOOT_ENC_IMAGES
int
boot_write_enc_key(const struct flash_area *fap, uint8_t slot,
@@ -342,3 +360,5 @@
return 0;
}
#endif
+
+#endif /* !MCUBOOT_SWAP_USING_STATUS */
diff --git a/boot/bootutil/src/bootutil_priv.h b/boot/bootutil/src/bootutil_priv.h
index d2ebca2..37a9350 100644
--- a/boot/bootutil/src/bootutil_priv.h
+++ b/boot/bootutil/src/bootutil_priv.h
@@ -217,6 +217,13 @@
size_t num_sectors;
} scratch;
#endif
+#if MCUBOOT_SWAP_USING_STATUS
+ struct {
+ const struct flash_area *area;
+ boot_sector_t *sectors;
+ size_t num_sectors;
+ } status;
+#endif
uint8_t swap_type[BOOT_IMAGE_NUMBER];
uint32_t write_sz;
@@ -240,6 +247,7 @@
uint32_t boot_trailer_sz(uint32_t min_write_sz);
int boot_status_entries(int image_index, const struct flash_area *fap);
uint32_t boot_status_off(const struct flash_area *fap);
+uint32_t boot_swap_info_off(const struct flash_area *fap);
int boot_read_swap_state(const struct flash_area *fap,
struct boot_swap_state *state);
int boot_read_swap_state_by_id(int flash_area_id,
@@ -267,6 +275,13 @@
int boot_erase_region(const struct flash_area *fap, uint32_t off, uint32_t sz);
bool boot_status_is_reset(const struct boot_status *bs);
+#ifdef MCUBOOT_SWAP_USING_STATUS
+uint32_t boot_copy_done_off(const struct flash_area *fap);
+uint32_t boot_image_ok_off(const struct flash_area *fap);
+uint32_t boot_swap_size_off(const struct flash_area *fap);
+#endif
+
+
#ifdef MCUBOOT_ENC_IMAGES
int boot_write_enc_key(const struct flash_area *fap, uint8_t slot,
const struct boot_status *bs);
diff --git a/boot/bootutil/src/bootutil_public.c b/boot/bootutil/src/bootutil_public.c
index 793c4e3..6057b41 100644
--- a/boot/bootutil/src/bootutil_public.c
+++ b/boot/bootutil/src/bootutil_public.c
@@ -46,6 +46,7 @@
#include "bootutil/image.h"
#include "bootutil/bootutil_public.h"
#include "bootutil/bootutil_log.h"
+#include "swap_status.h"
#ifdef MCUBOOT_ENC_IMAGES
#include "bootutil/enc_key_public.h"
#endif
@@ -117,6 +118,7 @@
#define BOOT_SWAP_TABLES_COUNT \
(sizeof boot_swap_tables / sizeof boot_swap_tables[0])
+#ifndef MCUBOOT_SWAP_USING_STATUS
static int
boot_magic_decode(const uint32_t *magic)
{
@@ -125,6 +127,7 @@
}
return BOOT_MAGIC_BAD;
}
+#endif /* !MCUBOOT_SWAP_USING_STATUS */
static int
boot_flag_decode(uint8_t flag)
@@ -135,6 +138,7 @@
return BOOT_FLAG_SET;
}
+#ifndef MCUBOOT_SWAP_USING_STATUS
static inline uint32_t
boot_magic_off(const struct flash_area *fap)
{
@@ -153,17 +157,12 @@
return boot_image_ok_off(fap) - BOOT_MAX_ALIGN;
}
-static inline uint32_t
-boot_swap_size_off(const struct flash_area *fap)
-{
- return boot_swap_info_off(fap) - BOOT_MAX_ALIGN;
-}
-
uint32_t
boot_swap_info_off(const struct flash_area *fap)
{
return boot_copy_done_off(fap) - BOOT_MAX_ALIGN;
}
+#endif /* !MCUBOOT_SWAP_USING_STATUS */
/**
* Determines if a status source table is satisfied by the specified magic
@@ -191,19 +190,6 @@
}
}
-#ifdef MCUBOOT_ENC_IMAGES
-static inline uint32_t
-boot_enc_key_off(const struct flash_area *fap, uint8_t slot)
-{
-#if MCUBOOT_SWAP_SAVE_ENCTLV
- return boot_swap_size_off(fap) - ((slot + 1) *
- ((((BOOT_ENC_TLV_SIZE - 1) / BOOT_MAX_ALIGN) + 1) * BOOT_MAX_ALIGN));
-#else
- return boot_swap_size_off(fap) - ((slot + 1) * BOOT_ENC_KEY_SIZE);
-#endif
-}
-#endif
-
bool bootutil_buffer_is_erased(const struct flash_area *area,
const void *buffer, size_t len)
{
@@ -249,6 +235,7 @@
return boot_read_flag(fap, copy_done, boot_copy_done_off(fap));
}
+#ifndef MCUBOOT_SWAP_USING_STATUS
int
boot_read_swap_state(const struct flash_area *fap,
@@ -294,6 +281,8 @@
return boot_read_image_ok(fap, &state->image_ok);
}
+#endif /* !MCUBOOT_SWAP_USING_STATUS */
+
int
boot_read_swap_state_by_id(int flash_area_id, struct boot_swap_state *state)
{
@@ -310,6 +299,8 @@
return rc;
}
+#ifndef MCUBOOT_SWAP_USING_STATUS
+
int
boot_write_magic(const struct flash_area *fap)
{
@@ -361,6 +352,8 @@
return 0;
}
+#endif /* !MCUBOOT_SWAP_USING_STATUS */
+
int
boot_write_trailer_flag(const struct flash_area *fap, uint32_t off,
uint8_t flag_val)
@@ -408,6 +401,17 @@
return boot_write_trailer(fap, off, (const uint8_t *) &swap_info, 1);
}
+#define BOOT_LOG_SWAP_STATE(area, state) \
+ BOOT_LOG_INF("%s: magic=%s, swap_type=0x%x, copy_done=0x%x, " \
+ "image_ok=0x%x", \
+ (area), \
+ ((state)->magic == BOOT_MAGIC_GOOD ? "good" : \
+ (state)->magic == BOOT_MAGIC_UNSET ? "unset" : \
+ "bad"), \
+ (state)->swap_type, \
+ (state)->copy_done, \
+ (state)->image_ok)
+
int
boot_swap_type_multi(int image_index)
{
@@ -429,6 +433,9 @@
return BOOT_SWAP_TYPE_PANIC;
}
+ BOOT_LOG_SWAP_STATE("boot_swap_type_multi: Primary image", &primary_slot);
+ BOOT_LOG_SWAP_STATE("boot_swap_type_multi: Secondary image", &secondary_slot);
+
for (i = 0; i < BOOT_SWAP_TABLES_COUNT; i++) {
table = boot_swap_tables + i;
diff --git a/boot/bootutil/src/caps.c b/boot/bootutil/src/caps.c
index a21bc09..2033056 100644
--- a/boot/bootutil/src/caps.c
+++ b/boot/bootutil/src/caps.c
@@ -44,6 +44,8 @@
res |= BOOTUTIL_CAP_OVERWRITE_UPGRADE;
#elif defined(MCUBOOT_SWAP_USING_MOVE)
res |= BOOTUTIL_CAP_SWAP_USING_MOVE;
+#elif defined(MCUBOOT_SWAP_USING_STATUS)
+ res |= BOOTUTIL_CAP_SWAP_USING_STATUS;
#else
res |= BOOTUTIL_CAP_SWAP_USING_SCRATCH;
#endif
diff --git a/boot/bootutil/src/crc32c.c b/boot/bootutil/src/crc32c.c
new file mode 100644
index 0000000..d298a1f
--- /dev/null
+++ b/boot/bootutil/src/crc32c.c
@@ -0,0 +1,73 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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.
+ */
+
+#include "crc32c.h"
+
+#define NIBBLE_POS (4u)
+#define NIBBLE_MSK (0xFu)
+#define CRC_TABLE_SIZE (16u) /* A number of uint32_t elements in the CRC32 table */
+#define CRC_INIT (0xFFFFFFFFu)
+
+
+/*******************************************************************************
+* Function Name: crc32c_checksum
+****************************************************************************//**
+*
+* This function computes a CRC-32C for the provided number of bytes contained
+* in the provided buffer.
+*
+* \param address The pointer to a buffer containing the data to compute
+* the checksum for.
+* \param length The number of bytes in the buffer to compute the checksum
+* for.
+*
+* \return CRC-32C for the provided data.
+*
+*******************************************************************************/
+uint32_t crc32c_checksum(const uint8_t *address, uint32_t length)
+{
+ /* Contains generated values to calculate CRC-32C by 4 bits per iteration*/
+ static const uint32_t crcTable[CRC_TABLE_SIZE] =
+ {
+ 0x00000000u, 0x105ec76fu, 0x20bd8edeu, 0x30e349b1u,
+ 0x417b1dbcu, 0x5125dad3u, 0x61c69362u, 0x7198540du,
+ 0x82f63b78u, 0x92a8fc17u, 0xa24bb5a6u, 0xb21572c9u,
+ 0xc38d26c4u, 0xd3d3e1abu, 0xe330a81au, 0xf36e6f75u,
+ };
+
+ uint32_t crc = CRC_INIT;
+ if (length != 0u)
+ {
+ do
+ {
+ crc = crc ^ *address;
+ crc = (crc >> NIBBLE_POS) ^ crcTable[crc & NIBBLE_MSK];
+ crc = (crc >> NIBBLE_POS) ^ crcTable[crc & NIBBLE_MSK];
+ --length;
+ ++address;
+ } while (length != 0u);
+ }
+ return (~crc);
+}
diff --git a/boot/bootutil/src/crc32c.h b/boot/bootutil/src/crc32c.h
new file mode 100644
index 0000000..329b9d3
--- /dev/null
+++ b/boot/bootutil/src/crc32c.h
@@ -0,0 +1,32 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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_CRC32C_
+#define H_CRC32C_
+
+#include <stdint.h>
+
+uint32_t crc32c_checksum(const uint8_t *address, uint32_t length);
+
+#endif /* H_CRC32C_ */
diff --git a/boot/bootutil/src/encrypted.c b/boot/bootutil/src/encrypted.c
index d14855b..12c0a9c 100644
--- a/boot/bootutil/src/encrypted.c
+++ b/boot/bootutil/src/encrypted.c
@@ -297,15 +297,16 @@
* @param ikm_len Length of the input data.
* @param info An information tag.
* @param info_len Length of the information tag.
+ * @param salt An salt tag.
+ * @param salt_len Length of the salt tag.
* @param okm Output of the KDF computation.
* @param okm_len On input the requested length; on output the generated length
*/
static int
-hkdf(uint8_t *ikm, uint16_t ikm_len, uint8_t *info, uint16_t info_len,
- uint8_t *okm, uint16_t *okm_len)
+hkdf(const uint8_t *ikm, uint16_t ikm_len, const uint8_t *info, uint16_t info_len,
+ const uint8_t *salt, uint16_t salt_len, uint8_t *okm, uint16_t *okm_len)
{
bootutil_hmac_sha256_context hmac;
- uint8_t salt[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
uint8_t prk[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
uint8_t T[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
uint16_t off;
@@ -324,8 +325,7 @@
bootutil_hmac_sha256_init(&hmac);
- memset(salt, 0, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
- rc = bootutil_hmac_sha256_set_key(&hmac, salt, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
+ rc = bootutil_hmac_sha256_set_key(&hmac, salt, salt_len);
if (rc != 0) {
goto error;
}
@@ -429,21 +429,25 @@
return 0;
}
-#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE
+#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE
#if defined(MCUBOOT_ENCRYPT_RSA)
-# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048
+# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048
+# define EXPECTED_ENC_EXT_LEN EXPECTED_ENC_TLV
#elif defined(MCUBOOT_ENCRYPT_KW)
-# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW128
+# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW128
+# define EXPECTED_ENC_EXT_LEN EXPECTED_ENC_TLV
#elif defined(MCUBOOT_ENCRYPT_EC256)
-# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_EC256
+# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_EC256
+# define EXPECTED_ENC_EXT_LEN (EXPECTED_ENC_LEN + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE)
# define EC_PUBK_INDEX (0)
# define EC_TAG_INDEX (65)
# define EC_CIPHERKEY_INDEX (65 + 32)
_Static_assert(EC_CIPHERKEY_INDEX + 16 == EXPECTED_ENC_LEN,
"Please fix ECIES-P256 component indexes");
#elif defined(MCUBOOT_ENCRYPT_X25519)
-# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519
+# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519
+# define EXPECTED_ENC_EXT_LEN EXPECTED_ENC_TLV
# define EC_PUBK_INDEX (0)
# define EC_TAG_INDEX (32)
# define EC_CIPHERKEY_INDEX (32 + 32)
@@ -451,14 +455,19 @@
"Please fix ECIES-X25519 component indexes");
#endif
+#ifndef EXPECTED_ENC_EXT_LEN
+#define EXPECTED_ENC_EXT_LEN EXPECTED_ENC_LEN
+#endif
+
/*
* Decrypt an encryption key TLV.
*
- * @param buf An encryption TLV read from flash (build time fixed length)
+ * @param buf An encryption TLV buffer red from flash
+ * @param sz An encryption TLV buffer data size
* @param enckey An AES-128 key sized buffer to store to plain key.
*/
int
-boot_enc_decrypt(const uint8_t *buf, uint8_t *enckey)
+boot_enc_decrypt(const uint8_t *buf, uint8_t *enckey, uint32_t sz, uint8_t *enciv)
{
#if defined(MCUBOOT_ENCRYPT_RSA)
mbedtls_rsa_context rsa;
@@ -475,14 +484,22 @@
#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
bootutil_hmac_sha256_context hmac;
bootutil_aes_ctr_context aes_ctr;
+ uint8_t salt[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
uint8_t tag[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
uint8_t shared[SHARED_KEY_LEN];
- uint8_t derived_key[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
+ uint8_t derived_key[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE + BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE * 2];
uint8_t *cp;
uint8_t *cpend;
uint8_t private_key[PRIV_KEY_LEN];
uint8_t counter[BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE];
uint16_t len;
+ uint16_t out_len;
+ const uint8_t *my_salt = salt;
+ uint8_t *my_key_iv = counter;
+ uint8_t *my_counter = counter;
+#else
+ (void)sz;
+ (void)enciv;
#endif
int rc = -1;
@@ -532,6 +549,7 @@
bootutil_ecdh_p256_init(&ecdh_p256);
rc = bootutil_ecdh_p256_shared_secret(&ecdh_p256, &buf[EC_PUBK_INDEX], private_key, shared);
+
bootutil_ecdh_p256_drop(&ecdh_p256);
if (rc != 0) {
return -1;
@@ -573,10 +591,31 @@
* Expand shared secret to create keys for AES-128-CTR + HMAC-SHA256
*/
+ /* Prepare for default encryption scheme with zero salt and AES IVs */
+ memset(counter, 0, BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE);
+ memset(salt, 0, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
+
len = BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE;
- rc = hkdf(shared, SHARED_KEY_LEN, (uint8_t *)"MCUBoot_ECIES_v1", 16,
- derived_key, &len);
- if (rc != 0 || len != (BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE)) {
+
+ if (sz > EXPECTED_ENC_LEN) {
+ /* Use new enhanced encryption scheme with randomly generated salt and AES IVs */
+ len += BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE * 2;
+
+ my_salt = &buf[EXPECTED_ENC_LEN];
+
+ my_key_iv = &derived_key[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE +
+ BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
+
+ my_counter = &derived_key[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE +
+ BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE +
+ BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE];
+ }
+
+ out_len = len;
+ rc = hkdf(shared, SHARED_KEY_LEN, (uint8_t *)"MCUBoot_ECIES_v1", BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE,
+ my_salt, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE, derived_key, &out_len);
+
+ if (rc != 0 || len != out_len) {
return -1;
}
@@ -586,13 +625,13 @@
bootutil_hmac_sha256_init(&hmac);
- rc = bootutil_hmac_sha256_set_key(&hmac, &derived_key[16], 32);
+ rc = bootutil_hmac_sha256_set_key(&hmac, &derived_key[BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE], BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
if (rc != 0) {
(void)bootutil_hmac_sha256_drop(&hmac);
return -1;
}
- rc = bootutil_hmac_sha256_update(&hmac, &buf[EC_CIPHERKEY_INDEX], 16);
+ rc = bootutil_hmac_sha256_update(&hmac, &buf[EC_CIPHERKEY_INDEX], BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE);
if (rc != 0) {
(void)bootutil_hmac_sha256_drop(&hmac);
return -1;
@@ -605,22 +644,20 @@
return -1;
}
- if (bootutil_constant_time_compare(tag, &buf[EC_TAG_INDEX], 32) != 0) {
+ if (bootutil_constant_time_compare(tag, &buf[EC_TAG_INDEX], BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE) != 0) {
(void)bootutil_hmac_sha256_drop(&hmac);
return -1;
}
bootutil_hmac_sha256_drop(&hmac);
+ (void)memcpy(enciv, my_counter, BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE);
+
/*
* Finally decrypt the received ciphered key
*/
bootutil_aes_ctr_init(&aes_ctr);
- if (rc != 0) {
- bootutil_aes_ctr_drop(&aes_ctr);
- return -1;
- }
rc = bootutil_aes_ctr_set_key(&aes_ctr, derived_key);
if (rc != 0) {
@@ -628,8 +665,7 @@
return -1;
}
- memset(counter, 0, BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE);
- rc = bootutil_aes_ctr_decrypt(&aes_ctr, counter, &buf[EC_CIPHERKEY_INDEX], BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE, 0, enckey);
+ rc = bootutil_aes_ctr_decrypt(&aes_ctr, my_key_iv, &buf[EC_CIPHERKEY_INDEX], BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE, 0, enckey);
if (rc != 0) {
bootutil_aes_ctr_drop(&aes_ctr);
return -1;
@@ -658,7 +694,7 @@
#if MCUBOOT_SWAP_SAVE_ENCTLV
uint8_t *buf;
#else
- uint8_t buf[EXPECTED_ENC_LEN];
+ uint8_t buf[EXPECTED_ENC_EXT_LEN];
#endif
uint8_t slot;
int rc;
@@ -687,7 +723,7 @@
return rc;
}
- if (len != EXPECTED_ENC_LEN) {
+ if ((len < EXPECTED_ENC_LEN) || (len > EXPECTED_ENC_EXT_LEN)) {
return -1;
}
@@ -696,12 +732,12 @@
memset(buf, 0xff, BOOT_ENC_TLV_ALIGN_SIZE);
#endif
- rc = flash_area_read(fap, off, buf, EXPECTED_ENC_LEN);
+ rc = flash_area_read(fap, off, buf, len);
if (rc) {
return -1;
}
- return boot_enc_decrypt(buf, bs->enckey[slot]);
+ return (boot_enc_decrypt(buf, bs->enckey[slot], len, enc_state[slot].aes_iv));
}
bool
@@ -726,7 +762,7 @@
uint32_t blk_off, uint8_t *buf)
{
struct enc_key_data *enc;
- uint8_t nonce[16];
+ uint8_t *nonce;
int rc;
/* boot_copy_region will call boot_encrypt with sz = 0 when skipping over
@@ -735,13 +771,6 @@
return;
}
- memset(nonce, 0, 12);
- off >>= 4;
- nonce[12] = (uint8_t)(off >> 24);
- nonce[13] = (uint8_t)(off >> 16);
- nonce[14] = (uint8_t)(off >> 8);
- nonce[15] = (uint8_t)off;
-
rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
if (rc < 0) {
assert(0);
@@ -750,6 +779,15 @@
enc = &enc_state[rc];
assert(enc->valid == 1);
+
+ nonce = enc->aes_iv;
+
+ off >>= 4;
+ nonce[12] = (uint8_t)(off >> 24);
+ nonce[13] = (uint8_t)(off >> 16);
+ nonce[14] = (uint8_t)(off >> 8);
+ nonce[15] = (uint8_t)off;
+
bootutil_aes_ctr_encrypt(&enc->aes_ctr, nonce, buf, sz, blk_off, buf);
}
diff --git a/boot/bootutil/src/image_ec256.c b/boot/bootutil/src/image_ec256.c
index 5d73c9f..bdd72c6 100644
--- a/boot/bootutil/src/image_ec256.c
+++ b/boot/bootutil/src/image_ec256.c
@@ -97,7 +97,7 @@
}
return 0;
}
-#endif /* CY_MBEDTLS_HW_ACCELERATION */
+#else /* !CY_MBEDTLS_HW_ACCELERATION */
static int
bootutil_import_key(uint8_t **cp, uint8_t *end)
{
@@ -139,6 +139,7 @@
return 0;
}
+#endif /* CY_MBEDTLS_HW_ACCELERATION */
#ifndef MCUBOOT_ECDSA_NEED_ASN1_SIG
/*
diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c
index f066add..18967c5 100644
--- a/boot/bootutil/src/image_validate.c
+++ b/boot/bootutil/src/image_validate.c
@@ -490,6 +490,7 @@
fih_rc = fih_int_encode_zero_equality(img_security_cnt <
fih_int_decode(security_cnt));
if (fih_not_eq(fih_rc, FIH_SUCCESS)) {
+ /* The image's security counter is not accepted. */
goto out;
}
diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c
index e1f1e54..e4c0a3f 100644
--- a/boot/bootutil/src/loader.c
+++ b/boot/bootutil/src/loader.c
@@ -106,7 +106,7 @@
* Compute the total size of the given image. Includes the size of
* the TLVs.
*/
-#if !defined(MCUBOOT_OVERWRITE_ONLY) || defined(MCUBOOT_OVERWRITE_ONLY_FAST)
+#if !defined(MCUBOOT_OVERWRITE_ONLY) || defined(MCUBOOT_OVERWRITE_ONLY_FAST)
static int
boot_read_image_size(struct boot_loader_state *state, int slot, uint32_t *size)
{
@@ -166,6 +166,7 @@
#endif /* !MCUBOOT_OVERWRITE_ONLY */
#if !defined(MCUBOOT_RAM_LOAD)
+
static uint32_t
boot_write_sz(struct boot_loader_state *state)
{
@@ -241,6 +242,11 @@
out_sectors = state->scratch.sectors;
out_num_sectors = &state->scratch.num_sectors;
#endif
+#if MCUBOOT_SWAP_USING_STATUS
+ } else if (flash_area == FLASH_AREA_IMAGE_SWAP_STATUS) {
+ out_sectors = state->status.sectors;
+ out_num_sectors = &state->status.num_sectors;
+#endif
} else {
return BOOT_EFLASH;
}
@@ -278,6 +284,13 @@
return BOOT_EFLASH;
}
+#if MCUBOOT_SWAP_USING_STATUS
+ rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SWAP_STATUS);
+ if (rc != 0) {
+ return BOOT_EFLASH;
+ }
+#endif
+
#if MCUBOOT_SWAP_USING_SCRATCH
rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SCRATCH);
if (rc != 0) {
@@ -318,6 +331,7 @@
bs->state == BOOT_STATUS_STATE_0);
}
+#ifndef MCUBOOT_SWAP_USING_STATUS
/**
* Writes the supplied boot status to the flash file system. The boot status
* contains the current state of an in-progress image copy operation.
@@ -381,6 +395,9 @@
return rc;
}
#endif /* !MCUBOOT_RAM_LOAD */
+
+#endif /* MCUBOOT_SWAP_USING_STATUS */
+
#endif /* !MCUBOOT_DIRECT_XIP */
/*
@@ -525,6 +542,8 @@
#if (BOOT_IMAGE_NUMBER > 1) || \
defined(MCUBOOT_DIRECT_XIP) || \
defined(MCUBOOT_RAM_LOAD) || \
+ defined(MCUBOOT_SWAP_USING_SCRATCH) || \
+ defined(MCUBOOT_SWAP_USING_MOVE) || \
(defined(MCUBOOT_OVERWRITE_ONLY) && defined(MCUBOOT_DOWNGRADE_PREVENTION))
/**
* Compare image version numbers not including the build number
@@ -620,6 +639,8 @@
FIH_RET(fih_rc);
}
+ BOOT_LOG_DBG("> boot_validate_slot: fa_id = %d", fap->fa_id);
+
hdr = boot_img_hdr(state, slot);
if (boot_check_header_erased(state, slot) == 0 ||
(hdr->ih_flags & IMAGE_F_NON_BOOTABLE)) {
@@ -635,11 +656,14 @@
* through mcumgr; so we just get rid of the trailer here, if the header
* is erased.
*/
+ BOOT_LOG_DBG(" * Fix the secondary slot when image is invalid.");
if (slot != BOOT_PRIMARY_SLOT) {
+ BOOT_LOG_DBG(" * Erase secondary image trailer.");
swap_erase_trailer_sectors(state, fap);
}
#endif
+ BOOT_LOG_DBG(" * No bootable image in slot(%d); continue booting from the primary slot.", slot);
/* No bootable image in slot; continue booting from the primary slot. */
fih_rc = fih_int_encode(1);
goto out;
@@ -666,6 +690,7 @@
FIH_CALL(boot_image_check, fih_rc, state, hdr, fap, bs);
if (!boot_is_header_valid(hdr, fap) || fih_not_eq(fih_rc, FIH_SUCCESS)) {
if ((slot != BOOT_PRIMARY_SLOT) || ARE_SLOTS_EQUIVALENT()) {
+ BOOT_LOG_DBG(" * Image in the secondary slot is invalid. Erase the image");
flash_area_erase(fap, 0, fap->fa_size);
/* Image is invalid, erase it to prevent further unnecessary
* attempts to validate and boot it.
@@ -679,9 +704,11 @@
goto out;
}
+ /* Image in the secondary slot is valid. */
+
out:
flash_area_close(fap);
-
+ BOOT_LOG_DBG("< boot_validate_slot = %d", fih_int_decode(fih_rc));
FIH_RET(fih_rc);
}
@@ -834,23 +861,27 @@
#ifdef MCUBOOT_ENC_IMAGES
image_index = BOOT_CURR_IMG(state);
- if ((fap_src->fa_id == FLASH_AREA_IMAGE_SECONDARY(image_index) ||
- fap_dst->fa_id == FLASH_AREA_IMAGE_SECONDARY(image_index)) &&
+ if ((fap_src->fa_id == FLASH_AREA_IMAGE_PRIMARY(image_index) ||
+ fap_dst->fa_id == FLASH_AREA_IMAGE_PRIMARY(image_index)) &&
+
+ !(fap_src->fa_id == FLASH_AREA_IMAGE_PRIMARY(image_index) &&
+ fap_dst->fa_id == FLASH_AREA_IMAGE_PRIMARY(image_index)) &&
!(fap_src->fa_id == FLASH_AREA_IMAGE_SECONDARY(image_index) &&
- fap_dst->fa_id == FLASH_AREA_IMAGE_SECONDARY(image_index))) {
- /* assume the secondary slot as src, needs decryption */
- hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT);
+ fap_dst->fa_id == FLASH_AREA_IMAGE_SECONDARY(image_index)))
+ {
+ /* assume the primary slot as src, needs encryption */
+ hdr = boot_img_hdr(state, BOOT_PRIMARY_SLOT);
#if !defined(MCUBOOT_SWAP_USING_MOVE)
off = off_src;
- if (fap_dst->fa_id == FLASH_AREA_IMAGE_SECONDARY(image_index)) {
- /* might need encryption (metadata from the primary slot) */
- hdr = boot_img_hdr(state, BOOT_PRIMARY_SLOT);
+ if (fap_dst->fa_id == FLASH_AREA_IMAGE_PRIMARY(image_index)) {
+ /* might need decryption (metadata from the secondary slot) */
+ hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT);
off = off_dst;
}
#else
off = off_dst;
- if (fap_dst->fa_id == FLASH_AREA_IMAGE_SECONDARY(image_index)) {
- hdr = boot_img_hdr(state, BOOT_PRIMARY_SLOT);
+ if (fap_dst->fa_id == FLASH_AREA_IMAGE_PRIMARY(image_index)) {
+ hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT);
}
#endif
if (IS_ENCRYPTED(hdr)) {
@@ -859,8 +890,13 @@
if (off + bytes_copied < hdr->ih_hdr_size) {
/* do not decrypt header */
blk_off = 0;
- blk_sz = chunk_sz - hdr->ih_hdr_size;
- idx = hdr->ih_hdr_size;
+ if(chunk_sz > hdr->ih_hdr_size) {
+ blk_sz = chunk_sz - hdr->ih_hdr_size;
+ idx = hdr->ih_hdr_size - (off + bytes_copied);
+ } else {
+ /* still in header-area, no need to decrypt */
+ blk_sz = 0;
+ }
} else {
blk_off = ((off + bytes_copied) - hdr->ih_hdr_size) & 0xf;
}
@@ -873,9 +909,11 @@
blk_sz = tlv_off - (off + bytes_copied);
}
}
- boot_encrypt(BOOT_CURR_ENC(state), image_index, fap_src,
+ if(0 != blk_sz) {
+ boot_encrypt(BOOT_CURR_ENC(state), image_index, fap_src,
(off + bytes_copied + idx) - hdr->ih_hdr_size, blk_sz,
blk_off, &buf[idx]);
+ }
}
}
#endif
@@ -949,8 +987,12 @@
assert (rc == 0);
sect_count = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT);
+ BOOT_LOG_DBG(" * primary slot sectors: %d", sect_count);
for (sect = 0, size = 0; sect < sect_count; sect++) {
this_size = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, sect);
+ /* BOOT_LOG_DBG(" * primary slot erase region (0x%0lx / 0x%0lx): sector = %d, off = %0x, size = %d",
+ fap_primary_slot->fa_off, fap_primary_slot->fa_size,
+ sect, size, this_size); */
rc = boot_erase_region(fap_primary_slot, size, this_size);
assert(rc == 0);
@@ -994,7 +1036,7 @@
}
#endif
- BOOT_LOG_INF("Copying the secondary slot to the primary slot: 0x%zx bytes",
+ BOOT_LOG_INF("Copying the secondary slot to the primary slot: 0x%x bytes",
size);
rc = boot_copy_region(state, fap_secondary_slot, fap_primary_slot, 0, 0, size);
if (rc != 0) {
@@ -1326,7 +1368,7 @@
if (rc == 0) {
/* All dependencies've been satisfied, continue with next image. */
BOOT_CURR_IMG(state)++;
- } else {
+ } else if (rc == BOOT_EBADVERSION) {
/* Cannot upgrade due to non-met dependencies, so disable all
* image upgrades.
*/
@@ -1335,6 +1377,9 @@
BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
}
break;
+ } else {
+ /* Other error happened, images are inconsistent */
+ return rc;
}
}
return rc;
@@ -1356,6 +1401,8 @@
uint8_t swap_type;
#endif
+ BOOT_LOG_DBG("> boot_perform_update: bs->idx = %d", bs->idx);
+
/* At this point there are no aborted swaps. */
#if defined(MCUBOOT_OVERWRITE_ONLY)
rc = boot_copy_image(state, bs);
@@ -1551,6 +1598,8 @@
int rc;
fih_int fih_rc = FIH_FAILURE;
+ BOOT_LOG_DBG("> boot_prepare_image_for_update: image = %d", BOOT_CURR_IMG(state));
+
/* Determine the sector layout of the image slots and scratch area. */
rc = boot_read_sectors(state);
if (rc != 0) {
@@ -1565,6 +1614,7 @@
/* Attempt to read an image header from each slot. */
rc = boot_read_image_headers(state, false, NULL);
+ BOOT_LOG_DBG(" * Read an image (%d) header from each slot: rc = %d", BOOT_CURR_IMG(state), rc);
if (rc != 0) {
/* Continue with next image if there is one. */
BOOT_LOG_WRN("Failed reading image headers; Image=%u",
@@ -1590,12 +1640,13 @@
}
#endif
-#ifdef MCUBOOT_SWAP_USING_MOVE
+#if defined (MCUBOOT_SWAP_USING_MOVE) || defined(MCUBOOT_SWAP_USING_SCRATCH)
/*
* Must re-read image headers because the boot status might
* have been updated in the previous function call.
*/
rc = boot_read_image_headers(state, !boot_status_is_reset(bs), bs);
+ BOOT_LOG_DBG(" * re-read image(%d) headers: rc = %d.", BOOT_CURR_IMG(state), rc);
#ifdef MCUBOOT_BOOTSTRAP
/* When bootstrapping it's OK to not have image magic in the primary slot */
if (rc != 0 && (BOOT_CURR_IMG(state) != BOOT_PRIMARY_SLOT ||
@@ -1603,7 +1654,6 @@
#else
if (rc != 0) {
#endif
-
/* Continue with next image if there is one. */
BOOT_LOG_WRN("Failed reading image headers; Image=%u",
BOOT_CURR_IMG(state));
@@ -1642,6 +1692,8 @@
/* Swap has finished set to NONE */
BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
} else {
+ BOOT_LOG_DBG(" * There was no partial swap, determine swap type.");
+
/* There was no partial swap, determine swap type. */
if (bs->swap_type == BOOT_SWAP_TYPE_NONE) {
BOOT_SWAP_TYPE(state) = boot_validated_swap_type(state, bs);
@@ -1693,6 +1745,7 @@
/* In that case if slots are not compatible. */
BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
}
+ BOOT_LOG_DBG("< boot_prepare_image_for_update");
}
fih_int
@@ -1716,6 +1769,9 @@
#if MCUBOOT_SWAP_USING_SCRATCH
TARGET_STATIC boot_sector_t scratch_sectors[BOOT_MAX_IMG_SECTORS];
#endif
+#if MCUBOOT_SWAP_USING_STATUS
+ TARGET_STATIC boot_sector_t status_sectors[BOOT_MAX_SWAP_STATUS_SECTORS];
+#endif
memset(state, 0, sizeof(struct boot_loader_state));
has_upgrade = false;
@@ -1747,6 +1803,9 @@
#if MCUBOOT_SWAP_USING_SCRATCH
state->scratch.sectors = scratch_sectors;
#endif
+#if MCUBOOT_SWAP_USING_STATUS
+ state->status.sectors = status_sectors;
+#endif
/* Open primary and secondary image areas for the duration
* of this call.
@@ -1762,6 +1821,7 @@
assert(rc == 0);
#endif
+ BOOT_LOG_DBG(" * boot_prepare_image_for_update...");
/* Determine swap type and complete swap if it has been aborted. */
boot_prepare_image_for_update(state, &bs);
@@ -1810,6 +1870,8 @@
/* Set the previously determined swap type */
bs.swap_type = BOOT_SWAP_TYPE(state);
+ BOOT_LOG_DBG(" * process swap_type = %d", bs.swap_type);
+
switch (BOOT_SWAP_TYPE(state)) {
case BOOT_SWAP_TYPE_NONE:
break;
@@ -1817,6 +1879,7 @@
case BOOT_SWAP_TYPE_TEST: /* fallthrough */
case BOOT_SWAP_TYPE_PERM: /* fallthrough */
case BOOT_SWAP_TYPE_REVERT:
+ BOOT_LOG_DBG(" * perform update...", bs.swap_type);
rc = boot_perform_update(state, &bs);
assert(rc == 0);
break;
@@ -1827,6 +1890,7 @@
* pretending we just reverted back to primary slot.
*/
#ifndef MCUBOOT_OVERWRITE_ONLY
+ BOOT_LOG_DBG(" * update failed! Set image_ok manually for image(%d)", BOOT_CURR_IMG(state));
/* image_ok needs to be explicitly set to avoid a new revert. */
rc = swap_set_image_ok(BOOT_CURR_IMG(state));
if (rc != 0) {
diff --git a/boot/bootutil/src/swap_misc.c b/boot/bootutil/src/swap_misc.c
index 940d646..42ae7a4 100644
--- a/boot/bootutil/src/swap_misc.c
+++ b/boot/bootutil/src/swap_misc.c
@@ -31,6 +31,9 @@
MCUBOOT_LOG_MODULE_DECLARE(mcuboot);
#if defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE)
+
+#ifndef MCUBOOT_SWAP_USING_STATUS
+
int
swap_erase_trailer_sectors(const struct boot_loader_state *state,
const struct flash_area *fap)
@@ -164,7 +167,7 @@
rc = swap_read_status_bytes(fap, state, bs);
if (rc == 0) {
off = boot_swap_info_off(fap);
- rc = flash_area_read(fap, off, &swap_info, sizeof swap_info);
+ rc = flash_area_read(fap, off, &swap_info, sizeof swap_info);
if (rc != 0) {
return BOOT_EFLASH;
}
@@ -182,6 +185,7 @@
return rc;
}
+#endif /* !MCUBOOT_SWAP_USING_STATUS */
int
swap_set_copy_done(uint8_t image_index)
@@ -228,5 +232,4 @@
return rc;
}
-
#endif /* defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE) */
diff --git a/boot/bootutil/src/swap_move.c b/boot/bootutil/src/swap_move.c
index f2883f6..8fe0b44 100644
--- a/boot/bootutil/src/swap_move.c
+++ b/boot/bootutil/src/swap_move.c
@@ -24,6 +24,9 @@
#include "bootutil/bootutil.h"
#include "bootutil_priv.h"
#include "swap_priv.h"
+#ifdef MCUBOOT_SWAP_USING_STATUS
+#include "swap_status.h"
+#endif
#include "bootutil/bootutil_log.h"
#include "mcuboot_config/mcuboot_config.h"
@@ -115,6 +118,8 @@
return rc;
}
+#ifndef MCUBOOT_SWAP_USING_STATUS
+
int
swap_read_status_bytes(const struct flash_area *fap,
struct boot_loader_state *state, struct boot_status *bs)
@@ -181,7 +186,7 @@
} else if (found_idx < move_entries) {
bs->op = BOOT_STATUS_OP_MOVE;
bs->idx = (found_idx / BOOT_STATUS_MOVE_STATE_COUNT) + BOOT_STATUS_IDX_0;
- bs->state = (found_idx % BOOT_STATUS_MOVE_STATE_COUNT) + BOOT_STATUS_STATE_0;;
+ bs->state = (found_idx % BOOT_STATUS_MOVE_STATE_COUNT) + BOOT_STATUS_STATE_0;
} else {
bs->op = BOOT_STATUS_OP_SWAP;
bs->idx = ((found_idx - move_entries) / BOOT_STATUS_SWAP_STATE_COUNT) + BOOT_STATUS_IDX_0;
@@ -208,6 +213,8 @@
return off;
}
+#endif /* !MCUBOOT_SWAP_USING_STATUS */
+
int
boot_slots_compatible(struct boot_loader_state *state)
{
@@ -219,6 +226,12 @@
num_sectors_pri = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT);
num_sectors_sec = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT);
+
+ if (num_sectors_sec == 0) {
+ BOOT_LOG_WRN("Upgrade disabled for image %d", BOOT_CURR_IMG(state));
+ return 0;
+ }
+
if ((num_sectors_pri != num_sectors_sec) &&
(num_sectors_pri != (num_sectors_sec + 1))) {
BOOT_LOG_WRN("Cannot upgrade: not a compatible amount of sectors");
@@ -442,8 +455,6 @@
uint32_t sz;
uint32_t sector_sz;
uint32_t idx;
- uint32_t trailer_sz;
- uint32_t first_trailer_idx;
uint8_t image_index;
const struct flash_area *fap_pri;
const struct flash_area *fap_sec;
@@ -462,6 +473,10 @@
}
}
+#ifndef MCUBOOT_SWAP_USING_STATUS
+ uint32_t trailer_sz;
+ uint32_t first_trailer_idx;
+
/*
* When starting a new swap upgrade, check that there is enough space.
*/
@@ -484,6 +499,7 @@
return;
}
}
+#endif
image_index = BOOT_CURR_IMG(state);
diff --git a/boot/bootutil/src/swap_scratch.c b/boot/bootutil/src/swap_scratch.c
index 55fa61f..9b9228a 100644
--- a/boot/bootutil/src/swap_scratch.c
+++ b/boot/bootutil/src/swap_scratch.c
@@ -24,13 +24,16 @@
#include "bootutil/bootutil.h"
#include "bootutil_priv.h"
#include "swap_priv.h"
+#ifdef MCUBOOT_SWAP_USING_STATUS
+#include "swap_status.h"
+#endif
#include "bootutil/bootutil_log.h"
#include "mcuboot_config/mcuboot_config.h"
MCUBOOT_LOG_MODULE_DECLARE(mcuboot);
-#if !defined(MCUBOOT_SWAP_USING_MOVE)
+#ifndef MCUBOOT_SWAP_USING_MOVE
#if defined(MCUBOOT_VALIDATE_PRIMARY_SLOT)
/*
@@ -45,7 +48,7 @@
} while (0)
#else
#define BOOT_STATUS_ASSERT(x) ASSERT(x)
-#endif
+#endif /* defined(MCUBOOT_VALIDATE_PRIMARY_SLOT) */
int
boot_read_image_header(struct boot_loader_state *state, int slot,
@@ -55,12 +58,30 @@
int area_id;
int rc;
+ int saved_slot = slot;
+
(void)bs;
#if (BOOT_IMAGE_NUMBER == 1)
(void)state;
#endif
+ if (bs != NULL) {
+ if (bs->state == BOOT_STATUS_STATE_1) {
+ if (slot == 1) {
+ slot = 2;
+ }
+ }
+ else if (bs->state == BOOT_STATUS_STATE_2) {
+ if (slot == 0) {
+ slot = 1;
+ }
+ else {
+ slot = 2;
+ }
+ }
+ }
+
area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
rc = flash_area_open(area_id, &fap);
if (rc != 0) {
@@ -68,12 +89,43 @@
goto done;
}
- rc = flash_area_read(fap, 0, out_hdr, sizeof *out_hdr);
- if (rc != 0) {
+ rc = flash_area_read_is_empty(fap, 0, out_hdr, sizeof *out_hdr);
+ if (rc < 0) {
rc = BOOT_EFLASH;
goto done;
}
+ if (rc == 1) {
+ memset(out_hdr, 0, sizeof(*out_hdr));
+ }
+
+ /* We only know where the headers are located when bs is valid */
+ if (bs != NULL && out_hdr->ih_magic != IMAGE_MAGIC) {
+
+ if (bs->state != BOOT_STATUS_STATE_0) {
+
+ flash_area_close(fap);
+
+ area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), saved_slot);
+ rc = flash_area_open(area_id, &fap);
+ if (rc != 0) {
+ rc = BOOT_EFLASH;
+ goto done;
+ }
+
+ rc = flash_area_read(fap, 0, out_hdr, sizeof *out_hdr);
+ if (rc < 0) {
+ rc = BOOT_EFLASH;
+ goto done;
+ }
+
+ if (out_hdr->ih_magic != IMAGE_MAGIC) {
+ rc = -1;
+ goto done;
+ }
+ }
+ }
+
rc = 0;
done:
@@ -82,6 +134,8 @@
}
#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)
+
+#ifndef MCUBOOT_SWAP_USING_STATUS
/**
* Reads the status of a partially-completed swap, if any. This is necessary
* to recover in case the boot lodaer was reset in the middle of a swap
@@ -165,6 +219,7 @@
return (bs->idx - BOOT_STATUS_IDX_0) * idx_sz +
(bs->state - BOOT_STATUS_STATE_0) * elem_sz;
}
+#endif /* !MCUBOOT_SWAP_USING_STATUS */
/*
* Slots are compatible when all sectors that store up to to size of the image
@@ -187,9 +242,17 @@
num_sectors_primary = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT);
num_sectors_secondary = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT);
+
+ if (num_sectors_secondary == 0) {
+ BOOT_LOG_WRN("Upgrade disabled for image %d", BOOT_CURR_IMG(state));
+ return 0;
+ }
+
if ((num_sectors_primary > BOOT_MAX_IMG_SECTORS) ||
(num_sectors_secondary > BOOT_MAX_IMG_SECTORS)) {
BOOT_LOG_WRN("Cannot upgrade: more sectors than allowed");
+ BOOT_LOG_DBG("sectors_primary (%d) or sectors_secondary (%d) > BOOT_MAX_IMG_SECTORS (%d)",
+ num_sectors_primary, num_sectors_secondary, BOOT_MAX_IMG_SECTORS);
return 0;
}
@@ -399,7 +462,7 @@
source = table->bst_status_source;
#if (BOOT_IMAGE_NUMBER > 1)
- /* In case of multi-image boot it can happen that if boot status
+ /* In case of multi image boot it can happen that if boot status
* info is found on scratch area then it does not belong to the
* currently examined image.
*/
@@ -500,7 +563,8 @@
img_off = boot_img_sector_off(state, BOOT_PRIMARY_SLOT, idx);
copy_sz = sz;
- trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state));
+ // trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state)); // TODO: fixme for status use case
+ trailer_sz = BOOT_WRITE_SZ(state);
/* sz in this function is always sized on a multiple of the sector size.
* The check against the start offset of the last sector
@@ -557,8 +621,13 @@
assert(rc == 0);
/* Erase the temporary trailer from the scratch area. */
+#ifndef MCUBOOT_SWAP_USING_STATUS
rc = boot_erase_region(fap_scratch, 0, fap_scratch->fa_size);
assert(rc == 0);
+#else
+ rc = swap_erase_trailer_sectors(state, fap_scratch);
+ assert(rc == 0);
+#endif
}
}
@@ -655,8 +724,16 @@
BOOT_STATUS_ASSERT(rc == 0);
if (erase_scratch) {
+#ifndef MCUBOOT_SWAP_USING_STATUS
rc = boot_erase_region(fap_scratch, 0, sz);
assert(rc == 0);
+#else
+ rc = swap_erase_trailer_sectors(state, fap_scratch);
+ assert(rc == 0);
+
+ rc = swap_erase_trailer_sectors(state, fap_secondary_slot); // TODO: check if needed and fix
+ assert(rc == 0);
+#endif
}
}
@@ -709,6 +786,8 @@
last_idx_secondary_slot++;
}
+ bs->op = BOOT_STATUS_OP_SWAP;
+
swap_idx = 0;
while (last_sector_idx >= 0) {
sz = boot_copy_sz(state, last_sector_idx, &first_sector_idx);
diff --git a/boot/bootutil/src/swap_status.c b/boot/bootutil/src/swap_status.c
new file mode 100644
index 0000000..6b9d33b
--- /dev/null
+++ b/boot/bootutil/src/swap_status.c
@@ -0,0 +1,164 @@
+/*
+ * 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.
+ */
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include "bootutil/bootutil.h"
+#include "bootutil_priv.h"
+#include "swap_priv.h"
+#include "swap_status.h"
+#include "bootutil/bootutil_log.h"
+
+#include "mcuboot_config/mcuboot_config.h"
+
+MCUBOOT_LOG_MODULE_DECLARE(mcuboot);
+
+#ifdef MCUBOOT_SWAP_USING_STATUS
+
+#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)
+int
+swap_read_status_bytes(const struct flash_area *fap,
+ struct boot_loader_state *state, struct boot_status *bs)
+{
+ uint32_t off;
+ uint8_t status = 0;
+ uint8_t last_status = 0xff;
+ int max_entries;
+ int32_t found_idx;
+ bool found;
+ bool invalid;
+ int rc;
+ int i;
+ (void)state;
+
+ BOOT_LOG_DBG("> STATUS: swap_read_status_bytes: fa_id = %d", fap->fa_id);
+
+ if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
+ max_entries = 1;
+ } else {
+ max_entries = BOOT_STATUS_MAX_ENTRIES;
+ }
+
+ off = boot_status_off(fap);
+
+ found = false;
+ found_idx = -1;
+ invalid = false;
+
+ for (i = 0; i < max_entries; i++) {
+ rc = swap_status_retrieve(fap->fa_id, off + i, &status, 1);
+ if (rc < 0) {
+ return BOOT_EFLASH;
+ }
+
+ // if (status != flash_area_erased_val(fap)) { // TODO: fixup for external memory fap's
+ if (status == 0) {
+ if (found && (found_idx == -1)) {
+ found_idx = i;
+ }
+ } else {
+ last_status = status;
+
+ if (!found) {
+ found = true;
+ } else if (found_idx > 0) {
+ invalid = true;
+ break;
+ }
+ }
+ }
+
+ if (invalid) {
+ /* This means there was an error writing status on the last
+ * swap. Tell user and move on to validation!
+ */
+#if !defined(__BOOTSIM__)
+ BOOT_LOG_ERR("Detected inconsistent status!");
+#endif
+
+#if !defined(MCUBOOT_VALIDATE_PRIMARY_SLOT)
+ /* With validation of the primary slot disabled, there is no way
+ * to be sure the swapped primary slot is OK, so abort!
+ */
+ assert(0);
+#endif
+ }
+
+ if (found_idx == -1) {
+ /* no swap status found; nothing to do */
+ }
+ else {
+ uint8_t image_index = BOOT_CURR_IMG(state);
+ rc = boot_read_swap_size((int32_t)image_index, &bs->swap_size);
+ if (rc < 0) {
+ return BOOT_EFLASH;
+ }
+
+#ifdef MCUBOOT_SWAP_USING_MOVE
+ /* get image size in blocks */
+ uint32_t move_entries = bs->swap_size / state->write_sz + (uint32_t)(bs->swap_size % state->write_sz != 0u);
+
+ if (found_idx < (int32_t)move_entries) {
+ /* continue move sector up operation */
+ bs->op = (uint8_t)BOOT_STATUS_OP_MOVE;
+ bs->idx = (uint32_t)found_idx;
+ bs->state = (uint8_t)last_status;
+ } else
+#endif /* MCUBOOT_SWAP_USING_MOVE */
+ {
+ /* resume swap sectors operation */
+ last_status++;
+ if (last_status > BOOT_STATUS_STATE_COUNT) {
+ last_status = BOOT_STATUS_STATE_0;
+ found_idx++;
+ }
+
+ bs->op = (uint8_t)BOOT_STATUS_OP_SWAP;
+ bs->idx = (uint32_t)found_idx;
+ bs->state = (uint8_t)last_status;
+ }
+ }
+
+ return 0;
+}
+
+/* this is internal offset in swap status area */
+uint32_t
+boot_status_internal_off(const struct boot_status *bs, int elem_sz)
+{
+ uint32_t off = (bs->idx - BOOT_STATUS_IDX_0) * (uint32_t)elem_sz;
+
+ return off;
+}
+#endif /* !MCUBOOT_DIRECT_XIP && !MCUBOOT_RAM_LOAD */
+
+#endif /* MCUBOOT_SWAP_USING_STATUS */
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_ */
diff --git a/boot/bootutil/src/swap_status_misc.c b/boot/bootutil/src/swap_status_misc.c
new file mode 100644
index 0000000..c8f8f95
--- /dev/null
+++ b/boot/bootutil/src/swap_status_misc.c
@@ -0,0 +1,718 @@
+/*
+ * 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.
+ */
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include "bootutil/bootutil.h"
+#include "bootutil_priv.h"
+#include "swap_priv.h"
+#include "bootutil/bootutil_log.h"
+
+#include "swap_status.h"
+
+#include "mcuboot_config/mcuboot_config.h"
+
+MCUBOOT_LOG_MODULE_DECLARE(mcuboot);
+
+#if defined(MCUBOOT_SWAP_USING_STATUS)
+
+#define BOOT_MAGIC_ARR_SZ \
+ (sizeof boot_img_magic / sizeof boot_img_magic[0])
+
+static int
+boot_find_status(int image_index, const struct flash_area **fap);
+
+static int
+boot_magic_decode(const uint32_t *magic)
+{
+ if (memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0) {
+ return BOOT_MAGIC_GOOD;
+ }
+ return BOOT_MAGIC_BAD;
+}
+
+static int
+boot_flag_decode(uint8_t flag)
+{
+ if (flag != (uint8_t)BOOT_FLAG_SET) {
+ return BOOT_FLAG_BAD;
+ }
+ return BOOT_FLAG_SET;
+}
+
+static inline size_t
+boot_status_sector_size(const struct boot_loader_state *state, size_t sector)
+{
+ return state->status.sectors[sector].fs_size;
+}
+
+static inline uint32_t
+boot_status_sector_off(const struct boot_loader_state *state,
+ size_t sector)
+{
+ return state->status.sectors[sector].fs_off -
+ state->status.sectors[0].fs_off;
+}
+
+/* Offset Section */
+static inline uint32_t
+boot_magic_off(const struct flash_area *fap)
+{
+ (void)fap;
+ return ((uint32_t)BOOT_SWAP_STATUS_D_SIZE_RAW - (uint32_t)BOOT_MAGIC_SZ);
+}
+
+uint32_t
+boot_image_ok_off(const struct flash_area *fap)
+{
+ return (uint32_t)(boot_magic_off(fap) - 1u);
+}
+
+uint32_t
+boot_copy_done_off(const struct flash_area *fap)
+{
+ return (uint32_t)(boot_image_ok_off(fap) - 1u);
+}
+
+uint32_t
+boot_swap_info_off(const struct flash_area *fap)
+{
+ return (uint32_t)(boot_copy_done_off(fap) - 1u);
+}
+
+uint32_t
+boot_swap_size_off(const struct flash_area *fap)
+{
+ return (uint32_t)(boot_swap_info_off(fap) - 4u);
+}
+
+uint32_t
+boot_status_off(const struct flash_area *fap)
+{
+ (void)fap;
+ /* this offset is equal to 0, because swap status fields
+ in this implementation count from the start of partition */
+ return 0;
+}
+
+#ifdef MCUBOOT_ENC_IMAGES
+static inline uint32_t
+boot_enc_key_off(const struct flash_area *fap, uint8_t slot)
+{
+#ifdef MCUBOOT_SWAP_SAVE_ENCTLV
+ /* suggest encryption key is also stored in status partition */
+ return (uint32_t)(boot_swap_size_off(fap) - (uint32_t)((slot + 1u) * (uint32_t)BOOT_ENC_TLV_SIZE));
+#else
+ return (uint32_t)(boot_swap_size_off(fap) - (uint32_t)((slot + 1u) * (uint32_t)BOOT_ENC_KEY_SIZE));
+#endif
+}
+#endif
+
+/**
+ * Write trailer data; status bytes, swap_size, etc
+ *
+ * @returns 0 on success, != 0 on error.
+ */
+int
+boot_write_trailer(const struct flash_area *fap, uint32_t off,
+ const uint8_t *inbuf, uint8_t inlen)
+{
+ int rc;
+
+ rc = swap_status_update(fap->fa_id, off, (uint8_t *)inbuf, inlen);
+
+ if (rc != 0) {
+ return BOOT_EFLASH;
+ }
+ return rc;
+}
+
+#ifdef MCUBOOT_ENC_IMAGES
+int
+boot_write_enc_key(const struct flash_area *fap, uint8_t slot,
+ const struct boot_status *bs)
+{
+ uint32_t off;
+ int rc;
+
+ off = boot_enc_key_off(fap, slot);
+#ifdef MCUBOOT_SWAP_SAVE_ENCTLV
+ rc = swap_status_update(fap->fa_id, off,
+ (uint8_t *) bs->enctlv[slot], BOOT_ENC_TLV_ALIGN_SIZE);
+#else
+ rc = swap_status_update(fap->fa_id, off,
+ (uint8_t *) bs->enckey[slot], BOOT_ENC_KEY_SIZE);
+#endif
+ if (rc != 0) {
+ return BOOT_EFLASH;
+ }
+
+ return 0;
+}
+
+int
+boot_read_enc_key(int image_index, uint8_t slot, struct boot_status *bs)
+{
+ uint32_t off;
+ const struct flash_area *fap;
+#ifdef MCUBOOT_SWAP_SAVE_ENCTLV
+ int i;
+#endif
+ int rc;
+
+ rc = boot_find_status(image_index, &fap);
+ if (rc == 0) {
+ off = boot_enc_key_off(fap, slot);
+#ifdef MCUBOOT_SWAP_SAVE_ENCTLV
+ rc = swap_status_retrieve(fap->fa_id, off, bs->enctlv[slot], BOOT_ENC_TLV_ALIGN_SIZE);
+ if (rc == 0) {
+ for (i = 0; i < BOOT_ENC_TLV_ALIGN_SIZE; i++) {
+ if (bs->enctlv[slot][i] != 0xff) {
+ break;
+ }
+ }
+ /* Only try to decrypt non-erased TLV metadata */
+ if (i != BOOT_ENC_TLV_ALIGN_SIZE) {
+ rc = boot_enc_decrypt(bs->enctlv[slot], bs->enckey[slot]);
+ }
+ }
+#else
+ rc = swap_status_retrieve(fap->fa_id, off, bs->enckey[slot], BOOT_ENC_KEY_SIZE);
+#endif
+ flash_area_close(fap);
+ }
+
+ return rc;
+}
+#endif /* MCUBOOT_ENC_IMAGES */
+
+/* Write Section */
+int
+boot_write_magic(const struct flash_area *fap)
+{
+ uint32_t off;
+ int rc;
+
+ off = boot_magic_off(fap);
+
+ rc = swap_status_update(fap->fa_id, off,
+ (uint8_t *) boot_img_magic, BOOT_MAGIC_SZ);
+
+ if (rc != 0) {
+ return BOOT_EFLASH;
+ }
+ return 0;
+}
+
+int boot_status_num_sectors(const struct boot_loader_state *state)
+{
+ return (int)(BOOT_SWAP_STATUS_SIZE / boot_status_sector_size(state, 0));
+}
+
+/**
+ * Writes the supplied boot status to the flash file system. The boot status
+ * contains the current state of an in-progress image copy operation.
+ *
+ * @param bs The boot status to write.
+ *
+ * @return 0 on success; nonzero on failure.
+ */
+int
+boot_write_status(const struct boot_loader_state *state, struct boot_status *bs)
+{
+ const struct flash_area *fap = NULL;
+ uint32_t off;
+ int area_id;
+ int rc;
+ (void)state;
+
+ /* NOTE: The first sector copied (that is the last sector on slot) contains
+ * the trailer. Since in the last step the primary slot is erased, the
+ * first two status writes go to the scratch which will be copied to
+ * the primary slot!
+ */
+
+#ifdef MCUBOOT_SWAP_USING_SCRATCH
+ if (bs->use_scratch) {
+ /* Write to scratch status. */
+ area_id = FLASH_AREA_IMAGE_SCRATCH;
+ } else
+#endif
+ {
+ /* Write to the primary slot. */
+ area_id = (int)FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state));
+ }
+
+ rc = flash_area_open((uint8_t)area_id, &fap);
+ if (rc != 0) {
+ rc = BOOT_EFLASH;
+ goto done;
+ }
+ off = boot_status_off(fap) + boot_status_internal_off(bs, 1);
+
+ uint8_t tmp_state = bs->state;
+
+ rc = swap_status_update(fap->fa_id, off, &tmp_state, 1);
+ if (rc != 0) {
+ rc = BOOT_EFLASH;
+ goto done;
+ }
+
+done:
+ flash_area_close(fap);
+
+ return rc;
+}
+
+int
+boot_read_data_empty(const struct flash_area *fap, void *data, uint32_t len)
+{
+ uint8_t *buf;
+
+ buf = (uint8_t *)data;
+ for (uint32_t i = 0; i < len; i++) {
+ if (buf[i] != flash_area_erased_val(fap)) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+int
+boot_read_swap_state(const struct flash_area *fap,
+ struct boot_swap_state *state)
+{
+ uint32_t magic[BOOT_MAGIC_ARR_SZ];
+ uint32_t off;
+ uint32_t trailer_off = 0U;
+ uint8_t swap_info = 0U;
+ int rc;
+ uint32_t erase_trailer = 0;
+
+ const struct flash_area *fap_stat = NULL;
+
+ rc = flash_area_open(FLASH_AREA_IMAGE_SWAP_STATUS, &fap_stat);
+ if (rc != 0) {
+ return BOOT_EFLASH;
+ }
+
+ off = boot_magic_off(fap);
+ /* retrieve value for magic field from status partition area */
+ rc = swap_status_retrieve(fap->fa_id, off, magic, BOOT_MAGIC_SZ);
+ if (rc < 0) {
+ return BOOT_EFLASH;
+ }
+ rc = boot_read_data_empty(fap_stat, magic, BOOT_MAGIC_SZ);
+ if (rc < 0) {
+ return BOOT_EFLASH;
+ }
+ /* fill magic number value if equal to expected */
+ if (rc == 1) {
+
+ state->magic = BOOT_MAGIC_UNSET;
+
+ /* attempt to find magic in upgrade img slot trailer */
+ if (fap->fa_id == FLASH_AREA_IMAGE_1 ||
+ fap->fa_id == FLASH_AREA_IMAGE_3) {
+
+ trailer_off = fap->fa_size - BOOT_MAGIC_SZ;
+
+ rc = flash_area_read_is_empty(fap, trailer_off, magic, BOOT_MAGIC_SZ);
+ if (rc < 0) {
+ return BOOT_EFLASH;
+ }
+ if (rc == 1) {
+ state->magic = BOOT_MAGIC_UNSET;
+ } else {
+ state->magic = (uint8_t)boot_magic_decode(magic);
+ /* put magic to status partition for upgrade slot*/
+ if (state->magic == (uint32_t)BOOT_MAGIC_GOOD) {
+ rc = swap_status_update(fap->fa_id, off,
+ (uint8_t *) magic, BOOT_MAGIC_SZ);
+ }
+ if (rc < 0) {
+ return BOOT_EFLASH;
+ } else {
+ erase_trailer = 1;
+ }
+ }
+ }
+ } else {
+ state->magic = (uint8_t)boot_magic_decode(magic);
+ }
+
+ off = boot_swap_info_off(fap);
+ rc = swap_status_retrieve(fap->fa_id, off, &swap_info, sizeof swap_info);
+ if (rc < 0) {
+ return BOOT_EFLASH;
+ }
+ rc = boot_read_data_empty(fap_stat, &swap_info, sizeof swap_info);
+ if (rc < 0) {
+ return BOOT_EFLASH;
+ }
+ if (rc == 1 || state->swap_type > (uint8_t)BOOT_SWAP_TYPE_REVERT) {
+ state->swap_type = (uint8_t)BOOT_SWAP_TYPE_NONE;
+ state->image_num = 0;
+ }
+ else {
+ /* Extract the swap type and image number */
+ state->swap_type = (uint8_t)BOOT_GET_SWAP_TYPE_M(swap_info);
+ state->image_num = (uint8_t)BOOT_GET_IMAGE_NUM_M(swap_info);
+ }
+
+ off = boot_copy_done_off(fap);
+ rc = swap_status_retrieve(fap->fa_id, off, &state->copy_done, sizeof state->copy_done);
+ if (rc < 0) {
+ return BOOT_EFLASH;
+ }
+ rc = boot_read_data_empty(fap_stat, &state->copy_done, sizeof state->copy_done);
+ /* need to check swap_info was empty */
+ if (rc < 0) {
+ return BOOT_EFLASH;
+ }
+ if (rc == 1) {
+ state->copy_done = BOOT_FLAG_UNSET;
+ } else {
+ state->copy_done = (uint8_t)boot_flag_decode(state->copy_done);
+ }
+
+ off = boot_image_ok_off(fap);
+ rc = swap_status_retrieve(fap->fa_id, off, &state->image_ok, sizeof state->image_ok);
+ if (rc < 0) {
+ return BOOT_EFLASH;
+ }
+ rc = boot_read_data_empty(fap_stat, &state->image_ok, sizeof state->image_ok);
+ /* need to check swap_info was empty */
+ if (rc < 0) {
+ return BOOT_EFLASH;
+ }
+ if (rc == 1) {
+ /* assign img_ok unset */
+ state->image_ok = BOOT_FLAG_UNSET;
+
+ /* attempt to read img_ok value in upgrade img slots trailer area
+ * it is set when image in slot for upgrade is signed for swap_type permanent
+ */
+ uint32_t process_image_ok = 0;
+ switch (fap->fa_id) {
+ case FLASH_AREA_IMAGE_0:
+ case FLASH_AREA_IMAGE_2:
+ {
+ if (state->copy_done == (uint8_t)BOOT_FLAG_SET)
+ process_image_ok = 1;
+ }
+ break;
+ case FLASH_AREA_IMAGE_1:
+ case FLASH_AREA_IMAGE_3:
+ {
+ process_image_ok = 1;
+ }
+ break;
+ case FLASH_AREA_IMAGE_SCRATCH:
+ {
+ BOOT_LOG_DBG(" * selected SCRATCH area, copy_done = %d", state->copy_done);
+ {
+ if (state->copy_done == (uint8_t)BOOT_FLAG_SET)
+ process_image_ok = 1;
+ }
+ }
+ break;
+ default:
+ {
+ return BOOT_EFLASH;
+ }
+ break;
+ }
+ if (process_image_ok != 0u) {
+ trailer_off = fap->fa_size - (uint8_t)BOOT_MAGIC_SZ - (uint8_t)BOOT_MAX_ALIGN;
+
+ rc = flash_area_read_is_empty(fap, trailer_off, &state->image_ok, sizeof state->image_ok);
+ if (rc < 0) {
+ return BOOT_EFLASH;
+ }
+ if (rc == 1) {
+ state->image_ok = BOOT_FLAG_UNSET;
+ } else {
+ state->image_ok = (uint8_t)boot_flag_decode(state->image_ok);
+
+ /* put img_ok to status partition for upgrade slot */
+ if (state->image_ok != (uint8_t)BOOT_FLAG_BAD) {
+ rc = swap_status_update(fap->fa_id, off,
+ &state->image_ok, sizeof state->image_ok);
+ }
+ if (rc < 0) {
+ return BOOT_EFLASH;
+ }
+
+ /* mark img trailer needs to be erased */
+ erase_trailer = 1;
+ }
+ }
+ } else {
+ state->image_ok = (uint8_t)boot_flag_decode(state->image_ok);
+ }
+
+ if ((erase_trailer != 0u) && (fap->fa_id != FLASH_AREA_IMAGE_SCRATCH)) {
+ /* erase magic from upgrade img trailer */
+ rc = flash_area_erase(fap, trailer_off, BOOT_MAGIC_SZ);
+ if (rc != 0)
+ return rc;
+ }
+ return 0;
+}
+
+/**
+ * This functions tries to locate the status area after an aborted swap,
+ * by looking for the magic in the possible locations.
+ *
+ * If the magic is successfully found, a flash_area * is returned and it
+ * is the responsibility of the called to close it.
+ *
+ * @returns 0 on success, -1 on errors
+ */
+static int
+boot_find_status(int image_index, const struct flash_area **fap)
+{
+ uint32_t magic[BOOT_MAGIC_ARR_SZ] = {0};
+ uint32_t off;
+
+ /* the status is always in status partition */
+ uint8_t area = FLASH_AREA_IMAGE_PRIMARY((uint32_t)image_index);
+ int rc = -1;
+
+ /*
+ * In the middle a swap, tries to locate the area that is currently
+ * storing a valid magic, first on the primary slot, then on scratch.
+ * Both "slots" can end up being temporary storage for a swap and it
+ * is assumed that if magic is valid then other metadata is too,
+ * because magic is always written in the last step.
+ */
+ rc = flash_area_open(area, fap);
+ if (rc != 0) {
+ return rc;
+ }
+ off = boot_magic_off(*fap);
+ rc = swap_status_retrieve(area, off, magic, BOOT_MAGIC_SZ);
+
+ if (rc == 0) {
+ rc = memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ);
+ }
+
+ flash_area_close(*fap);
+ return rc;
+}
+
+int
+boot_read_swap_size(int image_index, uint32_t *swap_size)
+{
+ uint32_t off;
+ const struct flash_area *fap;
+ int rc;
+
+ rc = boot_find_status(image_index, &fap);
+ if (rc == 0) {
+ off = boot_swap_size_off(fap);
+
+ rc = swap_status_retrieve(fap->fa_id, off, swap_size, sizeof *swap_size);
+ }
+ return rc;
+}
+
+int
+swap_erase_trailer_sectors(const struct boot_loader_state *state,
+ const struct flash_area *fap)
+{
+ uint32_t sub_offs, trailer_offs;
+ uint32_t sz;
+ uint8_t fa_id_primary;
+ uint8_t fa_id_secondary;
+ uint8_t image_index;
+ int rc;
+ (void)state;
+
+ BOOT_LOG_INF("Erasing trailer; fa_id=%d", fap->fa_id);
+ /* trailer is located in status-partition */
+ const struct flash_area *fap_stat = NULL;
+
+ rc = flash_area_open(FLASH_AREA_IMAGE_SWAP_STATUS, &fap_stat);
+ if (rc != 0) {
+ return BOOT_EFLASH;
+ }
+
+ if (fap->fa_id != FLASH_AREA_IMAGE_SCRATCH)
+ {
+ image_index = BOOT_CURR_IMG(state);
+ fa_id_primary = (uint8_t)flash_area_id_from_multi_image_slot((int32_t)image_index,
+ BOOT_PRIMARY_SLOT);
+ fa_id_secondary = (uint8_t)flash_area_id_from_multi_image_slot((int32_t)image_index,
+ BOOT_SECONDARY_SLOT);
+
+ /* skip if Flash Area is not recognizable */
+ if ((fap->fa_id != fa_id_primary) && (fap->fa_id != fa_id_secondary)) {
+ return BOOT_EFLASH;
+ }
+ }
+
+ sub_offs = (uint32_t)swap_status_init_offset(fap->fa_id);
+
+ /* delete starting from last sector and moving to beginning */
+ /* calculate last sector of status sub-area */
+ sz = (uint32_t)BOOT_SWAP_STATUS_SIZE;
+
+ rc = flash_area_erase(fap_stat, sub_offs, sz);
+ assert((int)(rc == 0));
+
+ if (fap->fa_id != FLASH_AREA_IMAGE_SCRATCH)
+ {
+ /*
+ * it is also needed to erase trailer area in slots since they may contain
+ * data, which is already cleared in corresponding status partition
+ */
+ trailer_offs = fap->fa_size - BOOT_SWAP_STATUS_TRAILER_SIZE;
+ rc = flash_area_erase(fap, trailer_offs, BOOT_SWAP_STATUS_TRAILER_SIZE);
+ }
+
+ flash_area_close(fap_stat);
+
+ return rc;
+}
+
+int
+swap_status_init(const struct boot_loader_state *state,
+ const struct flash_area *fap,
+ const struct boot_status *bs)
+{
+ struct boot_swap_state swap_state;
+ uint8_t image_index;
+ int rc;
+
+#if (BOOT_IMAGE_NUMBER == 1)
+ (void)state;
+#endif
+
+ image_index = BOOT_CURR_IMG(state);
+
+ BOOT_LOG_DBG("initializing status; fa_id=%d", fap->fa_id);
+
+ rc = boot_read_swap_state_by_id((int32_t)FLASH_AREA_IMAGE_SECONDARY(image_index),
+ &swap_state);
+ assert((int)(rc == 0));
+
+ if (bs->swap_type != (uint8_t)BOOT_SWAP_TYPE_NONE) {
+ rc = boot_write_swap_info(fap, bs->swap_type, image_index);
+ assert((int)(rc == 0));
+ }
+
+ if (swap_state.image_ok == (uint8_t)BOOT_FLAG_SET) {
+ rc = boot_write_image_ok(fap);
+ assert((int)(rc == 0));
+ }
+
+ rc = boot_write_swap_size(fap, bs->swap_size);
+ assert((int)(rc == 0));
+
+#ifdef MCUBOOT_ENC_IMAGES
+ rc = boot_write_enc_key(fap, 0, bs);
+ assert((int)(rc == 0));
+
+ rc = boot_write_enc_key(fap, 1, bs);
+ assert((int)(rc == 0));
+#endif
+
+ rc = boot_write_magic(fap);
+ assert((int)(rc == 0));
+
+ return 0;
+}
+
+int
+swap_read_status(struct boot_loader_state *state, struct boot_status *bs)
+{
+ const struct flash_area *fap = NULL;
+ const struct flash_area *fap_stat = NULL;
+ uint32_t off;
+ uint8_t swap_info = 0;
+ int area_id;
+ int rc = 0;
+
+ bs->source = swap_status_source(state);
+
+ if (bs->source == BOOT_STATUS_SOURCE_NONE) {
+ return 0;
+ }
+
+ if (bs->source == BOOT_STATUS_SOURCE_PRIMARY_SLOT) {
+ area_id = (int32_t)FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state));
+ } else if (bs->source == BOOT_STATUS_SOURCE_SCRATCH) {
+ area_id = FLASH_AREA_IMAGE_SCRATCH;
+ } else {
+ return BOOT_EBADARGS;
+ }
+
+ rc = flash_area_open((uint8_t)area_id, &fap);
+ if (rc != 0) {
+ return BOOT_EFLASH;
+ }
+
+ rc = flash_area_open(FLASH_AREA_IMAGE_SWAP_STATUS, &fap_stat);
+ if (rc != 0) {
+ return BOOT_EFLASH;
+ }
+
+ rc = swap_read_status_bytes(fap, state, bs);
+ if (rc == 0) {
+ off = boot_swap_info_off(fap);
+ rc = swap_status_retrieve((uint8_t)area_id, off, &swap_info, sizeof swap_info);
+ if (rc < 0) {
+ return BOOT_EFLASH;
+ }
+ rc = boot_read_data_empty(fap_stat, &swap_info, sizeof swap_info);
+ if (rc < 0) {
+ return BOOT_EFLASH;
+ }
+
+ if (rc == 1) {
+ BOOT_SET_SWAP_INFO_M(swap_info, 0u, (uint8_t)BOOT_SWAP_TYPE_NONE);
+ rc = 0;
+ }
+
+ /* Extract the swap type info */
+ bs->swap_type = BOOT_GET_SWAP_TYPE_M(swap_info);
+ }
+
+ flash_area_close(fap);
+ flash_area_close(fap_stat);
+
+ return rc;
+}
+
+#endif /* MCUBOOT_SWAP_USING_STATUS */
diff --git a/boot/bootutil/src/swap_status_part.c b/boot/bootutil/src/swap_status_part.c
new file mode 100644
index 0000000..a2899a9
--- /dev/null
+++ b/boot/bootutil/src/swap_status_part.c
@@ -0,0 +1,404 @@
+/*
+ * 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.
+ */
+
+#include <assert.h>
+#include "crc32c.h"
+#include <string.h>
+#include "swap_status.h"
+
+#ifdef MCUBOOT_SWAP_USING_STATUS
+
+#define IMAGE_0_STATUS_OFFS 0
+#define IMAGE_0_STATUS_SIZE (BOOT_SWAP_STATUS_SIZE)
+
+#define IMAGE_1_STATUS_OFFS (IMAGE_0_STATUS_OFFS + IMAGE_0_STATUS_SIZE)
+#define IMAGE_1_STATUS_SIZE (BOOT_SWAP_STATUS_SIZE)
+
+#define SCRATCH_STATUS_OFFS (IMAGE_1_STATUS_OFFS + BOOT_SWAP_STATUS_SIZE)
+#ifdef MCUBOOT_SWAP_USING_SCRATCH
+#define SCRATCH_STATUS_SIZE (BOOT_SWAP_STATUS_SIZE)
+#else
+#define SCRATCH_STATUS_SIZE 0
+#endif
+
+#if (MCUBOOT_IMAGE_NUMBER == 2)
+#define IMAGE_2_STATUS_OFFS (SCRATCH_STATUS_OFFS + SCRATCH_STATUS_SIZE)
+#define IMAGE_2_STATUS_SIZE (BOOT_SWAP_STATUS_SIZE)
+
+#define IMAGE_3_STATUS_OFFS (IMAGE_2_STATUS_OFFS + IMAGE_2_STATUS_SIZE)
+#define IMAGE_3_STATUS_SIZE (BOOT_SWAP_STATUS_SIZE)
+#endif
+
+const uint32_t stat_part_magic[] = {
+ BOOT_SWAP_STATUS_MAGIC
+};
+
+uint32_t calc_rec_idx(uint32_t value)
+{
+ uint32_t rec_idx;
+
+ rec_idx = value/BOOT_SWAP_STATUS_PAYLD_SZ;
+
+ return rec_idx;
+}
+
+uint32_t calc_record_offs(uint32_t offs)
+{
+ uint32_t rec_offs;
+
+ rec_offs = BOOT_SWAP_STATUS_ROW_SZ*calc_rec_idx(offs);
+
+ return rec_offs;
+}
+
+uint32_t calc_record_crc(const uint8_t *data, uint32_t length)
+{
+ uint32_t crc;
+
+ crc = crc32c_checksum(data, length);
+
+ return crc;
+}
+
+int32_t swap_status_init_offset(uint32_t area_id)
+{
+ int32_t offset = -1;
+ /* calculate an offset caused by area type: primary_x/secondary_x */
+ switch (area_id) {
+ case FLASH_AREA_IMAGE_0:
+ offset = (int)IMAGE_0_STATUS_OFFS;
+ break;
+ case FLASH_AREA_IMAGE_1:
+ offset = (int)IMAGE_1_STATUS_OFFS;
+ break;
+#ifdef MCUBOOT_SWAP_USING_SCRATCH
+ case FLASH_AREA_IMAGE_SCRATCH:
+ offset = (int)SCRATCH_STATUS_OFFS;
+ break;
+#endif
+#if (MCUBOOT_IMAGE_NUMBER == 2)
+ case FLASH_AREA_IMAGE_2:
+ offset = (int)IMAGE_2_STATUS_OFFS;
+ break;
+ case FLASH_AREA_IMAGE_3:
+ offset = (int)IMAGE_3_STATUS_OFFS;
+ break;
+#endif
+ default:
+ offset = -1;
+ break;
+ }
+ return offset;
+}
+
+int swap_status_read_record(uint32_t rec_offset, uint8_t *data, uint32_t *copy_counter)
+{ /* returns BOOT_SWAP_STATUS_PAYLD_SZ of data */
+ int rc = -1;
+
+ uint32_t fin_offset;
+ uint32_t data_offset = 0;
+ uint32_t counter, crc, magic;
+ uint32_t crc_fail = 0;
+ uint32_t magic_fail = 0;
+ uint32_t max_cnt = 0;
+
+ int32_t max_idx = 0;
+
+ uint8_t buff[BOOT_SWAP_STATUS_ROW_SZ];
+
+ const struct flash_area *fap_stat = NULL;
+
+ rc = flash_area_open(FLASH_AREA_IMAGE_SWAP_STATUS, &fap_stat);
+ if (rc != 0) {
+ return BOOT_EFLASH;
+ }
+
+ /* loop over copies/duplicates */
+ for(uint32_t i = 0; i<BOOT_SWAP_STATUS_MULT; i++) {
+ /* calculate final duplicate offset */
+ fin_offset = rec_offset + i*BOOT_SWAP_STATUS_D_SIZE;
+
+ rc = flash_area_read(fap_stat, fin_offset, buff, sizeof(buff));
+ if (rc != 0) {
+ return BOOT_EFLASH;
+ }
+ /* read magic value to know if area was pre-erased */
+ magic = *((uint32_t *)&buff[BOOT_SWAP_STATUS_ROW_SZ -\
+ BOOT_SWAP_STATUS_MGCREC_SZ -\
+ BOOT_SWAP_STATUS_CNT_SZ-\
+ BOOT_SWAP_STATUS_CRC_SZ]);
+ if (magic == BOOT_SWAP_STATUS_MAGIC) { /* read CRC */
+ crc = *((uint32_t *)&buff[BOOT_SWAP_STATUS_ROW_SZ -\
+ BOOT_SWAP_STATUS_CRC_SZ]);
+ /* check record data integrity first */
+ if (crc == calc_record_crc(buff, BOOT_SWAP_STATUS_ROW_SZ-BOOT_SWAP_STATUS_CRC_SZ)) {
+ /* look for counter */
+ counter = *((uint32_t *)&buff[BOOT_SWAP_STATUS_ROW_SZ -\
+ BOOT_SWAP_STATUS_CNT_SZ - \
+ BOOT_SWAP_STATUS_CRC_SZ]);
+ /* find out counter max */
+ if (counter >= max_cnt) {
+ max_cnt = counter;
+ max_idx = (int32_t)i;
+ data_offset = fin_offset;
+ }
+ }
+ /* if crc != calculated() */
+ else {
+ crc_fail++;
+ }
+ }
+ else {
+ magic_fail++;
+ }
+ }
+ /* no magic found - status area is pre-erased, start from scratch */
+ if (magic_fail == BOOT_SWAP_STATUS_MULT) {
+ /* emulate last index was received, so next will start from beginning */
+ max_idx = (int32_t)(BOOT_SWAP_STATUS_MULT-1U);
+ *copy_counter = 0;
+ /* return all erased values */
+ (void)memset(data, (int32_t)flash_area_erased_val(fap_stat), BOOT_SWAP_STATUS_PAYLD_SZ);
+ }
+ else {
+ /* no valid CRC found - status pre-read failure */
+ if (crc_fail == BOOT_SWAP_STATUS_MULT) {
+ max_idx = -1;
+ }
+ else {
+ *copy_counter = max_cnt;
+ /* read payload data */
+ rc = flash_area_read(fap_stat, data_offset, data, BOOT_SWAP_STATUS_PAYLD_SZ);
+ if (rc != 0) {
+ return BOOT_EFLASH;
+ }
+ }
+ }
+ flash_area_close(fap_stat);
+
+ /* return back duplicate index */
+ return max_idx;
+}
+
+static int swap_status_write_record(uint32_t rec_offset, uint32_t copy_num, uint32_t copy_counter, const uint8_t *data)
+{ /* it receives explicitly BOOT_SWAP_STATUS_PAYLD_SZ of data */
+ int rc = -1;
+
+ uint32_t fin_offset;
+ /* increment counter field */
+ uint32_t next_counter = copy_counter + 1U;
+ uint32_t next_crc;
+
+ uint8_t buff[BOOT_SWAP_STATUS_ROW_SZ];
+
+ const struct flash_area *fap_stat = NULL;
+
+ rc = flash_area_open(FLASH_AREA_IMAGE_SWAP_STATUS, &fap_stat);
+ if (rc != 0) {
+ return BOOT_EFLASH;
+ }
+
+ /* copy data into buffer */
+ (void)memcpy(buff, data, BOOT_SWAP_STATUS_PAYLD_SZ);
+ /* append next counter to whole record row */
+ (void)memcpy(&buff[BOOT_SWAP_STATUS_ROW_SZ-BOOT_SWAP_STATUS_CNT_SZ-BOOT_SWAP_STATUS_CRC_SZ], \
+ &next_counter, \
+ BOOT_SWAP_STATUS_CNT_SZ);
+ /* append record magic */
+ (void)memcpy(&buff[BOOT_SWAP_STATUS_ROW_SZ-\
+ BOOT_SWAP_STATUS_MGCREC_SZ-\
+ BOOT_SWAP_STATUS_CNT_SZ-\
+ BOOT_SWAP_STATUS_CRC_SZ], \
+ stat_part_magic, \
+ BOOT_SWAP_STATUS_MGCREC_SZ);
+
+ /* calculate CRC field*/
+ next_crc = calc_record_crc(buff, BOOT_SWAP_STATUS_ROW_SZ-BOOT_SWAP_STATUS_CRC_SZ);
+
+ /* append new CRC to whole record row */
+ (void)memcpy(&buff[BOOT_SWAP_STATUS_ROW_SZ-BOOT_SWAP_STATUS_CRC_SZ], \
+ &next_crc, \
+ BOOT_SWAP_STATUS_CRC_SZ);
+
+ /* we already know what copy number was last and correct */
+ /* increment duplicate index */
+ /* calculate final duplicate offset */
+ if (copy_num == (BOOT_SWAP_STATUS_MULT - 1U)) {
+ copy_num = 0;
+ }
+ else {
+ copy_num++;
+ }
+ fin_offset = rec_offset + copy_num*BOOT_SWAP_STATUS_D_SIZE;
+
+ /* write prepared record into flash */
+ rc = flash_area_write(fap_stat, fin_offset, buff, sizeof(buff));
+
+ flash_area_close(fap_stat);
+
+ return rc;
+}
+
+/**
+ * Updates len bytes of status partition with values from *data-pointer.
+ *
+ * @param targ_area_id Target area id for which status is being written.
+ * Not a status-partition area id.
+ * @param offset Status byte offset inside status table. Should not include CRC and CNT.
+ * @param data Pointer to data status table to needs to be updated with.
+ * @param len Number of bytes to be written
+ *
+ * @return 0 on success; nonzero on failure.
+ */
+int swap_status_update(uint32_t targ_area_id, uint32_t offs, const void *data, uint32_t len)
+{
+ int rc = -1;
+
+ int32_t init_offs;
+ int32_t length = (int32_t)len;
+ int32_t copy_num;
+
+ uint32_t rec_offs;
+ uint32_t copy_sz;
+ uint32_t copy_counter;
+ uint32_t data_idx = 0;
+ uint32_t buff_idx = offs%BOOT_SWAP_STATUS_PAYLD_SZ;
+
+ uint8_t buff[BOOT_SWAP_STATUS_PAYLD_SZ];
+
+ /* check if end of data is still inside writable area */
+ assert ((int)((offs + len) <= BOOT_SWAP_STATUS_D_SIZE_RAW));
+
+ /* pre-calculate sub-area offset */
+ init_offs = swap_status_init_offset(targ_area_id);
+ assert ((int)(init_offs >= 0));
+
+ /* will start from it
+ * this will be write-aligned */
+ rec_offs = (uint32_t)init_offs + calc_record_offs(offs);
+
+ /* go over all records to be updated */
+ while (length > 0) {
+ /* preserve record */
+ copy_num = swap_status_read_record(rec_offs, buff, ©_counter);
+ /* it returns copy number */
+ if (copy_num < 0)
+ { /* something went wrong while read, exit */
+ rc = -1;
+ break;
+ }
+ /* update record data */
+ if (length > (int)BOOT_SWAP_STATUS_PAYLD_SZ) {
+ copy_sz = BOOT_SWAP_STATUS_PAYLD_SZ - buff_idx;
+ }
+ else {
+ copy_sz = (uint32_t)length;
+ }
+ (void)memcpy((void *)&buff[buff_idx], &((uint8_t *)data)[data_idx], copy_sz);
+ buff_idx = 0;
+
+ /* write record back */
+ rc = swap_status_write_record(rec_offs, (uint32_t)copy_num, copy_counter, buff);
+ assert ((int)(rc == 0));
+
+ /* proceed to next record */
+ length -= (int32_t)BOOT_SWAP_STATUS_PAYLD_SZ;
+ rec_offs += BOOT_SWAP_STATUS_ROW_SZ;
+ data_idx += BOOT_SWAP_STATUS_PAYLD_SZ;
+ }
+ return rc;
+}
+
+/**
+ * Reads len bytes of status partition with values from *data-pointer.
+ *
+ * @param targ_area_id Target area id for which status is being read.
+ * Not a status-partition area id.
+ * @param offset Status byte offset inside status table. Should not include CRC and CNT.
+ * @param data Pointer to data where status table values will be written.
+ * @param len Number of bytes to be read from status table.
+ *
+ * @return 0 on success; nonzero on failure.
+ */
+int swap_status_retrieve(uint32_t target_area_id, uint32_t offs, void *data, uint32_t len)
+{
+ int rc = 0;
+
+ int32_t init_offs;
+ int32_t length = (int32_t)len;
+ int32_t copy_num;
+
+ uint32_t rec_offs;
+ uint32_t copy_sz;
+ uint32_t copy_counter;
+ uint32_t data_idx = 0;
+ uint32_t buff_idx = offs % BOOT_SWAP_STATUS_PAYLD_SZ;
+
+ uint8_t buff[BOOT_SWAP_STATUS_PAYLD_SZ];
+
+ /* check if end of data is still inside writable area */
+ // TODO: update for multi image
+ assert ((int)((offs + len) <= BOOT_SWAP_STATUS_D_SIZE_RAW));
+
+ /* pre-calculate sub-area offset */
+ init_offs = swap_status_init_offset(target_area_id);
+ assert ((int)(init_offs >= 0));
+
+ /* will start from it
+ * this will be write-aligned */
+ rec_offs = (uint32_t)init_offs + calc_record_offs(offs);
+
+ /* go over all records to be updated */
+ while (length > 0) {
+ /* preserve record */
+ copy_num = swap_status_read_record(rec_offs, buff, ©_counter);
+ /* it returns copy number */
+ if (copy_num < 0) {
+ /* something went wrong while read, exit */
+ rc = -1;
+ break;
+ }
+ /* update record data */
+ if (length > (int)BOOT_SWAP_STATUS_PAYLD_SZ) {
+ copy_sz = BOOT_SWAP_STATUS_PAYLD_SZ - buff_idx;
+ }
+ else {
+ copy_sz = (uint32_t)length;
+ }
+ (void)memcpy(&((uint8_t *)data)[data_idx], &buff[buff_idx], copy_sz);
+ buff_idx = 0;
+
+ /* proceed to next record */
+ length -= (int32_t)BOOT_SWAP_STATUS_PAYLD_SZ;
+ rec_offs += BOOT_SWAP_STATUS_ROW_SZ;
+ data_idx += BOOT_SWAP_STATUS_PAYLD_SZ;
+ }
+ return rc;
+}
+
+#endif /* MCUBOOT_SWAP_USING_STATUS */
diff --git a/boot/cypress/BlinkyApp/BlinkyApp.md b/boot/cypress/BlinkyApp/BlinkyApp.md
new file mode 100644
index 0000000..d380673
--- /dev/null
+++ b/boot/cypress/BlinkyApp/BlinkyApp.md
@@ -0,0 +1,265 @@
+### Blinking LED Test Application For Mcubootapp Bootloading Application
+
+### Description
+
+Implements simple Blinky LED CM4 application to demonstrate MCUBootApp bootloading application operation in terms of boot and upgrade processes.
+
+It is validated and started by MCUBootApp which is running on CM0p core of PSoC 6 device.
+
+Functionality:
+
+* Blinks RED led with 2 different rates, depending on type of image - BOOT or UPGRADE.
+* Prints debug info and version of itself to terminal at 115200 baud rate.
+* Manages watchdog timer started in MCUBootApp as one of confirmation mechanisms.
+* Sets special bit in flash to confirm image is operable (UPGRADE image).
+* Can be built for BOOT slot or UPGRADE slot of bootloader.
+* Can be used to evaluate `swap` and `overwrite only` upgrade modes.
+
+### Hardware Limitations
+
+Since this application is created to demonstrate MCUBoot library features and not as reference examples some considerations are taken.
+
+1. Port/pin `P5_0` and `P5_1` used to configure serial port for debug prints. These pins are the most commonly used for serial port connection among available Cypress PSoC 6 kits. If you try to use custom hardware with this application - change definitions of `CY_DEBUG_UART_TX` and `CY_DEBUG_UART_RX` in `main.c` of BlinkyApp to port/pin pairs corresponding to your design.
+2. Port `GPIO_PRT13` pin `7U` used to define user connection LED. This pin is the most commonly used for USER_LED connection among available Cypress PSoC 6 kits. If you try to use custom hardware with this application - change definitions of `LED_PORT` and `LED_PIN` in `main.c` of BlinkyApp to port/pin pairs corresponding to your design.
+
+### Pre-build Action
+
+Pre-build action is implemented to define start address and size of flash, as well as RAM start address and size for BlinkyApp.
+
+These values are set by specifing following macros (default values shown):
+`SLOT_SIZE ?= 0x10000` - for slot located in internal flash
+`SLOT_SIZE ?= 0x40200` - for slot located in external flash
+
+For PSoC 6 2M devices:
+`DEFINES_APP += -DRAM_START=0x08040000`
+`DEFINES_APP += -DRAM_SIZE=0x10000`
+
+For PSoC 6 1M and 512K devices:
+`DEFINES_APP += -DRAM_START=0x08020000`
+`DEFINES_APP += -DRAM_SIZE=0x10000`
+
+For all devices:
+`DEFINES_APP += -DUSER_APP_START=0x10018000`
+
+in `boot/cypress/BlinkyApp.mk`.
+
+Pre-build action calls GCC preprocessor which replaces defines to particular values in `BlinkyApp_template.ld`.
+
+**Important**: make sure RAM areas of CM4-based BlinkyApp and CM0p-based MCUBootApp bootloader do not overlap.
+
+Memory (stack) corruption of CM0p application can cause failure if SystemCall-served operations invoked from CM4.
+
+### Building An Application
+
+Supported platforms:
+
+* PSOC_062_2M
+* PSOC_062_1M
+* PSOC_062_512K
+
+Root directory for build is **boot/cypress.**
+
+**Single image**
+
+The following command will build regular HEX file of a BlinkyApp for primary (BOOT) slot:
+
+ make app APP_NAME=BlinkyApp PLATFORM=PSOC_062_2M IMG_TYPE=BOOT
+
+_Note: HEADER_OFFSET=%SLOT_SIZE%_
+
+To build image for secondary (UPGRADE) slot to use in `swap` upgrade:
+
+ make app APP_NAME=BlinkyApp PLATFORM=PSOC_062_2M IMG_TYPE=UPGRADE HEADER_OFFSET=0x10000 SWAP_UPGRADE=1
+
+To build image for secondary (UPGRADE) slot to use in `overwrite only` upgrade:
+
+ make app APP_NAME=BlinkyApp PLATFORM=PSOC_062_2M IMG_TYPE=UPGRADE HEADER_OFFSET=0x10000 SWAP_UPGRADE=0
+
+To build image for primary (BOOT) image for custom slot size `0x70000`:
+
+ make app APP_NAME=BlinkyApp PLATFORM=PSOC_062_2M IMG_TYPE=BOOT SLOT_SIZE=0x70000
+
+To build image for secondary (UPGRADE) image for custom slot size `0x70000` to use in `swap` upgrade:
+
+ make app APP_NAME=BlinkyApp PLATFORM=PSOC_062_2M IMG_TYPE=UPGRADE SLOT_SIZE=0x70000 HEADER_OFFSET=0x70000 SWAP_UPGRADE=1
+
+**Multi image**
+
+`BlinkyApp` can be built to use in multi image bootloader configuration.
+
+To obtain appropriate hex files to use with multi image MCUBootApp, makefile flag `HEADER_OFFSET=` can be used.
+
+Example usage:
+
+Considering default config:
+
+* first image BOOT (PRIMARY) slot starts `0x10018000`
+* slot size `0x10000`
+* second image BOOT (PRIMARY) slot starts at `0x10038000`
+
+To obtain appropriate artifact for second image PRIMARY slot run this command:
+
+ make app APP_NAME=BlinkyApp PLATFORM=PSOC_062_2M IMG_TYPE=BOOT HEADER_OFFSET=0x20000
+
+*Note:* only 2 images are supported at the moment.
+
+**Upgrade mode dependency**
+
+`MCUBootApp` can upgrade image either by overwriting an image from a secondary slot to a primary slot or by swapping the two images.
+
+To build `BlinkyApp` for different upgrade mode `SWAP_UPGRADE` flag is used.
+
+`SWAP_UPGRADE=0` - for overwrite mode.
+`SWAP_UPGRADE=1` - for swap upgrade mode (default).
+
+**Upgrade image for external memory**
+
+To prepare MCUBootApp for work with external memory refer to `MCUBootApp/ExternalMemory.md`.
+
+To build `BlinkyApp` upgrade image for external memory use command:
+
+ make app APP_NAME=BlinkyApp PLATFORM=PSOC_062_2M IMG_TYPE=UPGRADE HEADER_OFFSET=0x7FE8000 ERASED_VALUE=0xff USE_EXTERNAL_FLASH=1
+
+`HEADER_OFFSET` defines the offset from original boot image address. This one in line above suggests secondary slot will start from `0x18000000`, which is a start of external memory related addreses on PSoC 6 devices.
+
+`ERASED_VALUE` defines the memory cell contents in erased state. It is `0x00` for PSoC 6 internal Flash and `0xff` for S25FL512S.
+
+In case of using muti-image configuration, upgrade image for second application can be built using next command:
+
+ make app APP_NAME=BlinkyApp PLATFORM=PSOC_062_2M IMG_TYPE=UPGRADE HEADER_OFFSET=0x8228000 ERASED_VALUE=0xff USE_EXTERNAL_FLASH=1
+
+Note: for S25FL512S block address should be mutiple of 0x40000.
+
+**Encrypted upgrade image**
+
+To prepare MCUBootApp for work with encrypted upgrade image please refer to `MCUBootApp/Readme.md`.
+
+To obtain encrypted upgrade image of BlinkyApp extra flag ENC_IMG=1 should be passed in command line, for example:
+
+ make app APP_NAME=BlinkyApp PLATFORM=PSOC_062_2M IMG_TYPE=UPGRADE HEADER_OFFSET=0x20000 ENC_IMG=1
+
+This also suggests user already placed corresponing *.pem key in \keys folder. The key variables are defined in root Makefile as SIGN_KEY_FILE and ENC_KEY_FILE
+
+### Complete Build Flags Description
+- `BUILDCFG` - configuration type
+ - Release
+ - Debug
+- `MAKEINFO` - build verbosity level
+ - 0 (default) - less build info
+ - 1 - verbose output of compilation
+- `PLATFORM`
+ - `PSOC_062_2M` - only supported now
+- `SLOT_SIZE` - size of primary/secondary slot of MCUBootApp this app will be used with
+ - 0x%VALUE%
+- `HEADER_OFFSET` - shift start address of image by value
+ - 0 (default) - no offset of output hex file
+ - 0x%VALUE% - offset for output hex file
+- `IMG_TYPE` - for which slot of MCUBootApp image is build
+ - `BOOT` (default) - build image for primary (BOOT) slot
+ - `UPGRADE` - build image for secondary (UPGRADE) slot
+- `SWAP_UPGRADE` - define upgrade mode type on `MCUBootApp` this app will be used with
+ - `0` - for overwrite mode.
+ - `1` - (default) for swap upgrade mode
+- `ERASED_VALUE` - define memory cell contents in erased state
+ - `0x0` - internal memory
+ - `0xff` - external memory
+- `TOOLCHAIN_PATH` - path to gcc compiler to use for build
+ - Example: TOOLCHAIN_PATH=/home/fw-security/ModusToolbox/tools_2.0/gcc-7.2.1
+ - Example: TOOLCHAIN_PATH=C:\gcc
+
+### Post-Build
+
+Post build action is executed at compile time for `BlinkyApp`. In case of build for `PSOC_062_2M`, `PSOC_062_1M`, `PSOC_062_512K` platforms it calls `imgtool` from `MCUBoot` scripts and adds signature to compiled image.
+
+Flags passed to `imgtool` for signature are defined in `SIGN_ARGS` variable in BlinkyApp.mk.
+
+### How To Program An Application
+
+There are couple ways of programming BlinkyApp firmware. Following instructions assume usage of one of Cypress development kits, for example `CY8CPROTO_062_4343W`.
+
+1. Direct usage of OpenOCD.
+
+OpenOCD package is supplied with ModusToolbox IDE and can be found in installation folder under `./tools_2.1/openocd`.
+
+Open terminal application - and execute following command after substitution `PATH_TO_APPLICATION.hex` and `OPENOCD` paths.
+
+Connect a board to your computer. Switch Kitprog3 to DAP-BULK mode by pressing `SW3 MODE` button until `LED2 STATUS` constantly shines.
+
+ export OPENOCD=/Applications/ModusToolbox/tools_2.1/openocd
+
+ ${OPENOCD}/bin/openocd -s ${OPENOCD}/scripts \
+ -f ${OPENOCD}/scripts/interface/kitprog3.cfg \
+ -f ${OPENOCD}/scripts/target/psoc6_2m.cfg \
+ -c "init; reset init; program PATH_TO_APPLICATION.hex" \
+ -c "resume; reset; exit"
+
+2. Using GUI tool `Cypress Programmer`
+
+Follow [link](https://www.cypress.com/products/psoc-programming-solutions) to download.
+
+Connect board to your computer. Switch Kitprog3 to DAP-BULK mode by pressing `SW3 MODE` button until `LED2 STATUS` constantly shines. Open `Cypress Programmer` and click `Connect`, then choose hex file: `MCUBootApp.hex` or `BlinkyApp.hex` and click `Program`. Check log to ensure programming success. Reset board.
+
+3. Using `DAPLINK`.
+
+Connect board to your computer. Switch embeded Kitprog3 to `DAPLINK` mode by pressing `SW3 MODE` button until `LED2 STATUS` blinks fast and mass storage device appeared in OS. Drag and drop `hex` files you wish to program to `DAPLINK` drive in your OS.
+
+**Hex file names to use for programming**
+
+`BlinkyApp` always produce build artifacts in 2 separate folders: `BlinkyApp/out/PSOC_062_2M/Debug/boot` and `BlinkyApp/out/PSOC_062_2M/Debug/upgrade`.
+
+These files are ready to be flashed to the board:
+
+* **BlinkyApp.hex** from `boot` folder
+* **BlinkyApp_upgrade.hex** from `upgrade` folder
+
+`BlinkyApp_unsigned.hex` hex file is also preserved in both cases for possible troubleshooting.
+
+**Important: When swap status upgrade mode used**
+
+ In case of using this application in a system with `swap` type of upgrade refer first to `MCUBootApp.md` section **SWAP/Expected lifecycle**.
+
+**BlinkyApp.hex** should be programmed to a device once. All firmware upgrades should be delivered using secondary (UPGRADE) slot thus **BlinkyApp_upgrade.hex** image.
+
+If user for some reason tries to program **BlinkyApp.hex** to primary slot directly second time - **system state should be reset**.
+
+To reset system state at least `swap status partition` area in flash should be erased - see addresses in `MCUBootApp.md` paragraph **Memory maps**.
+
+To erase swap status partition area in MCUBootApp with a single image configuration with default memory map using `OpenOCD` execute command:
+
+ $OPENOCD_PATH/bin/openocd -s "$OPENOCD_PATH/scripts" -f "$OPENOCD_PATH/ scripts/interface/kitprog3.cfg" -f "$OPENOCD_PATH/scripts/target/psoc6_2m.cfg" -c "init; reset init" -c "flash erase_address 0x10038000 0x1000" -c "reset; shutdown"
+
+To erase swap status partition area in MCUBootApp with a multi image configuration with default memory map using `OpenOCD` execute command:
+
+ $OPENOCD_PATH/bin/openocd -s "$OPENOCD_PATH/scripts" -f "$OPENOCD_PATH/ scripts/interface/kitprog3.cfg" -f "$OPENOCD_PATH/scripts/target/psoc6_2m.cfg" -c "init; reset init" -c "flash erase_address 0x10078000 0x2000" -c "reset; shutdown"
+
+In both cases it is easier to erase all device flash or all flash after MCUBootApp. This command erases all flash after MCUBootApp including primary, secondary and swap status partiton.
+
+ $OPENOCD_PATH/bin/openocd -s "$OPENOCD_PATH/scripts" -f "$OPENOCD_PATH/ scripts/interface/kitprog3.cfg" -f "$OPENOCD_PATH/scripts/target/psoc6_2m.cfg" -c "init; reset init" -c "flash erase_address 0x10018000" -c "reset; shutdown"
+
+### Example Terminal Output
+
+When user application programmed in BOOT slot:
+
+ ===========================
+ [BlinkyApp] BlinkyApp v1.0 [CM4]
+ ===========================
+ [BlinkyApp] GPIO initialized
+ [BlinkyApp] UART initialized
+ [BlinkyApp] Retarget I/O set to 115200 baudrate
+ [BlinkyApp] Red led blinks with 1 sec period
+ [BlinkyApp] Update watchdog timer started in MCUBootApp to mark sucessful start of user app
+ [BlinkyApp] Turn off watchdog timer
+
+When user application programmed in UPRADE slot and upgrade procedure was successful:
+
+ ===========================
+ [BlinkyApp] BlinkyApp v2.0 [+]
+ ===========================
+ [BlinkyApp] GPIO initialized
+ [BlinkyApp] UART initialized
+ [BlinkyApp] Retarget I/O set to 115200 baudrate
+ [BlinkyApp] Red led blinks with 0.25 sec period
+ [BlinkyApp] Update watchdog timer started in MCUBootApp to mark sucessful start of user app
+ [BlinkyApp] Turn off watchdog timer
+ [BlinkyApp] Try to set img_ok to confirm upgrade image
+ [BlinkyApp] SWAP Status : Image OK was set at 0x10027fe8.
diff --git a/boot/cypress/BlinkyApp/BlinkyApp.mk b/boot/cypress/BlinkyApp/BlinkyApp.mk
index 5ff2080..edfaed6 100644
--- a/boot/cypress/BlinkyApp/BlinkyApp.mk
+++ b/boot/cypress/BlinkyApp/BlinkyApp.mk
@@ -39,6 +39,10 @@
# image type can be BOOT or UPGRADE
IMG_TYPES = BOOT UPGRADE
+# use SWAP_UPGRADE = 0 for overwrite only mode
+# use SWAP_UPGRADE = 1 for swap upgrade mode
+SWAP_UPGRADE ?= 1
+
# possible values are 0 and 0xff
# internal Flash by default
ERASED_VALUE ?= 0
@@ -58,6 +62,7 @@
DEFINES_APP := -DBOOT_IMG
else
DEFINES_APP := -DUPGRADE_IMG
+ DEFINES_APP += -DSWAP_ENABLED=$(SWAP_UPGRADE)
endif
# Define start of application, RAM start and size, slot size
@@ -71,12 +76,15 @@
DEFINES_APP += -DRAM_START=0x08020000
DEFINES_APP += -DRAM_SIZE=0x10000
endif
+ifeq ($(USE_EXTERNAL_FLASH), 1)
+$(warning You are trying to build BlinkyApp for MCUBootApp with external memory support. Ensure you build MCUBootApp with USE_EXTERNAL_FLASH=1 flag!)
+ SLOT_SIZE ?= 0x40200
+else
+ SLOT_SIZE ?= 0x10000
+endif
-
-DEFINES_APP += -DRAM_SIZE=0x10000
+DEFINES_APP += -DUSER_APP_SIZE=$(SLOT_SIZE)
DEFINES_APP += -DUSER_APP_START=0x10018000
-SLOT_SIZE ?= 0x10000
-
# Collect Test Application sources
SOURCES_APP_SRC := $(wildcard $(CUR_APP_PATH)/*.c)
@@ -100,7 +108,12 @@
# We still need this for MCUBoot apps signing
IMGTOOL_PATH ?= ../../scripts/imgtool.py
-SIGN_ARGS := sign --header-size 1024 --pad-header --align 8 -v "2.0" -S $(SLOT_SIZE) -M 512 --overwrite-only -R $(ERASED_VALUE) -k keys/$(SIGN_KEY_FILE).pem
+# add flag to imgtool if not using swap for upgrade
+ifeq ($(SWAP_UPGRADE), 0)
+UPGRADE_TYPE := --overwrite-only
+endif
+
+SIGN_ARGS := sign --header-size 1024 --pad-header --align 8 -v "2.0" -S $(SLOT_SIZE) -M 512 $(UPGRADE_TYPE) -R $(ERASED_VALUE) -k keys/$(SIGN_KEY_FILE).pem
# Output folder
OUT := $(APP_NAME)/out
@@ -113,6 +126,7 @@
ifeq ($(IMG_TYPE), UPGRADE)
ifeq ($(ENC_IMG), 1)
SIGN_ARGS += --encrypt ../../$(ENC_KEY_FILE).pem
+ SIGN_ARGS += --use-random-iv
endif
SIGN_ARGS += --pad
UPGRADE_SUFFIX :=_upgrade
diff --git a/boot/cypress/BlinkyApp/Readme.md b/boot/cypress/BlinkyApp/Readme.md
deleted file mode 100644
index b10dda4..0000000
--- a/boot/cypress/BlinkyApp/Readme.md
+++ /dev/null
@@ -1,165 +0,0 @@
-### Blinking LED test application for MCUBoot Bootloader
-
-### Description
-
-Implements simple Blinky LED CM4 application to demonstrate MCUBoot Application operation in terms of BOOT and UPGRADE process.
-
-It is started by MCUBoot Application which is running on CM0p.
-
-Functionality:
-
-* Blinks RED led with 2 different rates, depending on type of image - BOOT or UPGRADE.
-* Prints debug info and version of itself to terminal at 115200 baud.
-* Can be built for BOOT slot or UPGRADE slot of bootloader.
-
-Currently supported platforms
-
-* PSOC_062_2M
-* PSOC_062_1M
-* PSOC_062_512K
-
-### Hardware limitations
-
-Since this application is created to demonstrate MCUBoot library features and not as reference examples some considerations are taken.
-
-1. Port/pin `P5_0` and `P5_1` used to configure serial port for debug prints. These pins are the most commonly used for serial port connection among available Cypress PSoC 6 kits. If you try to use custom hardware with this application - change definitions of `CY_DEBUG_UART_TX` and `CY_DEBUG_UART_RX` in `main.c` of BlinkyApp to port/pin pairs corresponding to your design.
-2. Port `GPIO_PRT13` pin `7U` used to define user connection LED. This pin is the most commonly used for USER_LED connection among available Cypress PSoC 6 kits. If you try to use custom hardware with this application - change definitions of `LED_PORT` and `LED_PIN` in `main.c` of BlinkyApp to port/pin pairs corresponding to your design.
-
-### Pre-build action
-
-Pre-build action is implemented for defining start address and size of flash, as well as RAM start address and size for BlinkyApp.
-These values are set by specifing following macros: `-DUSER_APP_SIZE`, `-DUSER_APP_START`, `-DRAM_SIZE`, `-DRAM_START` in makefile.
-
-Pre-build action calls GCC preprocessor which intantiates defines for particular values in `BlinkyApp_template.ld`.
-
-Default values set for currently supported targets:
-* `BlinkyApp.mk` to `-DUSER_APP_START=0x10018000`
-
-**Important**: make sure RAM areas of CM4-based BlinkyApp and CM0p-based MCUBootApp bootloader do not overlap.
-Memory (stack) corruption of CM0p application can cause failure if SystemCall-served operations invoked from CM4.
-
-### Building an application
-
-Root directory for build is **boot/cypress.**
-
-The following command will build regular HEX file of a BlinkyApp for BOOT slot. Substitute `PLATFORM=` to a paltform name you use in all following commands.
-
- make app APP_NAME=BlinkyApp PLATFORM=PSOC_062_2M IMG_TYPE=BOOT
-
-This have following defaults suggested:
-
- BUILDCFG=Debug
- IMG_TYPE=BOOT
-
-To build UPGRADE image use following command:
-
- make app APP_NAME=BlinkyApp PLATFORM=PSOC_062_2M IMG_TYPE=UPGRADE HEADER_OFFSET=0x10000
-
- Note: HEADER_OFFSET=%SLOT_SIZE%
-
-Example command-line for single-image:
-
- make app APP_NAME=BlinkyApp PLATFORM=PSOC_062_2M IMG_TYPE=BOOT
-
-**Building Multi-Image**
-
-`BlinkyApp` can be built to use in multi-image bootloader configuration.
-
-To get appropriate artifacts to use with multi image MCUBootApp, makefile flag `HEADER_OFFSET=` can be used.
-
-Example usage:
-
-Considering default config:
-
-* first image BOOT (PRIMARY) slot start `0x10018000`
-* slot size `0x10000`
-* second image BOOT (PRIMARY) slot start `0x10038000`
-
-To get appropriate artifact for second image PRIMARY slot run this command:
-
- make app APP_NAME=BlinkyApp PLATFORM=PSOC_062_2M IMG_TYPE=BOOT HEADER_OFFSET=0x20000
-
-*Note:* only 2 images are supported at the moment.
-
-**How to build upgrade image for external memory:**
-
-To prepare MCUBootApp for work with external memory please refer to `MCUBootApp/ExternalMemory.md`.
-
-For build BlinkyApp upgrade image for external memory use command:
-
- make app APP_NAME=BlinkyApp PLATFORM=PSOC_062_2M IMG_TYPE=UPGRADE HEADER_OFFSET=0x7FE8000 ERASED_VALUE=0xff
-
-`HEADER_OFFSET` defines the offset from original boot image address. This one in line above suggests secondary slot will start from `0x18000000`.
-
-`ERASED_VALUE` defines the memory cell contents in erased state. It is `0x00` for PSoC6's internal Flash and `0xff` for S25FL512S.
-
-In case of using muti-image configuration, upgrade image for second application can be built using next command:
-
- make app APP_NAME=BlinkyApp PLATFORM=PSOC_062_2M IMG_TYPE=UPGRADE HEADER_OFFSET=0x8028000 ERASED_VALUE=0xff
-
- Note: for S25FL512S block address shuld be mutiple by 0x40000
-
-**How to build encrypted upgrade image :**
-
-To prepare MCUBootApp for work with encrypted upgrade image please refer to `MCUBootApp/Readme.md`.
-
-To obtain encrypted upgrade image of BlinkyApp extra flag `ENC_IMG=1` should be passed in command line, for example:
-
- make app APP_NAME=BlinkyApp PLATFORM=PSOC_062_2M IMG_TYPE=UPGRADE HEADER_OFFSET=0x20000 ENC_IMG=1
-
-This also suggests user already placed corresponing `*.pem` key in `\keys` folder. The key variables are defined in root `Makefile` as `SIGN_KEY_FILE` and `ENC_KEY_FILE`
-
-### Post-Build
-
-Post build action is executed at compile time for `BlinkyApp`. In case of build for `PSOC_062_2M` platform it calls `imgtool` from `MCUBoot` scripts and adds signature to compiled image.
-
-Flags passed to `imgtool` for signature are defined in `SIGN_ARGS` variable in BlinkyApp.mk.
-
-### How to program an application
-
-Use any preferred tool for programming hex files.
-
-Hex file names to use for programming:
-
-`BlinkyApp` always produce build artifacts in 2 separate folders - `boot` and `upgrade`.
-
-`BlinkyApp` built to run with `MCUBootApp` produces files with name BlinkyApp.hex in `boot` directory and `BlinkyApp_upgrade.hex` in `upgrade` folder. These files are ready to be flashed to the board.
-
-`BlinkyApp_unsigned.hex` hex file is also preserved in both cases for possible troubleshooting.
-
-Files to use for programming are:
-
-`BOOT` - boot/BlinkyApp.hex
-`UPGRADE` - upgrade/BlinkyApp_upgrade.hex
-
-**Flags:**
-- `BUILDCFG` - configuration **Release** or **Debug**
-- `MAKEINFO` - 0 (default) - less build info, 1 - verbose output of compilation.
-- `HEADER_OFFSET` - 0 (default) - no offset of output hex file, 0x%VALUE% - offset for output hex file. Value 0x10000 is slot size MCUBoot Bootloader in this example.
-- `IMG_TYPE` - `BOOT` (default) - build image for BOOT slot of MCUBoot Bootloader, `UPGRADE` - build image for UPGRADE slot of MCUBoot Bootloader.
-- `ENC_IMG` - 0 (default) - build regular upgrade image, `1` - build encrypted upgrade image (MCUBootApp should also be built with this flash set 1)
-
-**NOTE**: In case of `UPGRADE` image `HEADER_OFFSET` should be set to MCUBoot Bootloader slot size.
-
-### Example terminal output
-
-When user application programmed in BOOT slot:
-
- ===========================
- [BlinkyApp] BlinkyApp v1.0 [CM4]
- ===========================
- [BlinkyApp] GPIO initialized
- [BlinkyApp] UART initialized
- [BlinkyApp] Retarget I/O set to 115200 baudrate
- [BlinkyApp] Red led blinks with 1 sec period
-
-When user application programmed in UPRADE slot and upgrade procedure was successful:
-
- ===========================
- [BlinkyApp] BlinkyApp v2.0 [+]
- ===========================
-
- [BlinkyApp] GPIO initialized
- [BlinkyApp] UART initialized
- [BlinkyApp] Retarget I/O set to 115200 baudrate
- [BlinkyApp] Red led blinks with 0.25 sec period
diff --git a/boot/cypress/BlinkyApp/libs.mk b/boot/cypress/BlinkyApp/libs.mk
index 7994d13..6e1ba7a 100644
--- a/boot/cypress/BlinkyApp/libs.mk
+++ b/boot/cypress/BlinkyApp/libs.mk
@@ -58,3 +58,4 @@
INCLUDE_DIRS_LIBS += $(addprefix -I,$(INCLUDE_DIRS_RETARGET_IO))
INCLUDE_DIRS_LIBS += $(addprefix -I,$(INCLUDE_DIRS_WATCHDOG))
INCLUDE_DIRS_LIBS += $(addprefix -I,$(INCLUDE_DIRS_HAL))
+INCLUDE_DIRS_LIBS += $(addprefix -I,$(INCLUDE_DIRS_WATCHDOG))
diff --git a/boot/cypress/BlinkyApp/main.c b/boot/cypress/BlinkyApp/main.c
index 97e1c84..1679bf2 100644
--- a/boot/cypress/BlinkyApp/main.c
+++ b/boot/cypress/BlinkyApp/main.c
@@ -89,6 +89,31 @@
}
}
+/*
+* Writes 1 byte `src` into flash memory at `address`
+* It does a sequence of RD/Modify/WR of data in a Flash Row.
+ */
+int flash_write_byte(uint32_t address, uint8_t src)
+{
+ cy_en_flashdrv_status_t rc = CY_FLASH_DRV_SUCCESS;
+ uint32_t row_addr = 0;
+ uint8_t row_buff[512];
+
+ /* accepting arbitrary address */
+ row_addr = (address/CY_FLASH_SIZEOF_ROW)*CY_FLASH_SIZEOF_ROW;
+
+ /* preserving Row */
+ memcpy(row_buff, (void *)row_addr, sizeof(row_buff));
+
+ /* Modifying the target byte */
+ row_buff[address%CY_FLASH_SIZEOF_ROW] = src;
+
+ /* Programming updated row back */
+ rc = Cy_Flash_WriteRow(row_addr, (const uint32_t *)row_buff);
+
+ return (int) rc;
+}
+
void test_app_init_hardware(void)
{
/* enable interrupts */
@@ -124,6 +149,35 @@
printf(WATCHDOG_FREE_MESSAGE);
cy_wdg_free();
+#if defined(SWAP_ENABLED) && defined(UPGRADE_IMG)
+
+ #define USER_SWAP_IMAGE_OK_OFFS (24)
+ #define USER_SWAP_IMAGE_OK (1)
+ uint32_t img_ok_addr;
+ int rc;
+
+ printf("[BlinkyApp] Try to set img_ok to confirm upgrade image\r\n");
+
+ /* Write Image OK flag to the slot trailer, so MCUBoot-loader
+ * will not revert new image */
+ img_ok_addr = USER_APP_START + USER_APP_SIZE - USER_SWAP_IMAGE_OK_OFFS;
+ if (*((uint8_t *)img_ok_addr) != USER_SWAP_IMAGE_OK)
+ {
+ rc = flash_write_byte(img_ok_addr, USER_SWAP_IMAGE_OK);
+ if (0 == rc)
+ {
+ printf("[BlinkyApp] SWAP Status : Image OK was set at 0x%08lx.\r\n", img_ok_addr);
+ }
+ else
+ {
+ printf("[BlinkyApp] SWAP Status : Failed to set Image OK.\r\n");
+ }
+ } else
+ {
+ printf("[BlinkyApp] Img_ok is already set in trailer\r\n");
+ }
+#endif
+
for (;;)
{
/* Toggle the user LED periodically */
diff --git a/boot/cypress/MCUBootApp/ExternalMemory.md b/boot/cypress/MCUBootApp/ExternalMemory.md
index e1281c8..ce1cb7e 100644
--- a/boot/cypress/MCUBootApp/ExternalMemory.md
+++ b/boot/cypress/MCUBootApp/ExternalMemory.md
@@ -1,66 +1,67 @@
-### External Memory support for Secondary Slot
+### External Memory Support For Secondary Slot
-**Description**
+#### Description
-Given document describes the use of external memory module as a secondary (upgrade) slot with Cypress' PSoC6 devices.
+Given document describes the use of external memory module as a secondary (upgrade) slot with Cypress' PSoC 6 devices.
-The demonstration device is CY8CPROTO-062-4343W board which is PSoC6 device with 2M of Flash available.
-The memory module present on board is S25FL512SAGMFI010 512-Mbit external Quad SPI NOR Flash.
+The demonstration device is `CY8CPROTO-062-4343W` board which is PSoC 6 device with 2M of Flash available, but other kits with 1M (CY8CKIT-062-WIFI-BT) or 512K (CY8CPROTO-062S3-4343W) chips can be used as well.
+The memory module present on boards is S25FL512SAGMFI010 512-Mbit external Quad SPI NOR Flash.
Using external memory for secondary slot allows to nearly double the size of Boot Image.
-**Operation Design and Flow**
+#### Operation Design and Flow
The design is based on using SFDP command's auto-discovery functionality of memory module IC and Cypress' SMIF PDL driver.
It is assumed that user's design meets following:
* The memory-module used is SFDP-compliant;
* There only one module is being used for secondary slot;
-* Only "OWERWRITE" bootloading scheme is used;
* The address for secondary slot should start from 0x18000000.
-This corresponds to PSoC6's SMIF (Serial Memory InterFace) IP block mapping.
-* The slot size for upgrade slot is even (or smaller) to erase size (0x40000) of given memory module.
-This requirement is accepted for code simplicity.
+This corresponds to PSoC 6's SMIF (Serial Memory InterFace) IP block mapping.
+* The slot size and start address for upgrade slot meets requirements, when using swap upgrade.
-The default flash map implemented is the following:
-
-Single-image mode.
-
-`[0x10000000, 0x10018000]` - MCUBootApp (bootloader) area;
-
-`[0x10018000, 0x10028000]` - primary slot for BlinkyApp;
-
-`[0x18000000, 0x18010000]` - secondary slot for BlinkyApp;
-
-`[0x10038000, 0x10039000]` - scratch area (not used);
-
-Multi(dual)-image mode.
-
-`[0x10000000, 0x10018000]` - MCUBootApp (bootloader) area;
-
-`[0x10018000, 0x10028000]` - primary1 slot for BlinkyApp;
-
-`[0x18000000, 0x18010000]` - secondary1 slot for BlinkyApp;
-
-`[0x10038000, 0x10048000]` - primary2 slot for user app ;
-
-`[0x18040000, 0x18050000]` - secondary2 slot for user app;
-
-`[0x10058000, 0x10059000]` - scratch area (not used);
-
-Size of slots `0x10000` - 64kB
-
-**Note 1**: make sure primary, secondary slot and bootloader app sizes are appropriate and correspond to flash area size defined in Applications' linker files.
-
-**Note 2**: make sure secondary slot start address is aligned (or smaller) to erase size (0x40000 - 256kB).
+The default flash map can be foung in MCUBootApp.md.
MCUBootApp's `main.c` contains the call to Init-SFDP API which performs required GPIO configurations, SMIF IP block configurations, SFDP protocol read and memory-config structure initialization.
After that MCUBootApp is ready to accept upgrade image from external memory module.
-Once valid upgrade image was accepted the image in external memory will be erased.
+Upgrades from external memory are supported for both `overwrite only` and `swap with status partition` modes of MCUBootApp.
-**How to enable external memory support:**
+##### Requirements to size and start address of upgrade slot when using swap mode.
+
+Due to mcuboot image structure some restrictions applies when using upgrades from external flash. The main requirement is the following:
+
+**Trailer portion of UPGRADE image should be possible to erase separately.**
+
+To achive this requirement image trailer should be placed separately on full flash page, which equls 0x40200 in case of S25FL512SAGMFI010. Considering default slot size for external memory case described in MCUBootApp.md, occupied external flash would look as follows:
+
+ 0x18000000 [xxxxxxxxxxxxxxxx][ttfffffffffffff][fffffffffffffff]
+
+Here:
+`0x18000000` - start address of external memory
+`[xxxxxxxxxxxxxxxx]` - first flash page of minimum erase size 0x40000 occupied by firmware.
+`[tt]` - trailer portion (last 0x200 of image) of upgrade slot placed on separate flash page.
+`[fffff]` - remained portion of flash page, used to store image trailer - this area should not be used for anything else.
+
+When using slots sizes other, then default `0x40200` described above shoulb be considered.
+
+When slot size does not aligned to `0x40000`, start address of UPGRADE image in external flash should be calculated starting from image trailer location. Consider example below.
+
+Primary slot size required is 590336 bytes (576k + 512b).
+
+4 flash pages are required to fit secondary slot (P1-P4):
+
+ 0x1800 0000 - 0x1804 0000 - P1
+ 0x1804 0000 - 0x1808 0000 - P2
+ 0x1808 0000 - 0x180C 0000 - P3
+ 0x1808 0000 - 0x180C 0000 - P4
+
+Primary slot consist of 512 bytes of image trailer, it goes to P4, 2 full sectors of 256k goes in P3 and P2, reminded 64k is resided in P1.
+
+Thus start address of secondary slot is: 0x1804 0000 - 0x10000 (64k) = 0x1803 0000. Size occupied is 4 * 256k = 786k
+
+##### How to enable external memory support:
1. Pass `USE_EXTERNAL_FLASH=1` flag to `make` command when building MCUBootApp.
2. Navigate to `cy_flash_map.c` and check if secondary slot start address and size meet the application's needs.
@@ -75,7 +76,7 @@
`HEADER_OFFSET` defines the offset from original boot image address. This one in line above suggests secondary slot will start from `0x18000000`.
-`ERASED_VALUE` defines the memory cell contents in erased state. It is `0x00` for PSoC6's internal Flash and `0xff` for S25FL512S.
+`ERASED_VALUE` defines the memory cell contents in erased state. It is `0x00` for PSoC 6's internal Flash and `0xff` for S25FL512S.
**Programming to external memory**
diff --git a/boot/cypress/MCUBootApp/MCUBootApp.md b/boot/cypress/MCUBootApp/MCUBootApp.md
new file mode 100644
index 0000000..f4337c7
--- /dev/null
+++ b/boot/cypress/MCUBootApp/MCUBootApp.md
@@ -0,0 +1,443 @@
+## MCUBootApp - demo bootloading application to be used with Cypress targets
+
+### Solution Description
+
+MCUBootApp is created to demonstrate operation of MCUBoot library on Cypress' PSoC 6 device. It supports various operation modes and features of MCUBoot library.
+
+* single/multi image operation modes
+* overwrite/swap upgrade modes
+* interrupted upgrade recovery for swap upgrades
+* upgrade image confirmation
+* reverting of bad upgrade images
+* secondary slots located in external flash
+
+This demo supports PSoC 6 chips with 1M, 2M and 512K Flash on board.
+Evaluation kits are:
+* `CY8CPROTO-062-4343W`
+* `CY8CKIT-062-WIFI-BT`
+* `CY8CPROTO-062S3-4343W`.
+
+### Memory Maps
+
+MCUBoot terminology assumes a slot from which **boot** is happening to be named **primary**, and a slot where **upgrade** image is placed - **secondary**.
+
+#### Internal Flash
+
+The flash map is defined at compile time. It can be configured through makefiles and `MCUBootApp/sysflash/sysflash.h` and `cypress/cy_flash_pal/cy_flash_map.c`.
+
+The default `MCUBootApp` flash map is defined for demonstration purpose. Sizes of slots are adjusted to be compatible with all supported device families: 1M, 2M and 512K.
+
+Actual addresses provided below are calculated by preprocessor in `sysflash.h` and `cy_flash_map.c` per slot sizes set.
+
+##### Single Image Mode
+
+| Start addr | End addr | Size | Description |
+|------------|------------|---------|-------------------------------------------|
+| 0x10000000 | 0x10018000 | 0x18000 | MCUBootApp (bootloader) area; |
+| 0x10018000 | 0x10028000 | 0x10000 | Primary_1 (BOOT) slot for BlinkyApp; |
+| 0x10028000 | 0x10038000 | 0x10000 | Secondary_1 (UPGRADE) slot for BlinkyApp; |
+
+If upgrade type is swap using scratch:
+
+| Start addr | Size | Description |
+|------------|-----------|---------------------------------|
+| 0x10038000 | 0x1800 | Start of swap status partition; |
+| 0x10039800 | 0x1000 | Start of scratch area partition;|
+
+##### Multi Image Mode
+
+| Start addr | End addr | Size | Description |
+|------------|------------|---------|-------------------------------------------|
+| 0x10000000 | 0x10018000 | 0x18000 | MCUBootApp (bootloader) area; |
+| 0x10018000 | 0x10028000 | 0x10000 | Primary_1 (BOOT) slot for BlinkyApp; |
+| 0x10028000 | 0x10038000 | 0x10000 | Secondary_1 (UPGRADE) slot for BlinkyApp; |
+| 0x10038000 | 0x10058000 | 0x20000 | Primary_2 (BOOT) slot of Bootloader |
+| 0x10058000 | 0x10078000 | 0x20000 | Secondary_2 (UPGRADE) slot of Bootloader |
+
+If upgrade type swap:
+
+| Start addr | Size | Description |
+|------------|-----------|---------------------------------|
+| 0x10078000 | 0x2800 | Start of swap status partition; |
+| 0x1007a800 | 0x1000 | Start of scratch area partition;|
+
+**SWAP upgrade from external memory**
+
+When MCUBootApp is configured to support upgrade images places in external memory following fixed addresses are predefined:
+
+| SMIF base address | Offset | Description |
+|-------------------|-------------|---------------------------------|
+| 0x18000000 | 0x0 | Start of Secondary_1 (UPGRADE) image; |
+| 0x18000000 | 0x240000 | Start of Secondary_2 (UPGRADE) image; |
+| 0x18000000 | 0x440000 | Start of scratch area partition;|
+
+##### Single Image Mode
+
+| Start addr | End addr | Size | Description |
+|------------|------------|---------|-------------------------------------------|
+| 0x10000000 | 0x10018000 | 0x18000 | MCUBootApp (bootloader) area; |
+| 0x10018000 | 0x10058200 | 0x40200 | Primary_1 (BOOT) slot for BlinkyApp; |
+| 0x18000000 | 0x18040200 | 0x40200 | Secondary_1 (UPGRADE) slot for BlinkyApp; |
+
+If upgrade type swap:
+
+| Start addr | Size | Description |
+|------------|-----------|---------------------------------|
+| 0x10058200 | 0x3c00 | Start of swap status partition; |
+
+##### Multi Image Mode
+
+| Start addr | End addr | Size | Description |
+|------------|------------|---------|-------------------------------------------|
+| 0x10000000 | 0x10018000 | 0x18000 | MCUBootApp (bootloader) area; |
+| 0x10018000 | 0x10058200 | 0x40200 | Primary_1 (BOOT) slot for BlinkyApp; |
+| 0x10058200 | 0x10098400 | 0x40200 | Primary_2 (BOOT) slot of Bootloader |
+| 0x18000000 | 0x18040200 | 0x40200 | Secondary_1 (UPGRADE) slot for BlinkyApp; |
+| 0x18240000 | 0x18280200 | 0x40200 | Secondary_2 (UPGRADE) slot of Bootloader; |
+
+If upgrade type is swap using scratch:
+
+| Start addr | Size | Description |
+|------------|-----------|---------------------------------|
+| 0x10098400 | 0x6400 | Start of swap status partition; |
+
+##### How To Modify Flash Map
+
+When modifying slots sizes - make sure to align new values with linker script files for appropriate applications.
+
+**Option 1**
+
+Navigate to `sysflash.h` and modify slots sizes directly to meet your needs.
+
+`CY_BOOT_BOOTLOADER_SIZE` defines size of MCUBootApp.
+`CY_BOOT_IMAGE_1_SIZE` defines slot size for single image case.
+`CY_BOOT_IMAGE_2_SIZE` defines slot size of second image in multi image case.
+
+__Option 2.__
+
+Navigate to `sysflash/sysflash.h` and uncomment `CY_FLASH_MAP_EXT_DESC` definition.
+Now define and initialize `struct flash_area *boot_area_descs[]` in a code with flash memory addresses and sizes you need at the beginning of application, so flash APIs from `cy_flash_pal/cy_flash_map.c` will use it.
+
+__Note:__ for both options make sure to use correct `MCUBOOT_MAX_IMG_SECTORS`. This should correspond to slot size used. Maximum value of sectors can be set by passing a flag `MAX_IMG_SECTORS=__number__` to `make`. By default it is set to 256 sectors, which corresponds to `0x20000` slot size in multi image use case. Sector size assumed to be 512 bytes, so 128 sectors needed to fill `0x10000`, 256 sectors for `0x20000` and so on.
+
+###### How To Override The Flash Map Values During Build Process
+
+It is possible to override MCUBootApp definitions from build system. Navigate to `MCUBootApp.mk`, find section `DEFINES_APP +=`
+Using this construction macros can be defined and passed to compiler.
+
+The full list of macros used to configure the custom multi image case with upgrade from external memory:
+
+* MCUBOOT_MAX_IMG_SECTORS
+* CY_FLASH_MAP_EXT_DESC
+* CY_BOOT_SCRATCH_SIZE
+* CY_BOOT_BOOTLOADER_SIZE
+* CY_BOOT_IMAGE_1_SIZE
+* CY_BOOT_IMAGE_2_SIZE
+* CY_BOOT_EXTERNAL_FLASH_SECONDARY_1_OFFSET
+* CY_BOOT_EXTERNAL_FLASH_SECONDARY_2_OFFSET
+* CY_BOOT_EXTERNAL_FLASH_SCRATCH_OFFSET
+
+As an example in a makefile slots sizes redefinition should look like following:
+
+`DEFINES_APP +=-DCY_BOOT_EXTERNAL_FLASH_SCRATCH_OFFSET=0x18780000`
+`DEFINES_APP +=-DMCUBOOT_MAX_IMG_SECTORS=168`
+`DEFINES_APP +=-DCY_BOOT_IMAGE_1_SIZE=0x15000`
+`DEFINES_APP +=-DCY_BOOT_IMAGE_2_SIZE=0x15000`
+
+#### External Flash
+
+It is also possible to place secondary (upgrade) slots in external memory module and use most of internal for primary image.
+Details about External Memory usage are described in separate guiding document `MCUBootApp/ExternalMemory.md`.
+
+#### RAM
+
+RAM areas in CM0p-based MCUBootApp bootloading application and CM4-based BlinkyApp are defined as an example pair. If your CM4 user application requires different RAM area make sure it is not overlap with MCUBootApp ram area. Memory (stack) corruption of CM0p application can cause failure if SystemCall-served operations invoked from CM4.
+
+MCUBootApp linker script also contains special section `public_ram`. This section serves for shared ram area between CM0p and CM4 cores. When CM4 and CM0p cores perform operations with internal flash, this area is used for interprocessor connection data sharing.
+
+### Hardware Cryptography Acceleration
+
+Cypress PSoC 6 MCU family supports hardware acceleration of cryptography based on mbedTLS Library via shim layer. Implementation of this layer is supplied as separate submodule `cy-mbedtls-acceleration`. HW acceleration of cryptography shortens boot time in more then 4 times, comparing to software implementation (observation results).
+
+To enable hardware acceleration in `MCUBootApp` pass flag `USE_CRYPTO_HW=1` to `make` while build.
+
+Hardware acceleration of cryptography is enabled for PSoC 6 devices by default.
+
+### Multi Image Mode
+
+Multi image operation considers upgrading and verification of more then one image on the device.
+
+By default MCUBootApp is configured for single image mode. To enable multi image operation pass `MCUBOOT_IMAGE_NUMBER=2` as parameter to `make`.
+
+ `MCUBOOT_IMAGE_NUMBER` can also be changed permanently in `MCUBootApp/config/mcuboot_config.h` file. This value can only be set to 2 (only dual-image is supported at the moment).
+
+In multi image operation (two images are considered for simplicity) MCUBootApp bootloading application operates as following:
+
+1. Verifies Primary_1 and Primary_2 images;
+2. Verifies Secondary_1 and Secondary_2 images;
+3. Upgrades Secondary to Primary if valid images found;
+4. Boots image from Primary_1 slot only;
+5. Boots Primary_1 only if both - Primary_1 and Primary_2 are present and valid;
+
+This ensures two dependent applications can be accepted by device only in case both images are valid.
+
+### Upgrade Modes
+
+There are two different types of upgrade process supported by MCUBootApp. In case of `overwrite only` type of upgrade - secondary image is simply copied to primary slot after successful validation. No way to revert upgrade in a case when secondary image is inoperable.
+
+In case of `swap` upgrade mode - images in primary and secondary slots are swaped. Upgrade can be reverted if secondary image did not confirm its operation.
+
+Upgrade mode is the same for all images in multi image mode.
+
+#### Overwrite Only
+
+To build MCUBootApp for overwrite upgrades only `MCUBootApp/config/mcuboot_config/mcuboot_config.h` should contain following define:
+
+`#define MCUBOOT_OVERWRITE_ONLY 1`
+
+This define can also be set in `MCUBootApp/MCUBootApp.mk`:
+
+`DEFINES_APP +=-DMCUBOOT_OVERWRITE_ONLY=1`
+
+In ovewrite only mode MCUBootApp first checks if any upgrade image is present in secondary slot(s), then validates digital signature of upgrade image in secondary slot(s). If validation is successful MCUBootApp starts copying secondary slot content to primary slot. After copy is done MCUBootApp starts upgrade image execution from primary slot.
+
+If upgraded application does not work - there is no way no revert back to previous working version. In this case only new upgrade firmware can fix previous broken upgrade.
+
+#### Swap Mode
+
+There are 2 basic types of swap modes supported in MCUBoot:
+* scratch
+* move
+
+For devices with large minimum erase size like PSoC 6 with 512 bytes and also for configurations which use external flash with even bigger minimum erase size there is an additional option in MCUBoot to use dedicated `status partition` for robust storage of swap related information.
+
+##### Why use swap with status partition
+
+Originally MCUBoot library has been designed with a consideration, that minimum write/erase size of flash would always be 8 bytes or less. This value is critical, because swap algorithms use it to align portions of data that contain swap operation status of each flash sector in slot before writing to flash. Data alignment is also performed before writes of special purpose data to image trailer.
+
+Writing of flash sector status or image trailer data should be `single cycle` operation to ensure power loss and unpredicted resets robustness of bootloading applications. This requirement eliminates usage of `read-modify-write` type of operations with flash.
+
+`Swap with status partition` is implemented specifically to address devices with large write/erase size. It is based on existing mcuboot swap algorithms, but does not have restriction of 8 bytes alignment. Instead minimum write/erase size can be specified by user and algorithm will calculate sizes of status partition, considering this value. All write/erase operations are aligned to this minimum write/erase size as well.
+
+##### Swap Status Partition Description
+
+The main distinction of `swap with status partition` is that separate flash area (partition) is used to store swap status values and image trailer instead of using free flash area at the end of primary/secondary image slot.
+
+This partition consists of separate areas:
+* area to store swap status values
+ * swap_status_0
+ * ...
+ * swap_status_x
+* area to store image trailer data:
+ * Encryption key 0
+ * Encryption key 1
+ * Swap size
+ * Swap info
+ * Copy done value
+ * Image ok
+ * Boot image magic
+
+Principal diagram of status partition:
+
+```
++-+-+-+-+-+-+ +-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ \
+| | | D0 | --> | swap_status_0 | \
+| | +-+-+-+-+-+-+ | swap_status_1 | \
+| | | D1 | | swap_status_2 | \
+| | +-+-+-+-+-+-+ | ... | \
+| PRIMARY | --> | | | swap_status_max | min write/erase
+| | | .... | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ size of flash hw
+| | +-+-+-+-+-+-+ | AREA_MAGIC | /
+| | | Dx | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /
++-+-+-+-+-+-+ +-+-+-+-+-+-+ | CRC | /
++-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /
+| | | CNT | /
+| | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ \
+| | | swap_status_max+1 | \
+| | | swap_status_max+2 | \
+| SECONDARY | | swap_status_max+3 | \
+| | | ... | \
+| | | swap_status_x | min write/erase
+| | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ size of flash hw
++-+-+-+-+-+-+ | AREA_MAGIC | /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /
+ | CRC | /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /
+ | CNT | /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ \
+ | | \
+ | Image trailer | \
+ | | \
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ min write/erase
+ | AREA_MAGIC | size of flash hw
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /
+ | CRC | /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /
+ | CNT | /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+```
+**Scheme legend:**
+
+`PRIMARY` and `SECONRADY` are areas in status partition to contain data regarding corresponding slot in mcuboot.
+`D0`, `D1` and `Dx` are duplicates of data described on the left. At least 2 duplicates should be present in system. This duplication is used to eliminate flash wear. Each of `Dx` contains valid data for `current swap step - 1`. Each swap operation for flash sector updates status for this sector in current `Dx` and value on `CNT` inreases. Next operation checks least value of `CNT` in available `Dx`'s, copies there data from `Dx` with `CNT+1` and updates status of current sector. This continues until all sectors in slot are moved and then swaped.
+`CRC` - 4 bytes value - checksum of data contaited in area.
+`CNT` - 4 bytes value.
+`swap_status_0`, `swap_status_1`- one byte values, that contain status for corresponding image sector.
+`swap_status_x` - last sector of `BOOT_MAX_IMAGE_SECTORS`.
+`swap_status_max` - maximum number of sectors that fits in min write/erase size for particular flash hardware. If `swap_status_max` is less then `swap_status_x` additional slice of min write/erase flash area is allocated to store swap status data.
+`Image trailer` - should be at least 64 bytes. Code calculates how many min write/erase sizes need to be allocated to store image trailer data.m.
+
+**Calculation example for PSoC 6 with minimum write/erase size of 512 bytes is used.**
+
+Following considered:
+* Single image case
+* Minimum write/erase size 512 bytes
+* PRIMARY/SECONDARY slots size `0x50000`
+* BOOT_MAX_IMG_SECTORS 0x50000 / 512 = 640
+* Number of duplicates `Dx = 2`
+
+One slice of `min write/erase` size can store data for maximum number of 500 sectors: 512 - 4 (CRC) - 4 (CNT) - 4 (area magic) = 500. Since BOOT_MAX_IMG_SECTORS is 640 - 2 slices of `min write/erase` is allocated. Total size is 1024 bytes.
+Image trailer data fits in 64 bytes, so one slice of `min write/erase` size is allocated. Total size is 1024 + 512 = 1536 bytes.
+Duplicates number equals 2. Total size is 1536 * 2 = 3072 bytes.
+2 slots are used in particular case PRIMARY and SECONDARY, each needs 3072 bytes to store swap status data. Tolal is 3072 * 2 = 6144 bytes.
+
+Swap status partition occupies 6144 bytes of flash area in this case.
+
+**Expected lifecycle**
+
+Since bootloading application that uses swap using status partition upgrade mode stores system state in separate flash area following product lifecycle is expected:
+`Empty` - Fully erased device
+`Ready` - `Empty` device is programmed with MCUBoot based bootloading application - MCUBootApp in this case.
+`Flashed` - Initial version v1.0 of user applicatio, BlinkyApp is this case, flashed to primary (BOOT) slot.
+`Upgraded` - updated firmware image of user application is delivered to secondary slot (UPGRADE) and bootloading application performs upgrade.
+
+It is expected that product stays in `Upgraded` state ultil end of its lifecycle.
+
+In case there is a need to wipe out product and flash new firmware directly to primary (BOOT) slot - device should be transfered to `Empty` or `Ready` state and then walk through all states again.
+
+### Hardware Limitations
+
+Since this application is created to demonstrate MCUBoot library features and not as reference examples some considerations are taken.
+
+1. `SCB5` used to configure serial port for debug prints. This is the most commonly used Serial Communication Block number among available Cypress PSoC 6 kits. If you try to use custom hardware with this application - change definition of `CYBSP_UART_HW` in `main.c` of MCUBootApp to SCB* that correspond to your design.
+
+2. `CY_SMIF_SLAVE_SELECT_0` is used as definition SMIF driver API. This configuration is used on evaluation kit for this example CY8CPROTO-062-4343W. If you try to use custom hardware with this application - change value of `smif_id` in `main.c` of MCUBootApp to value that corresponds to your design.
+
+### Downloading Solution's Assets
+
+There is a set assets required:
+
+* MCUBooot Library (root repository)
+* PSoC 6 HAL Library (submodule)
+* PSoC 6 Peripheral Drivers Library (PDL) (submodule)
+* mbedTLS Cryptographic Library (submodule)
+
+To get submodules - run the following command:
+
+ git submodule update --init --recursive
+
+### Configuring MCUBootApp Bootloading Application
+
+1. Choose upgrade mode:
+
+`SWAP` - this mode is set by default in `MCUBootApp/config/mcuboot_config/mcuboot_config.h`. `MCUBOOT_SWAP_USING_STATUS` preprocessor symbol is defined to enable this mode.
+
+`Ovewrite only` - pass `USE_OVERWRITE=1` parameter to `make` for overwrite mode compilation.
+
+2. Change memory map
+
+Check paragraph **How to modify Flash map** above.
+
+3. Enable hardware acceleration of cryptography
+
+Pass `USE_CRYPTO_HW=1` to `make` command. This option is enabled by default.
+
+4. Change number of images - single or multi image configuration
+
+Pass `MCUBOOT_IMAGE_NUMBER=1` for single image configuration
+Pass `MCUBOOT_IMAGE_NUMBER=2` for multi image configuration
+
+### Building Solution
+
+This folder `boot/cypress` contains make files infrastructure for building MCUBootApp bootloader application. Example build command are provided below for couple different build configurations.
+
+* Build MCUBootApp in `Debug` configuration for single image use case.
+
+ make app APP_NAME=MCUBootApp PLATFORM=PSOC_062_2M BUILDCFG=Debug MCUBOOT_IMAGE_NUMBER=1
+
+* Build MCUBootApp in `Release` configuration for multi image use case.
+
+ make app APP_NAME=MCUBootApp PLATFORM=PSOC_062_2M BUILDCFG=Release MCUBOOT_IMAGE_NUMBER=2
+
+Root directory for build is `boot/cypress`.
+
+### Encrypted Image Support
+
+To protect user image from unwanted read - Upgrade Image Encryption can be applied. The ECDH/HKDF with EC256 scheme is used in a given solution as well as mbedTLS as a crypto provider.
+
+To enable image encryption support use `ENC_IMG=1` build flag (BlinkyApp should also be built with this flash set 1).
+
+User is also responsible for providing corresponding binary key data in `enc_priv_key[]` (file `\MCUBootApp\keys.c`). The public part will be used by imgtool when signing and encrypting upgrade image. Signing image with encryption is described in `\BlinkyApp\Readme.md`.
+
+After MCUBootApp is built with these settings unencrypted and encrypted images will be accepted in secondary (upgrade) slot.
+
+Example command:
+
+ make app APP_NAME=MCUBootApp PLATFORM=PSOC_062_2M BUILDCFG=Debug MCUBOOT_IMAGE_NUMBER=1 ENC_IMG=1
+
+__NOTE__: Debug configuration of MCUBootApp with multi image encrypted upgrades in external flash (built with flags `BUILDCFG=Debug` `MCUBOOT_IMG_NUMBER=2 USE_EXTERNAL_FLASH=1 ENC_IMG=1`) is set to use optimization level `-O2 -g3` to fit into `0x18000` allocated for `MCUBootApp`.
+
+### Programming Solution
+
+There are couple ways of programming MCUBootApp firmware. Following instructions assume usage of one of Cypress development kits `CY8CPROTO_062_4343W`.
+
+1. Direct usage of OpenOCD.
+
+OpenOCD package is supplied with ModuToolbox IDE and can be found in installation folder under `./tools_2.1/openocd`.
+
+Open terminal application - and execute following command after substitution `PATH_TO_APPLICATION.hex` and `OPENOCD` paths.
+
+Connect a board to your computer. Switch Kitprog3 to DAP-BULK mode by pressing `SW3 MODE` button until `LED2 STATUS` constantly shines.
+
+ export OPENOCD=/Applications/ModusToolbox/tools_2.1/openocd
+
+ ${OPENOCD}/bin/openocd -s ${OPENOCD}/scripts \
+ -f ${OPENOCD}/scripts/interface/kitprog3.cfg \
+ -f ${OPENOCD}/scripts/target/psoc6_2m.cfg \
+ -c "init; reset init; program PATH_TO_APPLICATION.hex" \
+ -c "resume; reset; exit"
+
+2. Using GUI tool `Cypress Programmer`
+
+Follow [link](https://www.cypress.com/products/psoc-programming-solutions) to download.
+
+Connect board to your computer. Switch Kitprog3 to DAP-BULK mode by pressing `SW3 MODE` button until `LED2 STATUS` constantly shines. Open `Cypress Programmer` and click `Connect`, then choose hex file: `MCUBootApp.hex` or `BlinkyApp.hex` and click `Program`. Check log to ensure programming success. Reset board.
+
+3. Using `DAPLINK`.
+
+Connect board to your computer. Switch embeded Kitprog3 to `DAPLINK` mode by pressing `SW3 MODE` button until `LED2 STATUS` blinks fast and mass storage device appeared in OS. Drag and drop `hex` files you wish to program to `DAPLINK` drive in your OS.
+
+### Build Environment Troubleshooting
+
+Regular shell/terminal combination on Linux and MacOS.
+
+On Windows:
+
+* Cygwin
+* Msys2
+
+Also IDE may be used:
+* Eclipse / ModusToolbox ("makefile project from existing source")
+
+*Make* - make sure it is added to system's `PATH` variable and correct path is first in the list;
+
+*Python/Python3* - make sure you have correct path referenced in `PATH`;
+
+*Msys2* - to use systems PATH navigate to msys2 folder, open `msys2_shell.cmd`, uncomment set `MSYS2_PATH_TYPE=inherit`, restart MSYS2 shell.
+
+*Cygwin* - add following to build command `CURDIR=pwd | cygpath --mixed -f -` so that build command looks like that:
+
+ make app APP_NAME=MCUBootApp PLATFORM=PSOC_062_2M CURDIR=`pwd | cygpath --mixed -f -`
+
+This will iherit system's PATH so should find `python3.7` installed in regular way as well as imgtool and its dependencies.
+
diff --git a/boot/cypress/MCUBootApp/MCUBootApp.mk b/boot/cypress/MCUBootApp/MCUBootApp.mk
index 44da2fb..7b9a48a 100644
--- a/boot/cypress/MCUBootApp/MCUBootApp.mk
+++ b/boot/cypress/MCUBootApp/MCUBootApp.mk
@@ -31,6 +31,7 @@
USE_CRYPTO_HW ?= 1
USE_EXTERNAL_FLASH ?= 0
+USE_OVERWRITE ?= 0
MCUBOOT_IMAGE_NUMBER ?= 1
ENC_IMG ?= 0
@@ -47,17 +48,39 @@
include $(PRJ_DIR)/common_libs.mk
include $(PRJ_DIR)/toolchains.mk
-# default slot size is 0x10000, 512bytes per row/sector, so 128 sectors
-MAX_IMG_SECTORS ?= 128
+# default slot size is 0x10000 for single image
+# larger slot size is 0x20000 for multi image, 512bytes per row/sector, so 256 sectors will work for both
+MAX_IMG_SECTORS ?= 256
+
+# define slot sizes for IMAGE1 and IMAGE2 in case of usage with
+# external memory upgrade. 0x40000 slot size is acceptable for
+# all platforms in single image case with external upgrade
+ifeq ($(USE_EXTERNAL_FLASH), 1)
+IMAGE_1_SLOT_SIZE ?= 0x40200
+ifeq ($(MCUBOOT_IMAGE_NUMBER), 2)
+IMAGE_2_SLOT_SIZE ?= 0x40200
+endif
+endif
# Application-specific DEFINES
DEFINES_APP := -DMBEDTLS_CONFIG_FILE="\"mcuboot_crypto_config.h\""
DEFINES_APP += -DECC256_KEY_FILE="\"keys/$(SIGN_KEY_FILE).pub\""
DEFINES_APP += -DCORE=$(CORE)
DEFINES_APP += -DMCUBOOT_IMAGE_NUMBER=$(MCUBOOT_IMAGE_NUMBER)
+
+ifeq ($(USE_OVERWRITE), 1)
+DEFINES_APP += -DMCUBOOT_OVERWRITE_ONLY
+endif
+
ifeq ($(USE_EXTERNAL_FLASH), 1)
DEFINES_APP += -DCY_BOOT_USE_EXTERNAL_FLASH
+MAX_IMG_SECTORS = 1536
+DEFINES_APP += -DCY_BOOT_IMAGE_1_SIZE=$(IMAGE_1_SLOT_SIZE)
+ifeq ($(MCUBOOT_IMAGE_NUMBER), 2)
+DEFINES_APP += -DCY_BOOT_IMAGE_2_SIZE=$(IMAGE_2_SLOT_SIZE)
endif
+endif
+
DEFINES_APP += -DMCUBOOT_MAX_IMG_SECTORS=$(MAX_IMG_SECTORS)
# Hardrware acceleration support
ifeq ($(USE_CRYPTO_HW), 1)
@@ -68,6 +91,15 @@
# Encrypted image support
ifeq ($(ENC_IMG), 1)
DEFINES_APP += -DENC_IMG=1
+# Use higher optimization level for enc image in multi image mode
+# with external flash so it would fit into 0x18000 size of MCUBootApp
+ifeq ($(BUILDCFG), Debug)
+ifeq ($(MCUBOOT_IMAGE_NUMBER), 2)
+ifeq ($(USE_EXTERNAL_FLASH), 1)
+CFLAGS_OPTIMIZATION := -O2 -g3
+endif
+endif
+endif
endif
# Collect MCUBoot sourses
diff --git a/boot/cypress/MCUBootApp/README.md b/boot/cypress/MCUBootApp/README.md
deleted file mode 100644
index 17a9786..0000000
--- a/boot/cypress/MCUBootApp/README.md
+++ /dev/null
@@ -1,221 +0,0 @@
-### Port of MCUBoot library to be used with Cypress targets
-
-**Solution Description**
-
-Given solution demonstrates operation of MCUBoot on Cypress' PSoC6 device.
-
-There are two applications implemented:
-* MCUBootApp - PSoC6 MCUBoot-based bootloading application;
-* BlinkyApp - simple PSoC6 blinking LED application which is a target of BOOT/UPGRADE;
-
-Cypress boards, that can be used with this evaluation example:
-- CY8CPROTO-062-4343W - PSoC 6 2M on board
-- CY8CKIT-062-WIFI-BT - PSoC 6 1M on board
-- CY8CPROTO-062S3-4343W - PSoC 6 512K on board
-The default flash map implemented is the following:
-
-Single-image mode.
-
-`[0x10000000, 0x10018000]` - MCUBootApp (bootloader) area;
-
-`[0x10018000, 0x10028000]` - primary slot for BlinkyApp;
-
-`[0x10028000, 0x10038000]` - secondary slot for BlinkyApp;
-
-`[0x10038000, 0x10039000]` - scratch area (not used);
-
-Size of slots `0x10000` - 64kb
-
-MCUBootApp checks image integrity with SHA256, image authenticity with EC256 digital signature verification and uses completely SW implementation of cryptographic functions based on mbedTLS Library.
-
-**Important**: make sure primary, secondary slot and bootloader app sizes are appropriate and correspond to flash area size defined in Applications' linker files.
-
-**Important**: make sure RAM areas of CM0p-based MCUBootApp bootloader and CM4-based BlinkyApp do not overlap.
-Memory (stack) corruption of CM0p application can cause failure if SystemCall-served operations invoked from CM4.
-
-### Hardware cryptography acceleration
-
-Cypress PSOC6 MCU family supports hardware acceleration of cryptography based on mbedTLS Library via shim layer. Implementation of this layer is supplied as separate submodule `cy-mbedtls-acceleration`. HW acceleration of cryptography shortens boot time more then 4 times, comparing to software implementation (observation results).
-
-To enable hardware acceleration in `MCUBootApp` pass flag `USE_CRYPTO_HW=1` to `make` while build.
-
-Hardware acceleration of cryptography is enabled for PSOC6 devices by default.
-
-### How to modify memory map
-
-__Option 1.__
-
-Navigate to `sysflash.h` and modify the flash area(s) / slots sizes to meet your needs.
-
-__Option 2.__
-
-Navigate to `sysflash.h`, uncomment `CY_FLASH_MAP_EXT_DESC` definition.
-Now define and initialize `struct flash_area *boot_area_descs[]` with flash memory addresses and sizes you need at the beginning of application, so flash APIs from `cy_flash_map.c` will use it.
-
-__Note:__ for both options make sure you have updated `MCUBOOT_MAX_IMG_SECTORS` appropriatery with sector size assumed to be 512.
-
-**How to override the flash map values during build process:**
-
-Navigate to MCUBootApp.mk, find section `DEFINES_APP +=`
-Update this line and or add similar for flash map parameters to override.
-
-The possible list could be:
-
-* MCUBOOT_MAX_IMG_SECTORS
-* CY_FLASH_MAP_EXT_DESC
-* CY_BOOT_SCRATCH_SIZE
-* CY_BOOT_BOOTLOADER_SIZE
-* CY_BOOT_PRIMARY_1_SIZE
-* CY_BOOT_SECONDARY_1_SIZE
-* CY_BOOT_PRIMARY_2_SIZE
-* CY_BOOT_SECONDARY_2_SIZE
-
-As an example in a makefile it should look like following:
-
-`DEFINES_APP +=-DCY_FLASH_MAP_EXT_DESC`
-
-`DEFINES_APP +=-DMCUBOOT_MAX_IMG_SECTORS=512`
-
-`DEFINES_APP +=-DCY_BOOT_PRIMARY_1_SIZE=0x15000`
-
-**Multi-Image Operation**
-
-Multi-image operation considers upgrading and verification of more then one image on the device.
-
-To enable multi-image operation define `MCUBOOT_IMAGE_NUMBER` in `MCUBootApp/config/mcuboot_config.h` file should be set to 2 (only dual-image is supported at the moment). This could also be done on build time by passing `MCUBOOT_IMAGE_NUMBER=2` as parameter to `make`.
-
-Default value of `MCUBOOT_IMAGE_NUMBER` is 1, which corresponds to single image configuratios.
-
-In multi-image operation (two images are considered for simplicity) MCUBoot Bootloader application operates as following:
-
-* Verifies Primary_1 and Primary_2 images;
-* Verifies Secondary_1 and Secondary_2 images;
-* Upgrades Secondary to Primary if valid images found;
-* Boots image from Primary_1 slot only;
-* Boots Primary_1 only if both - Primary_1 and Primary_2 are present and valid;
-
-This ensures two dependent applications can be accepted by device only in case both images are valid.
-
-**Default Flash map for Multi-Image operation:**
-
-`0x10000000 - 0x10018000` - MCUBoot Bootloader
-
-`0x10018000 - 0x10028000` - Primary_1 (BOOT) slot of Bootloader
-
-`0x10028000 - 0x10038000` - Secondary_1 (UPGRADE) slot of Bootloader
-
-`0x10038000 - 0x10048000` - Primary_2 (BOOT) slot of Bootloader
-
-`0x10048000 - 0x10058000` - Secondary_2 (UPGRADE) slot of Bootloader
-
-`0x10058000 - 0x10059000` - Scratch of Bootloader
-
-Size of slots `0x10000` - 64kb
-
-__Note:__ It is also possible to place secondary (upgrade) slots in external memory module so resulting image size can be doubled.
-For more details about External Memory usage, please refer to separate guiding document `ExternalMemory.md`.
-
-### Hardware limitations
-
-Since this application is created to demonstrate MCUBoot library features and not as reference examples some considerations are taken.
-
-1. `SCB5` used to configure serial port for debug prints. This is the most commonly used Serial Communication Block number among available Cypress PSoC 6 kits. If you try to use custom hardware with this application - change definition of `CYBSP_UART_HW` in `main.c` of MCUBootApp to SCB* that correspond to your design.
-
-2. `CY_SMIF_SLAVE_SELECT_0` is used as definition SMIF driver API. This configuration is used on evaluation kit for this example CY8CPROTO-062-4343W, CY8PROTO-062S3-4343W, CY8CKIT-062-4343W. If you try to use custom hardware with this application - change value of `smif_id` in `main.c` of MCUBootApp to value that corresponds to your design.
-
-
-### Downloading Solution's Assets
-
-There is a set assets required:
-
-* MCUBooot Library (root repository)
-* PSoC6 HAL Library
-* PSoC6 Peripheral Drivers Library (PDL)
-* mbedTLS Cryptographic Library
-
-To get submodules - run the following command:
-
- git submodule update --init --recursive
-
-### Building Solution
-
-This folder contains make files infrastructure for building MCUBoot Bootloader. Same approach used in sample BlinkyLedApp application. Example command are provided below for couple different build configurations.
-
-* Build MCUBootApp in `Debug` for signle image use case.
-
- make app APP_NAME=MCUBootApp PLATFORM=PSOC_062_2M BUILDCFG=Debug MCUBOOT_IMAGE_NUMBER=1
-
-* Build MCUBootApp in `Release` for multi image use case.
-
- make app APP_NAME=MCUBootApp PLATFORM=PSOC_062_2M BUILDCFG=Release MCUBOOT_IMAGE_NUMBER=2
-
-* To Build MCUBootApp with external memory support - pass `USE_EXTERNAL_FLASH=1` flag to `make` command in examples above. In this case UPGRADE image will be located in external memory. Refer to ExternalMemory.md for additional details.
-
-Root directory for build is **boot/cypress.**
-
-**Encrypted Image Support**
-
-To protect user image from unwanted read - Upgrade Image Encryption can be applied. The ECDH/HKDF with EC256 scheme is used in a given solution as well as mbedTLS as a crypto provider.
-
-To enable image encryption support use `ENC_IMG=1` build flag (BlinkyApp should also be built with this flash set 1).
-
-User is also responsible for providing corresponding binary key data in `enc_priv_key[]` (file `\MCUBootApp\keys.c`). The public part will be used by imgtool when signing and encrypting upgrade image. Signing image with encryption is described in `\BlinkyApp\Readme.md`.
-
-After MCUBootApp is built with these settings unencrypted and encrypted images will be accepted in secondary (upgrade) slot.
-
-Example command:
-
- make app APP_NAME=MCUBootApp PLATFORM=PSOC_062_2M BUILDCFG=Debug MCUBOOT_IMAGE_NUMBER=1 ENC_IMG=1
-
-**Programming solution**
-
-There are couple ways of programming hex of MCUBootApp and BlinkyApp. Following instructions assume one of Cypress development kits, for example `CY8CPROTO_062_4343W`.
-
-1. Direct usage of OpenOCD.
-OpenOCD package is supplied with ModuToolbox IDE and can be found in installation folder under `./tools_2.1/openocd`.
-Open terminal application - and execute following command after substitution `PATH_TO_APPLICATION.hex` and `OPENOCD` paths.
-
-Connect a board to your computer. Switch Kitprog3 to DAP-BULK mode by pressing `SW3 MODE` button until `LED2 STATUS` constantly shines.
-
- export OPENOCD=/Applications/ModusToolbox/tools_2.1/openocd
-
- ${OPENOCD}/bin/openocd -s ${OPENOCD}/scripts \
- -f ${OPENOCD}/scripts/interface/kitprog3.cfg \
- -f ${OPENOCD}/scripts/target/psoc6_2m.cfg \
- -c "init; reset init; program PATH_TO_APPLICATION.hex" \
- -c "resume; reset; exit"
-
-2. Using GUI tool `Cypress Programmer` - follow [link](https://www.cypress.com/products/psoc-programming-solutions) to download.
- Connect board to your computer. Switch Kitprog3 to DAP-BULK mode by pressing `SW3 MODE` button until `LED2 STATUS` constantly shines. Open `Cypress Programmer` and click `Connect`, then choose hex file: `MCUBootApp.hex` or `BlinkyApp.hex` and click `Program`. Check log to ensure programming success. Reset board.
-
-3. Using `DAPLINK`.
- Connect board to your computer. Switch embeded Kitprog3 to `DAPLINK` mode by pressing `SW3 MODE` button until `LED2 STATUS` blinks fast and mass storage device appeared in OS. Drag and drop `hex` files you wish to program to `DAPLINK` drive in your OS.
-
-
-
-**Currently supported platforms:**
-
-* PSOC_062_2M
-* PSOC_062_1M
-* PSOC_062_512K
-
-**Build environment troubleshooting:**
-
-Regular shell/terminal combination on Linux and MacOS.
-
-On Windows:
-
-* Cygwin
-* Msys2
-
-Also IDE may be used:
-* Eclipse / ModusToolbox ("makefile project from existing source")
-
-*Make* - make sure it is added to system's `PATH` variable and correct path is first in the list;
-
-*Python/Python3* - make sure you have correct path referenced in `PATH`;
-
-*Msys2* - to use systems PATH navigate to msys2 folder, open `msys2_shell.cmd`, uncomment set `MSYS2_PATH_TYPE=inherit`, restart MSYS2 shell.
-
-This will iherit system's PATH so should find `python3.7` installed in regular way as well as imgtool and its dependencies.
-
diff --git a/boot/cypress/MCUBootApp/config/mcuboot_config/mcuboot_config.h b/boot/cypress/MCUBootApp/config/mcuboot_config/mcuboot_config.h
index a58d584..eeb15bc 100644
--- a/boot/cypress/MCUBootApp/config/mcuboot_config/mcuboot_config.h
+++ b/boot/cypress/MCUBootApp/config/mcuboot_config/mcuboot_config.h
@@ -22,7 +22,7 @@
/* Default maximum number of flash sectors per image slot; change
* as desirable. */
#ifndef MCUBOOT_MAX_IMG_SECTORS
-#define MCUBOOT_MAX_IMG_SECTORS 2560
+#define MCUBOOT_MAX_IMG_SECTORS 128u
#endif
/*
@@ -46,14 +46,16 @@
* simpler code path, which only supports overwriting the
* existing image with the update image, is also available.
*/
-
-/* Uncomment to enable the overwrite-only code path. */
-#define MCUBOOT_OVERWRITE_ONLY
-
#ifdef MCUBOOT_OVERWRITE_ONLY
/* Uncomment to only erase and overwrite those slot 0 sectors needed
* to install the new image, rather than the entire image slot. */
/* #define MCUBOOT_OVERWRITE_ONLY_FAST */
+#else
+/* Using SWAP w Scratch by default.
+ * Comment/Uncomment which is needed. */
+#define MCUBOOT_SWAP_USING_SCRATCH 1
+/* #define MCUBOOT_SWAP_USING_MOVE 1 */
+#define MCUBOOT_SWAP_USING_STATUS 1
#endif
/*
diff --git a/boot/cypress/MCUBootApp/config/mcuboot_config/mcuboot_logging.h b/boot/cypress/MCUBootApp/config/mcuboot_config/mcuboot_logging.h
index 0d6f787..8a91f3f 100644
--- a/boot/cypress/MCUBootApp/config/mcuboot_config/mcuboot_logging.h
+++ b/boot/cypress/MCUBootApp/config/mcuboot_config/mcuboot_logging.h
@@ -94,6 +94,7 @@
#define MCUBOOT_LOG_DBG(...) IGNORE(__VA_ARGS__)
#endif
-#define MCUBOOT_LOG_MODULE_DECLARE(...)
+#define MCUBOOT_LOG_MODULE_DECLARE(domain) /* ignore */
+#define MCUBOOT_LOG_MODULE_REGISTER(domain) /* ignore */
#endif /* MCUBOOT_LOGGING_H */
diff --git a/boot/cypress/MCUBootApp/main.c b/boot/cypress/MCUBootApp/main.c
index 6f987a6..dee1e1a 100644
--- a/boot/cypress/MCUBootApp/main.c
+++ b/boot/cypress/MCUBootApp/main.c
@@ -119,11 +119,6 @@
#ifdef CY_BOOT_USE_EXTERNAL_FLASH
rc = CY_SMIF_CMD_NOT_FOUND;
- #undef MCUBOOT_MAX_IMG_SECTORS
- /* redefine number of sectors as there 2MB will be
- * available on PSoC062-2M in case of external
- * memory usage */
- #define MCUBOOT_MAX_IMG_SECTORS 4096
rc = qspi_init_sfdp(smif_id);
if (rc == CY_SMIF_SUCCESS)
{
diff --git a/boot/cypress/MCUBootApp/sysflash/sysflash.h b/boot/cypress/MCUBootApp/sysflash/sysflash.h
index f1fc841..961e74e 100644
--- a/boot/cypress/MCUBootApp/sysflash/sysflash.h
+++ b/boot/cypress/MCUBootApp/sysflash/sysflash.h
@@ -1,18 +1,24 @@
/* Manual version of auto-generated version. */
-#ifndef __SYSFLASH_H__
-#define __SYSFLASH_H__
+#ifndef SYSFLASH_H
+#define SYSFLASH_H
-#define FLASH_DEVICE_INTERNAL_FLASH (0x7F)
+#include <stdint.h>
+#include "cy_syslib.h"
-#define FLASH_AREA_BOOTLOADER 0
-#define FLASH_AREA_IMAGE_0 1
-#define FLASH_AREA_IMAGE_1 2
-#define FLASH_AREA_IMAGE_SCRATCH 3
-#define FLASH_AREA_IMAGE_2 5
-#define FLASH_AREA_IMAGE_3 6
+#define FLASH_AREA_BOOTLOADER (0)
+#define FLASH_AREA_IMAGE_0 (1u)
+#define FLASH_AREA_IMAGE_1 (2u)
+#define FLASH_AREA_IMAGE_SCRATCH (3u)
+#define FLASH_AREA_IMAGE_2 (5u)
+#define FLASH_AREA_IMAGE_3 (6u)
+#define FLASH_AREA_IMAGE_SWAP_STATUS (7u)
-/* Uncomment if external flash is being used */
+/* it is related to multi-image case */
+#define FLASH_AREA_IMAGE_IDX_1 (0u)
+#define FLASH_AREA_IMAGE_IDX_2 (1u)
+
+/* This defines if External Flash (SMIF) will be used for Upgrade Slots */
/* #define CY_BOOT_USE_EXTERNAL_FLASH */
/* use PDL-defined offset or one from SMFI config */
@@ -22,31 +28,84 @@
#define CY_FLASH_DEVICE_BASE (CY_FLASH_BASE)
#ifndef CY_BOOT_SCRATCH_SIZE
-#define CY_BOOT_SCRATCH_SIZE (0x1000)
+#ifndef CY_BOOT_USE_EXTERNAL_FLASH
+#define CY_BOOT_SCRATCH_SIZE (0x1000u)
+#else /* CY_BOOT_USE_EXTERNAL_FLASH */
+#define CY_BOOT_SCRATCH_SIZE (0x80000)
+#endif /* CY_BOOT_USE_EXTERNAL_FLASH */
+#endif /* CY_BOOT_SCRATCH_SIZE */
+
+#ifndef CY_BOOT_SWAP_STATUS_SIZE
+#define CY_BOOT_SWAP_STATUS_SIZE (BOOT_SWAP_STATUS_SZ_PRIM + BOOT_SWAP_STATUS_SZ_SEC)
#endif
#ifndef CY_BOOT_BOOTLOADER_SIZE
#define CY_BOOT_BOOTLOADER_SIZE (0x18000)
#endif
+/* Sizes of CY_BOOT_IMAGE_1_SIZE and CY_BOOT_IMAGE_2_SIZE
+ * can be defined from build system. Use default values otherwise
+*/
+#ifndef CY_BOOT_USE_EXTERNAL_FLASH
+#ifndef CY_BOOT_IMAGE_1_SIZE
+#define CY_BOOT_IMAGE_1_SIZE (0x10000)
+#endif /* CY_BOOT_IMAGE_1_SIZE */
+#if (MCUBOOT_IMAGE_NUMBER == 2)
+#ifndef CY_BOOT_IMAGE_2_SIZE
+#define CY_BOOT_IMAGE_2_SIZE (0x20000)
+#endif /* CY_BOOT_IMAGE_2_SIZE */
+#endif /* (MCUBOOT_IMAGE_NUMBER == 2) */
+#else /* CY_BOOT_USE_EXTERNAL_FLASH */
+#ifndef CY_BOOT_IMAGE_1_SIZE
+#define CY_BOOT_IMAGE_1_SIZE (0xC0000)
+#endif /* CY_BOOT_IMAGE_1_SIZE */
+#if (MCUBOOT_IMAGE_NUMBER == 2)
+#ifndef CY_BOOT_IMAGE_2_SIZE
+#define CY_BOOT_IMAGE_2_SIZE (0xC0000)
+#endif /* CY_BOOT_IMAGE_2_SIZE */
+#endif /* (MCUBOOT_IMAGE_NUMBER == 2) */
+#endif /* CY_BOOT_USE_EXTERNAL_FLASH */
+
#ifndef CY_BOOT_PRIMARY_1_SIZE
-#define CY_BOOT_PRIMARY_1_SIZE (0x10000)
+#define CY_BOOT_PRIMARY_1_SIZE CY_BOOT_IMAGE_1_SIZE
#endif
#ifndef CY_BOOT_SECONDARY_1_SIZE
-#define CY_BOOT_SECONDARY_1_SIZE (0x10000)
+#define CY_BOOT_SECONDARY_1_SIZE CY_BOOT_IMAGE_1_SIZE
#endif
#if (MCUBOOT_IMAGE_NUMBER == 2) /* if dual-image */
#ifndef CY_BOOT_PRIMARY_2_SIZE
-#define CY_BOOT_PRIMARY_2_SIZE (0x10000)
+#define CY_BOOT_PRIMARY_2_SIZE CY_BOOT_IMAGE_2_SIZE
#endif
#ifndef CY_BOOT_SECONDARY_2_SIZE
-#define CY_BOOT_SECONDARY_2_SIZE (0x10000)
+#define CY_BOOT_SECONDARY_2_SIZE CY_BOOT_IMAGE_2_SIZE
#endif
#endif
+#ifndef CY_BOOT_EXTERNAL_FLASH_SECONDARY_1_OFFSET
+#define CY_BOOT_EXTERNAL_FLASH_SECONDARY_1_OFFSET (0x0u)
+#endif
+
+#ifndef CY_BOOT_EXTERNAL_FLASH_SECONDARY_2_OFFSET
+#define CY_BOOT_EXTERNAL_FLASH_SECONDARY_2_OFFSET (0x240000u)
+#endif
+
+#ifndef CY_BOOT_EXTERNAL_FLASH_SCRATCH_OFFSET
+#define CY_BOOT_EXTERNAL_FLASH_SCRATCH_OFFSET (0x440000u)
+#endif
+
+#ifndef CY_BOOT_SECONDARY_1_EXT_MEM_OFFSET
+#define CY_BOOT_SECONDARY_1_EXT_MEM_OFFSET (CY_SMIF_BASE_MEM_OFFSET + CY_BOOT_EXTERNAL_FLASH_SECONDARY_1_OFFSET)
+#endif
+
+#ifndef CY_BOOT_SECONDARY_2_EXT_MEM_OFFSET
+#define CY_BOOT_SECONDARY_2_EXT_MEM_OFFSET (CY_SMIF_BASE_MEM_OFFSET + CY_BOOT_EXTERNAL_FLASH_SECONDARY_2_OFFSET)
+#endif
+
+#define BOOT_MAX_SWAP_STATUS_SECTORS (64)
+
#if (MCUBOOT_IMAGE_NUMBER == 1)
#define FLASH_AREA_IMAGE_PRIMARY(x) (((x) == 0) ? \
FLASH_AREA_IMAGE_0 : \
@@ -57,6 +116,7 @@
#elif (MCUBOOT_IMAGE_NUMBER == 2)
+#ifndef CY_FLASH_MAP_EXT_DESC
#define FLASH_AREA_IMAGE_PRIMARY(x) (((x) == 0) ? \
FLASH_AREA_IMAGE_0 : \
((x) == 1) ? \
@@ -67,10 +127,55 @@
((x) == 1) ? \
FLASH_AREA_IMAGE_3 : \
255)
-
#else
-#warning "Image slot and flash area mapping is not defined"
+__STATIC_INLINE uint8_t FLASH_AREA_IMAGE_PRIMARY(uint32_t areaID)
+{
+ uint8_t result;
+
+ if (0U == areaID)
+ {
+ result = FLASH_AREA_IMAGE_0;
+ }
+ else
+ if (1U == areaID)
+ {
+ result = FLASH_AREA_IMAGE_2;
+ }
+ else
+ {
+ result = 0xFF;
+ }
+
+ return result;
+}
+
+__STATIC_INLINE uint8_t FLASH_AREA_IMAGE_SECONDARY(uint32_t areaID)
+{
+ uint8_t result;
+
+ if (0U == areaID)
+ {
+ result = FLASH_AREA_IMAGE_1;
+ }
+ else
+ if (1U == areaID)
+ {
+ result = FLASH_AREA_IMAGE_3;
+ }
+ else
+ {
+ result = 0xFF;
+ }
+
+ return result;
+}
#endif
+#endif
+
+// #else
+// #warning "Image slot and flash area mapping is not defined"
+// #endif
+
#define CY_IMG_HDR_SIZE 0x400
#ifndef CY_FLASH_MAP_EXT_DESC
@@ -78,4 +183,4 @@
/* #define CY_FLASH_MAP_EXT_DESC */
#endif
-#endif /* __SYSFLASH_H__ */
+#endif /* SYSFLASH_H */
diff --git a/boot/cypress/Makefile b/boot/cypress/Makefile
index 78ac445..b9952c5 100644
--- a/boot/cypress/Makefile
+++ b/boot/cypress/Makefile
@@ -98,7 +98,7 @@
endif
# updating CFLAGS at this point as DEFINES are completed
-CFLAGS += $(DEFINES)
+CFLAGS += $(DEFINES) $(CFLAGS_OPTIMIZATION)
VPATH = $(dir $(C_FILES) $(ASM_FILES))
@@ -120,6 +120,7 @@
MY_LDFLAGS := $(subst /cygdrive/c,c:,$(LDFLAGS))
#$(info MY_LDFLAGS $(MY_LDFLAGS))
LDFLAGS=$(MY_LDFLAGS)
+LDFLAGS += $(LDFLAGS_OPTIMIZATION)
# Default name pattern for output files
# may be modified in %Application%.mk file
diff --git a/boot/cypress/README.md b/boot/cypress/README.md
index 00c3c10..f2db991 100644
--- a/boot/cypress/README.md
+++ b/boot/cypress/README.md
@@ -1,4 +1,4 @@
-### Port of MCUBoot library for evaluation with Cypress PSoC 6 chips
+### Port Of Mcuboot Library For Evaluation With Cypress PSoC 6 Chips
### Disclaimer
@@ -14,29 +14,42 @@
### Solution Description
There are two applications implemented:
-* MCUBootApp - PSoC6 MCUBoot-based bootloading application;
-* BlinkyApp - simple PSoC6 blinking LED application which is a target of BOOT/UPGRADE;
+* MCUBootApp - PSoC 6 MCUBoot-based bootloading application;
+* BlinkyApp - simple PSoC 6 blinking LED application which is a target of BOOT/UPGRADE;
-The default flash map for MCUBootApp implemented is next:
+#### MCUBootApp
-* [0x10000000, 0x10018000] - MCUBootApp (bootloader) area;
-* [0x10018000, 0x10028000] - primary slot for BlinkyApp;
-* [0x10028000, 0x10038000] - secondary slot for BlinkyApp;
-* [0x10038000, 0x10039000] - scratch area;
+* There are two types of upgrade operation supported:
+ * **Overwrite only** - secondady image is only copied to primary slot after validation
+ * **Swap** - seconrady and primary slots images are swapped in process of upgrade. Upgrade operation can be reverted in case of bad secondary image.
-The flash map is defined through sysflash.h and cy_flash_map.c.
+* There are two types of operation modes supported:
+ * single image
+ * multi image
-It is also possible to place secondary (upgrade) slots in external memory module. In this case primary slot can be doubled in size.
-For more details about External Memory usage, please refer to separate guiding document `MCUBootApp/ExternalMemory.md`.
+* Secondary (upgrade) slot(s) can be placed in external memory. For more details about External Memory usage refer to separate guiding document `MCUBootApp/ExternalMemory.md`.
+
+* MCUBootApp checks image integrity with SHA256, image authenticity with EC256 digital signature verification
+* Cryptographic functions can be based on completely software implementation or be hardware accelerated. mbedTLS library is used in both cases.
+
+Detailed description of **MCUBootApp** is provided in `MCUBootApp/MCUBootApp.md`
MCUBootApp checks image integrity with SHA256, image authenticity with EC256 digital signature verification and uses either completely software implementation of cryptographic functions or accelerated by hardware - both based on mbedTLS Library.
+#### BlinkyApp
+* Can be built to use as primary or secondary image for both internal and external flash memory
+* Primary and secondary images differ in text printed to serial terminal and led blinking frequency.
+* Watchdog timer functionality is supported to confirm successful start/upgrade of application
+* User application side of mcuboot swap operation is demonstrated for secondary image build.
+
+Detailed description of **BlinkyApp** is provided in `BlinkyApp/BlinkyApp.md`
+
### Downloading Solution's Assets
There is a set assets required:
* MCUBooot Library (root repository)
-* PSoC6 Peripheral Drivers Library (PDL)
+* PSoC 6 Peripheral Drivers Library (PDL)
* mbedTLS Cryptographic Library
Those are represented as submodules.
@@ -50,15 +63,27 @@
cd mcuboot
git submodule update --init --recursive
-
-
### Building Solution
-Root directory for build is **boot/cypress.**
+Root directory for build is `boot/cypress`.
-This folder contains make files infrastructure for building both MCUBoot Bootloader and sample BlinkyApp application used for Bootloader demo functionality.
+Root folder contains make files infrastructure for building both MCUBootApp bootloading application and BlinkyApp user application.
-Instructions on how to build and upload MCUBootApp bootloader application and sample user applocation are located in `Readme.md` files in corresponding folders.
+Instructions on how to build and upload MCUBootApp bootloading application and sample user application are located in `MCUBootApp.md` and `BlinkyApp.md` files in corresponding folders.
+
+**Toolchain**
+
+**GCC_ARM** is the only supported (built and verified on GCC 7.2.1).
+
+It is inluded with [ModusToolbox® Software Environment](https://www.cypress.com/products/modustoolbox-software-environment) and can be found in folder `./ModusToolbox/tools_2.1/gcc-7.2.1`.
+
+Default installation folder is expected by makefile build system.
+
+In case of using another installation folder, version of **ModusToolbox IDE** or another GCC Compiler - path to a toolchain should be specified to a build system using **TOOLCHAIN_PATH** flag.
+
+**Example:**
+
+ make app APP_NAME=BlinkyApp PLATFORM=PSOC_062_2M IMG_TYPE=BOOT TOOLCHAIN_PATH=/home/fw-security/ModusToolbox/tools_2.0/gcc-7.2.1
Supported platforms for `MCUBoot`, `BlinkyApp`:
@@ -66,7 +91,7 @@
* PSOC_062_1M
* PSOC_062_512K
-### Build environment troubleshooting
+### Build Environment Troubleshooting
Following CLI / IDE are supported for project build:
diff --git a/boot/cypress/cy_flash_pal/cy_flash_map.c b/boot/cypress/cy_flash_pal/cy_flash_map.c
index 2e56031..11113fb 100644
--- a/boot/cypress/cy_flash_pal/cy_flash_map.c
+++ b/boot/cypress/cy_flash_pal/cy_flash_map.c
@@ -33,6 +33,7 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
+#include <string.h>
#include "mcuboot_config/mcuboot_config.h"
#include "flash_map_backend/flash_map_backend.h"
@@ -40,34 +41,38 @@
#include "bootutil/bootutil_log.h"
-#include "cy_pdl.h"
+#include "cy_flash.h"
#ifdef CY_BOOT_USE_EXTERNAL_FLASH
#include "cy_smif_psoc6.h"
#endif
+
+#ifdef MCUBOOT_SWAP_USING_STATUS
+#include "swap_status.h"
+#endif
/*
* For now, we only support one flash device.
*
* Pick a random device ID for it that's unlikely to collide with
* anything "real".
*/
-#define FLASH_DEVICE_ID 111
-#define FLASH_MAP_ENTRY_MAGIC 0xd00dbeef
+#define FLASH_DEVICE_ID 111
+#define FLASH_MAP_ENTRY_MAGIC (0xd00dbeefU)
#define FLASH_AREA_IMAGE_SECTOR_SIZE FLASH_AREA_IMAGE_SCRATCH_SIZE
#ifndef CY_BOOTLOADER_START_ADDRESS
-#define CY_BOOTLOADER_START_ADDRESS (0x10000000)
+#define CY_BOOTLOADER_START_ADDRESS (0x10000000u)
#endif
#ifndef CY_BOOT_INTERNAL_FLASH_ERASE_VALUE
/* This is the value of internal flash bytes after an erase */
-#define CY_BOOT_INTERNAL_FLASH_ERASE_VALUE (0x00)
+#define CY_BOOT_INTERNAL_FLASH_ERASE_VALUE (0x00u)
#endif
#ifndef CY_BOOT_EXTERNAL_FLASH_ERASE_VALUE
/* This is the value of external flash bytes after an erase */
-#define CY_BOOT_EXTERNAL_FLASH_ERASE_VALUE (0xff)
+#define CY_BOOT_EXTERNAL_FLASH_ERASE_VALUE (0xffu)
#endif
#ifdef CY_FLASH_MAP_EXT_DESC
@@ -89,42 +94,42 @@
.fa_size = CY_BOOT_PRIMARY_1_SIZE
};
-#ifndef CY_BOOT_USE_EXTERNAL_FLASH
static struct flash_area secondary_1 =
{
.fa_id = FLASH_AREA_IMAGE_SECONDARY(0),
+#ifndef CY_BOOT_USE_EXTERNAL_FLASH
.fa_device_id = FLASH_DEVICE_INTERNAL_FLASH,
.fa_off = CY_FLASH_BASE +\
CY_BOOT_BOOTLOADER_SIZE +\
CY_BOOT_PRIMARY_1_SIZE,
- .fa_size = CY_BOOT_SECONDARY_1_SIZE
-};
#else
-static struct flash_area secondary_1 =
-{
- .fa_id = FLASH_AREA_IMAGE_SECONDARY(0),
.fa_device_id = FLASH_DEVICE_EXTERNAL_FLASH(CY_BOOT_EXTERNAL_DEVICE_INDEX),
- .fa_off = CY_SMIF_BASE_MEM_OFFSET,
+ .fa_off = CY_BOOT_SECONDARY_1_EXT_MEM_OFFSET,
+#endif
.fa_size = CY_BOOT_SECONDARY_1_SIZE
};
-#endif
+
#if (MCUBOOT_IMAGE_NUMBER == 2) /* if dual-image */
static struct flash_area primary_2 =
{
.fa_id = FLASH_AREA_IMAGE_PRIMARY(1),
.fa_device_id = FLASH_DEVICE_INTERNAL_FLASH,
+#ifndef CY_BOOT_USE_EXTERNAL_FLASH
.fa_off = CY_FLASH_BASE +\
CY_BOOT_BOOTLOADER_SIZE +\
CY_BOOT_PRIMARY_1_SIZE +\
CY_BOOT_SECONDARY_1_SIZE,
+#else
+ .fa_off = CY_FLASH_BASE +\
+ CY_BOOT_BOOTLOADER_SIZE +\
+ CY_BOOT_PRIMARY_1_SIZE,
+#endif /* CY_BOOT_USE_EXTERNAL_FLASH */
.fa_size = CY_BOOT_PRIMARY_2_SIZE
};
static struct flash_area secondary_2 =
{
.fa_id = FLASH_AREA_IMAGE_SECONDARY(1),
- /* it is for external flash memory
- .fa_device_id = FLASH_DEVICE_EXTERNAL_FLASH(CY_BOOT_EXTERNAL_DEVICE_INDEX), */
#ifndef CY_BOOT_USE_EXTERNAL_FLASH
.fa_device_id = FLASH_DEVICE_INTERNAL_FLASH,
.fa_off = CY_FLASH_BASE +\
@@ -134,31 +139,88 @@
CY_BOOT_PRIMARY_2_SIZE,
#else
.fa_device_id = FLASH_DEVICE_EXTERNAL_FLASH(CY_BOOT_EXTERNAL_DEVICE_INDEX),
- .fa_off = CY_SMIF_BASE_MEM_OFFSET + 0x40000,
-#endif
+ .fa_off = CY_BOOT_SECONDARY_2_EXT_MEM_OFFSET,
+#endif /* CY_BOOT_USE_EXTERNAL_FLASH */
.fa_size = CY_BOOT_SECONDARY_2_SIZE
};
-#endif
-#endif
+#endif /* MCUBOOT_IMAGE_NUMBER == 2 */
+#endif /* CY_FLASH_MAP_EXT_DESC */
+
+#ifdef MCUBOOT_SWAP_USING_STATUS
+#define SWAP_STATUS_PARTITION_SIZE (CY_BOOT_SWAP_STATUS_SIZE * BOOT_IMAGE_NUMBER)
+
+#ifndef CY_BOOT_USE_EXTERNAL_FLASH
+#if (MCUBOOT_IMAGE_NUMBER == 1) /* if single image, internal flash */
+#define SWAP_STATUS_PARTITION_OFF (CY_FLASH_BASE + \
+ CY_BOOT_BOOTLOADER_SIZE + \
+ CY_BOOT_PRIMARY_1_SIZE + \
+ CY_BOOT_SECONDARY_1_SIZE)
+#elif (MCUBOOT_IMAGE_NUMBER == 2) /* if dual-image, internal flash */
+#define SWAP_STATUS_PARTITION_OFF (CY_FLASH_BASE + \
+ CY_BOOT_BOOTLOADER_SIZE + \
+ CY_BOOT_PRIMARY_1_SIZE + \
+ CY_BOOT_SECONDARY_1_SIZE + \
+ CY_BOOT_PRIMARY_2_SIZE + \
+ CY_BOOT_SECONDARY_2_SIZE)
+#endif /* MCUBOOT_IMAGE_NUMBER */
+#else /* CY_BOOT_USE_EXTERNAL_FLASH */
+#if (MCUBOOT_IMAGE_NUMBER == 1) /* if single image, external flash */
+#define SWAP_STATUS_PARTITION_OFF (CY_FLASH_BASE + \
+ CY_BOOT_BOOTLOADER_SIZE + \
+ CY_BOOT_PRIMARY_1_SIZE)
+#elif (MCUBOOT_IMAGE_NUMBER == 2) /* if dual-image, external flash */
+#define SWAP_STATUS_PARTITION_OFF (CY_FLASH_BASE + \
+ CY_BOOT_BOOTLOADER_SIZE + \
+ CY_BOOT_PRIMARY_1_SIZE + \
+ CY_BOOT_PRIMARY_2_SIZE)
+#endif /* MCUBOOT_IMAGE_NUMBER */
+#endif /* CY_BOOT_USE_EXTERNAL_FLASH */
+static struct flash_area status =
+{
+ .fa_id = FLASH_AREA_IMAGE_SWAP_STATUS,
+ .fa_device_id = FLASH_DEVICE_INTERNAL_FLASH,
+ .fa_off = SWAP_STATUS_PARTITION_OFF,
+#ifdef MCUBOOT_SWAP_USING_SCRATCH
+ .fa_size = (SWAP_STATUS_PARTITION_SIZE + BOOT_SWAP_STATUS_SZ_SCRATCH)
+#else
+ .fa_size = (SWAP_STATUS_PARTITION_SIZE)
+#endif /* MCUBOOT_SWAP_USING_SCRATCH */
+
+};
+#endif /* MCUBOOT_SWAP_USING_STATUS */
#ifdef MCUBOOT_SWAP_USING_SCRATCH
+#ifndef CY_BOOT_SCRATCH_SIZE
+#ifndef CY_BOOT_USE_EXTERNAL_FLASH
+#define CY_BOOT_SCRATCH_SIZE (CY_FLASH_SIZEOF_ROW)
+#else
+#define CY_BOOT_SCRATCH_SIZE (CY_BOOT_SCRATCH_SIZE)
+#endif
+#endif
static struct flash_area scratch =
{
.fa_id = FLASH_AREA_IMAGE_SCRATCH,
+#ifndef CY_BOOT_USE_EXTERNAL_FLASH
.fa_device_id = FLASH_DEVICE_INTERNAL_FLASH,
-#if (MCUBOOT_IMAGE_NUMBER == 1) /* if single-image */
+#if (MCUBOOT_IMAGE_NUMBER == 1) /* if single image */
.fa_off = CY_FLASH_BASE +\
CY_BOOT_BOOTLOADER_SIZE +\
CY_BOOT_PRIMARY_1_SIZE +\
- CY_BOOT_SECONDARY_1_SIZE,
+ CY_BOOT_SECONDARY_1_SIZE + \
+ (SWAP_STATUS_PARTITION_SIZE + BOOT_SWAP_STATUS_SZ_SCRATCH),
#elif (MCUBOOT_IMAGE_NUMBER == 2) /* if dual-image */
.fa_off = CY_FLASH_BASE +\
CY_BOOT_BOOTLOADER_SIZE +\
CY_BOOT_PRIMARY_1_SIZE +\
CY_BOOT_SECONDARY_1_SIZE +\
CY_BOOT_PRIMARY_2_SIZE +\
- CY_BOOT_SECONDARY_2_SIZE,
-#endif
+ CY_BOOT_SECONDARY_2_SIZE + \
+ (SWAP_STATUS_PARTITION_SIZE + BOOT_SWAP_STATUS_SZ_SCRATCH),
+#endif /* MCUBOOT_IMAGE_NUMBER */
+#else /* CY_BOOT_USE_EXTERNAL_FLASH */
+ .fa_device_id = FLASH_DEVICE_EXTERNAL_FLASH(CY_BOOT_EXTERNAL_DEVICE_INDEX),
+ .fa_off = CY_SMIF_BASE_MEM_OFFSET + CY_BOOT_EXTERNAL_FLASH_SCRATCH_OFFSET,
+#endif /* CY_BOOT_USE_EXTERNAL_FLASH */
.fa_size = CY_BOOT_SCRATCH_SIZE
};
#endif
@@ -179,14 +241,19 @@
#ifdef MCUBOOT_SWAP_USING_SCRATCH
&scratch,
#endif
+#ifdef MCUBOOT_SWAP_USING_STATUS
+ &status,
+#endif
NULL
};
-#endif
+#endif /* CY_FLASH_MAP_EXT_DESC */
-/* Returns device flash start based on supported fa_id */
+/*
+* Returns device flash start based on supported fa_id
+*/
int flash_device_base(uint8_t fd_id, uintptr_t *ret)
{
- if (fd_id != FLASH_DEVICE_INTERNAL_FLASH) {
+ if (fd_id != (uint8_t)FLASH_DEVICE_INTERNAL_FLASH) {
BOOT_LOG_ERR("invalid flash ID %d; expected %d",
fd_id, FLASH_DEVICE_INTERNAL_FLASH);
return -1;
@@ -195,7 +262,9 @@
return 0;
}
-/* Opens the area for use. id is one of the `fa_id`s */
+/*
+* Opens the area for use. id is one of the `fa_id`s
+*/
int flash_area_open(uint8_t id, const struct flash_area **fa)
{
int ret = -1;
@@ -211,12 +280,16 @@
}
i++;
}
+
return ret;
}
+/*
+* Clear pointer to flash area fa
+*/
void flash_area_close(const struct flash_area *fa)
{
- (void)fa;/* Nothing to do there */
+ (void)fa; /* Nothing to do there */
}
/*
@@ -229,20 +302,20 @@
size_t addr;
/* check if requested offset not less then flash area (fa) start */
- assert(off < fa->fa_off);
- assert(off + len < fa->fa_off);
+ assert((int)(off < fa->fa_off));
+ assert((int)(off + len < fa->fa_off));
/* convert to absolute address inside a device*/
- addr = fa->fa_off + off;
+ addr = fa->fa_off + off;
if (fa->fa_device_id == FLASH_DEVICE_INTERNAL_FLASH)
{
/* flash read by simple memory copying */
- memcpy((void *)dst, (const void*)addr, (size_t)len);
+ (void)memcpy((void *)dst, (const void*)addr, (size_t)len);
}
#ifdef CY_BOOT_USE_EXTERNAL_FLASH
else if ((fa->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
{
- rc = psoc6_smif_read(fa, addr, dst, len);
+ rc = psoc6_smif_read(fa, (int32_t)addr, dst, len);
}
#endif
else
@@ -251,7 +324,8 @@
rc = -1;
}
- if (rc != 0) {
+ if ((rc != 0) && (fa->fa_device_id != FLASH_DEVICE_UNDEFINED))
+ {
BOOT_LOG_ERR("Flash area read error, rc = %d", (int)rc);
}
return rc;
@@ -268,8 +342,8 @@
size_t write_end_addr;
const uint32_t * row_ptr = NULL;
- assert(off < fa->fa_off);
- assert(off + len < fa->fa_off);
+ assert((int)(off < fa->fa_off));
+ assert((int)(off + len < fa->fa_off));
/* convert to absolute address inside a device */
write_start_addr = fa->fa_off + off;
@@ -280,26 +354,26 @@
uint32_t row_number = 0;
uint32_t row_addr = 0;
- assert(!(len % CY_FLASH_SIZEOF_ROW));
- assert(!(write_start_addr % CY_FLASH_SIZEOF_ROW));
+ assert((int)((len % CY_FLASH_SIZEOF_ROW) == 0U));
+ assert((int)((write_start_addr % CY_FLASH_SIZEOF_ROW) == 0U));
row_number = (write_end_addr - write_start_addr) / CY_FLASH_SIZEOF_ROW;
row_addr = write_start_addr;
- row_ptr = (uint32_t *) src;
+ row_ptr = (const uint32_t *) src;
for (uint32_t i = 0; i < row_number; i++)
{
- rc = Cy_Flash_WriteRow(row_addr, row_ptr);
+ rc = (int)Cy_Flash_WriteRow(row_addr, row_ptr);
row_addr += (uint32_t) CY_FLASH_SIZEOF_ROW;
- row_ptr = row_ptr + CY_FLASH_SIZEOF_ROW / 4;
+ row_ptr = row_ptr + CY_FLASH_SIZEOF_ROW / 4U;
}
}
#ifdef CY_BOOT_USE_EXTERNAL_FLASH
else if ((fa->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
{
- rc = psoc6_smif_write(fa, write_start_addr, src, len);
+ rc = psoc6_smif_write(fa, (int32_t)write_start_addr, src, len);
}
#endif
else
@@ -318,9 +392,9 @@
size_t erase_start_addr;
size_t erase_end_addr;
- assert(off < fa->fa_off);
- assert(off + len < fa->fa_off);
- assert(!(len % CY_FLASH_SIZEOF_ROW));
+ assert((int)(len <= fa->fa_size));
+ assert((int)(off < fa->fa_size));
+ assert((int)(off + len < fa->fa_off + fa->fa_size));
/* convert to absolute address inside a device*/
erase_start_addr = fa->fa_off + off;
@@ -330,20 +404,27 @@
{
int row_number = 0;
uint32_t row_addr = 0;
+ uint32_t row_start_addr = (erase_start_addr / CY_FLASH_SIZEOF_ROW) * CY_FLASH_SIZEOF_ROW;
+ uint32_t row_end_addr = (erase_end_addr / CY_FLASH_SIZEOF_ROW) * CY_FLASH_SIZEOF_ROW;
- row_number = (erase_end_addr - erase_start_addr) / CY_FLASH_SIZEOF_ROW;
+ /* assume single row needs to be erased */
+ if (row_start_addr == row_end_addr) {
+ rc = (int)Cy_Flash_EraseRow(row_start_addr);
+ } else {
+ row_number = (int)((row_end_addr - row_start_addr) / CY_FLASH_SIZEOF_ROW);
- while (row_number != 0)
- {
- row_number--;
- row_addr = erase_start_addr + row_number * (uint32_t) CY_FLASH_SIZEOF_ROW;
- rc = Cy_Flash_EraseRow(row_addr);
- }
+ while (row_number != 0)
+ {
+ row_number--;
+ row_addr = row_start_addr + (uint32_t) row_number * (uint32_t) CY_FLASH_SIZEOF_ROW;
+ rc = (int)Cy_Flash_EraseRow(row_addr);
+ }
+ }
}
#ifdef CY_BOOT_USE_EXTERNAL_FLASH
else if ((fa->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
{
- rc = psoc6_smif_erase(erase_start_addr, len);
+ rc = psoc6_smif_erase((int)erase_start_addr, len);
}
#endif
else
@@ -357,7 +438,7 @@
/*< Returns this `flash_area`s alignment */
size_t flash_area_align(const struct flash_area *fa)
{
- int ret = -1;
+ size_t ret = (size_t)-1;
if (fa->fa_device_id == FLASH_DEVICE_INTERNAL_FLASH)
{
ret = CY_FLASH_ALIGN;
@@ -365,20 +446,20 @@
#ifdef CY_BOOT_USE_EXTERNAL_FLASH
else if ((fa->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
{
- return qspi_get_prog_size();
+ ret = qspi_get_prog_size();
}
#endif
else
{
/* incorrect/non-existing flash device id */
- ret = -1;
+ ret = (size_t)-1;
}
return ret;
}
#ifdef MCUBOOT_USE_FLASH_AREA_GET_SECTORS
/*< Initializes an array of flash_area elements for the slot's sectors */
-int flash_area_to_sectors(int idx, int *cnt, struct flash_area *fa)
+int flash_area_to_sectors(int idx, int *cnt, struct flash_area *fa)
{
int rc = 0;
@@ -412,13 +493,22 @@
*/
int flash_area_id_from_multi_image_slot(int image_index, int slot)
{
+ int rc;
switch (slot) {
- case 0: return FLASH_AREA_IMAGE_PRIMARY(image_index);
- case 1: return FLASH_AREA_IMAGE_SECONDARY(image_index);
- case 2: return FLASH_AREA_IMAGE_SCRATCH;
+ case 0:
+ rc = (int)FLASH_AREA_IMAGE_PRIMARY((uint32_t)image_index);
+ break;
+ case 1:
+ rc = (int)FLASH_AREA_IMAGE_SECONDARY((uint32_t)image_index);
+ break;
+ case 2:
+ rc = (int)FLASH_AREA_IMAGE_SCRATCH;
+ break;
+ default:
+ rc = -1; /* flash_area_open will fail on that */
+ break;
}
-
- return -1; /* flash_area_open will fail on that */
+ return rc;
}
int flash_area_id_from_image_slot(int slot)
@@ -428,10 +518,10 @@
int flash_area_id_to_multi_image_slot(int image_index, int area_id)
{
- if (area_id == FLASH_AREA_IMAGE_PRIMARY(image_index)) {
+ if (area_id == (int) FLASH_AREA_IMAGE_PRIMARY((uint32_t)image_index)) {
return 0;
}
- if (area_id == FLASH_AREA_IMAGE_SECONDARY(image_index)) {
+ if (area_id == (int) FLASH_AREA_IMAGE_SECONDARY((uint32_t)image_index)) {
return 1;
}
@@ -443,23 +533,40 @@
return flash_area_id_to_multi_image_slot(0, area_id);
}
-uint8_t flash_area_erased_val(const struct flash_area *fap)
+/*
+ * Erases aligned row of flash, where passed address resided
+ */
+int flash_erase_row(uint32_t address)
{
- int ret = 0;
+ cy_en_flashdrv_status_t rc = CY_FLASH_DRV_SUCCESS;
+ uint32_t row_addr = 0;
- if (fap->fa_device_id == FLASH_DEVICE_INTERNAL_FLASH)
+ /* Calculate start of row arbitrary address */
+ row_addr = (address/CY_FLASH_SIZEOF_ROW)*CY_FLASH_SIZEOF_ROW;
+
+ /* Erase whole row of flash */
+ rc = Cy_Flash_EraseRow(row_addr);
+
+ return (int) rc;
+}
+
+uint8_t flash_area_erased_val(const struct flash_area *fa)
+{
+ uint8_t ret = 0;
+
+ if (fa->fa_device_id == FLASH_DEVICE_INTERNAL_FLASH)
{
- ret = CY_BOOT_INTERNAL_FLASH_ERASE_VALUE;
+ ret = (uint8_t) CY_BOOT_INTERNAL_FLASH_ERASE_VALUE;
}
#ifdef CY_BOOT_USE_EXTERNAL_FLASH
- else if ((fap->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
+ else if ((fa->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
{
- ret = CY_BOOT_EXTERNAL_FLASH_ERASE_VALUE;
+ ret = (uint8_t) CY_BOOT_EXTERNAL_FLASH_ERASE_VALUE;
}
#endif
else
{
- assert(false) ;
+ assert(false);
}
return ret ;
@@ -468,18 +575,22 @@
int flash_area_read_is_empty(const struct flash_area *fa, uint32_t off,
void *dst, uint32_t len)
{
- uint8_t *mem_dest;
- int rc;
+ /* The disabled flash area always tracts as empty */
+ if (fa->fa_device_id != FLASH_DEVICE_UNDEFINED)
+ {
+ int rc;
+ uint8_t *mem_dest = (uint8_t *)dst;
+ uint8_t val = flash_area_erased_val(fa);
- mem_dest = (uint8_t *)dst;
- rc = flash_area_read(fa, off, dst, len);
- if (rc) {
- return -1;
- }
+ rc = flash_area_read(fa, off, dst, len);
+ if (rc != 0) {
+ return -1;
+ }
- for (uint8_t i = 0; i < len; i++) {
- if (mem_dest[i] != flash_area_erased_val(fa)) {
- return 0;
+ for (uint8_t i = 0; i < len; i++) {
+ if (mem_dest[i] != val) {
+ return 0;
+ }
}
}
return 1;
@@ -489,12 +600,12 @@
int flash_area_get_sectors(int idx, uint32_t *cnt, struct flash_sector *ret)
{
int rc = 0;
- uint32_t i = 0;
+ uint32_t i = 0u;
struct flash_area *fa = NULL;
while(NULL != boot_area_descs[i])
{
- if(idx == boot_area_descs[i]->fa_id)
+ if(idx == (int) boot_area_descs[i]->fa_id)
{
fa = boot_area_descs[i];
break;
@@ -502,44 +613,93 @@
i++;
}
- if(NULL != boot_area_descs[i])
+ if(NULL != fa)
{
size_t sector_size = 0;
+ size_t area_size = fa->fa_size;
if(fa->fa_device_id == FLASH_DEVICE_INTERNAL_FLASH)
{
- sector_size = CY_FLASH_SIZEOF_ROW;
- }
+#if defined(CY_BOOT_USE_EXTERNAL_FLASH) && defined(MCUBOOT_SWAP_USING_STATUS) \
+ && !defined(MCUBOOT_SWAP_USING_SCRATCH)
+ if(idx == (int) FLASH_AREA_IMAGE_SWAP_STATUS)
+ {
+ sector_size = CY_FLASH_SIZEOF_ROW;
+ }
+ else
+ {
+ sector_size = qspi_get_erase_size();
+#else
+ sector_size = CY_FLASH_SIZEOF_ROW;
+#endif /* MCUBOOT_SWAP_USING_STATUS && CY_BOOT_USE_EXTERNAL_FLASH */
+ }
#ifdef CY_BOOT_USE_EXTERNAL_FLASH
- else if((fa->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
- {
+ else if((fa->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
+ {
/* implement for SMIF */
/* lets assume they are equal */
- sector_size = CY_FLASH_SIZEOF_ROW;
- }
-#endif
+#ifdef MCUBOOT_SWAP_USING_STATUS
+ sector_size = qspi_get_erase_size();
+#else
+ sector_size = CY_FLASH_SIZEOF_ROW;
+#endif /* MCUBOOT_SWAP_USING_STATUS */
+ }
+#endif /* CY_BOOT_USE_EXTERNAL_FLASH */
else
{
- rc = -1;
+ /* fa->fa_device_id = FLASH_DEVICE_UNDEFINED,
+ in this case the area should be empty with a very simple sector size of 1 byte */
+ area_size = 0u;
+ sector_size = 1u;
}
if(0 == rc)
{
- uint32_t addr = 0;
- size_t sectors_n = 0;
+ size_t sectors_n;
+ uint32_t my_sector_addr = 0U;
+ uint32_t my_sector_size;
- sectors_n = (fa->fa_size + (sector_size - 1)) / sector_size;
- assert(sectors_n <= *cnt);
+ sectors_n = (area_size + (sector_size - 1U)) / sector_size;
- addr = fa->fa_off;
- for(i = 0; i < sectors_n; i++)
+ if (sectors_n > MCUBOOT_MAX_IMG_SECTORS)
{
- ret[i].fs_size = sector_size ;
- ret[i].fs_off = addr ;
- addr += sector_size ;
+ sector_size *= 2;
}
- *cnt = sectors_n;
+ sectors_n = 0;
+ my_sector_addr = fa->fa_off;
+ while (area_size > 0)
+ {
+ my_sector_size = sector_size;
+#ifdef MCUBOOT_SWAP_USING_SCRATCH
+ uint32_t my_sector_offs = my_sector_addr % my_sector_size;
+
+ if (my_sector_offs != 0)
+ {
+ my_sector_size = sector_size - my_sector_offs;
+ }
+
+ if (my_sector_size > area_size)
+ {
+ my_sector_size = area_size;
+ }
+#endif
+ ret[sectors_n].fs_size = my_sector_size;
+ ret[sectors_n].fs_off = my_sector_addr;
+
+ my_sector_addr += my_sector_size;
+ area_size -= my_sector_size;
+ sectors_n++;
+ }
+
+ if (sectors_n <= *cnt)
+ {
+ *cnt = sectors_n;
+ }
+ else
+ {
+ rc = -1;
+ }
}
}
else
diff --git a/boot/cypress/cy_flash_pal/cy_smif_psoc6.c b/boot/cypress/cy_flash_pal/cy_smif_psoc6.c
index 62f7137..c2dd5c3 100644
--- a/boot/cypress/cy_flash_pal/cy_smif_psoc6.c
+++ b/boot/cypress/cy_flash_pal/cy_smif_psoc6.c
@@ -83,7 +83,7 @@
cfg = qspi_get_memory_config(FLASH_DEVICE_GET_EXT_INDEX(fap->fa_device_id));
- address = addr - CY_SMIF_BASE_MEM_OFFSET;
+ address = (uint32_t) addr - CY_SMIF_BASE_MEM_OFFSET;
st = Cy_SMIF_MemRead(qspi_get_device(), cfg, address, data, len, qspi_get_context());
if (st == CY_SMIF_SUCCESS) {
@@ -104,7 +104,7 @@
cfg = qspi_get_memory_config(FLASH_DEVICE_GET_EXT_INDEX(fap->fa_device_id));
- address = addr - CY_SMIF_BASE_MEM_OFFSET;
+ address = (uint32_t) addr - CY_SMIF_BASE_MEM_OFFSET;
st = Cy_SMIF_MemWrite(qspi_get_device(), cfg, address, data, len, qspi_get_context());
if (st == CY_SMIF_SUCCESS) {
@@ -116,28 +116,37 @@
int psoc6_smif_erase(off_t addr, size_t size)
{
int rc = -1;
- cy_en_smif_status_t st;
+ cy_en_smif_status_t st = CY_SMIF_SUCCESS;
uint32_t address;
- /* It is erase sector-only
- *
- * There is no power-safe way to erase flash partially
- * this leads upgrade slots have to be at least
- * eraseSectorSize far from each other;
- */
- cy_stc_smif_mem_config_t *memCfg = qspi_get_memory_config(0);
+ if (size > 0)
+ {
+ /* It is erase sector-only
+ *
+ * There is no power-safe way to erase flash partially
+ * this leads upgrade slots have to be at least
+ * eraseSectorSize far from each other;
+ */
+ cy_stc_smif_mem_config_t *memCfg = qspi_get_memory_config(0);
- address = (addr - CY_SMIF_BASE_MEM_OFFSET ) & ~((uint32_t)(memCfg->deviceCfg->eraseSize - 1u));
+ address = ((uint32_t)addr - CY_SMIF_BASE_MEM_OFFSET ) & ~((uint32_t)(memCfg->deviceCfg->eraseSize - 1u));
- (void)size;
+ while ((size > 0) && (CY_SMIF_SUCCESS == st))
+ {
+ st = Cy_SMIF_MemEraseSector(qspi_get_device(),
+ memCfg,
+ address,
+ memCfg->deviceCfg->eraseSize,
+ qspi_get_context());
- st = Cy_SMIF_MemEraseSector(qspi_get_device(),
- memCfg,
- address,
- memCfg->deviceCfg->eraseSize,
- qspi_get_context());
- if (st == CY_SMIF_SUCCESS) {
- rc = 0;
+ size -= (size >= memCfg->deviceCfg->eraseSize) ? memCfg->deviceCfg->eraseSize : size;
+ address += memCfg->deviceCfg->eraseSize;
+ }
+
+ if (st == CY_SMIF_SUCCESS) {
+ rc = 0;
+ }
}
+
return rc;
}
diff --git a/boot/cypress/cy_flash_pal/flash_qspi/flash_qspi.c b/boot/cypress/cy_flash_pal/flash_qspi/flash_qspi.c
index e1f6c27..6ac5894 100644
--- a/boot/cypress/cy_flash_pal/flash_qspi/flash_qspi.c
+++ b/boot/cypress/cy_flash_pal/flash_qspi/flash_qspi.c
@@ -69,6 +69,8 @@
#define CY_SMIF_SYSCLK_HFCLK_DIVIDER CY_SYSCLK_CLKHF_DIVIDE_BY_4
+#define CY_SMIF_INIT_TRY_COUNT (10U)
+
/* This is the board specific stuff that should align with your board.
*
* QSPI resources:
@@ -155,7 +157,7 @@
static SMIF_Type *QSPIPort = SMIF0;
-cy_stc_smif_mem_cmd_t sfdpcmd =
+static cy_stc_smif_mem_cmd_t sfdpcmd =
{
.command = 0x5A,
.cmdWidth = CY_SMIF_WIDTH_SINGLE,
@@ -204,7 +206,7 @@
.deviceCfg = &dev_sfdp_0
};
-cy_stc_smif_mem_config_t *mems_sfdp[1] =
+static cy_stc_smif_mem_config_t *mems_sfdp[1] =
{
&mem_sfdp_0
};
@@ -223,10 +225,10 @@
cy_stc_smif_config_t const QSPI_config =
{
- .mode = CY_SMIF_NORMAL,
+ .mode = (uint32_t)CY_SMIF_NORMAL,
.deselectDelay = 1,
- .rxClockSel = CY_SMIF_SEL_INV_INTERNAL_CLK,
- .blockEvent = CY_SMIF_BUS_ERROR
+ .rxClockSel = (uint32_t)CY_SMIF_SEL_INV_INTERNAL_CLK,
+ .blockEvent = (uint32_t)CY_SMIF_BUS_ERROR
};
cy_stc_sysint_t smifIntConfig =
@@ -339,7 +341,7 @@
Cy_SMIF_Interrupt(QSPIPort, &QSPI_context);
}
-cy_en_smif_status_t qspi_init_hardware()
+cy_en_smif_status_t qspi_init_hardware(void)
{
cy_en_smif_status_t st;
@@ -451,7 +453,16 @@
Cy_GPIO_Pin_Init(SS_Port, SS_Pin, &QSPI_SS_config);
Cy_GPIO_SetHSIOM(SS_Port, SS_Pin, SS_MuxPort);
- stat = qspi_init(&smifBlockConfig_sfdp);
+ uint32_t try_count = CY_SMIF_INIT_TRY_COUNT;
+ do {
+ stat = qspi_init(&smifBlockConfig_sfdp);
+
+ try_count--;
+ if (stat != CY_SMIF_SUCCESS)
+ {
+ Cy_SysLib_Delay(500U);
+ }
+ } while ((stat != CY_SMIF_SUCCESS) && (try_count > 0U));
}
return stat;
}
diff --git a/boot/cypress/cy_flash_pal/include/flash_map_backend/flash_map_backend.h b/boot/cypress/cy_flash_pal/include/flash_map_backend/flash_map_backend.h
index da68618..4b9409b 100644
--- a/boot/cypress/cy_flash_pal/include/flash_map_backend/flash_map_backend.h
+++ b/boot/cypress/cy_flash_pal/include/flash_map_backend/flash_map_backend.h
@@ -25,15 +25,16 @@
*/
/*******************************************************************************/
-#ifndef __FLASH_MAP_BACKEND_H__
-#define __FLASH_MAP_BACKEND_H__
+#ifndef FLASH_MAP_BACKEND_H
+#define FLASH_MAP_BACKEND_H
#include <mcuboot_config/mcuboot_config.h>
#include "cy_flash.h"
-#define FLASH_DEVICE_INDEX_MASK (0x7F)
+#define FLASH_DEVICE_INDEX_MASK (0x7Fu)
#define FLASH_DEVICE_GET_EXT_INDEX(n) ((n) & FLASH_DEVICE_INDEX_MASK)
-#define FLASH_DEVICE_EXTERNAL_FLAG (0x80)
-#define FLASH_DEVICE_INTERNAL_FLASH (0x7F)
+#define FLASH_DEVICE_UNDEFINED (0x00u)
+#define FLASH_DEVICE_EXTERNAL_FLAG (0x80u)
+#define FLASH_DEVICE_INTERNAL_FLASH (0x7Fu)
#define FLASH_DEVICE_EXTERNAL_FLASH(index) (FLASH_DEVICE_EXTERNAL_FLAG | index)
#ifndef CY_BOOT_EXTERNAL_DEVICE_INDEX
@@ -126,20 +127,22 @@
int flash_device_base(uint8_t fd_id, uintptr_t *ret);
/*< Opens the area for use. id is one of the `fa_id`s */
-int flash_area_open(uint8_t id, const struct flash_area **);
+int flash_area_open(uint8_t id, const struct flash_area **fa);
void flash_area_close(const struct flash_area *);
/*< Reads `len` bytes of flash memory at `off` to the buffer at `dst` */
-int flash_area_read(const struct flash_area *, uint32_t off, void *dst,
+int flash_area_read(const struct flash_area *fa, uint32_t off, void *dst,
uint32_t len);
/*< Writes `len` bytes of flash memory at `off` from the buffer at `src` */
-int flash_area_write(const struct flash_area *, uint32_t off,
+int flash_area_write(const struct flash_area *fa, uint32_t off,
const void *src, uint32_t len);
/*< Erases `len` bytes of flash memory at `off` */
-int flash_area_erase(const struct flash_area *, uint32_t off, uint32_t len);
+int flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len);
+/*< Erases aligned row of flash, where passed address resided */
+int flash_erase_row(uint32_t address);
/*< Returns this `flash_area`s alignment */
-size_t flash_area_align(const struct flash_area *);
+size_t flash_area_align(const struct flash_area *fa);
/*< Initializes an array of flash_area elements for the slot's sectors */
-int flash_area_to_sectors(int idx, int *cnt, struct flash_area *ret);
+int flash_area_to_sectors(int idx, int *cnt, struct flash_area *fa);
/*< Returns the `fa_id` for slot, where slot is 0 (primary) or 1 (secondary) */
int flash_area_id_from_image_slot(int slot);
/*< Returns the slot, for the `fa_id` supplied */
@@ -154,7 +157,7 @@
* Returns the value expected to be read when accesing any erased
* flash byte.
*/
-uint8_t flash_area_erased_val(const struct flash_area *fap);
+uint8_t flash_area_erased_val(const struct flash_area *fa);
/*
* Reads len bytes from off, and checks if the read data is erased.
@@ -164,4 +167,4 @@
int flash_area_read_is_empty(const struct flash_area *fa, uint32_t off,
void *dst, uint32_t len);
-#endif /* __FLASH_MAP_BACKEND_H__ */
+#endif /* FLASH_MAP_BACKEND_H */
diff --git a/boot/cypress/platforms/PSOC_062_2M/CM0P/GCC_ARM/cy8c6xxa_cm0plus.ld b/boot/cypress/platforms/PSOC_062_2M/CM0P/GCC_ARM/cy8c6xxa_cm0plus.ld
deleted file mode 100644
index 1f3a5a9..0000000
--- a/boot/cypress/platforms/PSOC_062_2M/CM0P/GCC_ARM/cy8c6xxa_cm0plus.ld
+++ /dev/null
@@ -1,418 +0,0 @@
-/***************************************************************************//**
-* \file cy8c6xxa_cm0plus.ld
-* \version 2.70
-*
-* Linker file for the GNU C compiler.
-*
-* The main purpose of the linker script is to describe how the sections in the
-* input files should be mapped into the output file, and to control the memory
-* layout of the output file.
-*
-* \note The entry point location is fixed and starts at 0x10000000. The valid
-* application image should be placed there.
-*
-* \note The linker files included with the PDL template projects must be generic
-* and handle all common use cases. Your project may not use every section
-* defined in the linker files. In that case you may see warnings during the
-* build process. In your project, you can simply comment out or remove the
-* relevant code in the linker file.
-*
-********************************************************************************
-* \copyright
-* Copyright 2016-2019 Cypress Semiconductor Corporation
-* SPDX-License-Identifier: Apache-2.0
-*
-* Licensed 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.
-*******************************************************************************/
-
-OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
-SEARCH_DIR(.)
-GROUP(-lgcc -lc -lnosys)
-ENTRY(Reset_Handler)
-
-/* The size of the stack section at the end of CM0+ SRAM */
-STACK_SIZE = 0x1000;
-
-/* Force symbol to be entered in the output file as an undefined symbol. Doing
-* this may, for example, trigger linking of additional modules from standard
-* libraries. You may list several symbols for each EXTERN, and you may use
-* EXTERN multiple times. This command has the same effect as the -u command-line
-* option.
-*/
-EXTERN(Reset_Handler)
-
-/* The MEMORY section below describes the location and size of blocks of memory in the target.
-* Use this section to specify the memory regions available for allocation.
-*/
-MEMORY
-{
- /* The ram and flash regions control RAM and flash memory allocation for the CM0+ core.
- * You can change the memory allocation by editing the 'ram' and 'flash' regions.
- * Note that 2 KB of RAM (at the end of the SRAM) are reserved for system use.
- * Using this memory region for other purposes will lead to unexpected behavior.
- * Your changes must be aligned with the corresponding memory regions for the CM4 core in 'xx_cm4_dual.ld',
- * where 'xx' is the device group; for example, 'cy8c6xx7_cm4_dual.ld'.
- */
- ram (rwx) : ORIGIN = 0x08000000, LENGTH = 0x2000
- flash (rx) : ORIGIN = 0x10000000, LENGTH = 0x2000
-
- /* This is a 32K flash region used for EEPROM emulation. This region can also be used as the general purpose flash.
- * You can assign sections to this memory region for only one of the cores.
- * Note some middleware (e.g. BLE, Emulated EEPROM) can place their data into this memory region.
- * Therefore, repurposing this memory region will prevent such middleware from operation.
- */
- em_eeprom (rx) : ORIGIN = 0x14000000, LENGTH = 0x8000 /* 32 KB */
-
- /* The following regions define device specific memory regions and must not be changed. */
- sflash_user_data (rx) : ORIGIN = 0x16000800, LENGTH = 0x800 /* Supervisory flash: User data */
- sflash_nar (rx) : ORIGIN = 0x16001A00, LENGTH = 0x200 /* Supervisory flash: Normal Access Restrictions (NAR) */
- sflash_public_key (rx) : ORIGIN = 0x16005A00, LENGTH = 0xC00 /* Supervisory flash: Public Key */
- sflash_toc_2 (rx) : ORIGIN = 0x16007C00, LENGTH = 0x200 /* Supervisory flash: Table of Content # 2 */
- sflash_rtoc_2 (rx) : ORIGIN = 0x16007E00, LENGTH = 0x200 /* Supervisory flash: Table of Content # 2 Copy */
- xip (rx) : ORIGIN = 0x18000000, LENGTH = 0x8000000 /* 128 MB */
- efuse (r) : ORIGIN = 0x90700000, LENGTH = 0x100000 /* 1 MB */
-}
-
-/* Library configurations */
-GROUP(libgcc.a libc.a libm.a libnosys.a)
-
-/* Linker script to place sections and symbol values. Should be used together
- * with other linker script that defines memory regions FLASH and RAM.
- * It references following symbols, which must be defined in code:
- * Reset_Handler : Entry of reset handler
- *
- * It defines following symbols, which code can use without definition:
- * __exidx_start
- * __exidx_end
- * __copy_table_start__
- * __copy_table_end__
- * __zero_table_start__
- * __zero_table_end__
- * __etext
- * __data_start__
- * __preinit_array_start
- * __preinit_array_end
- * __init_array_start
- * __init_array_end
- * __fini_array_start
- * __fini_array_end
- * __data_end__
- * __bss_start__
- * __bss_end__
- * __end__
- * end
- * __HeapLimit
- * __StackLimit
- * __StackTop
- * __stack
- * __Vectors_End
- * __Vectors_Size
- */
-
-
-SECTIONS
-{
- .cy_app_header :
- {
- KEEP(*(.cy_app_header))
- } > flash
-
- /* Cortex-M0+ application flash area */
- .text :
- {
- . = ALIGN(4);
- __Vectors = . ;
- KEEP(*(.vectors))
- . = ALIGN(4);
- __Vectors_End = .;
- __Vectors_Size = __Vectors_End - __Vectors;
- __end__ = .;
-
- . = ALIGN(4);
- *(.text*)
-
- KEEP(*(.init))
- KEEP(*(.fini))
-
- /* .ctors */
- *crtbegin.o(.ctors)
- *crtbegin?.o(.ctors)
- *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
- *(SORT(.ctors.*))
- *(.ctors)
-
- /* .dtors */
- *crtbegin.o(.dtors)
- *crtbegin?.o(.dtors)
- *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
- *(SORT(.dtors.*))
- *(.dtors)
-
- /* Read-only code (constants). */
- *(.rodata .rodata.* .constdata .constdata.* .conststring .conststring.*)
-
- KEEP(*(.eh_frame*))
- } > flash
-
-
- .ARM.extab :
- {
- *(.ARM.extab* .gnu.linkonce.armextab.*)
- } > flash
-
- __exidx_start = .;
-
- .ARM.exidx :
- {
- *(.ARM.exidx* .gnu.linkonce.armexidx.*)
- } > flash
- __exidx_end = .;
-
-
- /* To copy multiple ROM to RAM sections,
- * uncomment .copy.table section and,
- * define __STARTUP_COPY_MULTIPLE in startup_psoc6_02_cm0plus.S */
- .copy.table :
- {
- . = ALIGN(4);
- __copy_table_start__ = .;
-
- /* Copy interrupt vectors from flash to RAM */
- LONG (__Vectors) /* From */
- LONG (__ram_vectors_start__) /* To */
- LONG (__Vectors_End - __Vectors) /* Size */
-
- /* Copy data section to RAM */
- LONG (__etext) /* From */
- LONG (__data_start__) /* To */
- LONG (__data_end__ - __data_start__) /* Size */
-
- __copy_table_end__ = .;
- } > flash
-
-
- /* To clear multiple BSS sections,
- * uncomment .zero.table section and,
- * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_psoc6_02_cm0plus.S */
- .zero.table :
- {
- . = ALIGN(4);
- __zero_table_start__ = .;
- LONG (__bss_start__)
- LONG (__bss_end__ - __bss_start__)
- __zero_table_end__ = .;
- } > flash
-
- __etext = . ;
-
-
- .ramVectors (NOLOAD) : ALIGN(8)
- {
- __ram_vectors_start__ = .;
- KEEP(*(.ram_vectors))
- __ram_vectors_end__ = .;
- } > ram
-
-
- .data __ram_vectors_end__ : AT (__etext)
- {
- __data_start__ = .;
-
- *(vtable)
- *(.data*)
-
- . = ALIGN(4);
- /* preinit data */
- PROVIDE_HIDDEN (__preinit_array_start = .);
- KEEP(*(.preinit_array))
- PROVIDE_HIDDEN (__preinit_array_end = .);
-
- . = ALIGN(4);
- /* init data */
- PROVIDE_HIDDEN (__init_array_start = .);
- KEEP(*(SORT(.init_array.*)))
- KEEP(*(.init_array))
- PROVIDE_HIDDEN (__init_array_end = .);
-
- . = ALIGN(4);
- /* finit data */
- PROVIDE_HIDDEN (__fini_array_start = .);
- KEEP(*(SORT(.fini_array.*)))
- KEEP(*(.fini_array))
- PROVIDE_HIDDEN (__fini_array_end = .);
-
- KEEP(*(.jcr*))
- . = ALIGN(4);
-
- KEEP(*(.cy_ramfunc*))
- . = ALIGN(4);
-
- __data_end__ = .;
-
- } > ram
-
-
- /* Place variables in the section that should not be initialized during the
- * device startup.
- */
- .noinit (NOLOAD) : ALIGN(8)
- {
- KEEP(*(.noinit))
- } > ram
-
-
- /* The uninitialized global or static variables are placed in this section.
- *
- * The NOLOAD attribute tells linker that .bss section does not consume
- * any space in the image. The NOLOAD attribute changes the .bss type to
- * NOBITS, and that makes linker to A) not allocate section in memory, and
- * A) put information to clear the section with all zeros during application
- * loading.
- *
- * Without the NOLOAD attribute, the .bss section might get PROGBITS type.
- * This makes linker to A) allocate zeroed section in memory, and B) copy
- * this section to RAM during application loading.
- */
- .bss (NOLOAD):
- {
- . = ALIGN(4);
- __bss_start__ = .;
- *(.bss*)
- *(COMMON)
- . = ALIGN(4);
- __bss_end__ = .;
- } > ram
-
-
- .heap (NOLOAD):
- {
- __HeapBase = .;
- __end__ = .;
- end = __end__;
- KEEP(*(.heap*))
- . = ORIGIN(ram) + LENGTH(ram) - STACK_SIZE;
- __HeapLimit = .;
- } > ram
-
-
- /* .stack_dummy section doesn't contains any symbols. It is only
- * used for linker to calculate size of stack sections, and assign
- * values to stack symbols later */
- .stack_dummy (NOLOAD):
- {
- KEEP(*(.stack*))
- } > ram
-
-
- /* Set stack top to end of RAM, and stack limit move down by
- * size of stack_dummy section */
- __StackTop = ORIGIN(ram) + LENGTH(ram);
- __StackLimit = __StackTop - SIZEOF(.stack_dummy);
- PROVIDE(__stack = __StackTop);
-
- /* Check if data + heap + stack exceeds RAM limit */
- ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
-
-
- /* Emulated EEPROM Flash area */
- .cy_em_eeprom :
- {
- KEEP(*(.cy_em_eeprom))
- } > em_eeprom
-
-
- /* Supervisory Flash: User data */
- .cy_sflash_user_data :
- {
- KEEP(*(.cy_sflash_user_data))
- } > sflash_user_data
-
-
- /* Supervisory Flash: Normal Access Restrictions (NAR) */
- .cy_sflash_nar :
- {
- KEEP(*(.cy_sflash_nar))
- } > sflash_nar
-
-
- /* Supervisory Flash: Public Key */
- .cy_sflash_public_key :
- {
- KEEP(*(.cy_sflash_public_key))
- } > sflash_public_key
-
-
- /* Supervisory Flash: Table of Content # 2 */
- .cy_toc_part2 :
- {
- KEEP(*(.cy_toc_part2))
- } > sflash_toc_2
-
-
- /* Supervisory Flash: Table of Content # 2 Copy */
- .cy_rtoc_part2 :
- {
- KEEP(*(.cy_rtoc_part2))
- } > sflash_rtoc_2
-
-
- /* Places the code in the Execute in Place (XIP) section. See the smif driver
- * documentation for details.
- */
- .cy_xip :
- {
- KEEP(*(.cy_xip))
- } > xip
-
-
- /* eFuse */
- .cy_efuse :
- {
- KEEP(*(.cy_efuse))
- } > efuse
-
-
- /* These sections are used for additional metadata (silicon revision,
- * Silicon/JTAG ID, etc.) storage.
- */
- .cymeta 0x90500000 : { KEEP(*(.cymeta)) } :NONE
-}
-
-
-/* The following symbols used by the cymcuelftool. */
-/* Flash */
-__cy_memory_0_start = 0x10000000;
-__cy_memory_0_length = 0x00200000;
-__cy_memory_0_row_size = 0x200;
-
-/* Emulated EEPROM Flash area */
-__cy_memory_1_start = 0x14000000;
-__cy_memory_1_length = 0x8000;
-__cy_memory_1_row_size = 0x200;
-
-/* Supervisory Flash */
-__cy_memory_2_start = 0x16000000;
-__cy_memory_2_length = 0x8000;
-__cy_memory_2_row_size = 0x200;
-
-/* XIP */
-__cy_memory_3_start = 0x18000000;
-__cy_memory_3_length = 0x08000000;
-__cy_memory_3_row_size = 0x200;
-
-/* eFuse */
-__cy_memory_4_start = 0x90700000;
-__cy_memory_4_length = 0x100000;
-__cy_memory_4_row_size = 1;
-
-/* EOF */
diff --git a/boot/cypress/platforms/PSOC_062_2M/CM0P/GCC_ARM/startup_psoc6_02_cm0plus.S b/boot/cypress/platforms/PSOC_062_2M/CM0P/GCC_ARM/startup_psoc6_02_cm0plus.S
deleted file mode 100644
index 2641f62..0000000
--- a/boot/cypress/platforms/PSOC_062_2M/CM0P/GCC_ARM/startup_psoc6_02_cm0plus.S
+++ /dev/null
@@ -1,372 +0,0 @@
-/**************************************************************************//**
- * @file startup_psoc6_02_cm0plus.S
- * @brief CMSIS Core Device Startup File for
- * ARMCM0plus Device Series
- * @version V5.00
- * @date 02. March 2016
- ******************************************************************************/
-/*
- * Copyright (c) 2009-2016 ARM Limited. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed 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
- *
- * 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.
- */
-
- /* Address of the NMI handler */
- #define CY_NMI_HANLDER_ADDR 0x0000000D
-
- /* The CPU VTOR register */
- #define CY_CPU_VTOR_ADDR 0xE000ED08
-
- /* Copy flash vectors and data section to RAM */
- #define __STARTUP_COPY_MULTIPLE
-
- /* Clear single BSS section */
- #define __STARTUP_CLEAR_BSS
-
- .syntax unified
- .arch armv6-m
-
- .section .stack
- .align 3
-#ifdef __STACK_SIZE
- .equ Stack_Size, __STACK_SIZE
-#else
- .equ Stack_Size, 0x00001000
-#endif
- .globl __StackTop
- .globl __StackLimit
-__StackLimit:
- .space Stack_Size
- .size __StackLimit, . - __StackLimit
-__StackTop:
- .size __StackTop, . - __StackTop
-
- .section .heap
- .align 3
-#ifdef __HEAP_SIZE
- .equ Heap_Size, __HEAP_SIZE
-#else
- .equ Heap_Size, 0x00000400
-#endif
- .globl __HeapBase
- .globl __HeapLimit
-__HeapBase:
- .if Heap_Size
- .space Heap_Size
- .endif
- .size __HeapBase, . - __HeapBase
-__HeapLimit:
- .size __HeapLimit, . - __HeapLimit
-
- .section .vectors
- .align 2
- .globl __Vectors
-__Vectors:
- .long __StackTop /* Top of Stack */
- .long Reset_Handler /* Reset Handler */
- .long CY_NMI_HANLDER_ADDR /* NMI Handler */
- .long HardFault_Handler /* Hard Fault Handler */
- .long 0 /* Reserved */
- .long 0 /* Reserved */
- .long 0 /* Reserved */
- .long 0 /* Reserved */
- .long 0 /* Reserved */
- .long 0 /* Reserved */
- .long 0 /* Reserved */
- .long SVC_Handler /* SVCall Handler */
- .long 0 /* Reserved */
- .long 0 /* Reserved */
- .long PendSV_Handler /* PendSV Handler */
- .long SysTick_Handler /* SysTick Handler */
-
- /* External interrupts Description */
- .long NvicMux0_IRQHandler /* CPU User Interrupt #0 */
- .long NvicMux1_IRQHandler /* CPU User Interrupt #1 */
- .long NvicMux2_IRQHandler /* CPU User Interrupt #2 */
- .long NvicMux3_IRQHandler /* CPU User Interrupt #3 */
- .long NvicMux4_IRQHandler /* CPU User Interrupt #4 */
- .long NvicMux5_IRQHandler /* CPU User Interrupt #5 */
- .long NvicMux6_IRQHandler /* CPU User Interrupt #6 */
- .long NvicMux7_IRQHandler /* CPU User Interrupt #7 */
- .long Internal0_IRQHandler /* Internal SW Interrupt #0 */
- .long Internal1_IRQHandler /* Internal SW Interrupt #1 */
- .long Internal2_IRQHandler /* Internal SW Interrupt #2 */
- .long Internal3_IRQHandler /* Internal SW Interrupt #3 */
- .long Internal4_IRQHandler /* Internal SW Interrupt #4 */
- .long Internal5_IRQHandler /* Internal SW Interrupt #5 */
- .long Internal6_IRQHandler /* Internal SW Interrupt #6 */
- .long Internal7_IRQHandler /* Internal SW Interrupt #7 */
-
- .size __Vectors, . - __Vectors
- .equ __VectorsSize, . - __Vectors
-
- .section .ram_vectors
- .align 2
- .globl __ramVectors
-__ramVectors:
- .space __VectorsSize
- .size __ramVectors, . - __ramVectors
-
-
- .text
- .thumb
- .thumb_func
- .align 2
-
- /*
- * Device startup customization
- *
- * Note. The global resources are not yet initialized (for example global variables, peripherals, clocks)
- * because this function is executed as the first instruction in the ResetHandler.
- * The PDL is also not initialized to use the proper register offsets.
- * The user of this function is responsible for initializing the PDL and resources before using them.
- */
- .weak Cy_OnResetUser
- .func Cy_OnResetUser, Cy_OnResetUser
- .type Cy_OnResetUser, %function
-
-Cy_OnResetUser:
- bx lr
- .size Cy_OnResetUser, . - Cy_OnResetUser
- .endfunc
-
- /* Reset handler */
- .weak Reset_Handler
- .type Reset_Handler, %function
-
-Reset_Handler:
- bl Cy_OnResetUser
- cpsid i
-
-/* Firstly it copies data from read only memory to RAM. There are two schemes
- * to copy. One can copy more than one sections. Another can only copy
- * one section. The former scheme needs more instructions and read-only
- * data to implement than the latter.
- * Macro __STARTUP_COPY_MULTIPLE is used to choose between two schemes. */
-
-#ifdef __STARTUP_COPY_MULTIPLE
-/* Multiple sections scheme.
- *
- * Between symbol address __copy_table_start__ and __copy_table_end__,
- * there are array of triplets, each of which specify:
- * offset 0: LMA of start of a section to copy from
- * offset 4: VMA of start of a section to copy to
- * offset 8: size of the section to copy. Must be multiply of 4
- *
- * All addresses must be aligned to 4 bytes boundary.
- */
- ldr r4, =__copy_table_start__
- ldr r5, =__copy_table_end__
-
-.L_loop0:
- cmp r4, r5
- bge .L_loop0_done
- ldr r1, [r4]
- ldr r2, [r4, #4]
- ldr r3, [r4, #8]
-
-.L_loop0_0:
- subs r3, #4
- blt .L_loop0_0_done
- ldr r0, [r1, r3]
- str r0, [r2, r3]
- b .L_loop0_0
-
-.L_loop0_0_done:
- adds r4, #12
- b .L_loop0
-
-.L_loop0_done:
-#else
-/* Single section scheme.
- *
- * The ranges of copy from/to are specified by following symbols
- * __etext: LMA of start of the section to copy from. Usually end of text
- * __data_start__: VMA of start of the section to copy to
- * __data_end__: VMA of end of the section to copy to
- *
- * All addresses must be aligned to 4 bytes boundary.
- */
- ldr r1, =__etext
- ldr r2, =__data_start__
- ldr r3, =__data_end__
-
- subs r3, r2
- ble .L_loop1_done
-
-.L_loop1:
- subs r3, #4
- ldr r0, [r1,r3]
- str r0, [r2,r3]
- bgt .L_loop1
-
-.L_loop1_done:
-#endif /*__STARTUP_COPY_MULTIPLE */
-
-/* This part of work usually is done in C library startup code. Otherwise,
- * define this macro to enable it in this startup.
- *
- * There are two schemes too. One can clear multiple BSS sections. Another
- * can only clear one section. The former is more size expensive than the
- * latter.
- *
- * Define macro __STARTUP_CLEAR_BSS_MULTIPLE to choose the former.
- * Otherwise define macro __STARTUP_CLEAR_BSS to choose the later.
- */
-#ifdef __STARTUP_CLEAR_BSS_MULTIPLE
-/* Multiple sections scheme.
- *
- * Between symbol address __copy_table_start__ and __copy_table_end__,
- * there are array of tuples specifying:
- * offset 0: Start of a BSS section
- * offset 4: Size of this BSS section. Must be multiply of 4
- */
- ldr r3, =__zero_table_start__
- ldr r4, =__zero_table_end__
-
-.L_loop2:
- cmp r3, r4
- bge .L_loop2_done
- ldr r1, [r3]
- ldr r2, [r3, #4]
- movs r0, 0
-
-.L_loop2_0:
- subs r2, #4
- blt .L_loop2_0_done
- str r0, [r1, r2]
- b .L_loop2_0
-.L_loop2_0_done:
-
- adds r3, #8
- b .L_loop2
-.L_loop2_done:
-#elif defined (__STARTUP_CLEAR_BSS)
-/* Single BSS section scheme.
- *
- * The BSS section is specified by following symbols
- * __bss_start__: start of the BSS section.
- * __bss_end__: end of the BSS section.
- *
- * Both addresses must be aligned to 4 bytes boundary.
- */
- ldr r1, =__bss_start__
- ldr r2, =__bss_end__
-
- movs r0, 0
-
- subs r2, r1
- ble .L_loop3_done
-
-.L_loop3:
- subs r2, #4
- str r0, [r1, r2]
- bgt .L_loop3
-.L_loop3_done:
-#endif /* __STARTUP_CLEAR_BSS_MULTIPLE || __STARTUP_CLEAR_BSS */
-
- /* Update Vector Table Offset Register. */
- ldr r0, =__ramVectors
- ldr r1, =CY_CPU_VTOR_ADDR
- str r0, [r1]
- dsb 0xF
-
-#ifndef __NO_SYSTEM_INIT
- bl SystemInit
-#endif
-
- bl main
-
- /* Should never get here */
- b .
-
- .pool
- .size Reset_Handler, . - Reset_Handler
-
- .align 1
- .thumb_func
- .weak Default_Handler
- .type Default_Handler, %function
-Default_Handler:
- b .
- .size Default_Handler, . - Default_Handler
- .weak Cy_SysLib_FaultHandler
- .type Cy_SysLib_FaultHandler, %function
-
-Cy_SysLib_FaultHandler:
- b .
- .size Cy_SysLib_FaultHandler, . - Cy_SysLib_FaultHandler
- .type Fault_Handler, %function
-
-Fault_Handler:
- /* Storing LR content for Creator call stack trace */
- push {LR}
- movs r0, #4
- mov r1, LR
- tst r0, r1
- beq .L_MSP
- mrs r0, PSP
- b .L_API_call
-.L_MSP:
- mrs r0, MSP
-.L_API_call:
- /* Compensation of stack pointer address due to pushing 4 bytes of LR */
- adds r0, r0, #4
- bl Cy_SysLib_FaultHandler
- b .
- .size Fault_Handler, . - Fault_Handler
-
-.macro def_fault_Handler fault_handler_name
- .weak \fault_handler_name
- .set \fault_handler_name, Fault_Handler
- .endm
-
-/* Macro to define default handlers. Default handler
- * will be weak symbol and just dead loops. They can be
- * overwritten by other handlers */
- .macro def_irq_handler handler_name
- .weak \handler_name
- .set \handler_name, Default_Handler
- .endm
-
- def_irq_handler NMI_Handler
-
- def_fault_Handler HardFault_Handler
-
- def_irq_handler SVC_Handler
- def_irq_handler PendSV_Handler
- def_irq_handler SysTick_Handler
-
- def_irq_handler NvicMux0_IRQHandler /* CPU User Interrupt #0 */
- def_irq_handler NvicMux1_IRQHandler /* CPU User Interrupt #1 */
- def_irq_handler NvicMux2_IRQHandler /* CPU User Interrupt #2 */
- def_irq_handler NvicMux3_IRQHandler /* CPU User Interrupt #3 */
- def_irq_handler NvicMux4_IRQHandler /* CPU User Interrupt #4 */
- def_irq_handler NvicMux5_IRQHandler /* CPU User Interrupt #5 */
- def_irq_handler NvicMux6_IRQHandler /* CPU User Interrupt #6 */
- def_irq_handler NvicMux7_IRQHandler /* CPU User Interrupt #7 */
- def_irq_handler Internal0_IRQHandler /* Internal SW Interrupt #0 */
- def_irq_handler Internal1_IRQHandler /* Internal SW Interrupt #1 */
- def_irq_handler Internal2_IRQHandler /* Internal SW Interrupt #2 */
- def_irq_handler Internal3_IRQHandler /* Internal SW Interrupt #3 */
- def_irq_handler Internal4_IRQHandler /* Internal SW Interrupt #4 */
- def_irq_handler Internal5_IRQHandler /* Internal SW Interrupt #5 */
- def_irq_handler Internal6_IRQHandler /* Internal SW Interrupt #6 */
- def_irq_handler Internal7_IRQHandler /* Internal SW Interrupt #7 */
-
- .end
-
-
-/* [] END OF FILE */
diff --git a/boot/cypress/platforms/PSOC_062_2M/CM4/GCC_ARM/cy8c6xxa_cm4_dual.ld b/boot/cypress/platforms/PSOC_062_2M/CM4/GCC_ARM/cy8c6xxa_cm4_dual.ld
deleted file mode 100644
index ec70309..0000000
--- a/boot/cypress/platforms/PSOC_062_2M/CM4/GCC_ARM/cy8c6xxa_cm4_dual.ld
+++ /dev/null
@@ -1,436 +0,0 @@
-/***************************************************************************//**
-* \file cy8c6xxa_cm4_dual.ld
-* \version 2.70
-*
-* Linker file for the GNU C compiler.
-*
-* The main purpose of the linker script is to describe how the sections in the
-* input files should be mapped into the output file, and to control the memory
-* layout of the output file.
-*
-* \note The entry point location is fixed and starts at 0x10000000. The valid
-* application image should be placed there.
-*
-* \note The linker files included with the PDL template projects must be generic
-* and handle all common use cases. Your project may not use every section
-* defined in the linker files. In that case you may see warnings during the
-* build process. In your project, you can simply comment out or remove the
-* relevant code in the linker file.
-*
-********************************************************************************
-* \copyright
-* Copyright 2016-2019 Cypress Semiconductor Corporation
-* SPDX-License-Identifier: Apache-2.0
-*
-* Licensed 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.
-*******************************************************************************/
-
-OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
-SEARCH_DIR(.)
-GROUP(-lgcc -lc -lnosys)
-ENTRY(Reset_Handler)
-
-/* The size of the stack section at the end of CM4 SRAM */
-STACK_SIZE = 0x1000;
-
-/* The size of the Cortex-M0+ application image at the start of FLASH */
-FLASH_CM0P_SIZE = 0x2000;
-
-/* Force symbol to be entered in the output file as an undefined symbol. Doing
-* this may, for example, trigger linking of additional modules from standard
-* libraries. You may list several symbols for each EXTERN, and you may use
-* EXTERN multiple times. This command has the same effect as the -u command-line
-* option.
-*/
-EXTERN(Reset_Handler)
-
-/* The MEMORY section below describes the location and size of blocks of memory in the target.
-* Use this section to specify the memory regions available for allocation.
-*/
-MEMORY
-{
- /* The ram and flash regions control RAM and flash memory allocation for the CM4 core.
- * You can change the memory allocation by editing the 'ram' and 'flash' regions.
- * Note that 2 KB of RAM (at the end of the SRAM) are reserved for system use.
- * Using this memory region for other purposes will lead to unexpected behavior.
- * Your changes must be aligned with the corresponding memory regions for CM0+ core in 'xx_cm0plus.ld',
- * where 'xx' is the device group; for example, 'cy8c6xx7_cm0plus.ld'.
- */
- ram (rwx) : ORIGIN = 0x08002000, LENGTH = 0xFD800
- flash (rx) : ORIGIN = 0x10000000, LENGTH = 0x200000
-
- /* This is a 32K flash region used for EEPROM emulation. This region can also be used as the general purpose flash.
- * You can assign sections to this memory region for only one of the cores.
- * Note some middleware (e.g. BLE, Emulated EEPROM) can place their data into this memory region.
- * Therefore, repurposing this memory region will prevent such middleware from operation.
- */
- em_eeprom (rx) : ORIGIN = 0x14000000, LENGTH = 0x8000 /* 32 KB */
-
- /* The following regions define device specific memory regions and must not be changed. */
- sflash_user_data (rx) : ORIGIN = 0x16000800, LENGTH = 0x800 /* Supervisory flash: User data */
- sflash_nar (rx) : ORIGIN = 0x16001A00, LENGTH = 0x200 /* Supervisory flash: Normal Access Restrictions (NAR) */
- sflash_public_key (rx) : ORIGIN = 0x16005A00, LENGTH = 0xC00 /* Supervisory flash: Public Key */
- sflash_toc_2 (rx) : ORIGIN = 0x16007C00, LENGTH = 0x200 /* Supervisory flash: Table of Content # 2 */
- sflash_rtoc_2 (rx) : ORIGIN = 0x16007E00, LENGTH = 0x200 /* Supervisory flash: Table of Content # 2 Copy */
- xip (rx) : ORIGIN = 0x18000000, LENGTH = 0x8000000 /* 128 MB */
- efuse (r) : ORIGIN = 0x90700000, LENGTH = 0x100000 /* 1 MB */
-}
-
-/* Library configurations */
-GROUP(libgcc.a libc.a libm.a libnosys.a)
-
-/* Linker script to place sections and symbol values. Should be used together
- * with other linker script that defines memory regions FLASH and RAM.
- * It references following symbols, which must be defined in code:
- * Reset_Handler : Entry of reset handler
- *
- * It defines following symbols, which code can use without definition:
- * __exidx_start
- * __exidx_end
- * __copy_table_start__
- * __copy_table_end__
- * __zero_table_start__
- * __zero_table_end__
- * __etext
- * __data_start__
- * __preinit_array_start
- * __preinit_array_end
- * __init_array_start
- * __init_array_end
- * __fini_array_start
- * __fini_array_end
- * __data_end__
- * __bss_start__
- * __bss_end__
- * __end__
- * end
- * __HeapLimit
- * __StackLimit
- * __StackTop
- * __stack
- * __Vectors_End
- * __Vectors_Size
- */
-
-
-SECTIONS
-{
- /* Cortex-M0+ application flash image area */
- .cy_m0p_image ORIGIN(flash) :
- {
- . = ALIGN(4);
- __cy_m0p_code_start = . ;
- KEEP(*(.cy_m0p_image))
- __cy_m0p_code_end = . ;
- } > flash
-
- /* Check if .cy_m0p_image size exceeds FLASH_CM0P_SIZE */
- ASSERT(__cy_m0p_code_end <= ORIGIN(flash) + FLASH_CM0P_SIZE, "CM0+ flash image overflows with CM4, increase FLASH_CM0P_SIZE")
-
- /* Cortex-M4 application flash area */
- .text ORIGIN(flash) + FLASH_CM0P_SIZE :
- {
- . = ALIGN(4);
- __Vectors = . ;
- KEEP(*(.vectors))
- . = ALIGN(4);
- __Vectors_End = .;
- __Vectors_Size = __Vectors_End - __Vectors;
- __end__ = .;
-
- . = ALIGN(4);
- *(.text*)
-
- KEEP(*(.init))
- KEEP(*(.fini))
-
- /* .ctors */
- *crtbegin.o(.ctors)
- *crtbegin?.o(.ctors)
- *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
- *(SORT(.ctors.*))
- *(.ctors)
-
- /* .dtors */
- *crtbegin.o(.dtors)
- *crtbegin?.o(.dtors)
- *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
- *(SORT(.dtors.*))
- *(.dtors)
-
- /* Read-only code (constants). */
- *(.rodata .rodata.* .constdata .constdata.* .conststring .conststring.*)
-
- KEEP(*(.eh_frame*))
- } > flash
-
-
- .ARM.extab :
- {
- *(.ARM.extab* .gnu.linkonce.armextab.*)
- } > flash
-
- __exidx_start = .;
-
- .ARM.exidx :
- {
- *(.ARM.exidx* .gnu.linkonce.armexidx.*)
- } > flash
- __exidx_end = .;
-
-
- /* To copy multiple ROM to RAM sections,
- * uncomment .copy.table section and,
- * define __STARTUP_COPY_MULTIPLE in startup_psoc6_02_cm4.S */
- .copy.table :
- {
- . = ALIGN(4);
- __copy_table_start__ = .;
-
- /* Copy interrupt vectors from flash to RAM */
- LONG (__Vectors) /* From */
- LONG (__ram_vectors_start__) /* To */
- LONG (__Vectors_End - __Vectors) /* Size */
-
- /* Copy data section to RAM */
- LONG (__etext) /* From */
- LONG (__data_start__) /* To */
- LONG (__data_end__ - __data_start__) /* Size */
-
- __copy_table_end__ = .;
- } > flash
-
-
- /* To clear multiple BSS sections,
- * uncomment .zero.table section and,
- * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_psoc6_02_cm4.S */
- .zero.table :
- {
- . = ALIGN(4);
- __zero_table_start__ = .;
- LONG (__bss_start__)
- LONG (__bss_end__ - __bss_start__)
- __zero_table_end__ = .;
- } > flash
-
- __etext = . ;
-
-
- .ramVectors (NOLOAD) : ALIGN(8)
- {
- __ram_vectors_start__ = .;
- KEEP(*(.ram_vectors))
- __ram_vectors_end__ = .;
- } > ram
-
-
- .data __ram_vectors_end__ : AT (__etext)
- {
- __data_start__ = .;
-
- *(vtable)
- *(.data*)
-
- . = ALIGN(4);
- /* preinit data */
- PROVIDE_HIDDEN (__preinit_array_start = .);
- KEEP(*(.preinit_array))
- PROVIDE_HIDDEN (__preinit_array_end = .);
-
- . = ALIGN(4);
- /* init data */
- PROVIDE_HIDDEN (__init_array_start = .);
- KEEP(*(SORT(.init_array.*)))
- KEEP(*(.init_array))
- PROVIDE_HIDDEN (__init_array_end = .);
-
- . = ALIGN(4);
- /* finit data */
- PROVIDE_HIDDEN (__fini_array_start = .);
- KEEP(*(SORT(.fini_array.*)))
- KEEP(*(.fini_array))
- PROVIDE_HIDDEN (__fini_array_end = .);
-
- KEEP(*(.jcr*))
- . = ALIGN(4);
-
- KEEP(*(.cy_ramfunc*))
- . = ALIGN(4);
-
- __data_end__ = .;
-
- } > ram
-
-
- /* Place variables in the section that should not be initialized during the
- * device startup.
- */
- .noinit (NOLOAD) : ALIGN(8)
- {
- KEEP(*(.noinit))
- } > ram
-
-
- /* The uninitialized global or static variables are placed in this section.
- *
- * The NOLOAD attribute tells linker that .bss section does not consume
- * any space in the image. The NOLOAD attribute changes the .bss type to
- * NOBITS, and that makes linker to A) not allocate section in memory, and
- * A) put information to clear the section with all zeros during application
- * loading.
- *
- * Without the NOLOAD attribute, the .bss section might get PROGBITS type.
- * This makes linker to A) allocate zeroed section in memory, and B) copy
- * this section to RAM during application loading.
- */
- .bss (NOLOAD):
- {
- . = ALIGN(4);
- __bss_start__ = .;
- *(.bss*)
- *(COMMON)
- . = ALIGN(4);
- __bss_end__ = .;
- } > ram
-
-
- .heap (NOLOAD):
- {
- __HeapBase = .;
- __end__ = .;
- end = __end__;
- KEEP(*(.heap*))
- . = ORIGIN(ram) + LENGTH(ram) - STACK_SIZE;
- __HeapLimit = .;
- } > ram
-
-
- /* .stack_dummy section doesn't contains any symbols. It is only
- * used for linker to calculate size of stack sections, and assign
- * values to stack symbols later */
- .stack_dummy (NOLOAD):
- {
- KEEP(*(.stack*))
- } > ram
-
-
- /* Set stack top to end of RAM, and stack limit move down by
- * size of stack_dummy section */
- __StackTop = ORIGIN(ram) + LENGTH(ram);
- __StackLimit = __StackTop - SIZEOF(.stack_dummy);
- PROVIDE(__stack = __StackTop);
-
- /* Check if data + heap + stack exceeds RAM limit */
- ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
-
-
- /* Used for the digital signature of the secure application and the Bootloader SDK application.
- * The size of the section depends on the required data size. */
- .cy_app_signature ORIGIN(flash) + LENGTH(flash) - 256 :
- {
- KEEP(*(.cy_app_signature))
- } > flash
-
-
- /* Emulated EEPROM Flash area */
- .cy_em_eeprom :
- {
- KEEP(*(.cy_em_eeprom))
- } > em_eeprom
-
-
- /* Supervisory Flash: User data */
- .cy_sflash_user_data :
- {
- KEEP(*(.cy_sflash_user_data))
- } > sflash_user_data
-
-
- /* Supervisory Flash: Normal Access Restrictions (NAR) */
- .cy_sflash_nar :
- {
- KEEP(*(.cy_sflash_nar))
- } > sflash_nar
-
-
- /* Supervisory Flash: Public Key */
- .cy_sflash_public_key :
- {
- KEEP(*(.cy_sflash_public_key))
- } > sflash_public_key
-
-
- /* Supervisory Flash: Table of Content # 2 */
- .cy_toc_part2 :
- {
- KEEP(*(.cy_toc_part2))
- } > sflash_toc_2
-
-
- /* Supervisory Flash: Table of Content # 2 Copy */
- .cy_rtoc_part2 :
- {
- KEEP(*(.cy_rtoc_part2))
- } > sflash_rtoc_2
-
-
- /* Places the code in the Execute in Place (XIP) section. See the smif driver
- * documentation for details.
- */
- .cy_xip :
- {
- KEEP(*(.cy_xip))
- } > xip
-
-
- /* eFuse */
- .cy_efuse :
- {
- KEEP(*(.cy_efuse))
- } > efuse
-
-
- /* These sections are used for additional metadata (silicon revision,
- * Silicon/JTAG ID, etc.) storage.
- */
- .cymeta 0x90500000 : { KEEP(*(.cymeta)) } :NONE
-}
-
-
-/* The following symbols used by the cymcuelftool. */
-/* Flash */
-__cy_memory_0_start = 0x10000000;
-__cy_memory_0_length = 0x00200000;
-__cy_memory_0_row_size = 0x200;
-
-/* Emulated EEPROM Flash area */
-__cy_memory_1_start = 0x14000000;
-__cy_memory_1_length = 0x8000;
-__cy_memory_1_row_size = 0x200;
-
-/* Supervisory Flash */
-__cy_memory_2_start = 0x16000000;
-__cy_memory_2_length = 0x8000;
-__cy_memory_2_row_size = 0x200;
-
-/* XIP */
-__cy_memory_3_start = 0x18000000;
-__cy_memory_3_length = 0x08000000;
-__cy_memory_3_row_size = 0x200;
-
-/* eFuse */
-__cy_memory_4_start = 0x90700000;
-__cy_memory_4_length = 0x100000;
-__cy_memory_4_row_size = 1;
-
-/* EOF */
diff --git a/boot/cypress/platforms/PSOC_062_2M/CM4/GCC_ARM/startup_psoc6_02_cm4.S b/boot/cypress/platforms/PSOC_062_2M/CM4/GCC_ARM/startup_psoc6_02_cm4.S
deleted file mode 100644
index 3eb9dab..0000000
--- a/boot/cypress/platforms/PSOC_062_2M/CM4/GCC_ARM/startup_psoc6_02_cm4.S
+++ /dev/null
@@ -1,697 +0,0 @@
-/**************************************************************************//**
- * @file startup_psoc6_02_cm4.S
- * @brief CMSIS Core Device Startup File for
- * ARMCM4 Device Series
- * @version V5.00
- * @date 02. March 2016
- ******************************************************************************/
-/*
- * Copyright (c) 2009-2016 ARM Limited. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed 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
- *
- * 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.
- */
-
- /* Address of the NMI handler */
- #define CY_NMI_HANLDER_ADDR 0x0000000D
-
- /* The CPU VTOR register */
- #define CY_CPU_VTOR_ADDR 0xE000ED08
-
- /* Copy flash vectors and data section to RAM */
- #define __STARTUP_COPY_MULTIPLE
-
- /* Clear single BSS section */
- #define __STARTUP_CLEAR_BSS
-
- .syntax unified
- .arch armv7-m
-
- .section .stack
- .align 3
-#ifdef __STACK_SIZE
- .equ Stack_Size, __STACK_SIZE
-#else
- .equ Stack_Size, 0x00001000
-#endif
- .globl __StackTop
- .globl __StackLimit
-__StackLimit:
- .space Stack_Size
- .size __StackLimit, . - __StackLimit
-__StackTop:
- .size __StackTop, . - __StackTop
-
- .section .heap
- .align 3
-#ifdef __HEAP_SIZE
- .equ Heap_Size, __HEAP_SIZE
-#else
- .equ Heap_Size, 0x00000400
-#endif
- .globl __HeapBase
- .globl __HeapLimit
-__HeapBase:
- .if Heap_Size
- .space Heap_Size
- .endif
- .size __HeapBase, . - __HeapBase
-__HeapLimit:
- .size __HeapLimit, . - __HeapLimit
-
- .section .vectors
- .align 2
- .globl __Vectors
-__Vectors:
- .long __StackTop /* Top of Stack */
- .long Reset_Handler /* Reset Handler */
- .long CY_NMI_HANLDER_ADDR /* NMI Handler */
- .long HardFault_Handler /* Hard Fault Handler */
- .long MemManage_Handler /* MPU Fault Handler */
- .long BusFault_Handler /* Bus Fault Handler */
- .long UsageFault_Handler /* Usage Fault Handler */
- .long 0 /* Reserved */
- .long 0 /* Reserved */
- .long 0 /* Reserved */
- .long 0 /* Reserved */
- .long SVC_Handler /* SVCall Handler */
- .long DebugMon_Handler /* Debug Monitor Handler */
- .long 0 /* Reserved */
- .long PendSV_Handler /* PendSV Handler */
- .long SysTick_Handler /* SysTick Handler */
-
- /* External interrupts Description */
- .long ioss_interrupts_gpio_0_IRQHandler /* GPIO Port Interrupt #0 */
- .long ioss_interrupts_gpio_1_IRQHandler /* GPIO Port Interrupt #1 */
- .long ioss_interrupts_gpio_2_IRQHandler /* GPIO Port Interrupt #2 */
- .long ioss_interrupts_gpio_3_IRQHandler /* GPIO Port Interrupt #3 */
- .long ioss_interrupts_gpio_4_IRQHandler /* GPIO Port Interrupt #4 */
- .long ioss_interrupts_gpio_5_IRQHandler /* GPIO Port Interrupt #5 */
- .long ioss_interrupts_gpio_6_IRQHandler /* GPIO Port Interrupt #6 */
- .long ioss_interrupts_gpio_7_IRQHandler /* GPIO Port Interrupt #7 */
- .long ioss_interrupts_gpio_8_IRQHandler /* GPIO Port Interrupt #8 */
- .long ioss_interrupts_gpio_9_IRQHandler /* GPIO Port Interrupt #9 */
- .long ioss_interrupts_gpio_10_IRQHandler /* GPIO Port Interrupt #10 */
- .long ioss_interrupts_gpio_11_IRQHandler /* GPIO Port Interrupt #11 */
- .long ioss_interrupts_gpio_12_IRQHandler /* GPIO Port Interrupt #12 */
- .long ioss_interrupts_gpio_13_IRQHandler /* GPIO Port Interrupt #13 */
- .long ioss_interrupts_gpio_14_IRQHandler /* GPIO Port Interrupt #14 */
- .long ioss_interrupt_gpio_IRQHandler /* GPIO All Ports */
- .long ioss_interrupt_vdd_IRQHandler /* GPIO Supply Detect Interrupt */
- .long lpcomp_interrupt_IRQHandler /* Low Power Comparator Interrupt */
- .long scb_8_interrupt_IRQHandler /* Serial Communication Block #8 (DeepSleep capable) */
- .long srss_interrupt_mcwdt_0_IRQHandler /* Multi Counter Watchdog Timer interrupt */
- .long srss_interrupt_mcwdt_1_IRQHandler /* Multi Counter Watchdog Timer interrupt */
- .long srss_interrupt_backup_IRQHandler /* Backup domain interrupt */
- .long srss_interrupt_IRQHandler /* Other combined Interrupts for SRSS (LVD, WDT, CLKCAL) */
- .long cpuss_interrupts_ipc_0_IRQHandler /* CPUSS Inter Process Communication Interrupt #0 */
- .long cpuss_interrupts_ipc_1_IRQHandler /* CPUSS Inter Process Communication Interrupt #1 */
- .long cpuss_interrupts_ipc_2_IRQHandler /* CPUSS Inter Process Communication Interrupt #2 */
- .long cpuss_interrupts_ipc_3_IRQHandler /* CPUSS Inter Process Communication Interrupt #3 */
- .long cpuss_interrupts_ipc_4_IRQHandler /* CPUSS Inter Process Communication Interrupt #4 */
- .long cpuss_interrupts_ipc_5_IRQHandler /* CPUSS Inter Process Communication Interrupt #5 */
- .long cpuss_interrupts_ipc_6_IRQHandler /* CPUSS Inter Process Communication Interrupt #6 */
- .long cpuss_interrupts_ipc_7_IRQHandler /* CPUSS Inter Process Communication Interrupt #7 */
- .long cpuss_interrupts_ipc_8_IRQHandler /* CPUSS Inter Process Communication Interrupt #8 */
- .long cpuss_interrupts_ipc_9_IRQHandler /* CPUSS Inter Process Communication Interrupt #9 */
- .long cpuss_interrupts_ipc_10_IRQHandler /* CPUSS Inter Process Communication Interrupt #10 */
- .long cpuss_interrupts_ipc_11_IRQHandler /* CPUSS Inter Process Communication Interrupt #11 */
- .long cpuss_interrupts_ipc_12_IRQHandler /* CPUSS Inter Process Communication Interrupt #12 */
- .long cpuss_interrupts_ipc_13_IRQHandler /* CPUSS Inter Process Communication Interrupt #13 */
- .long cpuss_interrupts_ipc_14_IRQHandler /* CPUSS Inter Process Communication Interrupt #14 */
- .long cpuss_interrupts_ipc_15_IRQHandler /* CPUSS Inter Process Communication Interrupt #15 */
- .long scb_0_interrupt_IRQHandler /* Serial Communication Block #0 */
- .long scb_1_interrupt_IRQHandler /* Serial Communication Block #1 */
- .long scb_2_interrupt_IRQHandler /* Serial Communication Block #2 */
- .long scb_3_interrupt_IRQHandler /* Serial Communication Block #3 */
- .long scb_4_interrupt_IRQHandler /* Serial Communication Block #4 */
- .long scb_5_interrupt_IRQHandler /* Serial Communication Block #5 */
- .long scb_6_interrupt_IRQHandler /* Serial Communication Block #6 */
- .long scb_7_interrupt_IRQHandler /* Serial Communication Block #7 */
- .long scb_9_interrupt_IRQHandler /* Serial Communication Block #9 */
- .long scb_10_interrupt_IRQHandler /* Serial Communication Block #10 */
- .long scb_11_interrupt_IRQHandler /* Serial Communication Block #11 */
- .long scb_12_interrupt_IRQHandler /* Serial Communication Block #12 */
- .long csd_interrupt_IRQHandler /* CSD (Capsense) interrupt */
- .long cpuss_interrupts_dmac_0_IRQHandler /* CPUSS DMAC, Channel #0 */
- .long cpuss_interrupts_dmac_1_IRQHandler /* CPUSS DMAC, Channel #1 */
- .long cpuss_interrupts_dmac_2_IRQHandler /* CPUSS DMAC, Channel #2 */
- .long cpuss_interrupts_dmac_3_IRQHandler /* CPUSS DMAC, Channel #3 */
- .long cpuss_interrupts_dw0_0_IRQHandler /* CPUSS DataWire #0, Channel #0 */
- .long cpuss_interrupts_dw0_1_IRQHandler /* CPUSS DataWire #0, Channel #1 */
- .long cpuss_interrupts_dw0_2_IRQHandler /* CPUSS DataWire #0, Channel #2 */
- .long cpuss_interrupts_dw0_3_IRQHandler /* CPUSS DataWire #0, Channel #3 */
- .long cpuss_interrupts_dw0_4_IRQHandler /* CPUSS DataWire #0, Channel #4 */
- .long cpuss_interrupts_dw0_5_IRQHandler /* CPUSS DataWire #0, Channel #5 */
- .long cpuss_interrupts_dw0_6_IRQHandler /* CPUSS DataWire #0, Channel #6 */
- .long cpuss_interrupts_dw0_7_IRQHandler /* CPUSS DataWire #0, Channel #7 */
- .long cpuss_interrupts_dw0_8_IRQHandler /* CPUSS DataWire #0, Channel #8 */
- .long cpuss_interrupts_dw0_9_IRQHandler /* CPUSS DataWire #0, Channel #9 */
- .long cpuss_interrupts_dw0_10_IRQHandler /* CPUSS DataWire #0, Channel #10 */
- .long cpuss_interrupts_dw0_11_IRQHandler /* CPUSS DataWire #0, Channel #11 */
- .long cpuss_interrupts_dw0_12_IRQHandler /* CPUSS DataWire #0, Channel #12 */
- .long cpuss_interrupts_dw0_13_IRQHandler /* CPUSS DataWire #0, Channel #13 */
- .long cpuss_interrupts_dw0_14_IRQHandler /* CPUSS DataWire #0, Channel #14 */
- .long cpuss_interrupts_dw0_15_IRQHandler /* CPUSS DataWire #0, Channel #15 */
- .long cpuss_interrupts_dw0_16_IRQHandler /* CPUSS DataWire #0, Channel #16 */
- .long cpuss_interrupts_dw0_17_IRQHandler /* CPUSS DataWire #0, Channel #17 */
- .long cpuss_interrupts_dw0_18_IRQHandler /* CPUSS DataWire #0, Channel #18 */
- .long cpuss_interrupts_dw0_19_IRQHandler /* CPUSS DataWire #0, Channel #19 */
- .long cpuss_interrupts_dw0_20_IRQHandler /* CPUSS DataWire #0, Channel #20 */
- .long cpuss_interrupts_dw0_21_IRQHandler /* CPUSS DataWire #0, Channel #21 */
- .long cpuss_interrupts_dw0_22_IRQHandler /* CPUSS DataWire #0, Channel #22 */
- .long cpuss_interrupts_dw0_23_IRQHandler /* CPUSS DataWire #0, Channel #23 */
- .long cpuss_interrupts_dw0_24_IRQHandler /* CPUSS DataWire #0, Channel #24 */
- .long cpuss_interrupts_dw0_25_IRQHandler /* CPUSS DataWire #0, Channel #25 */
- .long cpuss_interrupts_dw0_26_IRQHandler /* CPUSS DataWire #0, Channel #26 */
- .long cpuss_interrupts_dw0_27_IRQHandler /* CPUSS DataWire #0, Channel #27 */
- .long cpuss_interrupts_dw0_28_IRQHandler /* CPUSS DataWire #0, Channel #28 */
- .long cpuss_interrupts_dw1_0_IRQHandler /* CPUSS DataWire #1, Channel #0 */
- .long cpuss_interrupts_dw1_1_IRQHandler /* CPUSS DataWire #1, Channel #1 */
- .long cpuss_interrupts_dw1_2_IRQHandler /* CPUSS DataWire #1, Channel #2 */
- .long cpuss_interrupts_dw1_3_IRQHandler /* CPUSS DataWire #1, Channel #3 */
- .long cpuss_interrupts_dw1_4_IRQHandler /* CPUSS DataWire #1, Channel #4 */
- .long cpuss_interrupts_dw1_5_IRQHandler /* CPUSS DataWire #1, Channel #5 */
- .long cpuss_interrupts_dw1_6_IRQHandler /* CPUSS DataWire #1, Channel #6 */
- .long cpuss_interrupts_dw1_7_IRQHandler /* CPUSS DataWire #1, Channel #7 */
- .long cpuss_interrupts_dw1_8_IRQHandler /* CPUSS DataWire #1, Channel #8 */
- .long cpuss_interrupts_dw1_9_IRQHandler /* CPUSS DataWire #1, Channel #9 */
- .long cpuss_interrupts_dw1_10_IRQHandler /* CPUSS DataWire #1, Channel #10 */
- .long cpuss_interrupts_dw1_11_IRQHandler /* CPUSS DataWire #1, Channel #11 */
- .long cpuss_interrupts_dw1_12_IRQHandler /* CPUSS DataWire #1, Channel #12 */
- .long cpuss_interrupts_dw1_13_IRQHandler /* CPUSS DataWire #1, Channel #13 */
- .long cpuss_interrupts_dw1_14_IRQHandler /* CPUSS DataWire #1, Channel #14 */
- .long cpuss_interrupts_dw1_15_IRQHandler /* CPUSS DataWire #1, Channel #15 */
- .long cpuss_interrupts_dw1_16_IRQHandler /* CPUSS DataWire #1, Channel #16 */
- .long cpuss_interrupts_dw1_17_IRQHandler /* CPUSS DataWire #1, Channel #17 */
- .long cpuss_interrupts_dw1_18_IRQHandler /* CPUSS DataWire #1, Channel #18 */
- .long cpuss_interrupts_dw1_19_IRQHandler /* CPUSS DataWire #1, Channel #19 */
- .long cpuss_interrupts_dw1_20_IRQHandler /* CPUSS DataWire #1, Channel #20 */
- .long cpuss_interrupts_dw1_21_IRQHandler /* CPUSS DataWire #1, Channel #21 */
- .long cpuss_interrupts_dw1_22_IRQHandler /* CPUSS DataWire #1, Channel #22 */
- .long cpuss_interrupts_dw1_23_IRQHandler /* CPUSS DataWire #1, Channel #23 */
- .long cpuss_interrupts_dw1_24_IRQHandler /* CPUSS DataWire #1, Channel #24 */
- .long cpuss_interrupts_dw1_25_IRQHandler /* CPUSS DataWire #1, Channel #25 */
- .long cpuss_interrupts_dw1_26_IRQHandler /* CPUSS DataWire #1, Channel #26 */
- .long cpuss_interrupts_dw1_27_IRQHandler /* CPUSS DataWire #1, Channel #27 */
- .long cpuss_interrupts_dw1_28_IRQHandler /* CPUSS DataWire #1, Channel #28 */
- .long cpuss_interrupts_fault_0_IRQHandler /* CPUSS Fault Structure Interrupt #0 */
- .long cpuss_interrupts_fault_1_IRQHandler /* CPUSS Fault Structure Interrupt #1 */
- .long cpuss_interrupt_crypto_IRQHandler /* CRYPTO Accelerator Interrupt */
- .long cpuss_interrupt_fm_IRQHandler /* FLASH Macro Interrupt */
- .long cpuss_interrupts_cm4_fp_IRQHandler /* Floating Point operation fault */
- .long cpuss_interrupts_cm0_cti_0_IRQHandler /* CM0+ CTI #0 */
- .long cpuss_interrupts_cm0_cti_1_IRQHandler /* CM0+ CTI #1 */
- .long cpuss_interrupts_cm4_cti_0_IRQHandler /* CM4 CTI #0 */
- .long cpuss_interrupts_cm4_cti_1_IRQHandler /* CM4 CTI #1 */
- .long tcpwm_0_interrupts_0_IRQHandler /* TCPWM #0, Counter #0 */
- .long tcpwm_0_interrupts_1_IRQHandler /* TCPWM #0, Counter #1 */
- .long tcpwm_0_interrupts_2_IRQHandler /* TCPWM #0, Counter #2 */
- .long tcpwm_0_interrupts_3_IRQHandler /* TCPWM #0, Counter #3 */
- .long tcpwm_0_interrupts_4_IRQHandler /* TCPWM #0, Counter #4 */
- .long tcpwm_0_interrupts_5_IRQHandler /* TCPWM #0, Counter #5 */
- .long tcpwm_0_interrupts_6_IRQHandler /* TCPWM #0, Counter #6 */
- .long tcpwm_0_interrupts_7_IRQHandler /* TCPWM #0, Counter #7 */
- .long tcpwm_1_interrupts_0_IRQHandler /* TCPWM #1, Counter #0 */
- .long tcpwm_1_interrupts_1_IRQHandler /* TCPWM #1, Counter #1 */
- .long tcpwm_1_interrupts_2_IRQHandler /* TCPWM #1, Counter #2 */
- .long tcpwm_1_interrupts_3_IRQHandler /* TCPWM #1, Counter #3 */
- .long tcpwm_1_interrupts_4_IRQHandler /* TCPWM #1, Counter #4 */
- .long tcpwm_1_interrupts_5_IRQHandler /* TCPWM #1, Counter #5 */
- .long tcpwm_1_interrupts_6_IRQHandler /* TCPWM #1, Counter #6 */
- .long tcpwm_1_interrupts_7_IRQHandler /* TCPWM #1, Counter #7 */
- .long tcpwm_1_interrupts_8_IRQHandler /* TCPWM #1, Counter #8 */
- .long tcpwm_1_interrupts_9_IRQHandler /* TCPWM #1, Counter #9 */
- .long tcpwm_1_interrupts_10_IRQHandler /* TCPWM #1, Counter #10 */
- .long tcpwm_1_interrupts_11_IRQHandler /* TCPWM #1, Counter #11 */
- .long tcpwm_1_interrupts_12_IRQHandler /* TCPWM #1, Counter #12 */
- .long tcpwm_1_interrupts_13_IRQHandler /* TCPWM #1, Counter #13 */
- .long tcpwm_1_interrupts_14_IRQHandler /* TCPWM #1, Counter #14 */
- .long tcpwm_1_interrupts_15_IRQHandler /* TCPWM #1, Counter #15 */
- .long tcpwm_1_interrupts_16_IRQHandler /* TCPWM #1, Counter #16 */
- .long tcpwm_1_interrupts_17_IRQHandler /* TCPWM #1, Counter #17 */
- .long tcpwm_1_interrupts_18_IRQHandler /* TCPWM #1, Counter #18 */
- .long tcpwm_1_interrupts_19_IRQHandler /* TCPWM #1, Counter #19 */
- .long tcpwm_1_interrupts_20_IRQHandler /* TCPWM #1, Counter #20 */
- .long tcpwm_1_interrupts_21_IRQHandler /* TCPWM #1, Counter #21 */
- .long tcpwm_1_interrupts_22_IRQHandler /* TCPWM #1, Counter #22 */
- .long tcpwm_1_interrupts_23_IRQHandler /* TCPWM #1, Counter #23 */
- .long pass_interrupt_sar_IRQHandler /* SAR ADC interrupt */
- .long audioss_0_interrupt_i2s_IRQHandler /* I2S0 Audio interrupt */
- .long audioss_0_interrupt_pdm_IRQHandler /* PDM0/PCM0 Audio interrupt */
- .long audioss_1_interrupt_i2s_IRQHandler /* I2S1 Audio interrupt */
- .long profile_interrupt_IRQHandler /* Energy Profiler interrupt */
- .long smif_interrupt_IRQHandler /* Serial Memory Interface interrupt */
- .long usb_interrupt_hi_IRQHandler /* USB Interrupt */
- .long usb_interrupt_med_IRQHandler /* USB Interrupt */
- .long usb_interrupt_lo_IRQHandler /* USB Interrupt */
- .long sdhc_0_interrupt_wakeup_IRQHandler /* SDIO wakeup interrupt for mxsdhc */
- .long sdhc_0_interrupt_general_IRQHandler /* Consolidated interrupt for mxsdhc for everything else */
- .long sdhc_1_interrupt_wakeup_IRQHandler /* EEMC wakeup interrupt for mxsdhc, not used */
- .long sdhc_1_interrupt_general_IRQHandler /* Consolidated interrupt for mxsdhc for everything else */
-
-
- .size __Vectors, . - __Vectors
- .equ __VectorsSize, . - __Vectors
-
- .section .ram_vectors
- .align 2
- .globl __ramVectors
-__ramVectors:
- .space __VectorsSize
- .size __ramVectors, . - __ramVectors
-
-
- .text
- .thumb
- .thumb_func
- .align 2
-
- /*
- * Device startup customization
- *
- * Note. The global resources are not yet initialized (for example global variables, peripherals, clocks)
- * because this function is executed as the first instruction in the ResetHandler.
- * The PDL is also not initialized to use the proper register offsets.
- * The user of this function is responsible for initializing the PDL and resources before using them.
- */
- .weak Cy_OnResetUser
- .func Cy_OnResetUser, Cy_OnResetUser
- .type Cy_OnResetUser, %function
-
-Cy_OnResetUser:
- bx lr
- .size Cy_OnResetUser, . - Cy_OnResetUser
- .endfunc
-
- /* OS-specific low-level initialization */
- .weak cy_toolchain_init
- .func cy_toolchain_init, cy_toolchain_init
- .type cy_toolchain_init, %function
-
-cy_toolchain_init:
- bx lr
- .size cy_toolchain_init, . - cy_toolchain_init
- .endfunc
-
- /* Reset handler */
- .weak Reset_Handler
- .type Reset_Handler, %function
-
-Reset_Handler:
- bl Cy_OnResetUser
- cpsid i
-
-/* Firstly it copies data from read only memory to RAM. There are two schemes
- * to copy. One can copy more than one sections. Another can only copy
- * one section. The former scheme needs more instructions and read-only
- * data to implement than the latter.
- * Macro __STARTUP_COPY_MULTIPLE is used to choose between two schemes. */
-
-#ifdef __STARTUP_COPY_MULTIPLE
-/* Multiple sections scheme.
- *
- * Between symbol address __copy_table_start__ and __copy_table_end__,
- * there are array of triplets, each of which specify:
- * offset 0: LMA of start of a section to copy from
- * offset 4: VMA of start of a section to copy to
- * offset 8: size of the section to copy. Must be multiply of 4
- *
- * All addresses must be aligned to 4 bytes boundary.
- */
- ldr r4, =__copy_table_start__
- ldr r5, =__copy_table_end__
-
-.L_loop0:
- cmp r4, r5
- bge .L_loop0_done
- ldr r1, [r4]
- ldr r2, [r4, #4]
- ldr r3, [r4, #8]
-
-.L_loop0_0:
- subs r3, #4
- ittt ge
- ldrge r0, [r1, r3]
- strge r0, [r2, r3]
- bge .L_loop0_0
-
- adds r4, #12
- b .L_loop0
-
-.L_loop0_done:
-#else
-/* Single section scheme.
- *
- * The ranges of copy from/to are specified by following symbols
- * __etext: LMA of start of the section to copy from. Usually end of text
- * __data_start__: VMA of start of the section to copy to
- * __data_end__: VMA of end of the section to copy to
- *
- * All addresses must be aligned to 4 bytes boundary.
- */
- ldr r1, =__etext
- ldr r2, =__data_start__
- ldr r3, =__data_end__
-
-.L_loop1:
- cmp r2, r3
- ittt lt
- ldrlt r0, [r1], #4
- strlt r0, [r2], #4
- blt .L_loop1
-#endif /*__STARTUP_COPY_MULTIPLE */
-
-/* This part of work usually is done in C library startup code. Otherwise,
- * define this macro to enable it in this startup.
- *
- * There are two schemes too. One can clear multiple BSS sections. Another
- * can only clear one section. The former is more size expensive than the
- * latter.
- *
- * Define macro __STARTUP_CLEAR_BSS_MULTIPLE to choose the former.
- * Otherwise define macro __STARTUP_CLEAR_BSS to choose the later.
- */
-#ifdef __STARTUP_CLEAR_BSS_MULTIPLE
-/* Multiple sections scheme.
- *
- * Between symbol address __copy_table_start__ and __copy_table_end__,
- * there are array of tuples specifying:
- * offset 0: Start of a BSS section
- * offset 4: Size of this BSS section. Must be multiply of 4
- */
- ldr r3, =__zero_table_start__
- ldr r4, =__zero_table_end__
-
-.L_loop2:
- cmp r3, r4
- bge .L_loop2_done
- ldr r1, [r3]
- ldr r2, [r3, #4]
- movs r0, 0
-
-.L_loop2_0:
- subs r2, #4
- itt ge
- strge r0, [r1, r2]
- bge .L_loop2_0
-
- adds r3, #8
- b .L_loop2
-.L_loop2_done:
-#elif defined (__STARTUP_CLEAR_BSS)
-/* Single BSS section scheme.
- *
- * The BSS section is specified by following symbols
- * __bss_start__: start of the BSS section.
- * __bss_end__: end of the BSS section.
- *
- * Both addresses must be aligned to 4 bytes boundary.
- */
- ldr r1, =__bss_start__
- ldr r2, =__bss_end__
-
- movs r0, 0
-.L_loop3:
- cmp r1, r2
- itt lt
- strlt r0, [r1], #4
- blt .L_loop3
-#endif /* __STARTUP_CLEAR_BSS_MULTIPLE || __STARTUP_CLEAR_BSS */
-
- /* Update Vector Table Offset Register. */
- ldr r0, =__ramVectors
- ldr r1, =CY_CPU_VTOR_ADDR
- str r0, [r1]
- dsb 0xF
-
- /* Enable the FPU if used */
- bl Cy_SystemInitFpuEnable
-
-#ifndef __NO_SYSTEM_INIT
- bl SystemInit
-#endif
-
- /* OS-specific low-level initialization */
- bl cy_toolchain_init
-
- /* Call C/C++ static constructors */
- bl __libc_init_array
-
- /* Execute main application */
- bl main
-
- /* Call C/C++ static destructors */
- bl __libc_fini_array
-
- /* Should never get here */
- b .
-
- .pool
- .size Reset_Handler, . - Reset_Handler
-
- .align 1
- .thumb_func
- .weak Default_Handler
- .type Default_Handler, %function
-
-Default_Handler:
- b .
- .size Default_Handler, . - Default_Handler
-
-
- .weak Cy_SysLib_FaultHandler
- .type Cy_SysLib_FaultHandler, %function
-
-Cy_SysLib_FaultHandler:
- b .
- .size Cy_SysLib_FaultHandler, . - Cy_SysLib_FaultHandler
- .type Fault_Handler, %function
-
-Fault_Handler:
- /* Storing LR content for Creator call stack trace */
- push {LR}
- movs r0, #4
- mov r1, LR
- tst r0, r1
- beq .L_MSP
- mrs r0, PSP
- b .L_API_call
-.L_MSP:
- mrs r0, MSP
-.L_API_call:
- /* Compensation of stack pointer address due to pushing 4 bytes of LR */
- adds r0, r0, #4
- bl Cy_SysLib_FaultHandler
- b .
- .size Fault_Handler, . - Fault_Handler
-
-.macro def_fault_Handler fault_handler_name
- .weak \fault_handler_name
- .set \fault_handler_name, Fault_Handler
- .endm
-
-/* Macro to define default handlers. Default handler
- * will be weak symbol and just dead loops. They can be
- * overwritten by other handlers */
- .macro def_irq_handler handler_name
- .weak \handler_name
- .set \handler_name, Default_Handler
- .endm
-
- def_irq_handler NMI_Handler
-
- def_fault_Handler HardFault_Handler
- def_fault_Handler MemManage_Handler
- def_fault_Handler BusFault_Handler
- def_fault_Handler UsageFault_Handler
-
- def_irq_handler SVC_Handler
- def_irq_handler DebugMon_Handler
- def_irq_handler PendSV_Handler
- def_irq_handler SysTick_Handler
-
- def_irq_handler ioss_interrupts_gpio_0_IRQHandler /* GPIO Port Interrupt #0 */
- def_irq_handler ioss_interrupts_gpio_1_IRQHandler /* GPIO Port Interrupt #1 */
- def_irq_handler ioss_interrupts_gpio_2_IRQHandler /* GPIO Port Interrupt #2 */
- def_irq_handler ioss_interrupts_gpio_3_IRQHandler /* GPIO Port Interrupt #3 */
- def_irq_handler ioss_interrupts_gpio_4_IRQHandler /* GPIO Port Interrupt #4 */
- def_irq_handler ioss_interrupts_gpio_5_IRQHandler /* GPIO Port Interrupt #5 */
- def_irq_handler ioss_interrupts_gpio_6_IRQHandler /* GPIO Port Interrupt #6 */
- def_irq_handler ioss_interrupts_gpio_7_IRQHandler /* GPIO Port Interrupt #7 */
- def_irq_handler ioss_interrupts_gpio_8_IRQHandler /* GPIO Port Interrupt #8 */
- def_irq_handler ioss_interrupts_gpio_9_IRQHandler /* GPIO Port Interrupt #9 */
- def_irq_handler ioss_interrupts_gpio_10_IRQHandler /* GPIO Port Interrupt #10 */
- def_irq_handler ioss_interrupts_gpio_11_IRQHandler /* GPIO Port Interrupt #11 */
- def_irq_handler ioss_interrupts_gpio_12_IRQHandler /* GPIO Port Interrupt #12 */
- def_irq_handler ioss_interrupts_gpio_13_IRQHandler /* GPIO Port Interrupt #13 */
- def_irq_handler ioss_interrupts_gpio_14_IRQHandler /* GPIO Port Interrupt #14 */
- def_irq_handler ioss_interrupt_gpio_IRQHandler /* GPIO All Ports */
- def_irq_handler ioss_interrupt_vdd_IRQHandler /* GPIO Supply Detect Interrupt */
- def_irq_handler lpcomp_interrupt_IRQHandler /* Low Power Comparator Interrupt */
- def_irq_handler scb_8_interrupt_IRQHandler /* Serial Communication Block #8 (DeepSleep capable) */
- def_irq_handler srss_interrupt_mcwdt_0_IRQHandler /* Multi Counter Watchdog Timer interrupt */
- def_irq_handler srss_interrupt_mcwdt_1_IRQHandler /* Multi Counter Watchdog Timer interrupt */
- def_irq_handler srss_interrupt_backup_IRQHandler /* Backup domain interrupt */
- def_irq_handler srss_interrupt_IRQHandler /* Other combined Interrupts for SRSS (LVD, WDT, CLKCAL) */
- def_irq_handler cpuss_interrupts_ipc_0_IRQHandler /* CPUSS Inter Process Communication Interrupt #0 */
- def_irq_handler cpuss_interrupts_ipc_1_IRQHandler /* CPUSS Inter Process Communication Interrupt #1 */
- def_irq_handler cpuss_interrupts_ipc_2_IRQHandler /* CPUSS Inter Process Communication Interrupt #2 */
- def_irq_handler cpuss_interrupts_ipc_3_IRQHandler /* CPUSS Inter Process Communication Interrupt #3 */
- def_irq_handler cpuss_interrupts_ipc_4_IRQHandler /* CPUSS Inter Process Communication Interrupt #4 */
- def_irq_handler cpuss_interrupts_ipc_5_IRQHandler /* CPUSS Inter Process Communication Interrupt #5 */
- def_irq_handler cpuss_interrupts_ipc_6_IRQHandler /* CPUSS Inter Process Communication Interrupt #6 */
- def_irq_handler cpuss_interrupts_ipc_7_IRQHandler /* CPUSS Inter Process Communication Interrupt #7 */
- def_irq_handler cpuss_interrupts_ipc_8_IRQHandler /* CPUSS Inter Process Communication Interrupt #8 */
- def_irq_handler cpuss_interrupts_ipc_9_IRQHandler /* CPUSS Inter Process Communication Interrupt #9 */
- def_irq_handler cpuss_interrupts_ipc_10_IRQHandler /* CPUSS Inter Process Communication Interrupt #10 */
- def_irq_handler cpuss_interrupts_ipc_11_IRQHandler /* CPUSS Inter Process Communication Interrupt #11 */
- def_irq_handler cpuss_interrupts_ipc_12_IRQHandler /* CPUSS Inter Process Communication Interrupt #12 */
- def_irq_handler cpuss_interrupts_ipc_13_IRQHandler /* CPUSS Inter Process Communication Interrupt #13 */
- def_irq_handler cpuss_interrupts_ipc_14_IRQHandler /* CPUSS Inter Process Communication Interrupt #14 */
- def_irq_handler cpuss_interrupts_ipc_15_IRQHandler /* CPUSS Inter Process Communication Interrupt #15 */
- def_irq_handler scb_0_interrupt_IRQHandler /* Serial Communication Block #0 */
- def_irq_handler scb_1_interrupt_IRQHandler /* Serial Communication Block #1 */
- def_irq_handler scb_2_interrupt_IRQHandler /* Serial Communication Block #2 */
- def_irq_handler scb_3_interrupt_IRQHandler /* Serial Communication Block #3 */
- def_irq_handler scb_4_interrupt_IRQHandler /* Serial Communication Block #4 */
- def_irq_handler scb_5_interrupt_IRQHandler /* Serial Communication Block #5 */
- def_irq_handler scb_6_interrupt_IRQHandler /* Serial Communication Block #6 */
- def_irq_handler scb_7_interrupt_IRQHandler /* Serial Communication Block #7 */
- def_irq_handler scb_9_interrupt_IRQHandler /* Serial Communication Block #9 */
- def_irq_handler scb_10_interrupt_IRQHandler /* Serial Communication Block #10 */
- def_irq_handler scb_11_interrupt_IRQHandler /* Serial Communication Block #11 */
- def_irq_handler scb_12_interrupt_IRQHandler /* Serial Communication Block #12 */
- def_irq_handler csd_interrupt_IRQHandler /* CSD (Capsense) interrupt */
- def_irq_handler cpuss_interrupts_dmac_0_IRQHandler /* CPUSS DMAC, Channel #0 */
- def_irq_handler cpuss_interrupts_dmac_1_IRQHandler /* CPUSS DMAC, Channel #1 */
- def_irq_handler cpuss_interrupts_dmac_2_IRQHandler /* CPUSS DMAC, Channel #2 */
- def_irq_handler cpuss_interrupts_dmac_3_IRQHandler /* CPUSS DMAC, Channel #3 */
- def_irq_handler cpuss_interrupts_dw0_0_IRQHandler /* CPUSS DataWire #0, Channel #0 */
- def_irq_handler cpuss_interrupts_dw0_1_IRQHandler /* CPUSS DataWire #0, Channel #1 */
- def_irq_handler cpuss_interrupts_dw0_2_IRQHandler /* CPUSS DataWire #0, Channel #2 */
- def_irq_handler cpuss_interrupts_dw0_3_IRQHandler /* CPUSS DataWire #0, Channel #3 */
- def_irq_handler cpuss_interrupts_dw0_4_IRQHandler /* CPUSS DataWire #0, Channel #4 */
- def_irq_handler cpuss_interrupts_dw0_5_IRQHandler /* CPUSS DataWire #0, Channel #5 */
- def_irq_handler cpuss_interrupts_dw0_6_IRQHandler /* CPUSS DataWire #0, Channel #6 */
- def_irq_handler cpuss_interrupts_dw0_7_IRQHandler /* CPUSS DataWire #0, Channel #7 */
- def_irq_handler cpuss_interrupts_dw0_8_IRQHandler /* CPUSS DataWire #0, Channel #8 */
- def_irq_handler cpuss_interrupts_dw0_9_IRQHandler /* CPUSS DataWire #0, Channel #9 */
- def_irq_handler cpuss_interrupts_dw0_10_IRQHandler /* CPUSS DataWire #0, Channel #10 */
- def_irq_handler cpuss_interrupts_dw0_11_IRQHandler /* CPUSS DataWire #0, Channel #11 */
- def_irq_handler cpuss_interrupts_dw0_12_IRQHandler /* CPUSS DataWire #0, Channel #12 */
- def_irq_handler cpuss_interrupts_dw0_13_IRQHandler /* CPUSS DataWire #0, Channel #13 */
- def_irq_handler cpuss_interrupts_dw0_14_IRQHandler /* CPUSS DataWire #0, Channel #14 */
- def_irq_handler cpuss_interrupts_dw0_15_IRQHandler /* CPUSS DataWire #0, Channel #15 */
- def_irq_handler cpuss_interrupts_dw0_16_IRQHandler /* CPUSS DataWire #0, Channel #16 */
- def_irq_handler cpuss_interrupts_dw0_17_IRQHandler /* CPUSS DataWire #0, Channel #17 */
- def_irq_handler cpuss_interrupts_dw0_18_IRQHandler /* CPUSS DataWire #0, Channel #18 */
- def_irq_handler cpuss_interrupts_dw0_19_IRQHandler /* CPUSS DataWire #0, Channel #19 */
- def_irq_handler cpuss_interrupts_dw0_20_IRQHandler /* CPUSS DataWire #0, Channel #20 */
- def_irq_handler cpuss_interrupts_dw0_21_IRQHandler /* CPUSS DataWire #0, Channel #21 */
- def_irq_handler cpuss_interrupts_dw0_22_IRQHandler /* CPUSS DataWire #0, Channel #22 */
- def_irq_handler cpuss_interrupts_dw0_23_IRQHandler /* CPUSS DataWire #0, Channel #23 */
- def_irq_handler cpuss_interrupts_dw0_24_IRQHandler /* CPUSS DataWire #0, Channel #24 */
- def_irq_handler cpuss_interrupts_dw0_25_IRQHandler /* CPUSS DataWire #0, Channel #25 */
- def_irq_handler cpuss_interrupts_dw0_26_IRQHandler /* CPUSS DataWire #0, Channel #26 */
- def_irq_handler cpuss_interrupts_dw0_27_IRQHandler /* CPUSS DataWire #0, Channel #27 */
- def_irq_handler cpuss_interrupts_dw0_28_IRQHandler /* CPUSS DataWire #0, Channel #28 */
- def_irq_handler cpuss_interrupts_dw1_0_IRQHandler /* CPUSS DataWire #1, Channel #0 */
- def_irq_handler cpuss_interrupts_dw1_1_IRQHandler /* CPUSS DataWire #1, Channel #1 */
- def_irq_handler cpuss_interrupts_dw1_2_IRQHandler /* CPUSS DataWire #1, Channel #2 */
- def_irq_handler cpuss_interrupts_dw1_3_IRQHandler /* CPUSS DataWire #1, Channel #3 */
- def_irq_handler cpuss_interrupts_dw1_4_IRQHandler /* CPUSS DataWire #1, Channel #4 */
- def_irq_handler cpuss_interrupts_dw1_5_IRQHandler /* CPUSS DataWire #1, Channel #5 */
- def_irq_handler cpuss_interrupts_dw1_6_IRQHandler /* CPUSS DataWire #1, Channel #6 */
- def_irq_handler cpuss_interrupts_dw1_7_IRQHandler /* CPUSS DataWire #1, Channel #7 */
- def_irq_handler cpuss_interrupts_dw1_8_IRQHandler /* CPUSS DataWire #1, Channel #8 */
- def_irq_handler cpuss_interrupts_dw1_9_IRQHandler /* CPUSS DataWire #1, Channel #9 */
- def_irq_handler cpuss_interrupts_dw1_10_IRQHandler /* CPUSS DataWire #1, Channel #10 */
- def_irq_handler cpuss_interrupts_dw1_11_IRQHandler /* CPUSS DataWire #1, Channel #11 */
- def_irq_handler cpuss_interrupts_dw1_12_IRQHandler /* CPUSS DataWire #1, Channel #12 */
- def_irq_handler cpuss_interrupts_dw1_13_IRQHandler /* CPUSS DataWire #1, Channel #13 */
- def_irq_handler cpuss_interrupts_dw1_14_IRQHandler /* CPUSS DataWire #1, Channel #14 */
- def_irq_handler cpuss_interrupts_dw1_15_IRQHandler /* CPUSS DataWire #1, Channel #15 */
- def_irq_handler cpuss_interrupts_dw1_16_IRQHandler /* CPUSS DataWire #1, Channel #16 */
- def_irq_handler cpuss_interrupts_dw1_17_IRQHandler /* CPUSS DataWire #1, Channel #17 */
- def_irq_handler cpuss_interrupts_dw1_18_IRQHandler /* CPUSS DataWire #1, Channel #18 */
- def_irq_handler cpuss_interrupts_dw1_19_IRQHandler /* CPUSS DataWire #1, Channel #19 */
- def_irq_handler cpuss_interrupts_dw1_20_IRQHandler /* CPUSS DataWire #1, Channel #20 */
- def_irq_handler cpuss_interrupts_dw1_21_IRQHandler /* CPUSS DataWire #1, Channel #21 */
- def_irq_handler cpuss_interrupts_dw1_22_IRQHandler /* CPUSS DataWire #1, Channel #22 */
- def_irq_handler cpuss_interrupts_dw1_23_IRQHandler /* CPUSS DataWire #1, Channel #23 */
- def_irq_handler cpuss_interrupts_dw1_24_IRQHandler /* CPUSS DataWire #1, Channel #24 */
- def_irq_handler cpuss_interrupts_dw1_25_IRQHandler /* CPUSS DataWire #1, Channel #25 */
- def_irq_handler cpuss_interrupts_dw1_26_IRQHandler /* CPUSS DataWire #1, Channel #26 */
- def_irq_handler cpuss_interrupts_dw1_27_IRQHandler /* CPUSS DataWire #1, Channel #27 */
- def_irq_handler cpuss_interrupts_dw1_28_IRQHandler /* CPUSS DataWire #1, Channel #28 */
- def_irq_handler cpuss_interrupts_fault_0_IRQHandler /* CPUSS Fault Structure Interrupt #0 */
- def_irq_handler cpuss_interrupts_fault_1_IRQHandler /* CPUSS Fault Structure Interrupt #1 */
- def_irq_handler cpuss_interrupt_crypto_IRQHandler /* CRYPTO Accelerator Interrupt */
- def_irq_handler cpuss_interrupt_fm_IRQHandler /* FLASH Macro Interrupt */
- def_irq_handler cpuss_interrupts_cm4_fp_IRQHandler /* Floating Point operation fault */
- def_irq_handler cpuss_interrupts_cm0_cti_0_IRQHandler /* CM0+ CTI #0 */
- def_irq_handler cpuss_interrupts_cm0_cti_1_IRQHandler /* CM0+ CTI #1 */
- def_irq_handler cpuss_interrupts_cm4_cti_0_IRQHandler /* CM4 CTI #0 */
- def_irq_handler cpuss_interrupts_cm4_cti_1_IRQHandler /* CM4 CTI #1 */
- def_irq_handler tcpwm_0_interrupts_0_IRQHandler /* TCPWM #0, Counter #0 */
- def_irq_handler tcpwm_0_interrupts_1_IRQHandler /* TCPWM #0, Counter #1 */
- def_irq_handler tcpwm_0_interrupts_2_IRQHandler /* TCPWM #0, Counter #2 */
- def_irq_handler tcpwm_0_interrupts_3_IRQHandler /* TCPWM #0, Counter #3 */
- def_irq_handler tcpwm_0_interrupts_4_IRQHandler /* TCPWM #0, Counter #4 */
- def_irq_handler tcpwm_0_interrupts_5_IRQHandler /* TCPWM #0, Counter #5 */
- def_irq_handler tcpwm_0_interrupts_6_IRQHandler /* TCPWM #0, Counter #6 */
- def_irq_handler tcpwm_0_interrupts_7_IRQHandler /* TCPWM #0, Counter #7 */
- def_irq_handler tcpwm_1_interrupts_0_IRQHandler /* TCPWM #1, Counter #0 */
- def_irq_handler tcpwm_1_interrupts_1_IRQHandler /* TCPWM #1, Counter #1 */
- def_irq_handler tcpwm_1_interrupts_2_IRQHandler /* TCPWM #1, Counter #2 */
- def_irq_handler tcpwm_1_interrupts_3_IRQHandler /* TCPWM #1, Counter #3 */
- def_irq_handler tcpwm_1_interrupts_4_IRQHandler /* TCPWM #1, Counter #4 */
- def_irq_handler tcpwm_1_interrupts_5_IRQHandler /* TCPWM #1, Counter #5 */
- def_irq_handler tcpwm_1_interrupts_6_IRQHandler /* TCPWM #1, Counter #6 */
- def_irq_handler tcpwm_1_interrupts_7_IRQHandler /* TCPWM #1, Counter #7 */
- def_irq_handler tcpwm_1_interrupts_8_IRQHandler /* TCPWM #1, Counter #8 */
- def_irq_handler tcpwm_1_interrupts_9_IRQHandler /* TCPWM #1, Counter #9 */
- def_irq_handler tcpwm_1_interrupts_10_IRQHandler /* TCPWM #1, Counter #10 */
- def_irq_handler tcpwm_1_interrupts_11_IRQHandler /* TCPWM #1, Counter #11 */
- def_irq_handler tcpwm_1_interrupts_12_IRQHandler /* TCPWM #1, Counter #12 */
- def_irq_handler tcpwm_1_interrupts_13_IRQHandler /* TCPWM #1, Counter #13 */
- def_irq_handler tcpwm_1_interrupts_14_IRQHandler /* TCPWM #1, Counter #14 */
- def_irq_handler tcpwm_1_interrupts_15_IRQHandler /* TCPWM #1, Counter #15 */
- def_irq_handler tcpwm_1_interrupts_16_IRQHandler /* TCPWM #1, Counter #16 */
- def_irq_handler tcpwm_1_interrupts_17_IRQHandler /* TCPWM #1, Counter #17 */
- def_irq_handler tcpwm_1_interrupts_18_IRQHandler /* TCPWM #1, Counter #18 */
- def_irq_handler tcpwm_1_interrupts_19_IRQHandler /* TCPWM #1, Counter #19 */
- def_irq_handler tcpwm_1_interrupts_20_IRQHandler /* TCPWM #1, Counter #20 */
- def_irq_handler tcpwm_1_interrupts_21_IRQHandler /* TCPWM #1, Counter #21 */
- def_irq_handler tcpwm_1_interrupts_22_IRQHandler /* TCPWM #1, Counter #22 */
- def_irq_handler tcpwm_1_interrupts_23_IRQHandler /* TCPWM #1, Counter #23 */
- def_irq_handler pass_interrupt_sar_IRQHandler /* SAR ADC interrupt */
- def_irq_handler audioss_0_interrupt_i2s_IRQHandler /* I2S0 Audio interrupt */
- def_irq_handler audioss_0_interrupt_pdm_IRQHandler /* PDM0/PCM0 Audio interrupt */
- def_irq_handler audioss_1_interrupt_i2s_IRQHandler /* I2S1 Audio interrupt */
- def_irq_handler profile_interrupt_IRQHandler /* Energy Profiler interrupt */
- def_irq_handler smif_interrupt_IRQHandler /* Serial Memory Interface interrupt */
- def_irq_handler usb_interrupt_hi_IRQHandler /* USB Interrupt */
- def_irq_handler usb_interrupt_med_IRQHandler /* USB Interrupt */
- def_irq_handler usb_interrupt_lo_IRQHandler /* USB Interrupt */
- def_irq_handler sdhc_0_interrupt_wakeup_IRQHandler /* SDIO wakeup interrupt for mxsdhc */
- def_irq_handler sdhc_0_interrupt_general_IRQHandler /* Consolidated interrupt for mxsdhc for everything else */
- def_irq_handler sdhc_1_interrupt_wakeup_IRQHandler /* EEMC wakeup interrupt for mxsdhc, not used */
- def_irq_handler sdhc_1_interrupt_general_IRQHandler /* Consolidated interrupt for mxsdhc for everything else */
-
- .end
-
-
-/* [] END OF FILE */
diff --git a/boot/cypress/toolchains.mk b/boot/cypress/toolchains.mk
index 11c1413..970f325 100644
--- a/boot/cypress/toolchains.mk
+++ b/boot/cypress/toolchains.mk
@@ -83,10 +83,11 @@
ifeq ($(COMPILER), GCC_ARM)
# set build-in compiler flags
CFLAGS_COMMON := -mcpu=cortex-$(CORE_SIFFX) -mthumb -mfloat-abi=soft -fno-stack-protector -ffunction-sections -fdata-sections -ffat-lto-objects -fstrict-aliasing -g -Wall -Wextra
+ # preset default level of optimization - can be changed in application.mk
ifeq ($(BUILDCFG), Debug)
- CFLAGS_COMMON += -Og -g3
+ CFLAGS_OPTIMIZATION ?= -Og -g3
else ifeq ($(BUILDCFG), Release)
- CFLAGS_COMMON += -Os -g
+ CFLAGS_OPTIMIZATION ?= -Os -g
else
$(error BUILDCFG : '$(BUILDCFG)' is not supported)
endif
@@ -96,9 +97,10 @@
LDFLAGS_COMMON := -mcpu=cortex-$(CORE_SIFFX) -mthumb -specs=nano.specs -ffunction-sections -fdata-sections -Wl,--gc-sections -L "$(GCC_PATH)/lib/gcc/arm-none-eabi/7.2.1/thumb/v6-m" -ffat-lto-objects -g --enable-objc-gc
ifeq ($(BUILDCFG), Debug)
- LDFLAGS_COMMON += -Og
+ # preset default level of optimization - can be changed in application.mk
+ LDFLAGS_OPTIMIZATION ?= -Og
else ifeq ($(BUILDCFG), Release)
- LDFLAGS_COMMON += -Os
+ LDFLAGS_OPTIMIZATION ?= -Os
else
$(error BUILDCFG : '$(BUILDCFG)' is not supported)
endif
diff --git a/boot/zephyr/include/flash_map_backend/flash_map_backend.h b/boot/zephyr/include/flash_map_backend/flash_map_backend.h
index 08deca5..958cdcb 100644
--- a/boot/zephyr/include/flash_map_backend/flash_map_backend.h
+++ b/boot/zephyr/include/flash_map_backend/flash_map_backend.h
@@ -62,7 +62,7 @@
int flash_area_id_to_image_slot(int area_id);
/**
- * Converts the specified flash area ID and image index (in multi-image setup)
+ * Converts the specified flash area ID and image index (in multi image setup)
* to an image slot index.
*
* Returns image slot index (0 or 1), or -1 if ID doesn't correspond to an image
@@ -82,6 +82,14 @@
*/
uint8_t flash_area_erased_val(const struct flash_area *fap);
+/*
+ * Reads len bytes from off, and checks if the read data is erased.
+ *
+ * Returns 1 if erased, 0 if non-erased, and -1 on failure.
+ */
+int flash_area_read_is_empty(const struct flash_area *fa, uint32_t off,
+ void *dst, uint32_t len);
+
#ifdef __cplusplus
}
#endif