boot/bootutil: Split RAM load code to its own file

RAM loading code is currently under bootutil/loader.c, and it's not
accessible for different loaders, such as the single loaders. Future
patches will make use of the RAM loading code outside the
bootutil/loader.c context, and this patch prepares for that by making it
standalone on boot/bootutil/src/ram_load.c

Signed-off-by: Ederson de Souza <ederson.desouza@intel.com>
Signed-off-by: Tom Burdick <thomas.burdick@intel.com>
(cherry picked from commit 9f1e573efe83bdbd5456a379248b6ab2d013a929)
Signed-off-by: Jamie McCrae <jamie.mccrae@nordicsemi.no>
diff --git a/boot/bootutil/CMakeLists.txt b/boot/bootutil/CMakeLists.txt
index 9097706..3d1b327 100644
--- a/boot/bootutil/CMakeLists.txt
+++ b/boot/bootutil/CMakeLists.txt
@@ -33,3 +33,9 @@
         src/swap_scratch.c
         src/tlv.c
 )
+if(CONFIG_BOOT_RAM_LOAD)
+    target_sources(bootutil
+        PRIVATE
+            src/ram_load.c
+    )
+endif()
diff --git a/boot/bootutil/pkg.yml b/boot/bootutil/pkg.yml
index e919785..ed6f358 100644
--- a/boot/bootutil/pkg.yml
+++ b/boot/bootutil/pkg.yml
@@ -45,6 +45,9 @@
     - "loader.c"
     - "swap_scratch.c"
 
+pkg.ign_files:
+    - "ram_load.c"
+
 pkg.deps.BOOTUTIL_USE_MBED_TLS:
     - "@apache-mynewt-core/crypto/mbedtls"
 
diff --git a/boot/bootutil/src/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c
index 4620213..09fbe89 100644
--- a/boot/bootutil/src/bootutil_misc.c
+++ b/boot/bootutil/src/bootutil_misc.c
@@ -355,3 +355,68 @@
     return boot_swap_info_off(fap);
 #endif
 }
+
+/*
+ * Compute the total size of the given image.  Includes the size of
+ * the TLVs.
+ */
+#if !defined(MCUBOOT_DIRECT_XIP) && \
+    (!defined(MCUBOOT_OVERWRITE_ONLY) || \
+    defined(MCUBOOT_OVERWRITE_ONLY_FAST))
+int
+boot_read_image_size(struct boot_loader_state *state, int slot, uint32_t *size)
+{
+    const struct flash_area *fap;
+    struct image_tlv_info info;
+    uint32_t off;
+    uint32_t protect_tlv_size;
+    int area_id;
+    int rc;
+
+#if (BOOT_IMAGE_NUMBER == 1)
+    (void)state;
+#endif
+
+    area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
+    rc = flash_area_open(area_id, &fap);
+    if (rc != 0) {
+        rc = BOOT_EFLASH;
+        goto done;
+    }
+
+    off = BOOT_TLV_OFF(boot_img_hdr(state, slot));
+
+    if (flash_area_read(fap, off, &info, sizeof(info))) {
+        rc = BOOT_EFLASH;
+        goto done;
+    }
+
+    protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size;
+    if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) {
+        if (protect_tlv_size != info.it_tlv_tot) {
+            rc = BOOT_EBADIMAGE;
+            goto done;
+        }
+
+        if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) {
+            rc = BOOT_EFLASH;
+            goto done;
+        }
+    } else if (protect_tlv_size != 0) {
+        rc = BOOT_EBADIMAGE;
+        goto done;
+    }
+
+    if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
+        rc = BOOT_EBADIMAGE;
+        goto done;
+    }
+
+    *size = off + protect_tlv_size + info.it_tlv_tot;
+    rc = 0;
+
+done:
+    flash_area_close(fap);
+    return rc;
+}
+#endif /* !MCUBOOT_OVERWRITE_ONLY */
diff --git a/boot/bootutil/src/bootutil_priv.h b/boot/bootutil/src/bootutil_priv.h
index 208d189..345933a 100644
--- a/boot/bootutil/src/bootutil_priv.h
+++ b/boot/bootutil/src/bootutil_priv.h
@@ -51,6 +51,8 @@
 
 #define BOOT_TMPBUF_SZ  256
 
+#define NO_ACTIVE_SLOT UINT32_MAX
+
 /** Number of image slots in flash; currently limited to two. */
 #define BOOT_NUM_SLOTS                  2
 
@@ -467,15 +469,24 @@
 #define LOAD_IMAGE_DATA(hdr, fap, start, output, size)       \
     (memcpy((output),(void*)(IMAGE_RAM_BASE + (hdr)->ih_load_addr + (start)), \
     (size)), 0)
+
+int boot_load_image_to_sram(struct boot_loader_state *state);
+int boot_remove_image_from_sram(struct boot_loader_state *state);
+int boot_remove_image_from_flash(struct boot_loader_state *state,
+                                 uint32_t slot);
 #else
 #define IMAGE_RAM_BASE ((uintptr_t)0)
 
 #define LOAD_IMAGE_DATA(hdr, fap, start, output, size)       \
     (flash_area_read((fap), (start), (output), (size)))
