boot: bootutil: move scratch swap functionality
This moves the functionality that is unique to a scratch based swap
upgrade into a separate file. Later other upgrade strategies can be
added by reimplementing those functions.
Signed-off-by: Fabio Utzig <utzig@apache.org>
diff --git a/boot/bootutil/src/swap_misc.c b/boot/bootutil/src/swap_misc.c
new file mode 100644
index 0000000..f194538
--- /dev/null
+++ b/boot/bootutil/src/swap_misc.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2019 JUUL Labs
+ *
+ * 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.
+ */
+
+#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 "mcuboot_config/mcuboot_config.h"
+
+MCUBOOT_LOG_MODULE_DECLARE(mcuboot);
+
+#if defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE)
+
+int
+swap_erase_trailer_sectors(const struct boot_loader_state *state,
+ const struct flash_area *fap)
+{
+ uint8_t slot;
+ uint32_t sector;
+ uint32_t trailer_sz;
+ uint32_t total_sz;
+ uint32_t off;
+ uint32_t sz;
+ int fa_id_primary;
+ int fa_id_secondary;
+ uint8_t image_index;
+ int rc;
+
+ BOOT_LOG_DBG("erasing trailer; fa_id=%d", fap->fa_id);
+
+ image_index = BOOT_CURR_IMG(state);
+ fa_id_primary = flash_area_id_from_multi_image_slot(image_index,
+ BOOT_PRIMARY_SLOT);
+ fa_id_secondary = flash_area_id_from_multi_image_slot(image_index,
+ BOOT_SECONDARY_SLOT);
+
+ if (fap->fa_id == fa_id_primary) {
+ slot = BOOT_PRIMARY_SLOT;
+ } else if (fap->fa_id == fa_id_secondary) {
+ slot = BOOT_SECONDARY_SLOT;
+ } else {
+ return BOOT_EFLASH;
+ }
+
+ /* delete starting from last sector and moving to beginning */
+ sector = boot_img_num_sectors(state, slot) - 1;
+ trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state));
+ total_sz = 0;
+ do {
+ sz = boot_img_sector_size(state, slot, sector);
+ off = boot_img_sector_off(state, slot, sector);
+ rc = boot_erase_region(fap, off, sz);
+ assert(rc == 0);
+
+ sector--;
+ total_sz += sz;
+ } while (total_sz < trailer_sz);
+
+ 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(FLASH_AREA_IMAGE_SECONDARY(image_index),
+ &swap_state);
+ assert(rc == 0);
+
+ if (bs->swap_type != BOOT_SWAP_TYPE_NONE) {
+ rc = boot_write_swap_info(fap, bs->swap_type, image_index);
+ assert(rc == 0);
+ }
+
+ if (swap_state.image_ok == BOOT_FLAG_SET) {
+ rc = boot_write_image_ok(fap);
+ assert(rc == 0);
+ }
+
+ rc = boot_write_swap_size(fap, bs->swap_size);
+ assert(rc == 0);
+
+#ifdef MCUBOOT_ENC_IMAGES
+ rc = boot_write_enc_key(fap, 0, bs->enckey[0]);
+ assert(rc == 0);
+
+ rc = boot_write_enc_key(fap, 1, bs->enckey[1]);
+ assert(rc == 0);
+#endif
+
+ rc = boot_write_magic(fap);
+ assert(rc == 0);
+
+ return 0;
+}
+
+int
+swap_read_status(struct boot_loader_state *state, struct boot_status *bs)
+{
+ const struct flash_area *fap;
+ uint32_t off;
+ uint8_t swap_info;
+ int status_loc;
+ int area_id;
+ int rc;
+
+ status_loc = swap_status_source(state);
+ switch (status_loc) {
+ case BOOT_STATUS_SOURCE_NONE:
+ return 0;
+
+#if MCUBOOT_SWAP_USING_SCRATCH
+ case BOOT_STATUS_SOURCE_SCRATCH:
+ area_id = FLASH_AREA_IMAGE_SCRATCH;
+ break;
+#endif
+
+ case BOOT_STATUS_SOURCE_PRIMARY_SLOT:
+ area_id = FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state));
+ break;
+
+ default:
+ assert(0);
+ return BOOT_EBADARGS;
+ }
+
+ rc = flash_area_open(area_id, &fap);
+ if (rc != 0) {
+ return BOOT_EFLASH;
+ }
+
+ rc = swap_read_status_bytes(fap, state, bs);
+ if (rc == 0) {
+ off = boot_swap_info_off(fap);
+ rc = flash_area_read_is_empty(fap, off, &swap_info, sizeof swap_info);
+ if (rc == 1) {
+ BOOT_SET_SWAP_INFO(swap_info, 0, BOOT_SWAP_TYPE_NONE);
+ rc = 0;
+ }
+
+ /* Extract the swap type info */
+ bs->swap_type = BOOT_GET_SWAP_TYPE(swap_info);
+ }
+
+ flash_area_close(fap);
+
+ return rc;
+}
+
+int
+swap_set_copy_done(uint8_t image_index)
+{
+ const struct flash_area *fap;
+ int rc;
+
+ rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(image_index),
+ &fap);
+ if (rc != 0) {
+ return BOOT_EFLASH;
+ }
+
+ rc = boot_write_copy_done(fap);
+ flash_area_close(fap);
+ return rc;
+}
+
+int
+swap_set_image_ok(uint8_t image_index)
+{
+ const struct flash_area *fap;
+ struct boot_swap_state state;
+ int rc;
+
+ rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(image_index),
+ &fap);
+ if (rc != 0) {
+ return BOOT_EFLASH;
+ }
+
+ rc = boot_read_swap_state(fap, &state);
+ if (rc != 0) {
+ rc = BOOT_EFLASH;
+ goto out;
+ }
+
+ if (state.image_ok == BOOT_FLAG_UNSET) {
+ rc = boot_write_image_ok(fap);
+ }
+
+out:
+ flash_area_close(fap);
+ return rc;
+}
+
+
+#endif /* defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE) */