| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| library fuchsia.paver; |
| |
| using fuchsia.hardware.block; |
| using fuchsia.hardware.block.volume; |
| using fuchsia.io; |
| using fuchsia.mem; |
| using zx; |
| |
| /// Describes the version of an asset. |
| enum Configuration { |
| A = 1; |
| B = 2; |
| RECOVERY = 3; |
| }; |
| |
| /// Describes assets which may be updated. Each asset has 3 versions, each tied to a particular |
| /// configuration. |
| enum Asset { |
| /// Zircon Boot Image (ZBI) containing the kernel image as well as bootfs. |
| KERNEL = 1; |
| /// Metadata used for verified boot purposes. |
| VERIFIED_BOOT_METADATA = 2; |
| }; |
| |
| /// Set of states configuration may be in. |
| enum ConfigurationStatus { |
| /// Bootable and health checked. |
| HEALTHY = 1; |
| /// Bootable but not yet marked healthy. |
| PENDING = 2; |
| /// Unbootable. |
| UNBOOTABLE = 3; |
| }; |
| |
| struct ReadInfo { |
| /// Offset into VMO where read data starts. |
| zx.off offset; |
| /// Size of read data. |
| uint64 size; |
| }; |
| |
| union ReadResult { |
| /// Error encountered while reading data. |
| 1: zx.status err; |
| /// End of file reached. |
| 2: bool eof; |
| /// Information about location of successfully read data within pre-registered VMO. |
| 3: ReadInfo info; |
| }; |
| |
| union WriteFirmwareResult { |
| /// The result status if a write was attempted. |
| 1: zx.status status; |
| |
| /// True if a write was not attempted due to unsupported content type. |
| /// |
| /// Callers must not treat this as a fatal error, but instead ignore it and |
| /// continue to update the device. This is important to be able to add new |
| /// items to an update package without breaking updates on older devices. |
| 2: bool unsupported_type; |
| }; |
| |
| /// Protocol for streaming the FVM payload. |
| protocol PayloadStream { |
| /// Registers a VMO to stream into. |
| /// |
| /// This can be called once per PayloadStream. |
| /// Any subsequent calls will return ZX_ERR_ALREADY_BOUND. |
| RegisterVmo(handle<vmo> vmo) -> (zx.status status); |
| |
| /// Reads data into the pre-registered vmo. |
| ReadData() -> (ReadResult result); |
| }; |
| |
| [Discoverable] |
| protocol Paver { |
| /// Attempts to auto-discover the data sink where assets and volumes will get paved to. |
| /// On devices with GPT, the partition must have a valid FVM partition in order for |
| /// auto-discovery to find it. If multiple devices are found suitable, error is returned. |
| /// |
| /// `data_sink` will be closed on error, with an epitaph provided on failure reason. |
| FindDataSink(request<DataSink> data_sink); |
| |
| /// Provide a block device to use as a data sink. Assets and volumes will be paved to |
| /// partitions within this block device. |
| /// |
| /// It assumes that channel backing `block_device` also implements `fuchsia.io.Node` for now. |
| /// |
| /// `data_sink` will be closed on error, with an epitaph provided on failure reason. |
| UseBlockDevice(request<fuchsia.hardware.block.Block> block_device, |
| request<DynamicDataSink> data_sink); |
| |
| /// Attempts to auto-discover the boot manager. |
| /// |
| /// `boot_manager` will be closed on error, with an epitaph provided on failure reason. |
| /// ZX_ERR_NOT_SUPPORTED indicates lack of support and configuration A is always booted from. |
| FindBootManager(request<BootManager> boot_manager); |
| }; |
| |
| /// Protocol for reading and writing boot partitions. |
| protocol DataSink { |
| /// Reads partition corresponding to `configuration` and `asset` into a |
| /// vmo and returns it. |
| ReadAsset(Configuration configuration, Asset asset) |
| -> (fuchsia.mem.Buffer asset) error zx.status; |
| |
| /// Writes partition corresponding to `configuration` and `asset` with data from `payload`. |
| /// `payload` may need to be resized to the partition size, so the provided vmo must have |
| /// been created with `ZX_VMO_RESIZABLE` or must be a child VMO that was created with |
| /// `ZX_VMO_CHILD_RESIZABLE`. Will zero out rest of the partition if `payload` is smaller |
| /// than the size of the partition being written. |
| /// |
| /// |
| /// Returns `ZX_ERR_INVALID_ARGS` if `configuration` specifies active configuration. |
| WriteAsset(Configuration configuration, Asset asset, fuchsia.mem.Buffer payload) |
| -> (zx.status status); |
| |
| /// Writes firmware data from `payload`. |
| /// |
| /// `type` is a device-specific string identifying the payload contents, |
| /// used to select the proper paving logic. For example, a device with |
| /// multiple bootloader stages might send them as separate calls to |
| /// `WriteFirmware()`, differentiated by `type`. An empty string |
| /// indicates the default type. |
| /// |
| /// `payload` may need to be resized to the partition size, so the provided |
| /// vmo must have been created with `ZX_VMO_RESIZABLE` or must be a child |
| /// VMO that was created with `ZX_VMO_CHILD_RESIZABLE`. |
| WriteFirmware(string:256 type, fuchsia.mem.Buffer payload) -> (WriteFirmwareResult result); |
| |
| /// Writes FVM with data from streamed via `payload`. This potentially affects all |
| /// configurations. |
| WriteVolumes(PayloadStream payload) -> (zx.status status); |
| |
| /// Writes bootloader partition with data from `payload`. |
| /// |
| /// `payload` may need to be resized to the partition size, so the provided vmo must have |
| /// been created with `ZX_VMO_RESIZABLE` or must be a child VMO that was created with |
| /// `ZX_VMO_CHILD_RESIZABLE`. |
| // TODO(45606): transition users to `WriteFirmware()` and delete this. |
| [Deprecated] |
| WriteBootloader(fuchsia.mem.Buffer payload) -> (zx.status status); |
| |
| /// Writes /data/`filename` with data from `payload`. Overwrites file if it already exists. |
| WriteDataFile(string:fuchsia.io.MAX_PATH filename, fuchsia.mem.Buffer payload) |
| -> (zx.status status); |
| |
| /// Wipes the FVM partition from the device. Should not be confused with factory reset, which |
| /// is less intrusive. The result is that the default FVM volumes are re-created, but empty. |
| /// |
| /// Notable use cases include recovering from corrupted FVM as well as setting device to a |
| /// "clean" state for automation. |
| /// |
| /// If `block_device` is not provided, the paver will perform a search for the the FVM. |
| /// If multiple block devices have valid GPT, `block_device` can be provided to specify |
| /// which one to target. It assumed that channel backing `block_device` also implements |
| /// `fuchsia.io.Node` for now. |
| /// |
| /// On success, returns a channel to the initialized FVM volume. |
| WipeVolume() -> (request<fuchsia.hardware.block.volume.VolumeManager> volume) error zx.status; |
| }; |
| |
| /// Specialized DataSink with dynamic partition tables. |
| protocol DynamicDataSink { |
| compose DataSink; |
| |
| /// Initializes partitions on given block device. |
| InitializePartitionTables() -> (zx.status status); |
| |
| /// Wipes all entries from the partition table of the specified block device. |
| /// Currently only supported on devices with a GPT. |
| /// |
| /// *WARNING*: This API may destructively remove non-fuchsia maintained partitions from |
| /// the block device. |
| WipePartitionTables() -> (zx.status status); |
| }; |
| |
| /// Protocol for managing boot configurations. |
| /// |
| /// All functions will first check the A/B/R metadata and reset it to |
| /// the default state if it's invalid. |
| protocol BootManager { |
| /// Queries active configuration. |
| QueryActiveConfiguration() -> (Configuration configuration) error zx.status; |
| |
| /// Queries status of `configuration`. |
| /// |
| /// Returns `ZX_ERR_INVALID_ARGS` if `Configuration.RECOVERY` is passed in via `configuration`. |
| QueryConfigurationStatus(Configuration configuration) |
| -> (ConfigurationStatus status) error zx.status; |
| |
| /// Updates persistent metadata identifying which configuration should be selected as 'primary' |
| /// for booting purposes. Should only be called after `KERNEL` as well as optional |
| /// `VERIFIED_BOOT_METADATA` assets for specified `configuration` were written successfully. |
| /// |
| /// Returns `ZX_ERR_INVALID_ARGS` if `Configuration.RECOVERY` is passed in via `configuration`. |
| SetConfigurationActive(Configuration configuration) -> (zx.status status); |
| |
| /// Updates persistent metadata identifying whether `configuration` is bootable. |
| /// Should only be called in the following situations: |
| /// * Before `KERNEL` as well as optional `VERIFIED_BOOT_METADATA` assets for specified |
| /// `configuration` are written. |
| /// * After successfully booting from a new configuration and marking it healthy. This method |
| /// would be then called on the old configuration. |
| /// * After "successfully" booting from a new configuration, but encountering an unrecoverable |
| /// error during health check. This method would be then called on the new configuration. |
| /// |
| /// If the configuration is unbootable, no action is taken. |
| /// |
| /// Returns `ZX_ERR_INVALID_ARGS` if `Configuration.RECOVERY` is passed in via `configuration`. |
| SetConfigurationUnbootable(Configuration configuration) -> (zx.status status); |
| |
| /// Updates persistent metadata identifying that active configuration is stable. Used to signal |
| /// "rollback to previous slot" logic is not needed anymore. Meant to be called in subsequent |
| /// boot attempt after `SetActiveConfiguration` was called. Will return error if active |
| /// configuration is currently unbootable. |
| /// |
| /// If the configuration is already marked healthy, no action is taken. |
| SetActiveConfigurationHealthy() -> (zx.status status); |
| }; |