+
 #endif /* MCUBOOT_RAM_LOAD */
 
 uint32_t bootutil_max_image_size(const struct flash_area *fap);
 
+int boot_read_image_size(struct boot_loader_state *state, int slot,
+                         uint32_t *size);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c
index 12d4abf..1303394 100644
--- a/boot/bootutil/src/loader.c
+++ b/boot/bootutil/src/loader.c
@@ -110,8 +110,6 @@
 #define BUF_SZ 1024
 #endif
 
-#define NO_ACTIVE_SLOT UINT32_MAX
-
 static int
 boot_read_image_headers(struct boot_loader_state *state, bool require_all,
         struct boot_status *bs)
@@ -482,11 +480,6 @@
 }
 #else
 
-#if defined MCUBOOT_RAM_LOAD
-static inline int
-boot_remove_image_from_sram(struct boot_loader_state *state);
-#endif
-
 /**
  * Checks the dependency of all the active slots. If an image found with
  * invalid or not satisfied dependencies the image is removed from SRAM (in
@@ -600,68 +593,6 @@
 #endif /* (BOOT_IMAGE_NUMBER > 1) */
 
 #if !defined(MCUBOOT_DIRECT_XIP)
-/*
- * Compute the total size of the given image.  Includes the size of
- * the TLVs.
- */
-#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)
-{
-    const struct flash_area *fap;
-    struct image_tlv_info info;
-    uint32_t off;
-    uint32_t protect_tlv_size;
-    int area_id;
-    int rc;
-
-#if (BOOT_IMAGE_NUMBER == 1)
-    (void)state;
-#endif
-
-    area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
-    rc = flash_area_open(area_id, &fap);
-    if (rc != 0) {
-        rc = BOOT_EFLASH;
-        goto done;
-    }
-
-    off = BOOT_TLV_OFF(boot_img_hdr(state, slot));
-
-    if (flash_area_read(fap, off, &info, sizeof(info))) {
-        rc = BOOT_EFLASH;
-        goto done;
-    }
-
-    protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size;
-    if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) {
-        if (protect_tlv_size != info.it_tlv_tot) {
-            rc = BOOT_EBADIMAGE;
-            goto done;
-        }
-
-        if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) {
-            rc = BOOT_EFLASH;
-            goto done;
-        }
-    } else if (protect_tlv_size != 0) {
-        rc = BOOT_EBADIMAGE;
-        goto done;
-    }
-
-    if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
-        rc = BOOT_EBADIMAGE;
-        goto done;
-    }
-
-    *size = off + protect_tlv_size + info.it_tlv_tot;
-    rc = 0;
-
-done:
-    flash_area_close(fap);
-    return rc;
-}
-#endif /* !MCUBOOT_OVERWRITE_ONLY */
 
 #if !defined(MCUBOOT_RAM_LOAD)
 static uint32_t
@@ -2764,406 +2695,6 @@
 }
 #endif /* MCUBOOT_DIRECT_XIP && MCUBOOT_DIRECT_XIP_REVERT */
 
