Remove current_image global and macro updates

Currently to determine which image is being operated on, there is a global
variable called current_image which is used by most macros and APIs to
correctly access the flash areas required by the bootloader. This moves
this variable to the already existing state struct and refactors all
macros and APIs to receive the current image by parameters. To maintain
compatibility some of the macros were not updated and use image 0 when
called.

The definitions of FLASH_AREA_IMAGE_PRIMARY and FLASH_AREA_IMAGE_SECONDARY
for Mynewt compatibility were moved out of bootutil sources to a Mynewt
specific include file.

Signed-off-by: Fabio Utzig <utzig@apache.org>
diff --git a/boot/bootutil/src/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c
index a2fd7e3..01c54d5 100644
--- a/boot/bootutil/src/bootutil_misc.c
+++ b/boot/bootutil/src/bootutil_misc.c
@@ -170,14 +170,16 @@
 }
 
 int
-boot_status_entries(const struct flash_area *fap)
+boot_status_entries(int image_index, const struct flash_area *fap)
 {
     if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
         return BOOT_STATUS_STATE_COUNT;
-    } else if ((fap->fa_id == FLASH_AREA_IMAGE_PRIMARY) ||
-               (fap->fa_id == FLASH_AREA_IMAGE_SECONDARY)) {
+    } else if (fap->fa_id == FLASH_AREA_IMAGE_PRIMARY(image_index) ||
+               fap->fa_id == FLASH_AREA_IMAGE_SECONDARY(image_index)) {
         return BOOT_STATUS_STATE_COUNT * BOOT_STATUS_MAX_ENTRIES;
     } else {
+        /* FIXME: make error values negative and check on caller */
+        assert(0);
         return BOOT_EBADARGS;
     }
 }
@@ -300,15 +302,9 @@
     const struct flash_area *fap;
     int rc;
 
-    if (flash_area_id == FLASH_AREA_IMAGE_SCRATCH ||
-        flash_area_id == FLASH_AREA_IMAGE_PRIMARY ||
-        flash_area_id == FLASH_AREA_IMAGE_SECONDARY) {
-        rc = flash_area_open(flash_area_id, &fap);
-        if (rc != 0) {
-            return BOOT_EFLASH;
-        }
-    } else {
-        return BOOT_EBADARGS;
+    rc = flash_area_open(flash_area_id, &fap);
+    if (rc != 0) {
+        return BOOT_EFLASH;
     }
 
     rc = boot_read_swap_state(fap, state);
@@ -317,7 +313,7 @@
 }
 
 int
-boot_read_swap_size(uint32_t *swap_size)
+boot_read_swap_size(int image_index, uint32_t *swap_size)
 {
     uint32_t magic[BOOT_MAGIC_ARR_SZ];
     uint32_t off;
@@ -332,7 +328,7 @@
      * magic is always written in the last step.
      */
 
-    rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY, &fap);
+    rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(image_index), &fap);
     if (rc != 0) {
         return BOOT_EFLASH;
     }
@@ -379,14 +375,14 @@
 
 #ifdef MCUBOOT_ENC_IMAGES
 int
-boot_read_enc_key(uint8_t slot, uint8_t *enckey)
+boot_read_enc_key(int image_index, uint8_t slot, uint8_t *enckey)
 {
     uint32_t magic[BOOT_MAGIC_SZ];
     uint32_t off;
     const struct flash_area *fap;
     int rc;
 
-    rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY, &fap);
+    rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(image_index), &fap);
     if (rc != 0) {
         return BOOT_EFLASH;
     }
@@ -563,7 +559,7 @@
 #endif
 
 int
-boot_swap_type(void)
+boot_swap_type_multi(int image_index)
 {
     const struct boot_swap_table *table;
     struct boot_swap_state primary_slot;
@@ -571,12 +567,13 @@
     int rc;
     size_t i;
 
-    rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_PRIMARY, &primary_slot);
+    rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_PRIMARY(image_index),
+                                    &primary_slot);
     if (rc) {
         return BOOT_SWAP_TYPE_PANIC;
     }
 
-    rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_SECONDARY,
+    rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_SECONDARY(image_index),
                                     &secondary_slot);
     if (rc) {
         return BOOT_SWAP_TYPE_PANIC;
@@ -611,6 +608,13 @@
     return BOOT_SWAP_TYPE_NONE;
 }
 
