bootloader_common.c
1 // Copyright 2018 Espressif Systems (Shanghai) PTE LTD 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 #include <stdbool.h> 15 #include <assert.h> 16 #include "string.h" 17 #include "sdkconfig.h" 18 #include "esp_err.h" 19 #include "esp_log.h" 20 #if CONFIG_IDF_TARGET_ESP32 21 #include "esp32/rom/spi_flash.h" 22 #elif CONFIG_IDF_TARGET_ESP32S2 23 #include "esp32s2/rom/spi_flash.h" 24 #elif CONFIG_IDF_TARGET_ESP32S3 25 #include "esp32s3/rom/spi_flash.h" 26 #endif 27 #include "esp_rom_crc.h" 28 #include "esp_rom_gpio.h" 29 #include "esp_rom_sys.h" 30 #include "esp_flash_partitions.h" 31 #include "bootloader_flash_priv.h" 32 #include "bootloader_common.h" 33 #include "bootloader_utility.h" 34 #include "soc/gpio_periph.h" 35 #include "soc/rtc.h" 36 #include "soc/efuse_reg.h" 37 #include "hal/gpio_ll.h" 38 #include "esp_image_format.h" 39 #include "bootloader_sha.h" 40 #include "sys/param.h" 41 42 #define ESP_PARTITION_HASH_LEN 32 /* SHA-256 digest length */ 43 44 static const char* TAG = "boot_comm"; 45 46 esp_comm_gpio_hold_t bootloader_common_check_long_hold_gpio(uint32_t num_pin, uint32_t delay_sec) 47 { 48 esp_rom_gpio_pad_select_gpio(num_pin); 49 if (GPIO_PIN_MUX_REG[num_pin]) { 50 PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[num_pin]); 51 } 52 esp_rom_gpio_pad_pullup_only(num_pin); 53 uint32_t tm_start = esp_log_early_timestamp(); 54 if (gpio_ll_get_level(&GPIO, num_pin) == 1) { 55 return GPIO_NOT_HOLD; 56 } 57 do { 58 if (gpio_ll_get_level(&GPIO, num_pin) != 0) { 59 return GPIO_SHORT_HOLD; 60 } 61 } while (delay_sec > ((esp_log_early_timestamp() - tm_start) / 1000L)); 62 return GPIO_LONG_HOLD; 63 } 64 65 // Search for a label in the list. list = "nvs1, nvs2, otadata, nvs"; label = "nvs". 66 bool bootloader_common_label_search(const char *list, char *label) 67 { 68 if (list == NULL || label == NULL) { 69 return false; 70 } 71 const char *sub_list_start_like_label = strstr(list, label); 72 while (sub_list_start_like_label != NULL) { 73 74 // ["," or " "] + label + ["," or " " or "\0"] 75 // first character before the label found there must be a delimiter ["," or " "]. 76 int idx_first = sub_list_start_like_label - list; 77 if (idx_first == 0 || (idx_first != 0 && (list[idx_first - 1] == ',' || list[idx_first - 1] == ' '))) { 78 // next character after the label found there must be a delimiter ["," or " " or "\0"]. 79 int len_label = strlen(label); 80 if (sub_list_start_like_label[len_label] == 0 || 81 sub_list_start_like_label[len_label] == ',' || 82 sub_list_start_like_label[len_label] == ' ') { 83 return true; 84 } 85 } 86 87 // [start_delim] + label + [end_delim] was not found. 88 // Position is moving to next delimiter if it is not the end of list. 89 int pos_delim = strcspn(sub_list_start_like_label, ", "); 90 if (pos_delim == strlen(sub_list_start_like_label)) { 91 break; 92 } 93 sub_list_start_like_label = strstr(&sub_list_start_like_label[pos_delim], label); 94 } 95 return false; 96 } 97 98 bool bootloader_common_erase_part_type_data(const char *list_erase, bool ota_data_erase) 99 { 100 const esp_partition_info_t *partitions; 101 const char *marker; 102 esp_err_t err; 103 int num_partitions; 104 bool ret = true; 105 106 partitions = bootloader_mmap(ESP_PARTITION_TABLE_OFFSET, ESP_PARTITION_TABLE_MAX_LEN); 107 if (!partitions) { 108 ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", ESP_PARTITION_TABLE_OFFSET, ESP_PARTITION_TABLE_MAX_LEN); 109 return false; 110 } 111 ESP_LOGD(TAG, "mapped partition table 0x%x at 0x%x", ESP_PARTITION_TABLE_OFFSET, (intptr_t)partitions); 112 113 err = esp_partition_table_verify(partitions, true, &num_partitions); 114 if (err != ESP_OK) { 115 ESP_LOGE(TAG, "Failed to verify partition table"); 116 ret = false; 117 } else { 118 ESP_LOGI(TAG, "## Label Usage Offset Length Cleaned"); 119 for (int i = 0; i < num_partitions; i++) { 120 const esp_partition_info_t *partition = &partitions[i]; 121 char label[sizeof(partition->label) + 1] = {0}; 122 if (partition->type == PART_TYPE_DATA) { 123 bool fl_ota_data_erase = false; 124 if (ota_data_erase == true && partition->subtype == PART_SUBTYPE_DATA_OTA) { 125 fl_ota_data_erase = true; 126 } 127 // partition->label is not null-terminated string. 128 strncpy(label, (char *)&partition->label, sizeof(label) - 1); 129 if (fl_ota_data_erase == true || (bootloader_common_label_search(list_erase, label) == true)) { 130 err = bootloader_flash_erase_range(partition->pos.offset, partition->pos.size); 131 if (err != ESP_OK) { 132 ret = false; 133 marker = "err"; 134 } else { 135 marker = "yes"; 136 } 137 } else { 138 marker = "no"; 139 } 140 141 ESP_LOGI(TAG, "%2d %-16s data %08x %08x [%s]", i, partition->label, 142 partition->pos.offset, partition->pos.size, marker); 143 } 144 } 145 } 146 147 bootloader_munmap(partitions); 148 149 return ret; 150 } 151 152 esp_err_t bootloader_common_get_sha256_of_partition (uint32_t address, uint32_t size, int type, uint8_t *out_sha_256) 153 { 154 if (out_sha_256 == NULL || size == 0) { 155 return ESP_ERR_INVALID_ARG; 156 } 157 158 if (type == PART_TYPE_APP) { 159 const esp_partition_pos_t partition_pos = { 160 .offset = address, 161 .size = size, 162 }; 163 esp_image_metadata_t data; 164 // Function esp_image_verify() verifies and fills the structure data. 165 // here important to get: image_digest, image_len, hash_appended. 166 if (esp_image_verify(ESP_IMAGE_VERIFY_SILENT, &partition_pos, &data) != ESP_OK) { 167 return ESP_ERR_IMAGE_INVALID; 168 } 169 if (data.image.hash_appended) { 170 memcpy(out_sha_256, data.image_digest, ESP_PARTITION_HASH_LEN); 171 return ESP_OK; 172 } 173 // If image doesn't have a appended hash then hash calculates for entire image. 174 size = data.image_len; 175 } 176 // If image is type by data then hash is calculated for entire image. 177 return bootloader_sha256_flash_contents(address, size, out_sha_256); 178 } 179 180 void bootloader_common_vddsdio_configure(void) 181 { 182 #if CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V 183 rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config(); 184 if (cfg.enable == 1 && cfg.tieh == RTC_VDDSDIO_TIEH_1_8V) { // VDDSDIO regulator is enabled @ 1.8V 185 cfg.drefh = 3; 186 cfg.drefm = 3; 187 cfg.drefl = 3; 188 cfg.force = 1; 189 rtc_vddsdio_set_config(cfg); 190 esp_rom_delay_us(10); // wait for regulator to become stable 191 } 192 #endif // CONFIG_BOOTLOADER_VDDSDIO_BOOST 193 } 194 195 196 RESET_REASON bootloader_common_get_reset_reason(int cpu_no) 197 { 198 return rtc_get_reset_reason(cpu_no); 199 }