Skip to content

Commit

Permalink
Merge branch 'feature/add_config_option_to_support_large_ota' into 'm…
Browse files Browse the repository at this point in the history
…aster'

feat: add config option under partition menu to support large size ota

Closes IDF-10338

See merge request espressif/esp-idf!31923
  • Loading branch information
mahavirj committed Jul 15, 2024
2 parents 097fd37 + 55bbd9c commit 45c1565
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 15 deletions.
18 changes: 18 additions & 0 deletions components/partition_table/Kconfig.projbuild
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -45,13 +47,25 @@ 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
Specify the path to the partition table CSV to use for your project.

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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
7 changes: 7 additions & 0 deletions components/partition_table/partitions_two_ota_large.csv
Original file line number Diff line number Diff line change
@@ -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,
34 changes: 19 additions & 15 deletions examples/system/ota/simple_ota_example/pytest_simple_ota.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import ssl
import subprocess
import sys
from typing import Optional
from typing import Tuple

import pexpect
Expand Down Expand Up @@ -69,8 +70,11 @@
'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:
Expand Down Expand Up @@ -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
Expand All @@ -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()
Expand All @@ -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))
Expand All @@ -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()
Expand Down Expand Up @@ -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:
Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -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()
Expand All @@ -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:
Expand All @@ -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()
Expand All @@ -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
Expand All @@ -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()
Expand Down
3 changes: 3 additions & 0 deletions examples/system/ota/simple_ota_example/sdkconfig.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 45c1565

Please sign in to comment.