+int
+boot_swap_type(void)
+{
+    return boot_swap_type_multi(0);
+}
+
+
 /**
  * Marks the image in the secondary slot as pending.  On the next reboot,
  * the system will perform a one-time boot of the the secondary slot image.
@@ -630,7 +634,7 @@
     uint8_t swap_type;
     int rc;
 
-    rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_SECONDARY,
+    rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_SECONDARY(0),
                                     &state_secondary_slot);
     if (rc != 0) {
         return rc;
@@ -642,7 +646,7 @@
         return 0;
 
     case BOOT_MAGIC_UNSET:
-        rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY, &fap);
+        rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(0), &fap);
         if (rc != 0) {
             rc = BOOT_EFLASH;
         } else {
@@ -669,7 +673,7 @@
         /* The image slot is corrupt.  There is no way to recover, so erase the
          * slot to allow future upgrades.
          */
-        rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY, &fap);
+        rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(0), &fap);
         if (rc != 0) {
             return BOOT_EFLASH;
         }
@@ -698,7 +702,7 @@
     struct boot_swap_state state_primary_slot;
     int rc;
 
-    rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_PRIMARY,
+    rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_PRIMARY(0),
                                     &state_primary_slot);
     if (rc != 0) {
         return rc;
@@ -718,7 +722,7 @@
         return BOOT_EBADVECT;
     }
 
