1 /*
2 * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdint.h>
8 #include <errno.h>
9 #include "esp_log.h"
10 #include "bootloader_flash_priv.h"
11 #include <zephyr/storage/flash_map.h>
12 #include "esp_app_format.h"
13 #include "bootloader_common.h"
14 #include "hal/efuse_ll.h"
15 #include "hal/efuse_hal.h"
16 #include "soc/chip_revision.h"
17 #include <hal/wdt_hal.h>
18 #include "soc_init.h"
19
20 #define IS_MAX_REV_SET(max_chip_rev_full) \
21 (((max_chip_rev_full) != 65535) && ((max_chip_rev_full) != 0))
22
23 static const char *TAG = "soc_init";
24
25 extern esp_image_header_t WORD_ALIGNED_ATTR bootloader_image_hdr;
26
print_banner(void)27 void print_banner(void)
28 {
29 #ifdef CONFIG_MCUBOOT
30 ESP_EARLY_LOGI(TAG, "MCUboot 2nd stage bootloader");
31 #elif CONFIG_BOOTLOADER_MCUBOOT
32 ESP_EARLY_LOGI(TAG, "MCUboot Application image");
33 #else /* CONFIG_ESP_SIMPLE_BOOT */
34 ESP_EARLY_LOGI(TAG, "ESP Simple boot");
35 #endif
36 ESP_EARLY_LOGI(TAG, "compile time " __DATE__ " " __TIME__);
37 #ifndef CONFIG_SMP
38 #if (SOC_CPU_CORES_NUM > 1)
39 ESP_EARLY_LOGW(TAG, "Unicore bootloader");
40 #endif
41 #else
42 ESP_EARLY_LOGI(TAG, "Multicore bootloader");
43 #endif
44 }
45
read_bootloader_header(void)46 int read_bootloader_header(void)
47 {
48 /* load bootloader image header */
49 if (esp_rom_flash_read(FIXED_PARTITION_OFFSET(boot_partition), &bootloader_image_hdr,
50 sizeof(esp_image_header_t), true) != 0) {
51 ESP_EARLY_LOGE(TAG, "failed to load bootloader image header!");
52 return -EIO;
53 }
54
55 return 0;
56 }
57
check_chip_validity(const esp_image_header_t * img_hdr,esp_image_type type)58 static int check_chip_validity(const esp_image_header_t *img_hdr, esp_image_type type)
59 {
60 int err = 0;
61 esp_chip_id_t chip_id = CONFIG_IDF_FIRMWARE_CHIP_ID;
62
63 if (chip_id != img_hdr->chip_id) {
64 ESP_EARLY_LOGE(TAG, "mismatch chip ID, expected %d, found %d", chip_id,
65 img_hdr->chip_id);
66 err = -EIO;
67 } else {
68 unsigned int revision = efuse_hal_chip_revision();
69 unsigned int major_rev = revision / 100;
70 unsigned int minor_rev = revision % 100;
71 unsigned int min_rev = img_hdr->min_chip_rev_full;
72
73 if (type == ESP_IMAGE_BOOTLOADER || type == ESP_IMAGE_APPLICATION) {
74 if (!ESP_CHIP_REV_ABOVE(revision, min_rev)) {
75 ESP_EARLY_LOGE(
76 TAG,
77 "Image requires chip rev >= v%d.%d, but chip is v%d.%d",
78 min_rev / 100, min_rev % 100, major_rev, minor_rev);
79 err = ESP_FAIL;
80 }
81 }
82 if (type == ESP_IMAGE_APPLICATION) {
83 unsigned int max_rev = img_hdr->max_chip_rev_full;
84
85 if ((IS_MAX_REV_SET(max_rev) && (revision > max_rev) &&
86 !efuse_ll_get_disable_wafer_version_major())) {
87 ESP_EARLY_LOGE(
88 TAG,
89 "Image requires chip rev <= v%d.%d, but chip is v%d.%d",
90 max_rev / 100, max_rev % 100, major_rev, minor_rev);
91 err = ESP_FAIL;
92 }
93 }
94 }
95
96 return err;
97 }
98
config_wdt(void)99 void config_wdt(void)
100 {
101 /*
102 * At this point, the flashboot protection of RWDT and MWDT0 will have been
103 * automatically enabled. We can disable flashboot protection as it's not
104 * needed anymore. If configured to do so, we also initialize the RWDT to
105 * protect the remainder of the bootloader process.
106 */
107 wdt_hal_context_t rwdt_ctx = RWDT_HAL_CONTEXT_DEFAULT();
108
109 wdt_hal_write_protect_disable(&rwdt_ctx);
110 wdt_hal_set_flashboot_en(&rwdt_ctx, false);
111 wdt_hal_write_protect_enable(&rwdt_ctx);
112
113 /* Disable MWDT0 flashboot protection. But only after we've enabled the RWDT first so that
114 * there's not gap in WDT protection.
115 */
116 wdt_hal_context_t mwdt_ctx = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0};
117
118 wdt_hal_write_protect_disable(&mwdt_ctx);
119 wdt_hal_set_flashboot_en(&mwdt_ctx, false);
120 wdt_hal_write_protect_enable(&mwdt_ctx);
121 }
122
check_bootloader_validity(void)123 int check_bootloader_validity(void)
124 {
125 unsigned int revision = efuse_hal_chip_revision();
126 unsigned int major = revision / 100;
127 unsigned int minor = revision % 100;
128
129 ESP_EARLY_LOGI(TAG, "chip revision: v%d.%d", major, minor);
130
131 #ifndef CONFIG_MCUBOOT
132 #if defined(CONFIG_SOC_SERIES_ESP32)
133 if (major < 3) {
134 ESP_EARLY_LOGE(TAG,
135 "You are using ESP32 chip revision (%d) that is unsupported. While "
136 "it may work, it could cause unexpected behavior or issues.",
137 major);
138 ESP_EARLY_LOGE(TAG,
139 "Proceeding with this ESP32 chip revision is not recommended unless "
140 "you fully understand the potential risk and limitations.");
141 #if !defined(CONFIG_ESP32_USE_UNSUPPORTED_REVISION)
142 ESP_EARLY_LOGE(
143 TAG,
144 "If you choose to continue, please enable "
145 "'CONFIG_ESP32_USE_UNSUPPORTED_REVISION=y' in your project configuration.");
146 config_wdt(); // disable watchdog to avoid reset
147 abort();
148 #endif /* !CONFIG_ESP32_USE_UNSUPPORTED_REVISION */
149 }
150 #endif /* CONFIG_SOC_SERIES_ESP32 */
151 #endif /* CONFIG_MCUBOOT */
152
153 /* compare with the one set in bootloader image header */
154 if (check_chip_validity(&bootloader_image_hdr, ESP_IMAGE_BOOTLOADER) != 0) {
155 return ESP_FAIL;
156 }
157 return 0;
158 }
159