-#ifdef MCUBOOT_RAM_LOAD
-
-#ifndef MULTIPLE_EXECUTABLE_RAM_REGIONS
-#if !defined(IMAGE_EXECUTABLE_RAM_START) || !defined(IMAGE_EXECUTABLE_RAM_SIZE)
-#error "Platform MUST define executable RAM bounds in case of RAM_LOAD"
-#endif
-#endif
-
-/**
- * Verifies that the active slot of the current image can be loaded within the
- * predefined bounds that are allowed to be used by executable images.
- *
- * @param  state        Boot loader status information.
- *
- * @return              0 on success; nonzero on failure.
- */
-static int
-boot_verify_ram_load_address(struct boot_loader_state *state)
-{
-    uint32_t img_dst;
-    uint32_t img_sz;
-    uint32_t img_end_addr;
-    uint32_t exec_ram_start;
-    uint32_t exec_ram_size;
-
-    (void)state;
-
-#ifdef MULTIPLE_EXECUTABLE_RAM_REGIONS
-    int      rc;
-
-    rc = boot_get_image_exec_ram_info(BOOT_CURR_IMG(state), &exec_ram_start,
-                                      &exec_ram_size);
-    if (rc != 0) {
-        return BOOT_EBADSTATUS;
-    }
-#else
-    exec_ram_start = IMAGE_EXECUTABLE_RAM_START;
-    exec_ram_size = IMAGE_EXECUTABLE_RAM_SIZE;
-#endif
-
-    img_dst = state->slot_usage[BOOT_CURR_IMG(state)].img_dst;
-    img_sz = state->slot_usage[BOOT_CURR_IMG(state)].img_sz;
-
-    if (img_dst < exec_ram_start) {
-        return BOOT_EBADIMAGE;
-    }
-
-    if (!boot_u32_safe_add(&img_end_addr, img_dst, img_sz)) {
-        return BOOT_EBADIMAGE;
-    }
-
-    if (img_end_addr > (exec_ram_start + exec_ram_size)) {
-        return BOOT_EBADIMAGE;
-    }
-
-    return 0;
-}
-
-#ifdef MCUBOOT_ENC_IMAGES
-
-/**
- * Copies and decrypts an image from a slot in the flash to an SRAM address.
- *
- * @param  state    Boot loader status information.
- * @param  slot     The flash slot of the image to be copied to SRAM.
- * @param  hdr      The image header.
- * @param  src_sz   Size of the image.
- * @param  img_dst  Pointer to the address at which the image needs to be
- *                  copied to SRAM.
- *
- * @return          0 on success; nonzero on failure.
- */
-static int
-boot_decrypt_and_copy_image_to_sram(struct boot_loader_state *state,
-                                    uint32_t slot, struct image_header *hdr,
-                                    uint32_t src_sz, uint32_t img_dst)
-{
-    /* The flow for the decryption and copy of the image is as follows :
-     * 1. The whole image is copied to the RAM (header + payload + TLV).
-     * 2. The encryption key is loaded from the TLV in flash.
-     * 3. The image is then decrypted chunk by chunk in RAM (1 chunk
-     * is 1024 bytes). Only the payload section is decrypted.
-     * 4. The image is authenticated in RAM.
-     */
-    const struct flash_area *fap_src = NULL;
-    struct boot_status bs;
-    uint32_t blk_off;
-    uint32_t tlv_off;
-    uint32_t blk_sz;
-    uint32_t bytes_copied = hdr->ih_hdr_size;
-    uint32_t chunk_sz;
-    uint32_t max_sz = 1024;
-    uint16_t idx;
-    uint8_t * cur_dst;
-    int area_id;
-    int rc;
-    uint8_t * ram_dst = (void *)(IMAGE_RAM_BASE + img_dst);
-
-    area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
-    rc = flash_area_open(area_id, &fap_src);
-    if (rc != 0){
-        return BOOT_EFLASH;
-    }
-
-    tlv_off = BOOT_TLV_OFF(hdr);
-
-    /* Copying the whole image in RAM */
-    rc = flash_area_read(fap_src, 0, ram_dst, src_sz);
-    if (rc != 0) {
-        goto done;
-    }
-
-    rc = boot_enc_load(BOOT_CURR_ENC(state), slot, hdr, fap_src, &bs);
-    if (rc < 0) {
-        goto done;
-    }
-
-    /* if rc > 0 then the key has already been loaded */
-    if (rc == 0 && boot_enc_set_key(BOOT_CURR_ENC(state), slot, &bs)) {
-        goto done;
-    }
-
-    /* Starting at the end of the header as the header section is not encrypted */
-    while (bytes_copied < tlv_off) { /* TLV section copied previously */
-        if (src_sz - bytes_copied > max_sz) {
-            chunk_sz = max_sz;
-        } else {
-            chunk_sz = src_sz - bytes_copied;
-        }
-
-        cur_dst = ram_dst + bytes_copied;
-        blk_sz = chunk_sz;
-        idx = 0;
-        blk_off = ((bytes_copied) - hdr->ih_hdr_size) & 0xf;
-        if (bytes_copied + chunk_sz > tlv_off) {
-            /* Going over TLV section
-             * Part of the chunk is encrypted payload */
-            blk_sz = tlv_off - (bytes_copied);
-        }
-        boot_enc_decrypt(BOOT_CURR_ENC(state), slot,
-                (bytes_copied + idx) - hdr->ih_hdr_size, blk_sz,
-                blk_off, cur_dst);
-        bytes_copied += chunk_sz;
-    }
-    rc = 0;
-
-done:
-    flash_area_close(fap_src);
-
-    return rc;
-}
-
-#endif /* MCUBOOT_ENC_IMAGES */
-/**
- * Copies a slot of the current image into SRAM.
- *
- * @param  state    Boot loader status information.
- * @param  slot     The flash slot of the image to be copied to SRAM.
- * @param  img_dst  The address at which the image needs to be copied to
- *                  SRAM.
- * @param  img_sz   The size of the image that needs to be copied to SRAM.
- *
- * @return          0 on success; nonzero on failure.
- */
-static int
-boot_copy_image_to_sram(struct boot_loader_state *state, int slot,
-                        uint32_t img_dst, uint32_t img_sz)
-{
-    int rc;
-    const struct flash_area *fap_src = NULL;
-    int area_id;
-
-#if (BOOT_IMAGE_NUMBER == 1)
-    (void)state;
-#endif
-
-    area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
-
-    rc = flash_area_open(area_id, &fap_src);
-    if (rc != 0) {
-        return BOOT_EFLASH;
-    }
-
-    /* Direct copy from flash to its new location in SRAM. */
-    rc = flash_area_read(fap_src, 0, (void *)(IMAGE_RAM_BASE + img_dst), img_sz);
-    if (rc != 0) {
-        BOOT_LOG_INF("Error whilst copying image %d from Flash to SRAM: %d",
-                     BOOT_CURR_IMG(state), rc);
-    }
-
-    flash_area_close(fap_src);
-
-    return rc;
-}
-
-#if (BOOT_IMAGE_NUMBER > 1)
-/**
- * Checks if two memory regions (A and B) are overlap or not.
- *
- * @param  start_a  Start of the A region.
- * @param  end_a    End of the A region.
- * @param  start_b  Start of the B region.
- * @param  end_b    End of the B region.
- *
- * @return          true if there is overlap; false otherwise.
- */
-static bool
-do_regions_overlap(uint32_t start_a, uint32_t end_a,
-                   uint32_t start_b, uint32_t end_b)
-{
-    if (start_b > end_a) {
-        return false;
-    } else if (start_b >= start_a) {
-        return true;
-    } else if (end_b > start_a) {
-        return true;
-    }
-
-    return false;
-}
-
-/**
- * Checks if the image we want to load to memory overlap with an already
- * ramloaded image.
- *
- * @param  state    Boot loader status information.
- *
- * @return                    0 if there is no overlap; nonzero otherwise.
- */
-static int
-boot_check_ram_load_overlapping(struct boot_loader_state *state)
-{
-    uint32_t i;
-
-    uint32_t start_a;
-    uint32_t end_a;
-    uint32_t start_b;
-    uint32_t end_b;
-    uint32_t image_id_to_check = BOOT_CURR_IMG(state);
-
-    start_a = state->slot_usage[image_id_to_check].img_dst;
-    /* Safe to add here, values are already verified in
-     * boot_verify_ram_load_address() */
-    end_a = start_a + state->slot_usage[image_id_to_check].img_sz;
-
-    for (i = 0; i < BOOT_IMAGE_NUMBER; i++) {
-        if (state->slot_usage[i].active_slot == NO_ACTIVE_SLOT
-            || i == image_id_to_check) {
-            continue;
-        }
-
-        start_b = state->slot_usage[i].img_dst;
-        /* Safe to add here, values are already verified in
-         * boot_verify_ram_load_address() */
-        end_b = start_b + state->slot_usage[i].img_sz;
-
-        if (do_regions_overlap(start_a, end_a, start_b, end_b)) {
-            return -1;
-        }
-    }
-
-    return 0;
-}
-#endif
-
-/**
- * Loads the active slot of the current image into SRAM. The load address and
- * image size is extracted from the image header.
- *
- * @param  state        Boot loader status information.
- *
- * @return              0 on success; nonzero on failure.
- */
-static int
-boot_load_image_to_sram(struct boot_loader_state *state)
-{
-    uint32_t active_slot;
-    struct image_header *hdr = NULL;
-    uint32_t img_dst;
-    uint32_t img_sz;
-    int rc;
-
-    active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot;
-    hdr = boot_img_hdr(state, active_slot);
-
-    if (hdr->ih_flags & IMAGE_F_RAM_LOAD) {
-
-        img_dst = hdr->ih_load_addr;
-
-        rc = boot_read_image_size(state, active_slot, &img_sz);
-        if (rc != 0) {
-            return rc;
-        }
-
-        state->slot_usage[BOOT_CURR_IMG(state)].img_dst = img_dst;
-        state->slot_usage[BOOT_CURR_IMG(state)].img_sz = img_sz;
-
-        rc = boot_verify_ram_load_address(state);
-        if (rc != 0) {
-            BOOT_LOG_INF("Image %d RAM load address 0x%x is invalid.", BOOT_CURR_IMG(state), img_dst);
-            return rc;
-        }
-
-#if (BOOT_IMAGE_NUMBER > 1)
-        rc = boot_check_ram_load_overlapping(state);
-        if (rc != 0) {
-            BOOT_LOG_INF("Image %d RAM loading to address 0x%x would overlap with\
-                         another image.", BOOT_CURR_IMG(state), img_dst);
-            return rc;
-        }
-#endif
-#ifdef MCUBOOT_ENC_IMAGES
-        /* decrypt image if encrypted and copy it to RAM */
-        if (IS_ENCRYPTED(hdr)) {
-            rc = boot_decrypt_and_copy_image_to_sram(state, active_slot, hdr, img_sz, img_dst);
-        } else {
-            rc = boot_copy_image_to_sram(state, active_slot, img_dst, img_sz);
-        }
-#else
-        /* Copy image to the load address from where it currently resides in
-         * flash.
-         */
-        rc = boot_copy_image_to_sram(state, active_slot, img_dst, img_sz);
-#endif
-        if (rc != 0) {
-            BOOT_LOG_INF("Image %d RAM loading to 0x%x is failed.", BOOT_CURR_IMG(state), img_dst);
-        } else {
-            BOOT_LOG_INF("Image %d RAM loading to 0x%x is succeeded.", BOOT_CURR_IMG(state), img_dst);
-        }
-    } else {
-        /* Only images that support IMAGE_F_RAM_LOAD are allowed if
-         * MCUBOOT_RAM_LOAD is set.
-         */
-        rc = BOOT_EBADIMAGE;
-    }
-
-    if (rc != 0) {
-        state->slot_usage[BOOT_CURR_IMG(state)].img_dst = 0;
-        state->slot_usage[BOOT_CURR_IMG(state)].img_sz = 0;
-    }
-
-    return rc;
-}
-
-/**
- * Removes an image from SRAM, by overwriting it with zeros.
- *
- * @param  state        Boot loader status information.
- *
- * @return              0 on success; nonzero on failure.
- */
-static inline int
-boot_remove_image_from_sram(struct boot_loader_state *state)
-{
-    (void)state;
-
-    BOOT_LOG_INF("Removing image %d from SRAM at address 0x%x",
-                 BOOT_CURR_IMG(state),
-                 state->slot_usage[BOOT_CURR_IMG(state)].img_dst);
-
-    memset((void*)(IMAGE_RAM_BASE + state->slot_usage[BOOT_CURR_IMG(state)].img_dst),
-           0, state->slot_usage[BOOT_CURR_IMG(state)].img_sz);
-
-    state->slot_usage[BOOT_CURR_IMG(state)].img_dst = 0;
-    state->slot_usage[BOOT_CURR_IMG(state)].img_sz = 0;
-
-    return 0;
-}
-
-/**
- * Removes an image from flash by erasing the corresponding flash area
- *
- * @param  state    Boot loader status information.
- * @param  slot     The flash slot of the image to be erased.
- *
- * @return          0 on success; nonzero on failure.
- */
-static inline int
-boot_remove_image_from_flash(struct boot_loader_state *state, uint32_t slot)
-{
-    int area_id;
-    int rc;
-    const struct flash_area *fap;
-
-    (void)state;
-
-    BOOT_LOG_INF("Removing image %d slot %d from flash", BOOT_CURR_IMG(state),
-                                                         slot);
-    area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
-    rc = flash_area_open(area_id, &fap);
-    if (rc == 0) {
-        flash_area_erase(fap, 0, flash_area_get_size(fap));
-        flash_area_close(fap);
-    }
-
-    return rc;
-}
-#endif /* MCUBOOT_RAM_LOAD */
-
-
 /**
  * Tries to load a slot for all the images with validation.
  *
diff --git a/boot/bootutil/src/ram_load.c b/boot/bootutil/src/ram_load.c
new file mode 100644
index 0000000..7225536
--- /dev/null
+++ b/boot/bootutil/src/ram_load.c
@@ -0,0 +1,440 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Copyright (c) 2016-2020 Linaro LTD
+ * Copyright (c) 2016-2019 JUUL Labs
+ * Copyright (c) 2019-2023 Arm Limited
+ * Copyright (c) 2024 Nordic Semiconductor ASA
+ *
+ * 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 "bootutil/bootutil.h"
+#include "bootutil/bootutil_log.h"
+#include "bootutil/bootutil_public.h"
+#include "bootutil/image.h"
+#include "bootutil_priv.h"
+#include "bootutil/fault_injection_hardening.h"
+#include "bootutil/ramload.h"
+#include "bootutil/mcuboot_status.h"
+
+#ifdef MCUBOOT_ENC_IMAGES
+#include "bootutil/enc_key.h"
+#endif
+
+#include "mcuboot_config/mcuboot_config.h"
+
+BOOT_LOG_MODULE_DECLARE(mcuboot);
+
+#ifndef MULTIPLE_EXECUTABLE_RAM_REGIONS
+#if !defined(IMAGE_EXECUTABLE_RAM_START) || !defined(IMAGE_EXECUTABLE_RAM_SIZE)
+#error "Platform MUST define executable RAM bounds in case of RAM_LOAD"
+#endif
+#endif
+
+/**
+ * Verifies that the active slot of the current image can be loaded within the
+ * predefined bounds that are allowed to be used by executable images.
+ *
+ * @param  state        Boot loader status information.
+ *
+ * @return              0 on success; nonzero on failure.
+ */
+static int
+boot_verify_ram_load_address(struct boot_loader_state *state)
+{
+    uint32_t img_dst;
+    uint32_t img_sz;
+    uint32_t img_end_addr;
+    uint32_t exec_ram_start;
+    uint32_t exec_ram_size;
+
+    (void)state;
+
+#ifdef MULTIPLE_EXECUTABLE_RAM_REGIONS
+    int      rc;
+
+    rc = boot_get_image_exec_ram_info(BOOT_CURR_IMG(state), &exec_ram_start,
+                                      &exec_ram_size);
+    if (rc != 0) {
+        return BOOT_EBADSTATUS;
+    }
+#else
+    exec_ram_start = IMAGE_EXECUTABLE_RAM_START;
+    exec_ram_size = IMAGE_EXECUTABLE_RAM_SIZE;
+#endif
+
+    img_dst = state->slot_usage[BOOT_CURR_IMG(state)].img_dst;
+    img_sz = state->slot_usage[BOOT_CURR_IMG(state)].img_sz;
+
+    if (img_dst < exec_ram_start) {
+        return BOOT_EBADIMAGE;
+    }
+
+    if (!boot_u32_safe_add(&img_end_addr, img_dst, img_sz)) {
+        return BOOT_EBADIMAGE;
+    }
+
+    if (img_end_addr > (exec_ram_start + exec_ram_size)) {
+        return BOOT_EBADIMAGE;
+    }
+
+    return 0;
+}
+
+#ifdef MCUBOOT_ENC_IMAGES
+
+/**
+ * Copies and decrypts an image from a slot in the flash to an SRAM address.
+ *
+ * @param  state    Boot loader status information.
+ * @param  slot     The flash slot of the image to be copied to SRAM.
+ * @param  hdr      The image header.
+ * @param  src_sz   Size of the image.
+ * @param  img_dst  Pointer to the address at which the image needs to be
+ *                  copied to SRAM.
+ *
+ * @return          0 on success; nonzero on failure.
+ */
+static int
+boot_decrypt_and_copy_image_to_sram(struct boot_loader_state *state,
+                                    uint32_t slot, struct image_header *hdr,
+                                    uint32_t src_sz, uint32_t img_dst)
+{
+    /* The flow for the decryption and copy of the image is as follows :
+     * 1. The whole image is copied to the RAM (header + payload + TLV).
+     * 2. The encryption key is loaded from the TLV in flash.
+     * 3. The image is then decrypted chunk by chunk in RAM (1 chunk
+     * is 1024 bytes). Only the payload section is decrypted.
+     * 4. The image is authenticated in RAM.
+     */
+    const struct flash_area *fap_src = NULL;
+    struct boot_status bs;
+    uint32_t blk_off;
+    uint32_t tlv_off;
+    uint32_t blk_sz;
+    uint32_t bytes_copied = hdr->ih_hdr_size;
+    uint32_t chunk_sz;
+    uint32_t max_sz = 1024;
+    uint16_t idx;
+    uint8_t * cur_dst;
+    int area_id;
+    int rc;
+    uint8_t * ram_dst = (void *)(IMAGE_RAM_BASE + img_dst);
+
+    area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
+    rc = flash_area_open(area_id, &fap_src);
+    if (rc != 0){
+        return BOOT_EFLASH;
+    }
+
+    tlv_off = BOOT_TLV_OFF(hdr);
+
+    /* Copying the whole image in RAM */
+    rc = flash_area_read(fap_src, 0, ram_dst, src_sz);
+    if (rc != 0) {
+        goto done;
+    }
+
+    rc = boot_enc_load(BOOT_CURR_ENC(state), slot, hdr, fap_src, &bs);
+    if (rc < 0) {
+        goto done;
+    }
+
+    /* if rc > 0 then the key has already been loaded */
+    if (rc == 0 && boot_enc_set_key(BOOT_CURR_ENC(state), slot, &bs)) {
+        goto done;
+    }
+
+    /* Starting at the end of the header as the header section is not encrypted */
+    while (bytes_copied < tlv_off) { /* TLV section copied previously */
+        if (src_sz - bytes_copied > max_sz) {
+            chunk_sz = max_sz;
+        } else {
+            chunk_sz = src_sz - bytes_copied;
+        }
+
+        cur_dst = ram_dst + bytes_copied;
+        blk_sz = chunk_sz;
+        idx = 0;
+        blk_off = ((bytes_copied) - hdr->ih_hdr_size) & 0xf;
+        if (bytes_copied + chunk_sz > tlv_off) {
+            /* Going over TLV section
+             * Part of the chunk is encrypted payload */
+            blk_sz = tlv_off - (bytes_copied);
+        }
+        boot_enc_decrypt(BOOT_CURR_ENC(state), slot,
+                (bytes_copied + idx) - hdr->ih_hdr_size, blk_sz,
+                blk_off, cur_dst);
+        bytes_copied += chunk_sz;
+    }
+    rc = 0;
+
+done:
+    flash_area_close(fap_src);
+
+    return rc;
+}
+
+#endif /* MCUBOOT_ENC_IMAGES */
+/**
+ * Copies a slot of the current image into SRAM.
+ *
+ * @param  state    Boot loader status information.
+ * @param  slot     The flash slot of the image to be copied to SRAM.
+ * @param  img_dst  The address at which the image needs to be copied to
+ *                  SRAM.
+ * @param  img_sz   The size of the image that needs to be copied to SRAM.
+ *
+ * @return          0 on success; nonzero on failure.
+ */
+static int
+boot_copy_image_to_sram(struct boot_loader_state *state, int slot,
+                        uint32_t img_dst, uint32_t img_sz)
+{
+    int rc;
+    const struct flash_area *fap_src = NULL;
+    int area_id;
+
+#if (BOOT_IMAGE_NUMBER == 1)
+    (void)state;
+#endif
+
+    area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
+
+    rc = flash_area_open(area_id, &fap_src);
+    if (rc != 0) {
+        return BOOT_EFLASH;
+    }
+
+    /* Direct copy from flash to its new location in SRAM. */
+    rc = flash_area_read(fap_src, 0, (void *)(IMAGE_RAM_BASE + img_dst), img_sz);
+    if (rc != 0) {
+        BOOT_LOG_INF("Error whilst copying image %d from Flash to SRAM: %d",
+                     BOOT_CURR_IMG(state), rc);
+    }
+
+    flash_area_close(fap_src);
+
+    return rc;
+}
+
+#if (BOOT_IMAGE_NUMBER > 1)
+/**
+ * Checks if two memory regions (A and B) are overlap or not.
+ *
+ * @param  start_a  Start of the A region.
+ * @param  end_a    End of the A region.
+ * @param  start_b  Start of the B region.
+ * @param  end_b    End of the B region.
+ *
+ * @return          true if there is overlap; false otherwise.
+ */
+static bool
+do_regions_overlap(uint32_t start_a, uint32_t end_a,
+                   uint32_t start_b, uint32_t end_b)
+{
+    if (start_b > end_a) {
+        return false;
+    } else if (start_b >= start_a) {
+        return true;
+    } else if (end_b > start_a) {
+        return true;
+    }
+
+    return false;
+}
+
+/**
+ * Checks if the image we want to load to memory overlap with an already
+ * ramloaded image.
+ *
+ * @param  state    Boot loader status information.
+ *
+ * @return                    0 if there is no overlap; nonzero otherwise.
+ */
+static int
+boot_check_ram_load_overlapping(struct boot_loader_state *state)
+{
+    uint32_t i;
+
+    uint32_t start_a;
+    uint32_t end_a;
+    uint32_t start_b;
+    uint32_t end_b;
+    uint32_t image_id_to_check = BOOT_CURR_IMG(state);
+
+    start_a = state->slot_usage[image_id_to_check].img_dst;
+    /* Safe to add here, values are already verified in
+     * boot_verify_ram_load_address() */
+    end_a = start_a + state->slot_usage[image_id_to_check].img_sz;
+
+    for (i = 0; i < BOOT_IMAGE_NUMBER; i++) {
+        if (state->slot_usage[i].active_slot == NO_ACTIVE_SLOT
+            || i == image_id_to_check) {
+            continue;
+        }
+
+        start_b = state->slot_usage[i].img_dst;
+        /* Safe to add here, values are already verified in
+         * boot_verify_ram_load_address() */
+        end_b = start_b + state->slot_usage[i].img_sz;
+
+        if (do_regions_overlap(start_a, end_a, start_b, end_b)) {
+            return -1;
+        }
+    }
+
+    return 0;
+}
+#endif
+
+/**
+ * Loads the active slot of the current image into SRAM. The load address and
+ * image size is extracted from the image header.
+ *
+ * @param  state        Boot loader status information.
+ *
+ * @return              0 on success; nonzero on failure.
+ */
+int
+boot_load_image_to_sram(struct boot_loader_state *state)
+{
+    uint32_t active_slot;
+    struct image_header *hdr = NULL;
+    uint32_t img_dst;
+    uint32_t img_sz;
+    int rc;
+
+    active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot;
+    hdr = boot_img_hdr(state, active_slot);
+
+    if (hdr->ih_flags & IMAGE_F_RAM_LOAD) {
+
+        img_dst = hdr->ih_load_addr;
+
+        rc = boot_read_image_size(state, active_slot, &img_sz);
+        if (rc != 0) {
+            return rc;
+        }
+
+        state->slot_usage[BOOT_CURR_IMG(state)].img_dst = img_dst;
+        state->slot_usage[BOOT_CURR_IMG(state)].img_sz = img_sz;
+
+        rc = boot_verify_ram_load_address(state);
+        if (rc != 0) {
+            BOOT_LOG_INF("Image %d RAM load address 0x%x is invalid.", BOOT_CURR_IMG(state), img_dst);
+            return rc;
+        }
+
+#if (BOOT_IMAGE_NUMBER > 1)
+        rc = boot_check_ram_load_overlapping(state);
+        if (rc != 0) {
+            BOOT_LOG_INF("Image %d RAM loading to address 0x%x would overlap with\
+                         another image.", BOOT_CURR_IMG(state), img_dst);
+            return rc;
+        }
+#endif
+#ifdef MCUBOOT_ENC_IMAGES
+        /* decrypt image if encrypted and copy it to RAM */
+        if (IS_ENCRYPTED(hdr)) {
+            rc = boot_decrypt_and_copy_image_to_sram(state, active_slot, hdr, img_sz, img_dst);
+        } else {
+            rc = boot_copy_image_to_sram(state, active_slot, img_dst, img_sz);
+        }
+#else
+        /* Copy image to the load address from where it currently resides in
+         * flash.
+         */
+        rc = boot_copy_image_to_sram(state, active_slot, img_dst, img_sz);
+#endif
+        if (rc != 0) {
+            BOOT_LOG_INF("Image %d RAM loading to 0x%x is failed.", BOOT_CURR_IMG(state), img_dst);
+        } else {
+            BOOT_LOG_INF("Image %d RAM loading to 0x%x is succeeded.", BOOT_CURR_IMG(state), img_dst);
+        }
+    } else {
+        /* Only images that support IMAGE_F_RAM_LOAD are allowed if
+         * MCUBOOT_RAM_LOAD is set.
+         */
+        rc = BOOT_EBADIMAGE;
+    }
+
+    if (rc != 0) {
+        state->slot_usage[BOOT_CURR_IMG(state)].img_dst = 0;
+        state->slot_usage[BOOT_CURR_IMG(state)].img_sz = 0;
+    }
+
+    return rc;
+}
+
+/**
+ * Removes an image from SRAM, by overwriting it with zeros.
+ *
+ * @param  state        Boot loader status information.
+ *
+ * @return              0 on success; nonzero on failure.
+ */
+int
+boot_remove_image_from_sram(struct boot_loader_state *state)
+{
+    (void)state;
+
+    BOOT_LOG_INF("Removing image %d from SRAM at address 0x%x",
+                 BOOT_CURR_IMG(state),
+                 state->slot_usage[BOOT_CURR_IMG(state)].img_dst);
+
+    memset((void*)(IMAGE_RAM_BASE + state->slot_usage[BOOT_CURR_IMG(state)].img_dst),
+           0, state->slot_usage[BOOT_CURR_IMG(state)].img_sz);
+
+    state->slot_usage[BOOT_CURR_IMG(state)].img_dst = 0;
+    state->slot_usage[BOOT_CURR_IMG(state)].img_sz = 0;
+
+    return 0;
+}
+
+/**
+ * Removes an image from flash by erasing the corresponding flash area
+ *
+ * @param  state    Boot loader status information.
+ * @param  slot     The flash slot of the image to be erased.
+ *
+ * @return          0 on success; nonzero on failure.
+ */
+int
+boot_remove_image_from_flash(struct boot_loader_state *state, uint32_t slot)
+{
+    int area_id;
+    int rc;
+    const struct flash_area *fap;
+
+    (void)state;
+
+    BOOT_LOG_INF("Removing image %d slot %d from flash", BOOT_CURR_IMG(state),
+                                                         slot);
+    area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
+    rc = flash_area_open(area_id, &fap);
+    if (rc == 0) {
+        flash_area_erase(fap, 0, flash_area_get_size(fap));
+        flash_area_close(fap);
+    }
+
+    return rc;
+}
diff --git a/boot/espressif/CMakeLists.txt b/boot/espressif/CMakeLists.txt
index bc703fc..d1e18d2 100644
--- a/boot/espressif/CMakeLists.txt
+++ b/boot/espressif/CMakeLists.txt
@@ -231,6 +231,12 @@
     ${BOOTUTIL_DIR}/src/swap_scratch.c
     ${BOOTUTIL_DIR}/src/tlv.c
     )
