/ components / bootloader_support / src / bootloader_common.c
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  }