forked from espressif/esp-idf
Merge branch 'feature/add_config_option_to_support_large_ota' into 'master'
feat: add config option under partition menu to support large size ota Closes IDF-10338 See merge request espressif/esp-idf!31923
This commit is contained in:
@@ -25,6 +25,7 @@ menu "Partition Table"
|
|||||||
|
|
||||||
This partition table is not suitable for an app that needs OTA
|
This partition table is not suitable for an app that needs OTA
|
||||||
(over the air update) capability.
|
(over the air update) capability.
|
||||||
|
|
||||||
config PARTITION_TABLE_SINGLE_APP_LARGE
|
config PARTITION_TABLE_SINGLE_APP_LARGE
|
||||||
bool "Single factory app (large), no OTA"
|
bool "Single factory app (large), no OTA"
|
||||||
help
|
help
|
||||||
@@ -36,6 +37,7 @@ menu "Partition Table"
|
|||||||
|
|
||||||
This partition table is not suitable for an app that needs OTA
|
This partition table is not suitable for an app that needs OTA
|
||||||
(over the air update) capability.
|
(over the air update) capability.
|
||||||
|
|
||||||
config PARTITION_TABLE_TWO_OTA
|
config PARTITION_TABLE_TWO_OTA
|
||||||
bool "Factory app, two OTA definitions"
|
bool "Factory app, two OTA definitions"
|
||||||
help
|
help
|
||||||
@@ -45,6 +47,17 @@ menu "Partition Table"
|
|||||||
|
|
||||||
The corresponding CSV file in the IDF directory is
|
The corresponding CSV file in the IDF directory is
|
||||||
components/partition_table/partitions_two_ota.csv
|
components/partition_table/partitions_two_ota.csv
|
||||||
|
|
||||||
|
config PARTITION_TABLE_TWO_OTA_LARGE
|
||||||
|
bool "Two large size OTA partitions"
|
||||||
|
help
|
||||||
|
This is a basic OTA-enabled partition table with
|
||||||
|
two OTA app partitions. Both app partition sizes are 1700K,
|
||||||
|
so this partition table requires 4MB or larger flash size.
|
||||||
|
|
||||||
|
The corresponding CSV file in the IDF directory is
|
||||||
|
components/partition_table/partitions_two_ota_large.csv
|
||||||
|
|
||||||
config PARTITION_TABLE_CUSTOM
|
config PARTITION_TABLE_CUSTOM
|
||||||
bool "Custom partition table CSV"
|
bool "Custom partition table CSV"
|
||||||
help
|
help
|
||||||
@@ -52,6 +65,7 @@ menu "Partition Table"
|
|||||||
|
|
||||||
Consult the Partition Table section in the ESP-IDF Programmers Guide
|
Consult the Partition Table section in the ESP-IDF Programmers Guide
|
||||||
for more information.
|
for more information.
|
||||||
|
|
||||||
config PARTITION_TABLE_SINGLE_APP_ENCRYPTED_NVS
|
config PARTITION_TABLE_SINGLE_APP_ENCRYPTED_NVS
|
||||||
bool "Single factory app, no OTA, encrypted NVS"
|
bool "Single factory app, no OTA, encrypted NVS"
|
||||||
depends on !ESP32_COREDUMP_ENABLE_TO_FLASH && NVS_SEC_KEY_PROTECT_USING_FLASH_ENC
|
depends on !ESP32_COREDUMP_ENABLE_TO_FLASH && NVS_SEC_KEY_PROTECT_USING_FLASH_ENC
|
||||||
@@ -63,6 +77,7 @@ menu "Partition Table"
|
|||||||
|
|
||||||
The corresponding CSV file in the IDF directory is
|
The corresponding CSV file in the IDF directory is
|
||||||
components/partition_table/partitions_singleapp_encr_nvs.csv
|
components/partition_table/partitions_singleapp_encr_nvs.csv
|
||||||
|
|
||||||
config PARTITION_TABLE_SINGLE_APP_LARGE_ENC_NVS
|
config PARTITION_TABLE_SINGLE_APP_LARGE_ENC_NVS
|
||||||
bool "Single factory app (large), no OTA, encrypted NVS"
|
bool "Single factory app (large), no OTA, encrypted NVS"
|
||||||
depends on !ESP32_COREDUMP_ENABLE_TO_FLASH && NVS_SEC_KEY_PROTECT_USING_FLASH_ENC
|
depends on !ESP32_COREDUMP_ENABLE_TO_FLASH && NVS_SEC_KEY_PROTECT_USING_FLASH_ENC
|
||||||
@@ -73,6 +88,7 @@ menu "Partition Table"
|
|||||||
|
|
||||||
The corresponding CSV file in the IDF directory is
|
The corresponding CSV file in the IDF directory is
|
||||||
components/partition_table/partitions_singleapp_large_encr_nvs.csv
|
components/partition_table/partitions_singleapp_large_encr_nvs.csv
|
||||||
|
|
||||||
config PARTITION_TABLE_TWO_OTA_ENCRYPTED_NVS
|
config PARTITION_TABLE_TWO_OTA_ENCRYPTED_NVS
|
||||||
bool "Factory app, two OTA definitions, encrypted NVS"
|
bool "Factory app, two OTA definitions, encrypted NVS"
|
||||||
depends on !ESP_COREDUMP_ENABLE_TO_FLASH && NVS_SEC_KEY_PROTECT_USING_FLASH_ENC
|
depends on !ESP_COREDUMP_ENABLE_TO_FLASH && NVS_SEC_KEY_PROTECT_USING_FLASH_ENC
|
||||||
@@ -83,6 +99,7 @@ menu "Partition Table"
|
|||||||
|
|
||||||
The corresponding CSV file in the IDF directory is
|
The corresponding CSV file in the IDF directory is
|
||||||
components/partition_table/partitions_two_ota_encr_nvs.csv
|
components/partition_table/partitions_two_ota_encr_nvs.csv
|
||||||
|
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
config PARTITION_TABLE_CUSTOM_FILENAME
|
config PARTITION_TABLE_CUSTOM_FILENAME
|
||||||
@@ -104,6 +121,7 @@ menu "Partition Table"
|
|||||||
default "partitions_two_ota.csv" if PARTITION_TABLE_TWO_OTA && !ESP_COREDUMP_ENABLE_TO_FLASH
|
default "partitions_two_ota.csv" if PARTITION_TABLE_TWO_OTA && !ESP_COREDUMP_ENABLE_TO_FLASH
|
||||||
default "partitions_two_ota_coredump.csv" if PARTITION_TABLE_TWO_OTA && ESP_COREDUMP_ENABLE_TO_FLASH
|
default "partitions_two_ota_coredump.csv" if PARTITION_TABLE_TWO_OTA && ESP_COREDUMP_ENABLE_TO_FLASH
|
||||||
default "partitions_two_ota_encr_nvs.csv" if PARTITION_TABLE_TWO_OTA_ENCRYPTED_NVS
|
default "partitions_two_ota_encr_nvs.csv" if PARTITION_TABLE_TWO_OTA_ENCRYPTED_NVS
|
||||||
|
default "partitions_two_ota_large.csv" if PARTITION_TABLE_TWO_OTA_LARGE && !ESP_COREDUMP_ENABLE_TO_FLASH
|
||||||
default PARTITION_TABLE_CUSTOM_FILENAME if PARTITION_TABLE_CUSTOM
|
default PARTITION_TABLE_CUSTOM_FILENAME if PARTITION_TABLE_CUSTOM
|
||||||
|
|
||||||
config PARTITION_TABLE_OFFSET
|
config PARTITION_TABLE_OFFSET
|
||||||
|
7
components/partition_table/partitions_two_ota_large.csv
Normal file
7
components/partition_table/partitions_two_ota_large.csv
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# Name, Type, SubType, Offset, Size, Flags
|
||||||
|
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
|
||||||
|
nvs, data, nvs, , 0x6000,
|
||||||
|
otadata, data, ota, , 0x2000,
|
||||||
|
phy_init, data, phy, , 0x1000,
|
||||||
|
ota_0, app, ota_0, , 1700K,
|
||||||
|
ota_1, app, ota_1, , 1700K,
|
|
@@ -6,6 +6,7 @@ import os
|
|||||||
import ssl
|
import ssl
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
from typing import Optional
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
|
|
||||||
import pexpect
|
import pexpect
|
||||||
@@ -69,8 +70,11 @@ server_key = '-----BEGIN PRIVATE KEY-----\n'\
|
|||||||
'vSXnRLaxQhooWm+IuX9SuBQ=\n'\
|
'vSXnRLaxQhooWm+IuX9SuBQ=\n'\
|
||||||
'-----END PRIVATE KEY-----\n'
|
'-----END PRIVATE KEY-----\n'
|
||||||
|
|
||||||
|
OTA1_ADDRESS = '0x20000'
|
||||||
|
OTA2_ADDRESS = '0x1d0000'
|
||||||
|
|
||||||
def start_https_server(ota_image_dir: str, server_ip: str, server_port: int, server_file: str = None, key_file: str = None) -> None:
|
|
||||||
|
def start_https_server(ota_image_dir: str, server_ip: str, server_port: int, server_file: Optional[str] = None, key_file: Optional[str] = None) -> None:
|
||||||
os.chdir(ota_image_dir)
|
os.chdir(ota_image_dir)
|
||||||
|
|
||||||
if server_file is None:
|
if server_file is None:
|
||||||
@@ -147,7 +151,7 @@ def test_examples_protocol_simple_ota_example(dut: Dut) -> None:
|
|||||||
thread1.start()
|
thread1.start()
|
||||||
try:
|
try:
|
||||||
# start test
|
# start test
|
||||||
dut.expect('Loaded app from partition at offset 0x10000', timeout=30)
|
dut.expect(f'Loaded app from partition at offset {OTA1_ADDRESS}', timeout=30)
|
||||||
check_sha256(sha256_bootloader, str(dut.expect(r'SHA-256 for bootloader:\s+([a-f0-9]){64}')[0]))
|
check_sha256(sha256_bootloader, str(dut.expect(r'SHA-256 for bootloader:\s+([a-f0-9]){64}')[0]))
|
||||||
check_sha256(sha256_app, str(dut.expect(r'SHA-256 for current firmware:\s+([a-f0-9]){64}')[0]))
|
check_sha256(sha256_app, str(dut.expect(r'SHA-256 for current firmware:\s+([a-f0-9]){64}')[0]))
|
||||||
# Parse IP address of STA
|
# Parse IP address of STA
|
||||||
@@ -169,7 +173,7 @@ def test_examples_protocol_simple_ota_example(dut: Dut) -> None:
|
|||||||
dut.write('https://' + host_ip + ':8000/simple_ota.bin')
|
dut.write('https://' + host_ip + ':8000/simple_ota.bin')
|
||||||
dut.expect('OTA Succeed, Rebooting...', timeout=60)
|
dut.expect('OTA Succeed, Rebooting...', timeout=60)
|
||||||
# after reboot
|
# after reboot
|
||||||
dut.expect('Loaded app from partition at offset 0x110000', timeout=30)
|
dut.expect(f'Loaded app from partition at offset {OTA2_ADDRESS}', timeout=30)
|
||||||
dut.expect('OTA example app_main start', timeout=10)
|
dut.expect('OTA example app_main start', timeout=10)
|
||||||
finally:
|
finally:
|
||||||
thread1.terminate()
|
thread1.terminate()
|
||||||
@@ -191,7 +195,7 @@ def test_examples_protocol_simple_ota_example_ethernet_with_spiram_config(dut: D
|
|||||||
thread1.start()
|
thread1.start()
|
||||||
try:
|
try:
|
||||||
# start test
|
# start test
|
||||||
dut.expect('Loaded app from partition at offset 0x10000', timeout=30)
|
dut.expect(f'Loaded app from partition at offset {OTA1_ADDRESS}', timeout=30)
|
||||||
try:
|
try:
|
||||||
ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
|
ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
|
||||||
print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
|
print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
|
||||||
@@ -204,7 +208,7 @@ def test_examples_protocol_simple_ota_example_ethernet_with_spiram_config(dut: D
|
|||||||
dut.write('https://' + host_ip + ':8000/simple_ota.bin')
|
dut.write('https://' + host_ip + ':8000/simple_ota.bin')
|
||||||
dut.expect('OTA Succeed, Rebooting...', timeout=60)
|
dut.expect('OTA Succeed, Rebooting...', timeout=60)
|
||||||
# after reboot
|
# after reboot
|
||||||
dut.expect('Loaded app from partition at offset 0x110000', timeout=30)
|
dut.expect(f'Loaded app from partition at offset {OTA2_ADDRESS}', timeout=30)
|
||||||
dut.expect('OTA example app_main start', timeout=10)
|
dut.expect('OTA example app_main start', timeout=10)
|
||||||
finally:
|
finally:
|
||||||
thread1.terminate()
|
thread1.terminate()
|
||||||
@@ -232,7 +236,7 @@ def test_examples_protocol_simple_ota_example_with_flash_encryption_wifi(dut: Du
|
|||||||
thread1.daemon = True
|
thread1.daemon = True
|
||||||
thread1.start()
|
thread1.start()
|
||||||
try:
|
try:
|
||||||
dut.expect('Loaded app from partition at offset 0x20000', timeout=30)
|
dut.expect(f'Loaded app from partition at offset {OTA1_ADDRESS}', timeout=30)
|
||||||
dut.expect('Flash encryption mode is DEVELOPMENT', timeout=10)
|
dut.expect('Flash encryption mode is DEVELOPMENT', timeout=10)
|
||||||
# Parse IP address of STA
|
# Parse IP address of STA
|
||||||
if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True:
|
if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True:
|
||||||
@@ -253,7 +257,7 @@ def test_examples_protocol_simple_ota_example_with_flash_encryption_wifi(dut: Du
|
|||||||
dut.write('https://' + host_ip + ':8000/simple_ota.bin')
|
dut.write('https://' + host_ip + ':8000/simple_ota.bin')
|
||||||
dut.expect('OTA Succeed, Rebooting...', timeout=60)
|
dut.expect('OTA Succeed, Rebooting...', timeout=60)
|
||||||
# after reboot
|
# after reboot
|
||||||
dut.expect('Loaded app from partition at offset 0x120000', timeout=30)
|
dut.expect(f'Loaded app from partition at offset {OTA2_ADDRESS}', timeout=30)
|
||||||
dut.expect('Flash encryption mode is DEVELOPMENT', timeout=10)
|
dut.expect('Flash encryption mode is DEVELOPMENT', timeout=10)
|
||||||
dut.expect('OTA example app_main start', timeout=10)
|
dut.expect('OTA example app_main start', timeout=10)
|
||||||
finally:
|
finally:
|
||||||
@@ -277,7 +281,7 @@ def test_examples_protocol_simple_ota_example_with_verify_app_signature_on_updat
|
|||||||
thread1.start()
|
thread1.start()
|
||||||
try:
|
try:
|
||||||
# start test
|
# start test
|
||||||
dut.expect('Loaded app from partition at offset 0x20000', timeout=30)
|
dut.expect(f'Loaded app from partition at offset {OTA1_ADDRESS}', timeout=30)
|
||||||
check_sha256(sha256_bootloader, str(dut.expect(r'SHA-256 for bootloader:\s+([a-f0-9]){64}')[0]))
|
check_sha256(sha256_bootloader, str(dut.expect(r'SHA-256 for bootloader:\s+([a-f0-9]){64}')[0]))
|
||||||
check_sha256(sha256_app, str(dut.expect(r'SHA-256 for current firmware:\s+([a-f0-9]){64}')[0]))
|
check_sha256(sha256_app, str(dut.expect(r'SHA-256 for current firmware:\s+([a-f0-9]){64}')[0]))
|
||||||
try:
|
try:
|
||||||
@@ -290,11 +294,11 @@ def test_examples_protocol_simple_ota_example_with_verify_app_signature_on_updat
|
|||||||
dut.expect('Starting OTA example task', timeout=30)
|
dut.expect('Starting OTA example task', timeout=30)
|
||||||
print('writing to device: {}'.format('https://' + host_ip + ':8000/simple_ota.bin'))
|
print('writing to device: {}'.format('https://' + host_ip + ':8000/simple_ota.bin'))
|
||||||
dut.write('https://' + host_ip + ':8000/simple_ota.bin')
|
dut.write('https://' + host_ip + ':8000/simple_ota.bin')
|
||||||
dut.expect('Writing to partition subtype 16 at offset 0x120000', timeout=20)
|
dut.expect(f'Writing to partition subtype 17 at offset {OTA2_ADDRESS}', timeout=20)
|
||||||
dut.expect('Verifying image signature...', timeout=60)
|
dut.expect('Verifying image signature...', timeout=60)
|
||||||
dut.expect('OTA Succeed, Rebooting...', timeout=60)
|
dut.expect('OTA Succeed, Rebooting...', timeout=60)
|
||||||
# after reboot
|
# after reboot
|
||||||
dut.expect('Loaded app from partition at offset 0x120000', timeout=20)
|
dut.expect(f'Loaded app from partition at offset {OTA2_ADDRESS}', timeout=20)
|
||||||
dut.expect('OTA example app_main start', timeout=10)
|
dut.expect('OTA example app_main start', timeout=10)
|
||||||
finally:
|
finally:
|
||||||
thread1.terminate()
|
thread1.terminate()
|
||||||
@@ -317,7 +321,7 @@ def test_examples_protocol_simple_ota_example_with_verify_app_signature_on_updat
|
|||||||
thread1.start()
|
thread1.start()
|
||||||
try:
|
try:
|
||||||
# start test
|
# start test
|
||||||
dut.expect('Loaded app from partition at offset 0x20000', timeout=30)
|
dut.expect(f'Loaded app from partition at offset {OTA1_ADDRESS}', timeout=30)
|
||||||
check_sha256(sha256_bootloader, str(dut.expect(r'SHA-256 for bootloader:\s+([a-f0-9]){64}')[0]))
|
check_sha256(sha256_bootloader, str(dut.expect(r'SHA-256 for bootloader:\s+([a-f0-9]){64}')[0]))
|
||||||
check_sha256(sha256_app, str(dut.expect(r'SHA-256 for current firmware:\s+([a-f0-9]){64}')[0]))
|
check_sha256(sha256_app, str(dut.expect(r'SHA-256 for current firmware:\s+([a-f0-9]){64}')[0]))
|
||||||
try:
|
try:
|
||||||
@@ -330,14 +334,14 @@ def test_examples_protocol_simple_ota_example_with_verify_app_signature_on_updat
|
|||||||
dut.expect('Starting OTA example task', timeout=30)
|
dut.expect('Starting OTA example task', timeout=30)
|
||||||
print('writing to device: {}'.format('https://' + host_ip + ':8000/simple_ota.bin'))
|
print('writing to device: {}'.format('https://' + host_ip + ':8000/simple_ota.bin'))
|
||||||
dut.write('https://' + host_ip + ':8000/simple_ota.bin')
|
dut.write('https://' + host_ip + ':8000/simple_ota.bin')
|
||||||
dut.expect('Writing to partition subtype 16 at offset 0x120000', timeout=20)
|
dut.expect(f'Writing to partition subtype 17 at offset {OTA2_ADDRESS}', timeout=20)
|
||||||
dut.expect('Verifying image signature...', timeout=60)
|
dut.expect('Verifying image signature...', timeout=60)
|
||||||
dut.expect('#0 app key digest == #0 trusted key digest', timeout=10)
|
dut.expect('#0 app key digest == #0 trusted key digest', timeout=10)
|
||||||
dut.expect('Verifying with RSA-PSS...', timeout=10)
|
dut.expect('Verifying with RSA-PSS...', timeout=10)
|
||||||
dut.expect('Signature verified successfully!', timeout=10)
|
dut.expect('Signature verified successfully!', timeout=10)
|
||||||
dut.expect('OTA Succeed, Rebooting...', timeout=60)
|
dut.expect('OTA Succeed, Rebooting...', timeout=60)
|
||||||
# after reboot
|
# after reboot
|
||||||
dut.expect('Loaded app from partition at offset 0x120000', timeout=20)
|
dut.expect(f'Loaded app from partition at offset {OTA2_ADDRESS}', timeout=20)
|
||||||
dut.expect('OTA example app_main start', timeout=10)
|
dut.expect('OTA example app_main start', timeout=10)
|
||||||
finally:
|
finally:
|
||||||
thread1.terminate()
|
thread1.terminate()
|
||||||
@@ -358,7 +362,7 @@ def test_examples_protocol_simple_ota_example_tls1_3(dut: Dut) -> None:
|
|||||||
tls1_3_server = start_tls1_3_server(dut.app.binary_path, 8000)
|
tls1_3_server = start_tls1_3_server(dut.app.binary_path, 8000)
|
||||||
try:
|
try:
|
||||||
# start test
|
# start test
|
||||||
dut.expect('Loaded app from partition at offset 0x10000', timeout=30)
|
dut.expect(f'Loaded app from partition at offset {OTA1_ADDRESS}', timeout=30)
|
||||||
check_sha256(sha256_bootloader, str(dut.expect(r'SHA-256 for bootloader:\s+([a-f0-9]){64}')[0]))
|
check_sha256(sha256_bootloader, str(dut.expect(r'SHA-256 for bootloader:\s+([a-f0-9]){64}')[0]))
|
||||||
check_sha256(sha256_app, str(dut.expect(r'SHA-256 for current firmware:\s+([a-f0-9]){64}')[0]))
|
check_sha256(sha256_app, str(dut.expect(r'SHA-256 for current firmware:\s+([a-f0-9]){64}')[0]))
|
||||||
# Parse IP address of STA
|
# Parse IP address of STA
|
||||||
@@ -380,7 +384,7 @@ def test_examples_protocol_simple_ota_example_tls1_3(dut: Dut) -> None:
|
|||||||
dut.write('https://' + host_ip + ':8000/simple_ota.bin')
|
dut.write('https://' + host_ip + ':8000/simple_ota.bin')
|
||||||
dut.expect('OTA Succeed, Rebooting...', timeout=120)
|
dut.expect('OTA Succeed, Rebooting...', timeout=120)
|
||||||
# after reboot
|
# after reboot
|
||||||
dut.expect('Loaded app from partition at offset 0x110000', timeout=30)
|
dut.expect(f'Loaded app from partition at offset {OTA2_ADDRESS}', timeout=30)
|
||||||
dut.expect('OTA example app_main start', timeout=10)
|
dut.expect('OTA example app_main start', timeout=10)
|
||||||
finally:
|
finally:
|
||||||
tls1_3_server.kill()
|
tls1_3_server.kill()
|
||||||
|
@@ -7,3 +7,6 @@ CONFIG_PARTITION_TABLE_TWO_OTA=y
|
|||||||
CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN=y
|
CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN=y
|
||||||
CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE=y
|
CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE=y
|
||||||
CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="server_certs/ca_cert.pem"
|
CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="server_certs/ca_cert.pem"
|
||||||
|
|
||||||
|
# Default partition table config
|
||||||
|
CONFIG_PARTITION_TABLE_TWO_OTA_LARGE=y
|
||||||
|
Reference in New Issue
Block a user