Validate nvs partition, only allow partition-table option for OTA updates

This commit is contained in:
Mat931
2026-04-26 17:40:00 +02:00
parent 2af5c4d82c
commit e1fbb6ac5a
3 changed files with 22 additions and 12 deletions
+6 -1
View File
@@ -1078,6 +1078,11 @@ def upload_program(
port_type = get_port_type(host)
if port_type != PortType.NETWORK and getattr(args, "partition_table", False):
raise EsphomeError(
f"The option --partition-table can only be used for Over The Air updates."
)
if port_type == PortType.BOOTSEL:
exit_code = upload_using_picotool(config)
# Return None for device - BOOTSEL can't be used for logging,
@@ -1788,7 +1793,7 @@ def parse_args(argv):
)
parser_upload.add_argument(
"--partition-table",
help="Upload as partition table",
help="Upload as partition table (OTA).",
action="store_true",
)
@@ -230,8 +230,7 @@ void ESPHomeOTAComponent::handle_handshake_() {
this->extended_proto_ = this->ota_features_ & CLIENT_FEATURE_SUPPORTS_EXTENDED_PROTOCOL;
if (this->extended_proto_) {
// If the client supports the extended protocol, send 2 bytes: response type and server feature flags
this->handshake_buf_[0] =
ota::OTA_RESPONSE_FEATURE_FLAGS; // indicates the following byte contains feature flags
this->handshake_buf_[0] = ota::OTA_RESPONSE_FEATURE_FLAGS;
this->handshake_buf_[1] = SERVER_FEATURE_SUPPORTS_PARTITION_ACCESS; // supported if USE_OTA_PARTITIONS
if (supports_compression) {
this->handshake_buf_[1] |= SERVER_FEATURE_SUPPORTS_COMPRESSION;
+15 -9
View File
@@ -245,9 +245,10 @@ OTAResponseTypes IDFOTABackend::update_partition_table() {
int app_partitions_found = 0;
int new_app_part_index = -1;
int new_app_part_index_with_copy = -1;
int new_otadata_part_index = -1;
bool otadata_overlap = true;
const esp_partition_t *app_copy_target_part{nullptr};
const esp_partition_t *app_copy_target_part = nullptr;
bool otadata_partition_found = false;
bool otadata_overlap = false;
bool nvs_partition_found = false;
for (int i = 0; i < num_partitions; i++) { // Iterate over new partition table
const esp_partition_info_t *new_part = &new_partition_table[i];
if (new_part->type == ESP_PARTITION_TYPE_APP) {
@@ -275,18 +276,23 @@ OTAResponseTypes IDFOTABackend::update_partition_table() {
esp_partition_iterator_release(it);
}
}
} else if (new_part->type == ESP_PARTITION_TYPE_DATA && new_part->subtype == ESP_PARTITION_SUBTYPE_DATA_OTA) {
// Found the otadata partition in the new partition table
new_otadata_part_index = i;
otadata_overlap = check_overlap(running_app_offset, running_app_size, new_part->pos.offset, new_part->pos.size);
} else if (new_part->type == ESP_PARTITION_TYPE_DATA) {
if (new_part->subtype == ESP_PARTITION_SUBTYPE_DATA_OTA) {
// Found the otadata partition in the new partition table
otadata_partition_found = true;
otadata_overlap = check_overlap(running_app_offset, running_app_size, new_part->pos.offset, new_part->pos.size);
} else if (new_part->subtype == ESP_PARTITION_SUBTYPE_DATA_NVS && strcmp((char*)new_part->label, "nvs") == 0) {
// Found the nvs partition in the new partition table
nvs_partition_found = true;
}
}
}
if (new_app_part_index == -1 && new_app_part_index_with_copy == -1) {
ESP_LOGE(TAG, "No compatible app partition found in the new partition table");
return OTA_RESPONSE_ERROR_PARTITION_TABLE_VERIFY;
}
if (app_partitions_found < 2 || new_otadata_part_index == -1) {
ESP_LOGE(TAG, "New partition table is missing the required app or otadata partitions");
if (app_partitions_found < 2 || !otadata_partition_found || !nvs_partition_found) {
ESP_LOGE(TAG, "New partition table is missing the required app, otadata or nvs partitions");
return OTA_RESPONSE_ERROR_PARTITION_TABLE_VERIFY;
}
if (otadata_overlap) {