| // 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.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; |
| }; |
| |
| /// Protocol for streaming the FVM payload. |
| protocol PayloadStream { |
| /// Registers a VMO to stream into. |
| RegisterVmo(handle<vmo> vmo) -> (zx.status status); |
| |
| /// Reads data into the pre-registered vmo. |
| ReadData() -> (ReadResult result); |
| }; |
| |
| /// Protocol for managing boot partitions. |
| /// |
| /// Most of the protocol methods rely on auto-discovery of the storage device |
| /// which will be paved. If the device has no pre-initialized storage devices or |
| /// multiple, the methods will fail. For devices with dynamic partitions (i.e. GPT), |
| /// |InitializePartitionTables| and |WipeVolumes| can be used to control which device is |
| /// paved to. |
| [Discoverable] |
| protocol Paver { |
| /// Initializes ABR metadata. Should only be called to initialize ABR |
| /// metadata for the first time (i.e. it should not be called every boot), |
| /// or recover from corrupted ABR metadata. |
| /// |
| /// Returns `ZX_ERR_NOT_SUPPORTED` if A/B partition scheme is not supported |
| /// and we always boot from configuration A. |
| InitializeAbr() -> (zx.status status); |
| |
| /// Queries active configuration. |
| /// |
| /// Returns `ZX_ERR_NOT_SUPPORTED` if A/B partition scheme is not supported |
| /// and we always boot from configuration A. |
| 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. |
| /// |
| /// Returns `ZX_ERR_NOT_SUPPORTED` if A/B partition scheme is not supported. |
| SetActiveConfigurationHealthy() -> (zx.status status); |
| |
| /// 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 FVM with data from streamed via `payload`. This potentially affects all |
| /// configurations. |
| WriteVolumes(request<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`. |
| 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. |
| /// |
| /// 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.Block>? block_device) |
| -> (request<fuchsia.hardware.block.Block> volume) error zx.status; |
| |
| /// Initializes GPT on given block device and then adds an FVM partition. |
| /// |
| /// |gpt_block_device| specifies the block device to use. It assumed that channel |
| /// backing |gpt_block_device| also implements `fuchsia.io.Node` for now. |
| InitializePartitionTables(request<fuchsia.hardware.block.Block> gpt_block_device) |
| -> (zx.status status); |
| |
| /// Wipes all entries from the partition table of the specified block device. |
| /// Currently only supported on devices with a GPT. |
| /// |
| /// 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. |
| /// |
| /// *WARNING*: This API may destructively remove non-fuchsia maintained partitions from |
| /// the block device. |
| WipePartitionTables(request<fuchsia.hardware.block.Block>? block_device) -> (zx.status status); |
| }; |