-    rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY, &fap);
+    rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(0), &fap);
     if (rc) {
         rc = BOOT_EFLASH;
         goto done;
diff --git a/boot/bootutil/src/bootutil_priv.h b/boot/bootutil/src/bootutil_priv.h
index 2f2a6db..75709cc 100644
--- a/boot/bootutil/src/bootutil_priv.h
+++ b/boot/bootutil/src/bootutil_priv.h
@@ -125,7 +125,6 @@
  *      (`MCUBOOT_ENC_IMAGES`).
  */
 
-extern uint8_t current_image;
 extern const uint32_t boot_img_magic[4];
 
 struct boot_swap_state {
@@ -216,6 +215,9 @@
 
     uint8_t swap_type[BOOT_IMAGE_NUMBER];
     uint8_t write_sz;
+#if (BOOT_IMAGE_NUMBER > 1)
+    uint8_t curr_img_idx;
+#endif
 };
 
 int bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig,
@@ -223,7 +225,7 @@
 
 int boot_magic_compatible_check(uint8_t tbl_val, uint8_t val);
 uint32_t boot_trailer_sz(uint8_t min_write_sz);
-int boot_status_entries(const struct flash_area *fap);
+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,
@@ -238,11 +240,11 @@
 int boot_write_swap_info(const struct flash_area *fap, uint8_t swap_type,
                          uint8_t image_num);
 int boot_write_swap_size(const struct flash_area *fap, uint32_t swap_size);
-int boot_read_swap_size(uint32_t *swap_size);
+int boot_read_swap_size(int image_index, uint32_t *swap_size);
 #ifdef MCUBOOT_ENC_IMAGES
 int boot_write_enc_key(const struct flash_area *fap, uint8_t slot,
                        const uint8_t *enckey);
-int boot_read_enc_key(uint8_t slot, uint8_t *enckey);
+int boot_read_enc_key(int image_index, uint8_t slot, uint8_t *enckey);
 #endif
 #if (BOOT_IMAGE_NUMBER > 1)
 int boot_is_version_sufficient(struct image_version *req,
@@ -254,11 +256,16 @@
  */
 
 /* These are macros so they can be used as lvalues. */
-#define BOOT_IMG(state, slot) ((state)->imgs[current_image][(slot)])
+#if (BOOT_IMAGE_NUMBER > 1)
+#define BOOT_CURR_IMG(state) ((state)->curr_img_idx)
+#else
+#define BOOT_CURR_IMG(state) 0
+#endif
+#define BOOT_IMG(state, slot) ((state)->imgs[BOOT_CURR_IMG(state)][(slot)])
 #define BOOT_IMG_AREA(state, slot) (BOOT_IMG(state, slot).area)
 #define BOOT_SCRATCH_AREA(state) ((state)->scratch.area)
 #define BOOT_WRITE_SZ(state) ((state)->write_sz)
-#define BOOT_SWAP_TYPE(state) ((state)->swap_type[current_image])
+#define BOOT_SWAP_TYPE(state) ((state)->swap_type[BOOT_CURR_IMG(state)])
 
 static inline struct image_header*
 boot_img_hdr(struct boot_loader_state *state, size_t slot)
@@ -319,12 +326,12 @@
     int num_sectors = BOOT_MAX_IMG_SECTORS;
     int rc;
 
-    if (flash_area == FLASH_AREA_IMAGE_PRIMARY) {
+    if (flash_area == FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state))) {
         rc = flash_area_to_sectors(flash_area, &num_sectors,
                                    BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors);
         BOOT_IMG(state, BOOT_PRIMARY_SLOT).num_sectors = (size_t)num_sectors;
 
-    } else if (flash_area == FLASH_AREA_IMAGE_SECONDARY) {
+    } else if (flash_area == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) {
         rc = flash_area_to_sectors(flash_area, &num_sectors,
                                  BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors);
         BOOT_IMG(state, BOOT_SECONDARY_SLOT).num_sectors = (size_t)num_sectors;
@@ -367,10 +374,10 @@
 
     num_sectors = BOOT_MAX_IMG_SECTORS;
 
-    if (flash_area == FLASH_AREA_IMAGE_PRIMARY) {
+    if (flash_area == FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state))) {
         out_sectors = BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors;
         out_num_sectors = &BOOT_IMG(state, BOOT_PRIMARY_SLOT).num_sectors;
-    } else if (flash_area == FLASH_AREA_IMAGE_SECONDARY) {
+    } else if (flash_area == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) {
         out_sectors = BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors;
         out_num_sectors = &BOOT_IMG(state, BOOT_SECONDARY_SLOT).num_sectors;
     } else if (flash_area == FLASH_AREA_IMAGE_SCRATCH) {
diff --git a/boot/bootutil/src/encrypted.c b/boot/bootutil/src/encrypted.c
index 6dcaa22..f421f4c 100644
--- a/boot/bootutil/src/encrypted.c
+++ b/boot/bootutil/src/encrypted.c
@@ -215,8 +215,8 @@
  * Load encryption key.
  */
 int
-boot_enc_load(const struct image_header *hdr, const struct flash_area *fap,
-              uint8_t *enckey)
+boot_enc_load(int image_index, const struct image_header *hdr,
+        const struct flash_area *fap, uint8_t *enckey)
 {
 #if defined(MCUBOOT_ENCRYPT_RSA)
     mbedtls_rsa_context rsa;
@@ -233,7 +233,7 @@
     uint8_t enckey_type;
     int rc;
 
-    rc = flash_area_id_to_image_slot(fap->fa_id);
+    rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
     if (rc < 0) {
         return rc;
     }
@@ -307,14 +307,14 @@
 }
 
 bool
-boot_enc_valid(const struct flash_area *fap)
+boot_enc_valid(int image_index, const struct flash_area *fap)
 {
     int rc;
 
-    rc = flash_area_id_to_image_slot(fap->fa_id);
+    rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
     if (rc < 0) {
         /* can't get proper slot number - skip encryption, */
-        /* postpone the erro for a upper layer */
+        /* postpone the error for a upper layer */
         return false;
     }
 
@@ -332,8 +332,8 @@
 }
 
 void
-boot_encrypt(const struct flash_area *fap, uint32_t off, uint32_t sz,
-        uint32_t blk_off, uint8_t *buf)
+boot_encrypt(int image_index, const struct flash_area *fap, uint32_t off,
+        uint32_t sz, uint32_t blk_off, uint8_t *buf)
 {
     struct enc_key_data *enc;
     uint32_t i, j;
@@ -349,7 +349,7 @@
     nonce[14] = (uint8_t)(off >> 8);
     nonce[15] = (uint8_t)off;
 
-    rc = flash_area_id_to_image_slot(fap->fa_id);
+    rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
     if (rc < 0) {
         assert(0);
         return;
diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c
index b4defb2..256d125 100644
--- a/boot/bootutil/src/image_validate.c
+++ b/boot/bootutil/src/image_validate.c
@@ -51,9 +51,10 @@
  * Compute SHA256 over the image.
  */
 static int
-bootutil_img_hash(struct image_header *hdr, const struct flash_area *fap,
-                  uint8_t *tmp_buf, uint32_t tmp_buf_sz,
-                  uint8_t *hash_result, uint8_t *seed, int seed_len)
+bootutil_img_hash(int image_index, struct image_header *hdr,
+                  const struct flash_area *fap, uint8_t *tmp_buf,
+                  uint32_t tmp_buf_sz, uint8_t *hash_result, uint8_t *seed,
+                  int seed_len)
 {
     bootutil_sha256_context sha256_ctx;
     uint32_t blk_sz;
@@ -65,6 +66,10 @@
     uint32_t blk_off;
 #endif
 
+#if (BOOT_IMAGE_NUMBER == 1) || !defined(MCUBOOT_ENC_IMAGES)
+    (void)image_index;
+#endif
+
     bootutil_sha256_init(&sha256_ctx);
 
     /* in some cases (split image) the hash is seeded with data from
@@ -75,9 +80,8 @@
 
 #ifdef MCUBOOT_ENC_IMAGES
     /* Encrypted images only exist in the secondary slot */
-    if (fap->fa_id == FLASH_AREA_IMAGE_SECONDARY &&
-        IS_ENCRYPTED(hdr) &&
-        !boot_enc_valid(fap)) {
+    if (fap->fa_id == FLASH_AREA_IMAGE_SECONDARY(image_index) &&
+            IS_ENCRYPTED(hdr) && !boot_enc_valid(image_index, fap)) {
         return -1;
     }
 #endif
@@ -115,11 +119,11 @@
             return rc;
         }
 #ifdef MCUBOOT_ENC_IMAGES
-        if (fap->fa_id == FLASH_AREA_IMAGE_SECONDARY &&
-            IS_ENCRYPTED(hdr) &&
-            off >= hdr_size) {
+        if (fap->fa_id == FLASH_AREA_IMAGE_SECONDARY(image_index) &&
+                IS_ENCRYPTED(hdr) && off >= hdr_size) {
             blk_off = (off - hdr_size) & 0xf;
-            boot_encrypt(fap, off - hdr_size, blk_sz, blk_off, tmp_buf);
+            boot_encrypt(image_index, fap, off - hdr_size, blk_sz, blk_off,
+                    tmp_buf);
         }
 #endif
         bootutil_sha256_update(&sha256_ctx, tmp_buf, blk_sz);
@@ -197,9 +201,10 @@
  * Return non-zero if image could not be validated/does not validate.
  */
 int
-bootutil_img_validate(struct image_header *hdr, const struct flash_area *fap,
-                      uint8_t *tmp_buf, uint32_t tmp_buf_sz,
-                      uint8_t *seed, int seed_len, uint8_t *out_hash)
+bootutil_img_validate(int image_index, struct image_header *hdr,
+                      const struct flash_area *fap, uint8_t *tmp_buf,
+                      uint32_t tmp_buf_sz, uint8_t *seed, int seed_len,
+                      uint8_t *out_hash)
 {
     uint32_t off;
     uint32_t end;
@@ -214,7 +219,8 @@
     uint8_t hash[32];
     int rc;
 
-    rc = bootutil_img_hash(hdr, fap, tmp_buf, tmp_buf_sz, hash, seed, seed_len);
+    rc = bootutil_img_hash(image_index, hdr, fap, tmp_buf, tmp_buf_sz, hash,
+            seed, seed_len);
     if (rc) {
         return rc;
     }
diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c
index b875a1a..a01492f 100644
--- a/boot/bootutil/src/loader.c
+++ b/boot/bootutil/src/loader.c
@@ -47,7 +47,6 @@
 MCUBOOT_LOG_MODULE_DECLARE(mcuboot);
 
 static struct boot_loader_state boot_data;
-uint8_t current_image = 0;
 
 #if (BOOT_IMAGE_NUMBER > 1)
 #define IMAGES_ITER(x) for ((x) = 0; (x) < BOOT_IMAGE_NUMBER; ++(x))
@@ -174,9 +173,15 @@
     int rc;
     size_t i;
     uint8_t source;
+    uint8_t image_index;
 
-    rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_PRIMARY,
-                                    &state_primary_slot);
+#if (BOOT_IMAGE_NUMBER == 1)
+    (void)state;
+#endif
+
+    image_index = BOOT_CURR_IMG(&boot_data);
+    rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_PRIMARY(image_index),
+            &state_primary_slot);
     assert(rc == 0);
 
     rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_SCRATCH, &state_scratch);
@@ -203,7 +208,7 @@
              * currently examined image.
              */
             if (source == BOOT_STATUS_SOURCE_SCRATCH &&
-                state_scratch.image_num != current_image) {
+                state_scratch.image_num != BOOT_CURR_IMG(&boot_data)) {
                 source = BOOT_STATUS_SOURCE_NONE;
             }
 #endif
@@ -234,7 +239,8 @@
     int area_id;
     int rc;
 
-    area_id = flash_area_id_from_image_slot(slot);
+    area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(&boot_data),
+                                                  slot);
     rc = flash_area_open(area_id, &fap);
     if (rc != 0) {
         rc = BOOT_EFLASH;
@@ -267,7 +273,8 @@
     int area_id;
     int rc;
 
-    area_id = flash_area_id_from_image_slot(slot);
+    area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(&boot_data),
+                                                  slot);
     rc = flash_area_open(area_id, &fap);
     if (rc != 0) {
         rc = BOOT_EFLASH;
@@ -433,14 +440,18 @@
 static int
 boot_read_sectors(void)
 {
+    uint8_t image_index;
     int rc;
 
-    rc = boot_initialize_area(&boot_data, FLASH_AREA_IMAGE_PRIMARY);
+    image_index = BOOT_CURR_IMG(&boot_data);
+
+    rc = boot_initialize_area(state, FLASH_AREA_IMAGE_PRIMARY(image_index));
     if (rc != 0) {
         return BOOT_EFLASH;
     }
 
-    rc = boot_initialize_area(&boot_data, FLASH_AREA_IMAGE_SECONDARY);
+    rc = boot_initialize_area(&boot_data,
+            FLASH_AREA_IMAGE_SECONDARY(image_index));
     if (rc != 0) {
         return BOOT_EFLASH;
     }
@@ -484,7 +495,7 @@
     int i;
 
     off = boot_status_off(fap);
-    max_entries = boot_status_entries(fap);
+    max_entries = boot_status_entries(BOOT_CURR_IMG(&boot_data), fap);
 
     found = 0;
     found_idx = 0;
@@ -570,7 +581,7 @@
         break;
 
     case BOOT_STATUS_SOURCE_PRIMARY_SLOT:
-        area_id = FLASH_AREA_IMAGE_PRIMARY;
+        area_id = FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(&boot_data));
         break;
 
     default:
@@ -631,7 +642,7 @@
         area_id = FLASH_AREA_IMAGE_SCRATCH;
     } else {
         /* Write to the primary slot. */
-        area_id = FLASH_AREA_IMAGE_PRIMARY;
+        area_id = FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(&boot_data));
     }
 
     rc = flash_area_open(area_id, &fap);
@@ -669,14 +680,18 @@
         struct boot_status *bs)
 {
     static uint8_t tmpbuf[BOOT_TMPBUF_SZ];
+    uint8_t image_index;
     int rc;
 
+    image_index = BOOT_CURR_IMG(&boot_data);
+
 #ifndef MCUBOOT_ENC_IMAGES
     (void)bs;
     (void)rc;
 #else
-    if ((fap->fa_id == FLASH_AREA_IMAGE_SECONDARY) && IS_ENCRYPTED(hdr)) {
-        rc = boot_enc_load(hdr, fap, bs->enckey[1]);
+    if ((fap->fa_id == FLASH_AREA_IMAGE_SECONDARY(image_index))
+            && IS_ENCRYPTED(hdr)) {
+        rc = boot_enc_load(image_index, hdr, fap, bs->enckey[1]);
         if (rc < 0) {
             return BOOT_EBADIMAGE;
         }
@@ -686,8 +701,8 @@
     }
 #endif
 
-    if (bootutil_img_validate(hdr, fap, tmpbuf, BOOT_TMPBUF_SZ,
-                              NULL, 0, NULL)) {
+    if (bootutil_img_validate(image_index, hdr, fap, tmpbuf, BOOT_TMPBUF_SZ,
+                NULL, 0, NULL)) {
         return BOOT_EBADIMAGE;
     }
     return 0;
@@ -709,12 +724,12 @@
         }
     }
 
-    if (bootutil_img_validate(loader_hdr, loader_fap, tmpbuf, BOOT_TMPBUF_SZ,
+    if (bootutil_img_validate(0, loader_hdr, loader_fap, tmpbuf, BOOT_TMPBUF_SZ,
                               NULL, 0, loader_hash)) {
         return BOOT_EBADIMAGE;
     }
 
-    if (bootutil_img_validate(app_hdr, app_fap, tmpbuf, BOOT_TMPBUF_SZ,
+    if (bootutil_img_validate(0, app_hdr, app_fap, tmpbuf, BOOT_TMPBUF_SZ,
                               loader_hash, 32, NULL)) {
         return BOOT_EBADIMAGE;
     }
@@ -744,9 +759,12 @@
     const struct flash_area *fap;
     struct image_header *hdr;
     uint8_t erased_val;
+    int area_id;
     int rc;
 
-    rc = flash_area_open(flash_area_id_from_image_slot(slot), &fap);
+    area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(&boot_data),
+                                                  slot);
+    rc = flash_area_open(area_id, &fap);
     if (rc != 0) {
         return -1;
     }
@@ -767,9 +785,12 @@
 {
     const struct flash_area *fap;
     struct image_header *hdr;
+    int area_id;
     int rc;
 
-    rc = flash_area_open(flash_area_id_from_image_slot(slot), &fap);
+    area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(&boot_data),
+                                                  slot);
+    rc = flash_area_open(area_id, &fap);
     if (rc != 0) {
         return BOOT_EFLASH;
     }
@@ -815,7 +836,11 @@
 {
     int swap_type;
 
+#if (BOOT_IMAGE_NUMBER == 1)
     swap_type = boot_swap_type();
+#else
+    swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state));
+#endif
     switch (swap_type) {
     case BOOT_SWAP_TYPE_TEST:
     case BOOT_SWAP_TYPE_PERM:
@@ -921,6 +946,7 @@
     struct image_header *hdr;
     uint16_t idx;
     uint32_t blk_sz;
+    uint8_t image_index;
 #endif
 
     static uint8_t buf[1024];
@@ -939,12 +965,13 @@
         }
 
 #ifdef MCUBOOT_ENC_IMAGES
-        if ((fap_src->fa_id == FLASH_AREA_IMAGE_SECONDARY) ||
-            (fap_dst->fa_id == FLASH_AREA_IMAGE_SECONDARY)) {
+        image_index = BOOT_CURR_IMG(&boot_data);
+        if (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(&boot_data, BOOT_SECONDARY_SLOT);
             off = off_src;
-            if (fap_dst->fa_id == FLASH_AREA_IMAGE_SECONDARY) {
+            if (fap_dst->fa_id == FLASH_AREA_IMAGE_SECONDARY(image_index)) {
                 /* might need encryption (metadata from the primary slot) */
                 hdr = boot_img_hdr(&boot_data, BOOT_PRIMARY_SLOT);
                 off = off_dst;
@@ -968,8 +995,9 @@
                         blk_sz = (hdr->ih_hdr_size + hdr->ih_img_size) - (off + bytes_copied);
                     }
                 }
-                boot_encrypt(fap_src, (off + bytes_copied + idx) - hdr->ih_hdr_size,
-                        blk_sz, blk_off, &buf[idx]);
+                boot_encrypt(image_index, fap_src,
+                        (off + bytes_copied + idx) - hdr->ih_hdr_size, blk_sz,
+                        blk_off, &buf[idx]);
             }
         }
 #endif
@@ -992,17 +1020,19 @@
 boot_status_init(const struct flash_area *fap, const struct boot_status *bs)
 {
     struct boot_swap_state swap_state;
+    uint8_t image_index;
     int rc;
 
+    image_index = BOOT_CURR_IMG(&boot_data);
+
     BOOT_LOG_DBG("initializing status; fa_id=%d", fap->fa_id);
 
-    rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_SECONDARY, &swap_state);
+    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,
-                                  current_image);
+        rc = boot_write_swap_info(fap, bs->swap_type, image_index);
         assert(rc == 0);
     }
 
@@ -1042,12 +1072,16 @@
     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);
 
-    fa_id_primary   = flash_area_id_from_image_slot(BOOT_PRIMARY_SLOT);
-    fa_id_secondary = flash_area_id_from_image_slot(BOOT_SECONDARY_SLOT);
+    image_index = BOOT_CURR_IMG(&boot_data);
+    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;
@@ -1100,6 +1134,7 @@
     struct boot_swap_state swap_state;
     size_t last_sector;
     bool erase_scratch;
+    uint8_t image_index;
     int rc;
 
     /* Calculate offset from start of image area. */
@@ -1125,10 +1160,14 @@
 
     bs->use_scratch = (bs->idx == BOOT_STATUS_IDX_0 && copy_sz != sz);
 
-    rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY, &fap_primary_slot);
+    image_index = BOOT_CURR_IMG(&boot_data);
+
+    rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(image_index),
+            &fap_primary_slot);
     assert (rc == 0);
 
