1 /*
2 * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <string.h>
8
9 #include <bootutil/bootutil_log.h>
10 #include <bootutil/fault_injection_hardening.h>
11
12 #include "bootloader_memory_utils.h"
13 #include "bootloader_flash_priv.h"
14 #include "esp_flash_encrypt.h"
15
16 #include "rom/uart.h"
17
18 #include "esp_mcuboot_image.h"
19 #include "esp_loader.h"
20 #include "flash_map_backend/flash_map_backend.h"
21
22 #ifdef CONFIG_ESP_MULTI_PROCESSOR_BOOT
23 #include "app_cpu_start.h"
24 #endif
25
26 #include "esp_rom_sys.h"
27 #include "esp_cpu.h"
28
29 #if CONFIG_IDF_TARGET_ESP32
30 #define LP_RTC_PREFIX "RTC"
31 #elif CONFIG_IDF_TARGET_ESP32S2
32 #define LP_RTC_PREFIX "RTC"
33 #elif CONFIG_IDF_TARGET_ESP32S3
34 #define LP_RTC_PREFIX "RTC"
35 #elif CONFIG_IDF_TARGET_ESP32C2
36 #elif CONFIG_IDF_TARGET_ESP32C3
37 #define LP_RTC_PREFIX "RTC"
38 #elif CONFIG_IDF_TARGET_ESP32C6
39 #define LP_RTC_PREFIX "LP"
40 #elif CONFIG_IDF_TARGET_ESP32H2
41 #define LP_RTC_PREFIX "LP"
42 #endif
43
load_segment(const struct flash_area * fap,uint32_t data_addr,uint32_t data_len,uint32_t load_addr)44 static int load_segment(const struct flash_area *fap, uint32_t data_addr, uint32_t data_len, uint32_t load_addr)
45 {
46 const uint32_t *data = (const uint32_t *)bootloader_mmap((fap->fa_off + data_addr), data_len);
47 if (!data) {
48 BOOT_LOG_ERR("%s: Bootloader mmap failed", __func__);
49 return -1;
50 }
51 memcpy((void *)load_addr, data, data_len);
52 bootloader_munmap(data);
53 return 0;
54 }
55
esp_app_image_load(int image_index,int slot,unsigned int hdr_offset,unsigned int * entry_addr)56 void esp_app_image_load(int image_index, int slot, unsigned int hdr_offset, unsigned int *entry_addr)
57 {
58 const struct flash_area *fap;
59 int area_id;
60 int rc;
61
62 area_id = flash_area_id_from_multi_image_slot(image_index, slot);
63 rc = flash_area_open(area_id, &fap);
64 if (rc != 0) {
65 BOOT_LOG_ERR("%s: flash_area_open failed with %d", __func__, rc);
66 }
67
68 BOOT_LOG_INF("Loading image %d - slot %d from flash, area id: %d", image_index, slot, area_id);
69
70 const uint32_t *data = (const uint32_t *)bootloader_mmap((fap->fa_off + hdr_offset), sizeof(esp_image_load_header_t));
71 esp_image_load_header_t load_header = {0};
72 memcpy((void *)&load_header, data, sizeof(esp_image_load_header_t));
73 bootloader_munmap(data);
74
75 if (load_header.header_magic != ESP_LOAD_HEADER_MAGIC) {
76 BOOT_LOG_ERR("Load header magic verification failed. Aborting");
77 FIH_PANIC;
78 }
79
80 if (!esp_ptr_in_iram((void *)load_header.iram_dest_addr) || !esp_ptr_in_iram((void *)(load_header.iram_dest_addr + load_header.iram_size))) {
81 BOOT_LOG_ERR("IRAM region in load header is not valid. Aborting");
82 FIH_PANIC;
83 }
84
85 if (!esp_ptr_in_dram((void *)load_header.dram_dest_addr) || !esp_ptr_in_dram((void *)(load_header.dram_dest_addr + load_header.dram_size))) {
86 BOOT_LOG_ERR("DRAM region in load header is not valid. Aborting");
87 FIH_PANIC;
88 }
89
90 #if SOC_RTC_FAST_MEM_SUPPORTED
91 if (load_header.lp_rtc_iram_size > 0) {
92 if (!esp_ptr_in_rtc_iram_fast((void *)load_header.lp_rtc_iram_dest_addr) ||
93 !esp_ptr_in_rtc_iram_fast((void *)(load_header.lp_rtc_iram_dest_addr + load_header.lp_rtc_iram_size))) {
94 BOOT_LOG_ERR("%s_IRAM region in load header is not valid. Aborting", LP_RTC_PREFIX);
95 FIH_PANIC;
96 }
97 }
98 #endif
99
100 #if SOC_RTC_SLOW_MEM_SUPPORTED
101 if (load_header.lp_rtc_dram_size > 0) {
102 if (!esp_ptr_in_rtc_slow((void *)load_header.lp_rtc_dram_dest_addr) ||
103 !esp_ptr_in_rtc_slow((void *)(load_header.lp_rtc_dram_dest_addr + load_header.lp_rtc_dram_size))) {
104 BOOT_LOG_ERR("%s_RAM region in load header is not valid. Aborting %p", LP_RTC_PREFIX, load_header.lp_rtc_dram_dest_addr);
105 FIH_PANIC;
106 }
107 }
108 #endif
109
110 if (!esp_ptr_in_iram((void *)load_header.entry_addr)) {
111 BOOT_LOG_ERR("Application entry point (0x%x) is not in IRAM. Aborting", load_header.entry_addr);
112 FIH_PANIC;
113 }
114
115 BOOT_LOG_INF("DRAM segment: start=0x%x, size=0x%x, vaddr=0x%x", fap->fa_off + load_header.dram_flash_offset, load_header.dram_size, load_header.dram_dest_addr);
116 load_segment(fap, load_header.dram_flash_offset, load_header.dram_size, load_header.dram_dest_addr);
117
118 BOOT_LOG_INF("IRAM segment: start=0x%x, size=0x%x, vaddr=0x%x", fap->fa_off + load_header.iram_flash_offset, load_header.iram_size, load_header.iram_dest_addr);
119 load_segment(fap, load_header.iram_flash_offset, load_header.iram_size, load_header.iram_dest_addr);
120
121 #if SOC_RTC_FAST_MEM_SUPPORTED || SOC_RTC_SLOW_MEM_SUPPORTED
122 if (load_header.lp_rtc_dram_size > 0) {
123 soc_reset_reason_t reset_reason = esp_rom_get_reset_reason(0);
124
125 /* Unless waking from deep sleep (implying RTC memory is intact), load its segments */
126 if (reset_reason != RESET_REASON_CORE_DEEP_SLEEP) {
127 BOOT_LOG_INF("%s_RAM segment: paddr=%08xh, vaddr=%08xh, size=%05xh (%6d) load", LP_RTC_PREFIX,
128 (fap->fa_off + load_header.lp_rtc_dram_flash_offset), load_header.lp_rtc_dram_dest_addr,
129 load_header.lp_rtc_dram_size, load_header.lp_rtc_dram_size);
130 load_segment(fap, load_header.lp_rtc_dram_flash_offset,
131 load_header.lp_rtc_dram_size, load_header.lp_rtc_dram_dest_addr);
132 } else {
133 BOOT_LOG_INF("%s_RAM segment: paddr=%08xh, vaddr=%08xh, size=%05xh (%6d) noload", LP_RTC_PREFIX,
134 load_header.lp_rtc_dram_flash_offset, load_header.lp_rtc_dram_dest_addr,
135 load_header.lp_rtc_dram_size, load_header.lp_rtc_dram_size);
136 }
137 }
138
139 if (load_header.lp_rtc_iram_size > 0) {
140 BOOT_LOG_INF("%s_IRAM segment: paddr=%08xh, vaddr=%08xh, size=%05xh (%6d) load", LP_RTC_PREFIX,
141 (fap->fa_off + load_header.lp_rtc_iram_flash_offset), load_header.lp_rtc_iram_dest_addr,
142 load_header.lp_rtc_iram_size, load_header.lp_rtc_iram_size);
143 load_segment(fap, load_header.lp_rtc_iram_flash_offset,
144 load_header.lp_rtc_iram_size, load_header.lp_rtc_iram_dest_addr);
145 }
146 #endif
147
148 BOOT_LOG_INF("start=0x%x", load_header.entry_addr);
149 uart_tx_wait_idle(0);
150
151 assert(entry_addr != NULL);
152 *entry_addr = load_header.entry_addr;
153 }
154
start_cpu0_image(int image_index,int slot,unsigned int hdr_offset)155 void start_cpu0_image(int image_index, int slot, unsigned int hdr_offset)
156 {
157 unsigned int entry_addr;
158 esp_app_image_load(image_index, slot, hdr_offset, &entry_addr);
159 ((void (*)(void))entry_addr)(); /* Call to application entry address should not return */
160 FIH_PANIC; /* It should not get here */
161 }
162
163 #ifdef CONFIG_ESP_MULTI_PROCESSOR_BOOT
start_cpu1_image(int image_index,int slot,unsigned int hdr_offset)164 void start_cpu1_image(int image_index, int slot, unsigned int hdr_offset)
165 {
166 unsigned int entry_addr;
167 esp_app_image_load(image_index, slot, hdr_offset, &entry_addr);
168 appcpu_start(entry_addr);
169 }
170 #endif
171