1 /*
2  * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdint.h>
8 #include <string.h>
9 
10 #include <bootutil/bootutil_log.h>
11 
12 #include "sdkconfig.h"
13 #include "esp_attr.h"
14 #include "esp_image_format.h"
15 
16 #include "bootloader_init_common.h"
17 #include "bootloader_init.h"
18 #include "bootloader_mem.h"
19 #include "bootloader_console.h"
20 #include "bootloader_clock.h"
21 #include "bootloader_flash_config.h"
22 #include "bootloader_flash.h"
23 #include "bootloader_flash_priv.h"
24 
25 #include "soc/dport_reg.h"
26 #include "soc/efuse_reg.h"
27 #include "soc/rtc.h"
28 
29 #include "bootloader_wdt.h"
30 #include "hal/wdt_hal.h"
31 
32 #include "esp32/rom/cache.h"
33 #include "esp32/rom/spi_flash.h"
34 #include "esp32/rom/uart.h"
35 
36 #include <esp_rom_uart.h>
37 #include <esp_rom_gpio.h>
38 #include <esp_rom_sys.h>
39 #include <soc/uart_periph.h>
40 #include <soc/gpio_struct.h>
41 #include <hal/gpio_types.h>
42 #include <hal/gpio_ll.h>
43 #include <hal/uart_ll.h>
44 
45 extern esp_image_header_t WORD_ALIGNED_ATTR bootloader_image_hdr;
46 
47 #if CONFIG_ESP_CONSOLE_UART_CUSTOM
48 static uart_dev_t *alt_console_uart_dev =
49                (CONFIG_ESP_CONSOLE_UART_NUM == 0) ? &UART0 :
50                (CONFIG_ESP_CONSOLE_UART_NUM == 1) ? &UART1 : &UART2;
51 #endif /* CONFIG_ESP_CONSOLE_UART_CUSTOM */
52 
bootloader_common_vddsdio_configure(void)53 static void bootloader_common_vddsdio_configure(void)
54 {
55     rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config();
56     if (cfg.enable == 1 && cfg.tieh == RTC_VDDSDIO_TIEH_1_8V) {
57         /* VDDSDIO regulator is enabled @ 1.8V */
58         cfg.drefh = 3;
59         cfg.drefm = 3;
60         cfg.drefl = 3;
61         cfg.force = 1;
62         rtc_vddsdio_set_config(cfg);
63         /* wait for regulator to become stable */
64         esp_rom_delay_us(10);
65     }
66 }
67 
bootloader_reset_mmu(void)68 static void bootloader_reset_mmu(void)
69 {
70     /* completely reset MMU in case serial bootloader was running */
71     Cache_Read_Disable(0);
72 #if !CONFIG_FREERTOS_UNICORE
73     Cache_Read_Disable(1);
74 #endif
75     Cache_Flush(0);
76 #if !CONFIG_FREERTOS_UNICORE
77     Cache_Flush(1);
78 #endif
79     mmu_init(0);
80 #if !CONFIG_FREERTOS_UNICORE
81     /* The lines which manipulate DPORT_APP_CACHE_MMU_IA_CLR bit are
82      * necessary to work around a hardware bug.
83      */
84     DPORT_REG_SET_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
85     mmu_init(1);
86     DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
87 #endif
88 
89     /* normal ROM boot exits with DROM0 cache unmasked,
90      * but serial bootloader exits with it masked.
91      */
92     DPORT_REG_CLR_BIT(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MASK_DROM0);
93 #if !CONFIG_FREERTOS_UNICORE
94     DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DROM0);
95 #endif
96 }
97 
bootloader_check_rated_cpu_clock(void)98 static esp_err_t bootloader_check_rated_cpu_clock(void)
99 {
100     int rated_freq = bootloader_clock_get_rated_freq_mhz();
101     if (rated_freq < 80) {
102         BOOT_LOG_ERR("Chip CPU frequency misconfigured (%dMHz)", rated_freq);
103         return ESP_FAIL;
104     }
105     return ESP_OK;
106 }
107 
update_flash_config(const esp_image_header_t * bootloader_hdr)108 static void update_flash_config(const esp_image_header_t *bootloader_hdr)
109 {
110     uint32_t size;
111     switch (bootloader_hdr->spi_size) {
112     case ESP_IMAGE_FLASH_SIZE_1MB:
113         size = 1;
114         break;
115     case ESP_IMAGE_FLASH_SIZE_2MB:
116         size = 2;
117         break;
118     case ESP_IMAGE_FLASH_SIZE_4MB:
119         size = 4;
120         break;
121     case ESP_IMAGE_FLASH_SIZE_8MB:
122         size = 8;
123         break;
124     case ESP_IMAGE_FLASH_SIZE_16MB:
125         size = 16;
126         break;
127     default:
128         size = 2;
129     }
130     Cache_Read_Disable(0);
131     /* Set flash chip size */
132     esp_rom_spiflash_config_param(g_rom_flashchip.device_id,
133         size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff);
134 
135     Cache_Flush(0);
136     Cache_Read_Enable(0);
137 }
138 
bootloader_init_flash_configure(void)139 static void IRAM_ATTR bootloader_init_flash_configure(void)
140 {
141     bootloader_flash_clock_config(&bootloader_image_hdr);
142     bootloader_flash_gpio_config(&bootloader_image_hdr);
143     bootloader_flash_dummy_config(&bootloader_image_hdr);
144     bootloader_flash_cs_timing_config();
145 }
146 
bootloader_init_spi_flash(void)147 static esp_err_t bootloader_init_spi_flash(void)
148 {
149     bootloader_init_flash_configure();
150     esp_rom_spiflash_unlock();
151     update_flash_config(&bootloader_image_hdr);
152     bootloader_print_flash_info(&bootloader_image_hdr);
153 
154     return ESP_OK;
155 }
156 
157 #if CONFIG_ESP_CONSOLE_UART_CUSTOM
esp_rom_uart_putc(char c)158 void IRAM_ATTR esp_rom_uart_putc(char c)
159 {
160     while (uart_ll_get_txfifo_len(alt_console_uart_dev) == 0);
161     uart_ll_write_txfifo(alt_console_uart_dev, (const uint8_t *) &c, 1);
162 }
163 #endif /* CONFIG_ESP_CONSOLE_UART_CUSTOM */
164 
bootloader_init(void)165 esp_err_t bootloader_init(void)
166 {
167     esp_err_t ret = ESP_OK;
168 
169     bootloader_init_mem();
170 
171     /* check that static RAM is after the stack */
172 #ifdef NDEBUG
173     {
174         assert(&_bss_start <= &_bss_end);
175         assert(&_data_start <= &_data_end);
176         assert(sp < &_bss_start);
177         assert(sp < &_data_start);
178     }
179 #endif
180     /* bss section cleared in __esp_platform_start
181      */
182     /* boosts up vddsdio */
183     bootloader_common_vddsdio_configure();
184     /* reset MMU */
185     bootloader_reset_mmu();
186     /* check rated CPU clock */
187     if ((ret = bootloader_check_rated_cpu_clock()) != ESP_OK) {
188         goto err;
189     }
190     /* config clock */
191     bootloader_clock_configure();
192     /* initialize uart console, from now on, we can use ets_printf */
193     bootloader_console_init();
194     /* print mcuboot banner */
195     bootloader_print_banner();
196     /* read flash ID */
197     bootloader_flash_update_id();
198     /* check for XMC flash */
199     if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) {
200         BOOT_LOG_ERR("Failed when running XMC startup flow, reboot!");
201         goto err;
202     }
203     /* read bootloader header */
204     if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
205         goto err;
206     }
207     /* read chip revision and check if it's compatible to bootloader */
208     if ((ret = bootloader_check_bootloader_validity()) != ESP_OK) {
209         goto err;
210     }
211     /* initialize spi flash */
212     if ((ret = bootloader_init_spi_flash()) != ESP_OK) {
213         goto err;
214     }
215     /* config WDT */
216     bootloader_config_wdt();
217 
218 err:
219     esp_rom_uart_tx_wait_idle(0);
220     return ret;
221 }
222