+
+if(CONFIG_BOOT_RAM_LOAD)
+    list(APPEND bootutil_srcs
+        ${BOOTUTIL_DIR}/src/ram_load.c
+        )
+endif()
 set(bootutil_paths)
 
 set(CFLAGS
diff --git a/boot/espressif/hal/include/mcuboot_config/mcuboot_config.h b/boot/espressif/hal/include/mcuboot_config/mcuboot_config.h
index a7058e7..a299e3c 100644
--- a/boot/espressif/hal/include/mcuboot_config/mcuboot_config.h
+++ b/boot/espressif/hal/include/mcuboot_config/mcuboot_config.h
@@ -57,8 +57,10 @@
 /* Uncomment to enable the direct-xip code path. */
 /* #define MCUBOOT_DIRECT_XIP */
 
-/* Uncomment to enable the ram-load code path. */
-/* #define MCUBOOT_RAM_LOAD */
+/* Define to enable the ram-load code path. */
+#if defined(CONFIG_BOOT_RAM_LOAD)
+#define MCUBOOT_RAM_LOAD
+#endif
 
 /*
  * Cryptographic settings
diff --git a/boot/mynewt/pkg.yml b/boot/mynewt/pkg.yml
index e0b3132..9645a5e 100644
--- a/boot/mynewt/pkg.yml
+++ b/boot/mynewt/pkg.yml
@@ -39,6 +39,8 @@
     - "single_loader.c"
 pkg.ign_files.BOOTUTIL_SINGLE_APPLICATION_SLOT:
     - "swap_scratch.c"
+pkg.ign_files:
+    - "ram_load.c"
 
 pkg.deps.BOOTUTIL_NO_LOGGING:
     - "@apache-mynewt-core/sys/console/stub"
diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt
index 144dabd..ba62d2b 100644
--- a/boot/zephyr/CMakeLists.txt
+++ b/boot/zephyr/CMakeLists.txt
@@ -143,6 +143,12 @@
   )
 endif()
 
+if(CONFIG_BOOT_RAM_LOAD)
+  zephyr_library_sources(
+    ${BOOT_DIR}/bootutil/src/ram_load.c
+    )
+endif()
+
 if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256)
   zephyr_library_include_directories(
     ${MBEDTLS_ASN1_DIR}/include
diff --git a/sim/mcuboot-sys/build.rs b/sim/mcuboot-sys/build.rs
index ea17d80..47ee880 100644
--- a/sim/mcuboot-sys/build.rs
+++ b/sim/mcuboot-sys/build.rs
@@ -455,6 +455,9 @@
     }
 
     conf.file("../../boot/bootutil/src/loader.c");
+    if ram_load {
+        conf.file("../../boot/bootutil/src/ram_load.c");
+    }
     conf.file("../../boot/bootutil/src/swap_misc.c");
     conf.file("../../boot/bootutil/src/swap_scratch.c");
     conf.file("../../boot/bootutil/src/swap_move.c");