From 3997859a5661747a88c3b3adda121cf6522551f5 Mon Sep 17 00:00:00 2001 From: Carol Yang Date: Fri, 25 Mar 2022 19:57:36 -0700 Subject: [PATCH] [OTA] Update the READMEs related to software version and image header (#16690) --- .github/.wordlist.txt | 5 + examples/ota-provider-app/linux/README.md | 44 +++++--- examples/ota-requestor-app/linux/README.md | 102 ++++++++++++++---- .../clusters/ota-requestor/OTARequestor.cpp | 6 +- 4 files changed, 124 insertions(+), 33 deletions(-) diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt index 8c987aacb69624..807ce7b5edd996 100644 --- a/.github/.wordlist.txt +++ b/.github/.wordlist.txt @@ -895,6 +895,7 @@ OTADownloader otaDownloadPath otaImageList OTAImageProcessorDriver +OTAImageProcessorImpl OTAImageProcessorInterface OTAProvider OTAProviderIpAddress @@ -1176,6 +1177,7 @@ SulfurDioxideConcentrationMeasurement svg SVR SWD +SWU symlinks sysconfdir SysConfig @@ -1248,6 +1250,7 @@ TotalTrihalomethanesConcentrationMeasurement trackAlloc trackFree transitionTime +TransferSession TransportMgrBase TrustedRootCertificates TSG @@ -1354,12 +1357,14 @@ xab xaver xb xbef +xBEEF xc xcd Xcode xcodeproj xcworkspace xd +xDEAD xDEADBEEF xdeadbeefcafe xds diff --git a/examples/ota-provider-app/linux/README.md b/examples/ota-provider-app/linux/README.md index 7293b068867e0e..a52e87257c7b7f 100644 --- a/examples/ota-provider-app/linux/README.md +++ b/examples/ota-provider-app/linux/README.md @@ -3,7 +3,7 @@ This is a reference application that implements an example of an OTA Provider Cluster Server. -## Building +## Build Suggest doing the following: @@ -29,17 +29,15 @@ scripts/examples/gn_build_example.sh examples/ota-provider-app/linux out/debug c **Using `--filepath` and `--otaImageList`** - The two options cannot be supplied together -- If neither option is supplied, the application will respond with - `NotAvailable` status +- At least one option must be supplied - If `--filepath` is supplied, the application will automatically serve that - file to the OTA Requestor (SoftwareVersion will be requester software - version + 1) + file to the OTA Requestor - If `--otaImageList` is supplied, the application will parse the JSON file and extract all required data. The most recent/valid software version will be selected and the corresponding OTA file will be sent to the OTA Requestor - The SoftwareVersion and SoftwareVersionString sent in the QueryImageResponse is derived from the OTA image header. Please note that if the version in the - `--otaImageList` JSON file does not match that in the header, the + `--otaImageList` JSON file does not match that in the image header, the application will terminate. An example of the `--otaImageList` file contents: @@ -48,15 +46,38 @@ An example of the `--otaImageList` file contents: { "foo": 1, // ignored by parser "deviceSoftwareVersionModel": [ - { "vendorId": 1, "productId": 1, "softwareVersion": 10, "softwareVersionString": "1.0.0", "cDVersionNumber": 18, "softwareVersionValid": true, "minApplicableSoftwareVersion": 0, "maxApplicableSoftwareVersion": 100, "otaURL": "/tmp/ota.txt" }, - { "vendorId": 1, "productId": 1, "softwareVersion": 20, "softwareVersionString": "1.0.1", "cDVersionNumber": 18, "softwareVersionValid": false, "minApplicableSoftwareVersion": 0, "maxApplicableSoftwareVersion": 100, "otaURL": "/tmp/ota.txt" }, - { "vendorId": 1, "productId": 1, "softwareVersion": 30, "softwareVersionString": "1.0.2", "cDVersionNumber": 18, "softwareVersionValid": true, "minApplicableSoftwareVersion": 0, "maxApplicableSoftwareVersion": 100, "otaURL": "/tmp/ota.txt" }, - { "vendorId": 1, "productId": 1, "softwareVersion": 40, "softwareVersionString": "1.1.0", "cDVersionNumber": 18, "softwareVersionValid": true, "minApplicableSoftwareVersion": 0, "maxApplicableSoftwareVersion": 100, "otaURL": "/tmp/ota.txt" }, - { "vendorId": 1, "productId": 1, "softwareVersion": 50, "softwareVersionString": "1.1.1", "cDVersionNumber": 18, "softwareVersionValid": false, "minApplicableSoftwareVersion": 0, "maxApplicableSoftwareVersion": 100, "otaURL": "/tmp/ota.txt" } + { "vendorId": 1, "productId": 1, "softwareVersion": 10, "softwareVersionString": "1.0.0", "cDVersionNumber": 18, "softwareVersionValid": true, "minApplicableSoftwareVersion": 0, "maxApplicableSoftwareVersion": 100, "otaURL": "/tmp/ota_v10.bin" }, + { "vendorId": 1, "productId": 1, "softwareVersion": 20, "softwareVersionString": "1.0.1", "cDVersionNumber": 18, "softwareVersionValid": false, "minApplicableSoftwareVersion": 0, "maxApplicableSoftwareVersion": 100, "otaURL": "/tmp/ota_v20.bin" }, + { "vendorId": 1, "productId": 1, "softwareVersion": 30, "softwareVersionString": "1.0.2", "cDVersionNumber": 18, "softwareVersionValid": true, "minApplicableSoftwareVersion": 0, "maxApplicableSoftwareVersion": 100, "otaURL": "/tmp/ota_v30.bin" }, + { "vendorId": 1, "productId": 1, "softwareVersion": 40, "softwareVersionString": "1.1.0", "cDVersionNumber": 18, "softwareVersionValid": true, "minApplicableSoftwareVersion": 0, "maxApplicableSoftwareVersion": 100, "otaURL": "/tmp/ota_v40.bin" }, + { "vendorId": 1, "productId": 1, "softwareVersion": 50, "softwareVersionString": "1.1.1", "cDVersionNumber": 18, "softwareVersionValid": false, "minApplicableSoftwareVersion": 0, "maxApplicableSoftwareVersion": 100, "otaURL": "/tmp/ota_v50.bin" } ] } ``` +## Software Image Header + +All Matter software images must contain a header as defined in section 11.21.1 +of the specification. The +[ota_image_tool](https://github.com/project-chip/connectedhomeip/blob/master/src/app/ota_image_tool.py) +is available for generating the required header on a software image. + +All images supplied to the OTA Provider application (via `--filepath` or +`--otaImageList`) must contain the software image header. The OTA Provider +application will use the software version specified in the header to set the +`SoftwareVersion` field of the QueryImageResponse. For instance, if the image +supplied represents an image with software version 2, the tool can be used as +follows: + +``` +src/app/ota_image_tool.py create -v 0xDEAD -p 0xBEEF -vn 2 -vs "2.0" -da sha256 firmware.bin firmware.ota +``` + +Please see this +[section](https://github.com/project-chip/connectedhomeip/tree/master/examples/ota-requestor-app/linux#generate-images) +for information on building an OTA Requestor application with a specific +software version. + ## Access Control Requirements Commissioner or Administrator SHOULD install necessary ACL entries at @@ -86,5 +107,4 @@ being 0xDEADBEEF on endpoint 0. - Synchronous BDX transfer only - Does not check VID/PID -- No configuration for `AwaitNextAction` - Only one transfer at a time (does not check incoming `UpdateTokens`) diff --git a/examples/ota-requestor-app/linux/README.md b/examples/ota-requestor-app/linux/README.md index ad610c9a56e870..17bab9bd823b1e 100644 --- a/examples/ota-requestor-app/linux/README.md +++ b/examples/ota-requestor-app/linux/README.md @@ -4,7 +4,7 @@ This is a reference application that is both a server for the OTA Requestor Cluster, as well as a client of the OTA Provider Cluster. It can initiate a software update with a given OTA Provider node, and download a file. -## Building +## Build Suggest doing the following: @@ -25,15 +25,70 @@ following command line options are available for the OTA Requestor application. | -u/--userConsentState | The user consent state for the first QueryImage command. For all subsequent commands, the value of granted will be used.
  • granted: Authorize OTA requestor to download an OTA image
  • denied: Forbid OTA requestor to download an OTA image
  • deferred: Defer obtaining user consent | | -a/--autoApplyImage | If supplied, apply the image immediately after download. Otherwise, the OTA update is complete after image download. | -## Software Image Header +## Software Image Version -All Matter software images must contain a header as defined in section 11.21.1 -of the specification. The -[ota_image_tool](https://github.com/project-chip/connectedhomeip/blob/master/src/app/ota_image_tool.py) -is available for generating the required header on a software image. Any -software images that the OTA Requestor application receives must contain the -required header. If the header is missing, the software download will not -succeed. +The current software version of the OTA Requestor application is defined by +`CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION` in +[CHIPProjectConfig.h](https://github.com/project-chip/connectedhomeip/blob/master/config/standalone/CHIPProjectConfig.h). +This value can be confirmed by reading the `SoftwareVersion` attribute of the +Basic Information cluster: + +``` +out/chip-tool basic read software-version 0x1234567890 0 +``` + +### Validations + +On receiving the QueryImageResponse from the OTA Provider application, the OTA +Requestor application will verify that the software version specified in the +`SoftwareVersion` field of the response contains a value newer than the current +running version. If the update supplied does not pass this version check, the +following log message should be expected, indicating the update will not +proceed: + +``` +[1648233572232] [48462:7613274] CHIP: [SWU] Available update version 1 is <= current version 1, update ignored +``` + +If the OTA update progresses to downloading, the process will abort if the +software image +[header](https://github.com/project-chip/connectedhomeip/tree/master/examples/ota-provider-app/linux#software-image-header) +is missing. The following log messages should be expected: + +``` +[1648246917398] [71786:7874994] CHIP: [SWU] Image does not contain a valid header +[1648246917399] [71786:7874994] CHIP: [BDX] TransferSession error +``` + +On booting into the new image, if the running version does not match the version +specified in the QueryImageResponse, the following log message should be +expected: + +``` +[1648244159295] [58606:7774255] CHIP: [SWU] Failed to confirm image: ../../examples/ota-requestor-app/linux/third_party/connectedhomeip/src/platform/Linux/OTAImageProcessorImpl.cpp:110: CHIP Error 0x00000003: Incorrect state +``` + +This message serves as a warning that the new image is not expected. However, +the OTA Requestor application will recover gracefully and return to a state +where another OTA update may be initiated. + +### Generate Images + +To validate booting into a newer OTA Requestor image on the Linux platform, the +following must be performed: + +1. Modify `CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION` to a value greater than + the current running version +2. [Build](https://github.com/project-chip/connectedhomeip/blob/master/examples/ota-requestor-app/linux/README.md#build) + an OTA Requestor application with the new version +3. Using the executable created in step 2, generate an image with a software + image + [header](https://github.com/project-chip/connectedhomeip/tree/master/examples/ota-provider-app/linux#software-image-header) + that matches the version in step 1 +4. Use this generated binary when supplying the image file to the OTA Provider + application +5. Launch the original application (an OTA Requestor application generated prior + to step 1) with the command line option `--autoApplyImage` ## Common Instructions @@ -47,7 +102,7 @@ are some common instructions for building and commissioning the applications. #### Build the OTA Provider application Follow instructions -[here](https://github.com/project-chip/connectedhomeip/tree/master/examples/ota-provider-app/linux#building) +[here](https://github.com/project-chip/connectedhomeip/tree/master/examples/ota-provider-app/linux#build) #### Run the OTA Provider application @@ -81,15 +136,15 @@ out/chip-tool pairing onnetwork-long ${PROVIDER_NODE_ID} 20202021 ${PROVIDER_LON ### OTA Requestor application -#### Build the OTA Provider application +#### Build the OTA Requestor application Follow instructions -[here](https://github.com/project-chip/connectedhomeip/tree/master/examples/ota-requestor-app/linux#building) +[here](https://github.com/project-chip/connectedhomeip/tree/master/examples/ota-requestor-app/linux#build) #### Run the OTA Requestor application: ``` -out/chip-ota-requestor-app --discriminator ${REQUESTOR_LONG_DISCRIMINATOR} --secured-device-port ${REQUESTOR_UDP_PORT} --KVS ${KVS_STORE_LOCATION} --periodicQueryTimeout ${TIME_IN_SECONDS} +out/chip-ota-requestor-app --discriminator ${REQUESTOR_LONG_DISCRIMINATOR} --secured-device-port ${REQUESTOR_UDP_PORT} --KVS ${KVS_STORE_LOCATION} --periodicQueryTimeout ${TIME_IN_SECONDS} --autoApplyImage ``` @@ -106,6 +161,9 @@ out/chip-ota-requestor-app --discriminator ${REQUESTOR_LONG_DISCRIMINATOR} --sec - `${TIME_IN_SECONDS}` is the periodic timeout for querying providers in the default OTA provider list. If none or zero is supplied the timeout is set to every 24 hours. +- `--autoApplyImage` is supplied to indicate the image should be immediately + applied after download. If not supplied, the OTA update is complete after + image download. #### Commission the OTA Requestor application @@ -124,10 +182,18 @@ There are two methods for this reference application to connect to a device running OTA Provider server and download a software image. If the ACL entry on the provider has not been properly installed, the QueryImage -command will be denied. Follow instructions +command will be denied. Logs similar to the following may be observed on the OTA +Provider application: + +``` +[1648244658368] [59686:7786439] CHIP: [DMG] AccessControl: checking f=1 a=c s=0x000000000000FACE t= c=0x0000_0029 e=0 p=o +[1648244658368] [59686:7786439] CHIP: [DMG] AccessControl: denied +``` + +If this is encountered, follow instructions [here](https://github.com/project-chip/connectedhomeip/tree/master/examples/ota-provider-app/linux#access-control-requirements) -to install. Note that this only needs to be done once. There is no need to write -this ACL entry again unless the KVS store has been removed. +to install. Note that this only needs to be performed once. There is no need to +write this ACL entry again unless the KVS store has been removed. ### Trigger using AnnounceOTAProvider Command @@ -145,7 +211,7 @@ scripts/examples/gn_build_example.sh examples/ota-provider-app/linux/ out chip_c **Run the OTA Provider application** ``` -out/chip-ota-provider-app --discriminator 22 --KVS /tmp/chip_kvs_provider --filepath /tmp/test.bin +out/chip-ota-provider-app --discriminator 22 --secured-device-port 5565 --KVS /tmp/chip_kvs_provider --filepath /tmp/test.bin ``` #### In terminal 2: @@ -203,7 +269,7 @@ scripts/examples/gn_build_example.sh examples/ota-provider-app/linux/ out chip_c **Run the OTA Provider application** ``` -out/chip-ota-provider-app --discriminator 22 --KVS /tmp/chip_kvs_provider --filepath /tmp/test.bin +out/chip-ota-provider-app --discriminator 22 --secured-device-port 5565 --KVS /tmp/chip_kvs_provider --filepath /tmp/test.bin ``` #### In terminal 2: diff --git a/src/app/clusters/ota-requestor/OTARequestor.cpp b/src/app/clusters/ota-requestor/OTARequestor.cpp index 561c29f5c7f582..6e5b57fb145284 100644 --- a/src/app/clusters/ota-requestor/OTARequestor.cpp +++ b/src/app/clusters/ota-requestor/OTARequestor.cpp @@ -157,8 +157,8 @@ void OTARequestor::OnQueryImageResponse(void * context, const QueryImageResponse if (update.softwareVersion > requestorCore->mCurrentVersion) { - ChipLogDetail(SoftwareUpdate, "Update available from %" PRIu32 " to %" PRIu32 " version", - requestorCore->mCurrentVersion, update.softwareVersion); + ChipLogDetail(SoftwareUpdate, "Update available from version %" PRIu32 " to %" PRIu32, requestorCore->mCurrentVersion, + update.softwareVersion); MutableByteSpan updateToken(requestorCore->mUpdateTokenBuffer); // This function copies the bytespan to mutablebytespan only if size of mutablebytespan buffer is greater or equal to // bytespan otherwise we are copying data upto available size. @@ -188,7 +188,7 @@ void OTARequestor::OnQueryImageResponse(void * context, const QueryImageResponse } else { - ChipLogDetail(SoftwareUpdate, "Version %" PRIu32 " is older or same than current version %" PRIu32 ", not updating", + ChipLogDetail(SoftwareUpdate, "Available update version %" PRIu32 " is <= current version %" PRIu32 ", update ignored", update.softwareVersion, requestorCore->mCurrentVersion); requestorCore->RecordNewUpdateState(OTAUpdateStateEnum::kIdle, OTAChangeReasonEnum::kSuccess);