diff --git a/components/esp_wifi/Kconfig b/components/esp_wifi/Kconfig index 466389df67..6efb325d68 100644 --- a/components/esp_wifi/Kconfig +++ b/components/esp_wifi/Kconfig @@ -430,6 +430,16 @@ menu "PHY" If unsure, choose 'n'. + config ESP32_PHY_DEFAULT_INIT_IF_INVALID + bool "Reset default PHY init data if invalid" + default n + depends on ESP32_PHY_INIT_DATA_IN_PARTITION + help + If enabled, PHY init data will be restored to default if + it cannot be verified successfully to avoid endless bootloops. + + If unsure, choose 'n'. + if ESP32_PHY_INIT_DATA_IN_PARTITION config ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN bool "Support multiple PHY init data bin" diff --git a/components/esp_wifi/src/phy_init.c b/components/esp_wifi/src/phy_init.c index df9a94bbfc..e5a6213ebd 100644 --- a/components/esp_wifi/src/phy_init.c +++ b/components/esp_wifi/src/phy_init.c @@ -339,16 +339,42 @@ const esp_phy_init_data_t* esp_phy_get_init_data(void) ESP_LOGE(TAG, "failed to allocate memory for PHY init data"); return NULL; } + // read phy data from flash esp_err_t err = esp_partition_read(partition, 0, init_data_store, init_data_store_length); if (err != ESP_OK) { ESP_LOGE(TAG, "failed to read PHY data partition (0x%x)", err); + free(init_data_store); return NULL; } + // verify data if (memcmp(init_data_store, PHY_INIT_MAGIC, sizeof(phy_init_magic_pre)) != 0 || memcmp(init_data_store + init_data_store_length - sizeof(phy_init_magic_post), PHY_INIT_MAGIC, sizeof(phy_init_magic_post)) != 0) { +#ifndef CONFIG_ESP32_PHY_DEFAULT_INIT_IF_INVALID ESP_LOGE(TAG, "failed to validate PHY data partition"); return NULL; +#else + ESP_LOGE(TAG, "failed to validate PHY data partition, restoring default data into flash..."); + + memcpy(init_data_store, + PHY_INIT_MAGIC, sizeof(phy_init_magic_pre)); + memcpy(init_data_store + sizeof(phy_init_magic_pre), + &phy_init_data, sizeof(phy_init_data)); + memcpy(init_data_store + sizeof(phy_init_magic_pre) + sizeof(phy_init_data), + PHY_INIT_MAGIC, sizeof(phy_init_magic_post)); + + assert(memcmp(init_data_store, PHY_INIT_MAGIC, sizeof(phy_init_magic_pre)) == 0); + assert(memcmp(init_data_store + init_data_store_length - sizeof(phy_init_magic_post), + PHY_INIT_MAGIC, sizeof(phy_init_magic_post)) == 0); + + // write default data + err = esp_partition_write(partition, 0, init_data_store, init_data_store_length); + if (err != ESP_OK) { + ESP_LOGE(TAG, "failed to write default PHY data partition (0x%x)", err); + free(init_data_store); + return NULL; + } +#endif // CONFIG_ESP32_PHY_DEFAULT_INIT_IF_INVALID } #if CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN if ((*(init_data_store + (sizeof(phy_init_magic_pre) + PHY_SUPPORT_MULTIPLE_BIN_OFFSET)))) { @@ -751,8 +777,8 @@ static esp_err_t phy_get_multiple_init_data(const esp_partition_t* partition, err = phy_find_bin_data_according_type(init_data_store, init_data_control_info, init_data_multiple, init_data_type); if (err != ESP_OK) { - ESP_LOGW(TAG, "%s has not been certified, use DEFAULT PHY init data", s_phy_type[init_data_type]); - s_phy_init_data_type = ESP_PHY_INIT_DATA_TYPE_DEFAULT; + ESP_LOGW(TAG, "%s has not been certified, use DEFAULT PHY init data", s_phy_type[init_data_type]); + s_phy_init_data_type = ESP_PHY_INIT_DATA_TYPE_DEFAULT; } else { s_phy_init_data_type = init_data_type; }