blob: 417dbcaf99b96a0398d817f59d781f208469c70b [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.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);
};