-    rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY, &fap_secondary_slot);
+    rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(image_index),
+            &fap_secondary_slot);
     assert (rc == 0);
 
     rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, &fap_scratch);
@@ -1225,8 +1264,7 @@
 
             if (swap_state.swap_type != BOOT_SWAP_TYPE_NONE) {
                 rc = boot_write_swap_info(fap_primary_slot,
-                                          swap_state.swap_type,
-                                          current_image);
+                        swap_state.swap_type, image_index);
                 assert(rc == 0);
             }
 
@@ -1294,6 +1332,7 @@
     size_t last_sector;
     const struct flash_area *fap_primary_slot;
     const struct flash_area *fap_secondary_slot;
+    uint8_t image_index;
 
     (void)bs;
 
@@ -1308,10 +1347,14 @@
     BOOT_LOG_INF("Image upgrade secondary slot -> primary slot");
     BOOT_LOG_INF("Erasing the primary slot");
 
-    rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY, &fap_primary_slot);
+    image_index = BOOT_CURR_IMG(state);
+
+    rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(image_index),
+            &fap_primary_slot);
     assert (rc == 0);
 
-    rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY, &fap_secondary_slot);
+    rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(image_index),
+            &fap_secondary_slot);
     assert (rc == 0);
 
     sect_count = boot_img_num_sectors(&boot_data, BOOT_PRIMARY_SLOT);
