ARM-software / psa-firmware-update-spec

The PSA Firmware Update API specification, and discussion of future versions of this API.
Other
4 stars 2 forks source link

Image version information, and data structure definition #7

Open athoelke opened 2 years ago

athoelke commented 2 years ago

For a specific component Id and device model, the image 'version' precisely identifies the firmware image. It is important that the psa_fwu_query() function returns firmware version information for the component, so the Client knows exactly what firmware is currently installed.

Analysis

The version of an image is part of the image metadata, which is either embedded within the image binary (transferred using the psa_fwu_write() function), or within a manifest (transferred using the psa_fwu_set_manifest()/psa_fwu_start() function).

Rationale: The version is not supplied by the Client as a parameter because all of the metadata must be integrity-protected for a secure firmware update.

The type of the version information should be standard, to enable common Client handling of this data, and conversion into forms that are useful for managing the firmware update process.

Within the implementation, version information serves two purposes:

This does not require one specific format for the version data.

[ Aside: For comparison, the PSA Initial Attestation API uses a text string to report software versions. This is useful in a context where the only useful comparison is an equality test, and there is no need to provide an ordering. ]

Comparison

The v0.7 specification defines psa_fwu_version_t as follows:

typedef struct psa_image_version_t {
    uint16_t major;
    uint16_t minor;
    uint16_t patch;
} psa_image_version_t;

Feedback on v0.7, had resulted in a new proposal for this structure, adding a build member and making all fields 32-bit:

typedef struct psa_image_version_t {
    uint32_t major;
    uint32_t minor;
    uint32_t patch;
    uint32_t build;
} psa_image_version_t;

In comparison, the current TF-M implementation uses smaller integer types for the version fields (this form is also common in other contexts):

typedef struct tfm_image_version_s {
    uint8_t iv_major;
    uint8_t iv_minor;
    uint16_t iv_revision;
    uint32_t iv_build_num;
} psa_image_version_t;

Proposal

Sherryzhang2 commented 2 years ago

To make it support all possible cases, I suggest reserving 32 bits for each field.

d3zd3z commented 2 years ago

Using larger types makes sense if this is always about reading, since I expect the limitations would be in the images themselves. If we ever need to go in the other direction, we would need to define the behavior on overflow, though (perhaps if there is a version comparison needed).

Anton-TF commented 2 years ago
d3zd3z commented 2 years ago

The need for "build" is a bit questionable to me in the FWU context. It suggests that someone plans to upgrade a device differentiating images by the build without incrementing a version.

To be honest, I never understood the reasoning for having a build number. It was something we kind of inherited with MCUboot. I think it was supposed to be to distinguish various builds in pre-released versions. But, then we don't have any way to indicate something is a pre-release, so how is one supposed to know when it is pre-released.

We'd need more fields to support something closer to semantic versioning, which goes even more behind what would be desired in a constrained device.

athoelke commented 2 years ago

I am open to suggestions - the addition of build reflects changes made internally after v0.7, and also what is present in TF-M. I could see that it might be just used for information purposes, for example, it could indicate whether this is an A or B build of the firmware version; or it might be populated with the anti-rollback sequence number, to leave major and minor to indicate the semantic version of the firmware.

In the end, this is just a field used to communicate the state of the firmware to the Client, to enable correct management of the device firmware from the OTA Server or Client. The use of the fields will depend on the way that the Firmware Creator versions their firmware and the Update Service unpacks the image metadata. Those might be directed by the way that the Update Server and Client manage versioning and dependencies.

Should the spec be prescriptive about how this field is used, or provide some recommendations or examples, or just state that this is left to the implementation and Client/Server to agree on the usage?

athoelke commented 2 years ago

I've now had a look at the OTA section in the Matter specification, and it expects that software version information can be encoded in a 32-bit integer, and provides a total ordering between any two versions. This is fully compatible with a 8/8/16 structure.

It seems that we are unlikely to regret using a compact representation at this point, given the alignment this has with other projects.

athoelke commented 2 years ago

Proposal

Define a compact version structure in the v1.0 API:

typedef struct psa_fwu_image_version_t {
    uint8_t  major;
    uint8_t  minor;
    uint16_t patch;
    uint32_t build;
} psa_fwu_image_version_t;