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");