@@ -1331,9 +1374,9 @@
 
 #ifdef MCUBOOT_ENC_IMAGES
     if (IS_ENCRYPTED(boot_img_hdr(&boot_data, BOOT_SECONDARY_SLOT))) {
-        rc = boot_enc_load(boot_img_hdr(&boot_data, BOOT_SECONDARY_SLOT),
-                           fap_secondary_slot,
-                           bs->enckey[1]);
+        rc = boot_enc_load(image_index,
+                boot_img_hdr(&boot_data, BOOT_SECONDARY_SLOT),
+                fap_secondary_slot, bs->enckey[1]);
 
         if (rc < 0) {
             return BOOT_EBADIMAGE;
@@ -1409,11 +1452,13 @@
     uint32_t copy_size;
     uint32_t primary_slot_size;
     uint32_t secondary_slot_size;
+    uint8_t image_index;
     int rc;
 
     /* FIXME: just do this if asked by user? */
 
     size = copy_size = 0;
+    image_index = BOOT_CURR_IMG(&boot_data);
 
     if (bs->idx == BOOT_STATUS_IDX_0 && bs->state == BOOT_STATUS_STATE_0) {
         /*
@@ -1429,7 +1474,7 @@
 #ifdef MCUBOOT_ENC_IMAGES
         if (IS_ENCRYPTED(hdr)) {
             fap = BOOT_IMG_AREA(&boot_data, BOOT_PRIMARY_SLOT);
-            rc = boot_enc_load(hdr, fap, bs->enckey[0]);
+            rc = boot_enc_load(image_index, hdr, fap, bs->enckey[0]);
             assert(rc >= 0);
 
             if (rc == 0) {
@@ -1453,7 +1498,7 @@
         hdr = boot_img_hdr(&boot_data, BOOT_SECONDARY_SLOT);
         if (IS_ENCRYPTED(hdr)) {
             fap = BOOT_IMG_AREA(&boot_data, BOOT_SECONDARY_SLOT);
-            rc = boot_enc_load(hdr, fap, bs->enckey[1]);
+            rc = boot_enc_load(image_index, hdr, fap, bs->enckey[1]);
             assert(rc >= 0);
 
             if (rc == 0) {
@@ -1477,14 +1522,14 @@
          * If a swap was under way, the swap_size should already be present
          * in the trailer...
          */
-        rc = boot_read_swap_size(&bs->swap_size);
+        rc = boot_read_swap_size(image_index, &bs->swap_size);
         assert(rc == 0);
 
         copy_size = bs->swap_size;
 
 #ifdef MCUBOOT_ENC_IMAGES
         for (slot = 0; slot <= 1; slot++) {
-            rc = boot_read_enc_key(slot, bs->enckey[slot]);
+            rc = boot_read_enc_key(image_index, slot, bs->enckey[slot]);
             assert(rc == 0);
 
             for (i = 0; i < BOOT_ENC_KEY_SIZE; i++) {
@@ -1565,7 +1610,8 @@
     const struct flash_area *fap;
     int rc;
 
-    rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY, &fap);
+    rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(image_index),
+            &fap);
     if (rc != 0) {
         return BOOT_EFLASH;
     }
@@ -1593,7 +1639,8 @@
     struct boot_swap_state state;
     int rc;
 
-    rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY, &fap);
+    rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(image_index),
+            &fap);
     if (rc != 0) {
         return BOOT_EFLASH;
     }
@@ -1679,9 +1726,12 @@
     uint32_t off;
     uint32_t end;
     bool dep_tlvs_found = false;
+    int area_id;
     int rc;
 
-    rc = flash_area_open(flash_area_id_from_image_slot(slot), &fap);
+    area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(&boot_data),
+            slot);
+    rc = flash_area_open(area_id, &fap);
     if (rc != 0) {
         rc = BOOT_EFLASH;
         goto done;
@@ -1787,17 +1837,17 @@
 static void
 boot_verify_all_image_dependency(void)
 {
-    current_image = 0;
     int rc;
 
-    while (current_image < BOOT_IMAGE_NUMBER) {
+    BOOT_CURR_IMG(&boot_data) = 0;
+    while (BOOT_CURR_IMG(&boot_data) < BOOT_IMAGE_NUMBER) {
         rc = boot_verify_single_image_dependency();
         if (rc == 0) {
             /* All dependencies've been satisfied, continue with next image. */
-            current_image++;
+            BOOT_CURR_IMG(&boot_data)++;
         } else if (rc == BOOT_EBADVERSION) {
             /* Dependency check needs to be restarted. */
-            current_image = 0;
+            BOOT_CURR_IMG(&boot_data) = 0;
         } else {
             /* Other error happened, images are inconsistent */
             return;
@@ -1950,7 +2000,7 @@
      *      upgrades).
      */
 
-    if (current_image == 0) {
+    if (BOOT_CURR_IMG(&boot_data) == 0) {
         /* Nothing to do */
         return;
     }
@@ -1963,7 +2013,7 @@
         }
     }
 
-    for (uint8_t i = 0; i < current_image; i++) {
+    for (uint8_t i = 0; i < BOOT_CURR_IMG(&boot_data); i++) {
         if (boot_data.swap_type[i] == BOOT_SWAP_TYPE_REVERT) {
             boot_data.swap_type[i] = BOOT_SWAP_TYPE_NONE;
         }
@@ -2002,7 +2052,8 @@
     rc = boot_read_image_headers(false);
     if (rc != 0) {
         /* Continue with next image if there is one. */
-        BOOT_LOG_WRN("Failed reading image headers; Image=%u", current_image);
+        BOOT_LOG_WRN("Failed reading image headers; Image=%u",
+                BOOT_CURR_IMG(&boot_data));
         BOOT_SWAP_TYPE(&boot_data) = BOOT_SWAP_TYPE_NONE;
         return;
     }
@@ -2015,7 +2066,7 @@
         rc = boot_read_status(bs);
         if (rc != 0) {
             BOOT_LOG_WRN("Failed reading boot status; Image=%u",
-                         current_image);
+                    BOOT_CURR_IMG(&boot_data));
             /* Continue with next image if there is one. */
             BOOT_SWAP_TYPE(&boot_data) = BOOT_SWAP_TYPE_NONE;
             return;
@@ -2110,6 +2161,7 @@
     struct boot_status bs;
     int rc;
     int fa_id;
+    int image_index;
 
     /* The array of slot sectors are defined here (as opposed to file scope) so
      * that they don't get allocated for non-boot-loader apps.  This is
@@ -2131,7 +2183,7 @@
      * to be determined for each image and all aborted swaps have to be
      * completed.
      */
-    IMAGES_ITER(current_image) {
+    IMAGES_ITER(BOOT_CURR_IMG(&boot_data)) {
 
 #if defined(MCUBOOT_ENC_IMAGES) && (BOOT_IMAGE_NUMBER > 1)
         /* The keys used for encryption may no longer be valid (could belong to
@@ -2141,17 +2193,19 @@
         boot_enc_mark_keys_invalid();
 #endif
 
+        image_index = BOOT_CURR_IMG(&boot_data);
+
         BOOT_IMG(&boot_data, BOOT_PRIMARY_SLOT).sectors =
-                                        primary_slot_sectors[current_image];
+            primary_slot_sectors[image_index];
         BOOT_IMG(&boot_data, BOOT_SECONDARY_SLOT).sectors =
-                                        secondary_slot_sectors[current_image];
+            secondary_slot_sectors[image_index];
         boot_data.scratch.sectors = scratch_sectors;
 
         /* Open primary and secondary image areas for the duration
          * of this call.
          */
         for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
-            fa_id = flash_area_id_from_image_slot(slot);
+            fa_id = flash_area_id_from_multi_image_slot(image_index, slot);
             rc = flash_area_open(fa_id, &BOOT_IMG_AREA(&boot_data, slot));
             assert(rc == 0);
         }
@@ -2174,7 +2228,7 @@
      * and the swap types are determined for each image. By the end of the loop
      * all required update operations will have been finished.
      */
-    IMAGES_ITER(current_image) {
+    IMAGES_ITER(BOOT_CURR_IMG(&boot_data)) {
 
 #if (BOOT_IMAGE_NUMBER > 1)
 #ifdef MCUBOOT_ENC_IMAGES
@@ -2236,7 +2290,7 @@
      * have finished. By the end of the loop each image in the primary slot will
      * have been re-validated.
      */
-    IMAGES_ITER(current_image) {
+    IMAGES_ITER(BOOT_CURR_IMG(&boot_data)) {
         if (BOOT_SWAP_TYPE(&boot_data) != BOOT_SWAP_TYPE_NONE) {
             /* Attempt to read an image header from each slot. Ensure that image
              * headers in slots are aligned with headers in boot_data.
@@ -2267,15 +2321,17 @@
                 IMAGE_MAGIC) {
             BOOT_LOG_ERR("bad image magic 0x%lx; Image=%u", (unsigned long)
                          &boot_img_hdr(&boot_data,BOOT_PRIMARY_SLOT)->ih_magic,
-                         current_image);
+                         BOOT_CURR_IMG(&boot_data));
             rc = BOOT_EBADIMAGE;
             goto out;
         }
 #endif
     }
 
+#if (BOOT_IMAGE_NUMBER > 1)
     /* Always boot from the primary slot of Image 0. */
-    current_image = 0;
+    BOOT_CURR_IMG(&boot_data) = 0;
+#endif
     rsp->br_flash_dev_id =
             BOOT_IMG_AREA(&boot_data, BOOT_PRIMARY_SLOT)->fa_device_id;
     rsp->br_image_off =
@@ -2284,7 +2340,7 @@
             boot_img_hdr(&boot_data, BOOT_PRIMARY_SLOT);
 
  out:
-    IMAGES_ITER(current_image) {
+    IMAGES_ITER(BOOT_CURR_IMG(&boot_data)) {
         flash_area_close(BOOT_SCRATCH_AREA(&boot_data));
         for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
             flash_area_close(BOOT_IMG_AREA(&boot_data,