1 /*
2 * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <stdint.h>
7 #include <string.h>
8 #include "sdkconfig.h"
9 #include "bootloader_common.h"
10 #include "soc/efuse_reg.h"
11 #include "soc/gpio_periph.h"
12 #include "soc/gpio_sig_map.h"
13 #include "soc/io_mux_reg.h"
14
15 #include "bootloader_init.h"
16 #include "bootloader_clock.h"
17 #include "bootloader_flash_config.h"
18 #include "bootloader_mem.h"
19 #include "bootloader_console.h"
20 #include "bootloader_flash_priv.h"
21 #include "esp_private/bootloader_flash_internal.h"
22 #include "esp_rom_gpio.h"
23 #include "esp_rom_efuse.h"
24 #include "esp_rom_sys.h"
25 #include "esp_rom_spiflash.h"
26
27 #include "esp_attr.h"
28 #include "esp_log.h"
29 #include "esp_image_format.h"
30 #include "flash_qio_mode.h"
31 #include "soc/assist_debug_reg.h"
32 #include "esp_cpu.h"
33 #include "soc/dport_reg.h"
34 #include "soc/extmem_reg.h"
35 #include "soc/rtc.h"
36 #include "soc/rtc_cntl_reg.h"
37 #include "soc/spi_periph.h"
38 #include "esp_efuse.h"
39 #include "hal/mmu_hal.h"
40 #include "hal/cache_hal.h"
41 #if !defined(CONFIG_BOOTLOADER_MCUBOOT)
42 #include "esp_flash_internal.h"
43 #endif
44
45 static const char *TAG = "boot.esp32s2";
46
wdt_reset_cpu0_info_enable(void)47 static void wdt_reset_cpu0_info_enable(void)
48 {
49 DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_ASSIST_DEBUG);
50 DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_ASSIST_DEBUG);
51 REG_WRITE(ASSIST_DEBUG_PRO_PDEBUGENABLE, 1);
52 REG_WRITE(ASSIST_DEBUG_PRO_RCD_RECORDING, 1);
53 }
54
wdt_reset_info_dump(int cpu)55 static void wdt_reset_info_dump(int cpu)
56 {
57 /* FIXME: failing EDT test due to error in early log */
58 #if 0
59 uint32_t inst = 0, pid = 0, stat = 0, data = 0, pc = 0,
60 lsstat = 0, lsaddr = 0, lsdata = 0, dstat = 0;
61 const char *cpu_name = cpu ? "APP" : "PRO";
62
63 stat = 0xdeadbeef;
64 pid = 0;
65 inst = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGINST);
66 dstat = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGSTATUS);
67 data = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGDATA);
68 pc = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGPC);
69 lsstat = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGLS0STAT);
70 lsaddr = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGLS0ADDR);
71 lsdata = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGLS0DATA);
72
73 if (DPORT_RECORD_PDEBUGINST_SZ(inst) == 0 &&
74 DPORT_RECORD_PDEBUGSTATUS_BBCAUSE(dstat) == DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_WAITI) {
75 ESP_EARLY_LOGW(TAG, "WDT reset info: %s CPU PC=0x%"PRIx32" (waiti mode)", cpu_name, pc);
76 } else {
77 ESP_EARLY_LOGW(TAG, "WDT reset info: %s CPU PC=0x%"PRIx32, cpu_name, pc);
78 }
79 ESP_EARLY_LOGD(TAG, "WDT reset info: %s CPU STATUS 0x%08"PRIx32, cpu_name, stat);
80 ESP_EARLY_LOGD(TAG, "WDT reset info: %s CPU PID 0x%08"PRIx32, cpu_name, pid);
81 ESP_EARLY_LOGD(TAG, "WDT reset info: %s CPU PDEBUGINST 0x%08"PRIx32, cpu_name, inst);
82 ESP_EARLY_LOGD(TAG, "WDT reset info: %s CPU PDEBUGSTATUS 0x%08"PRIx32, cpu_name, dstat);
83 ESP_EARLY_LOGD(TAG, "WDT reset info: %s CPU PDEBUGDATA 0x%08"PRIx32, cpu_name, data);
84 ESP_EARLY_LOGD(TAG, "WDT reset info: %s CPU PDEBUGPC 0x%08"PRIx32, cpu_name, pc);
85 ESP_EARLY_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0STAT 0x%08"PRIx32, cpu_name, lsstat);
86 ESP_EARLY_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0ADDR 0x%08"PRIx32, cpu_name, lsaddr);
87 ESP_EARLY_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0DATA 0x%08"PRIx32, cpu_name, lsdata);
88 #endif
89 }
90
bootloader_check_wdt_reset(void)91 static void bootloader_check_wdt_reset(void)
92 {
93 int wdt_rst = 0;
94 soc_reset_reason_t rst_reason = esp_rom_get_reset_reason(0);
95 if (rst_reason == RESET_REASON_CORE_RTC_WDT || rst_reason == RESET_REASON_CORE_MWDT0 || rst_reason == RESET_REASON_CORE_MWDT1 ||
96 rst_reason == RESET_REASON_CPU0_MWDT0 || rst_reason == RESET_REASON_CPU0_MWDT1 || rst_reason == RESET_REASON_CPU0_RTC_WDT) {
97 // PRO CPU has been reset by WDT
98 wdt_rst = 1;
99 }
100 if (wdt_rst) {
101 // if reset by WDT dump info from trace port
102 wdt_reset_info_dump(0);
103 }
104 wdt_reset_cpu0_info_enable();
105 }
106
bootloader_super_wdt_auto_feed(void)107 static void bootloader_super_wdt_auto_feed(void)
108 {
109 REG_SET_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_AUTO_FEED_EN);
110 }
111
bootloader_init(void)112 esp_err_t bootloader_init(void)
113 {
114 esp_err_t ret = ESP_OK;
115 bootloader_super_wdt_auto_feed();
116 // protect memory region
117
118 // In RAM_APP, memory will be initialized in `call_start_cpu0`
119 #if !CONFIG_APP_BUILD_TYPE_RAM
120 bootloader_init_mem();
121
122 /* check that static RAM is after the stack */
123 #ifndef NDEBUG
124 {
125 assert(&_bss_start <= &_bss_end);
126 assert(&_data_start <= &_data_end);
127 }
128 #endif
129 #ifndef __ZEPHYR__
130 // clear bss section
131 bootloader_clear_bss_section();
132 #endif /* __ZEPHYR__ */
133 #endif // !CONFIG_APP_BUILD_TYPE_RAM
134
135 // init eFuse virtual mode (read eFuses to RAM)
136 #ifdef CONFIG_EFUSE_VIRTUAL
137 ESP_EARLY_LOGW(TAG, "eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!");
138 #ifndef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
139 esp_efuse_init_virtual_mode_in_ram();
140 #endif
141 #endif
142
143 // config clock
144 bootloader_clock_configure();
145 // initialize console, from now on, we can use esp_log
146 bootloader_console_init();
147 /* print 2nd bootloader banner */
148 bootloader_print_banner();
149
150 #ifndef CONFIG_BOOTLOADER_MCUBOOT
151 spi_flash_init_chip_state();
152 if ((ret = esp_flash_init_default_chip()) != ESP_OK) {
153 return ret;
154 }
155 #endif
156
157 #if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP
158 // init cache hal
159 cache_hal_init();
160 //init mmu
161 mmu_hal_init();
162 // Workaround: normal ROM bootloader exits with DROM0 cache unmasked, but 2nd bootloader exits with it masked.
163 REG_CLR_BIT(EXTMEM_PRO_ICACHE_CTRL1_REG, EXTMEM_PRO_ICACHE_MASK_DROM0);
164 // update flash ID
165 bootloader_flash_update_id();
166 // Check and run XMC startup flow
167 if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) {
168 ESP_EARLY_LOGE(TAG, "failed when running XMC startup flow, reboot!");
169 return ret;
170 }
171 #if !CONFIG_APP_BUILD_TYPE_RAM
172 // read bootloader header
173 if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
174 return ret;
175 }
176 // read chip revision and check if it's compatible to bootloader
177 if ((ret = bootloader_check_bootloader_validity()) != ESP_OK) {
178 return ret;
179 }
180 #endif // !CONFIG_APP_BUILD_TYPE_RAM
181 // initialize spi flash
182 if ((ret = bootloader_init_spi_flash()) != ESP_OK) {
183 return ret;
184 }
185 #endif // #if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP
186
187 // check whether a WDT reset happend
188 bootloader_check_wdt_reset();
189 // config WDT
190 bootloader_config_wdt();
191 // enable RNG early entropy source
192 bootloader_enable_random();
193
194 return ret;
195 }
196