diff --git a/components/partition_table/Kconfig.projbuild b/components/partition_table/Kconfig.projbuild index d4d7bd9b36..e3740d9dad 100644 --- a/components/partition_table/Kconfig.projbuild +++ b/components/partition_table/Kconfig.projbuild @@ -25,6 +25,7 @@ menu "Partition Table" This partition table is not suitable for an app that needs OTA (over the air update) capability. + config PARTITION_TABLE_SINGLE_APP_LARGE bool "Single factory app (large), no OTA" help @@ -36,6 +37,7 @@ menu "Partition Table" This partition table is not suitable for an app that needs OTA (over the air update) capability. + config PARTITION_TABLE_TWO_OTA bool "Factory app, two OTA definitions" help @@ -45,6 +47,17 @@ menu "Partition Table" The corresponding CSV file in the IDF directory is 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 bool "Custom partition table CSV" help @@ -52,6 +65,7 @@ menu "Partition Table" Consult the Partition Table section in the ESP-IDF Programmers Guide for more information. + config PARTITION_TABLE_SINGLE_APP_ENCRYPTED_NVS bool "Single factory app, no OTA, encrypted NVS" 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 components/partition_table/partitions_singleapp_encr_nvs.csv + config PARTITION_TABLE_SINGLE_APP_LARGE_ENC_NVS bool "Single factory app (large), no OTA, encrypted NVS" 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 components/partition_table/partitions_singleapp_large_encr_nvs.csv + config PARTITION_TABLE_TWO_OTA_ENCRYPTED_NVS bool "Factory app, two OTA definitions, encrypted NVS" 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 components/partition_table/partitions_two_ota_encr_nvs.csv + endchoice 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_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_large.csv" if PARTITION_TABLE_TWO_OTA_LARGE && !ESP_COREDUMP_ENABLE_TO_FLASH default PARTITION_TABLE_CUSTOM_FILENAME if PARTITION_TABLE_CUSTOM config PARTITION_TABLE_OFFSET diff --git a/components/partition_table/partitions_two_ota_large.csv b/components/partition_table/partitions_two_ota_large.csv new file mode 100644 index 0000000000..0e6dacd1fe --- /dev/null +++ b/components/partition_table/partitions_two_ota_large.csv @@ -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, diff --git a/examples/system/ota/simple_ota_example/pytest_simple_ota.py b/examples/system/ota/simple_ota_example/pytest_simple_ota.py index 0595a9c2f7..8fffb24cc2 100644 --- a/examples/system/ota/simple_ota_example/pytest_simple_ota.py +++ b/examples/system/ota/simple_ota_example/pytest_simple_ota.py @@ -6,6 +6,7 @@ import os import ssl import subprocess import sys +from typing import Optional from typing import Tuple import pexpect @@ -69,8 +70,11 @@ server_key = '-----BEGIN PRIVATE KEY-----\n'\ 'vSXnRLaxQhooWm+IuX9SuBQ=\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) if server_file is None: @@ -147,7 +151,7 @@ def test_examples_protocol_simple_ota_example(dut: Dut) -> None: thread1.start() try: # 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_app, str(dut.expect(r'SHA-256 for current firmware:\s+([a-f0-9]){64}')[0])) # 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.expect('OTA Succeed, Rebooting...', timeout=60) # 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) finally: thread1.terminate() @@ -191,7 +195,7 @@ def test_examples_protocol_simple_ota_example_ethernet_with_spiram_config(dut: D thread1.start() try: # 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: 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)) @@ -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.expect('OTA Succeed, Rebooting...', timeout=60) # 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) finally: thread1.terminate() @@ -232,7 +236,7 @@ def test_examples_protocol_simple_ota_example_with_flash_encryption_wifi(dut: Du thread1.daemon = True thread1.start() 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) # Parse IP address of STA 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.expect('OTA Succeed, Rebooting...', timeout=60) # 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('OTA example app_main start', timeout=10) finally: @@ -277,7 +281,7 @@ def test_examples_protocol_simple_ota_example_with_verify_app_signature_on_updat thread1.start() try: # 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_app, str(dut.expect(r'SHA-256 for current firmware:\s+([a-f0-9]){64}')[0])) 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) print('writing to device: {}'.format('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('OTA Succeed, Rebooting...', timeout=60) # 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) finally: thread1.terminate() @@ -317,7 +321,7 @@ def test_examples_protocol_simple_ota_example_with_verify_app_signature_on_updat thread1.start() try: # 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_app, str(dut.expect(r'SHA-256 for current firmware:\s+([a-f0-9]){64}')[0])) 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) print('writing to device: {}'.format('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('#0 app key digest == #0 trusted key digest', timeout=10) dut.expect('Verifying with RSA-PSS...', timeout=10) dut.expect('Signature verified successfully!', timeout=10) dut.expect('OTA Succeed, Rebooting...', timeout=60) # 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) finally: 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) try: # 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_app, str(dut.expect(r'SHA-256 for current firmware:\s+([a-f0-9]){64}')[0])) # 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.expect('OTA Succeed, Rebooting...', timeout=120) # 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) finally: tls1_3_server.kill() diff --git a/examples/system/ota/simple_ota_example/sdkconfig.defaults b/examples/system/ota/simple_ota_example/sdkconfig.defaults index 748f1e2f65..6ac294ee70 100644 --- a/examples/system/ota/simple_ota_example/sdkconfig.defaults +++ b/examples/system/ota/simple_ota_example/sdkconfig.defaults @@ -7,3 +7,6 @@ CONFIG_PARTITION_TABLE_TWO_OTA=y CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN=y CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE=y CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="server_certs/ca_cert.pem" + +# Default partition table config +CONFIG_PARTITION_TABLE_TWO_OTA_LARGE=y