aboutsummaryrefslogtreecommitdiff
path: root/pw_software_update/public/pw_software_update/bundled_update_backend.h
diff options
context:
space:
mode:
Diffstat (limited to 'pw_software_update/public/pw_software_update/bundled_update_backend.h')
-rw-r--r--pw_software_update/public/pw_software_update/bundled_update_backend.h105
1 files changed, 96 insertions, 9 deletions
diff --git a/pw_software_update/public/pw_software_update/bundled_update_backend.h b/pw_software_update/public/pw_software_update/bundled_update_backend.h
index 40b704a4b..ae80e065e 100644
--- a/pw_software_update/public/pw_software_update/bundled_update_backend.h
+++ b/pw_software_update/public/pw_software_update/bundled_update_backend.h
@@ -30,13 +30,17 @@ class BundledUpdateBackend {
public:
virtual ~BundledUpdateBackend() = default;
- // Optionally verify that the instance/content of the target file in use
- // on-device matches the metadata in the given manifest, called before apply.
- // (e.g. by checksum, if failed abort partial update and wipe/mark-invalid
- // running manifest)
+ // Perform optional, product-specific validations to the specified target
+ // file, using whatever metadata available in manifest.
+ //
+ // This is called for each target file after the standard verification has
+ // passed.
virtual Status VerifyTargetFile(
[[maybe_unused]] ManifestAccessor manifest,
[[maybe_unused]] std::string_view target_file_name) {
+ // TODO(backend): Perform any additional product-specific validations.
+ // It is safe to assume the target's payload has passed standard
+ // verification.
return OkStatus();
};
@@ -86,16 +90,99 @@ class BundledUpdateBackend {
stream::Reader& target_payload,
size_t update_bundle_offset) = 0;
- // Get reader of the device's current manifest.
+ // Backend to probe the device manifest and prepare a ready-to-go reader
+ // for it. See the comments to `GetCurrentManfestReader()` for more context.
+ virtual Status BeforeManifestRead() {
+ // Todo(backend):
+ // 1. Probe device to see if a well-formed manifest already exists.
+ // 2. If not, return `Status::NotFound()`. Note this will cause
+ // anti-rollback to skip. So please don't always return
+ // `Status::NotFound()`!
+ // 3. If yes, instantiate and activate a reader for the manifest!
+ // 4. Return any unexpected condition as errors but note this will cause
+ // the current software update session to abort.
+ return OkStatus();
+ }
+
+ // Backend to provide a ready-to-go reader for the on-device manifest blob.
+ // This function is called after a successful `BeforeManifestRead()`,
+ // potentially more than once.
+ //
+ // This manifest blob is a serialized `message Manifest{...}` as defined in
+ // update_bundle.proto.
+ //
+ // This manifest blob is ALWAYS and EXCLUSIVELY persisted by a successful
+ // software update. Thus it may not available before the first software
+ // update, in which case `BeforeManifestRead()` should've returned
+ // `Status::NotFound()`.
+ //
+ // This manifest contains trusted metadata of all software currently running
+ // on the device and used for anti-rollback checks. It MUST NOT be tampered
+ // by factory resets, flashing, or any other means other than software
+ // updates.
virtual Result<stream::SeekableReader*> GetCurrentManifestReader() {
+ // Todo(backend):
+ // 1. Double check if a ready-to-go reader has been prepared by
+ // `BeforeManifestRead()`.
+ // 2. If yes (expected), return the reader.
+ // 3. If not (unexpected), return `Status::FailedPrecondition()`.
return Status::Unimplemented();
}
- // Use a reader that provides a new manifest for the device to save.
- virtual Status UpdateCurrentManifest(
- [[maybe_unused]] stream::Reader& manifest) {
+ // TODO(alizhang): Deprecate GetCurrentManifestReader in favor of
+ // `GetManifestReader()`.
+ virtual Result<stream::SeekableReader*> GetManifestReader() {
+ return GetCurrentManifestReader();
+ }
+
+ // Backend to prepare for on-device manifest update, e.g. make necessary
+ // efforts to ready the manifest writer. The manifest writer is used to
+ // persist a new manifest on-device following a successful software update.
+ // Manifest writing is never mixed with reading (i.e. reader and writer are
+ // used sequentially).
+ virtual Status BeforeManifestWrite() {
+ // Todo(backend):
+ // 1. Instantiate and activate a manifest writer pointing at a persistent
+ // storage that at least could survive a factory data reset (FDR), if not
+ // tamper-resistant.
return OkStatus();
- };
+ }
+
+ // Backend to provide a ready-to-go writer for the on-device manifest blob.
+ // This function is called after a successful `BeforeManifestWrite()`,
+ // potentially more than once.
+ //
+ // This manifest blob is a serialized `message Manifest{...}` as defined in
+ // update_bundle.proto.
+ //
+ // This manifest blob is ALWAYS and EXCLUSIVELY persisted by a successful
+ // software update.
+ //
+ // This manifest contains trusted metadata of all software currently running
+ // on the device and used for anti-rollback checks. It MUST NOT be tampered
+ // by factory resets, flashing, or any other means other than software
+ // updates.
+ virtual Result<stream::Writer*> GetManifestWriter() {
+ // Todo(backend):
+ // 1. Double check a writer is ready to go as result of
+ // `BeforeManifestWrite()`.
+ // 2. If yes (expected), simply return the writer.
+ // 3. If not (unexpected), return `Status::FailedPrecondition()`.
+ return Status::Unimplemented();
+ }
+
+ // Backend to finish up manifest writing.
+ virtual Status AfterManifestWrite() {
+ // Todo(backend):
+ // Protect the newly persisted manifest blob. This is to make manifest
+ // probing / reading easier and more reliable. This could involve taking
+ // a measurement (e.g. checksum) and storing that measurement in a
+ // FDR-safe tag, replicating the manifest in a backup location if the
+ // backing media is unreliable (e.g. raw NAND) etc.
+ //
+ // It is safe to assume the writing has been successful in this function.
+ return OkStatus();
+ }
// Do any work needed to finish the apply of the update and do a required
// reboot of the device!