blob: 470ec33dfb36c8da3a75e18754c296c64546d3d7 [file] [log] [blame]
// 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);
};