blob: cc65ffe1fc6b37763fa72d85867a302af11c650f [file] [log] [blame]
// Copyright 2018 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.hardware.skipblock;
using zx;
// Matches the value of ZBI_PARTITION_GUID_LEN.
const GUID_LEN uint32 = 16;
@for_deprecated_c_bindings
type PartitionInfo = struct {
/// Partition type GUID.
partition_guid array<uint8, GUID_LEN>;
/// Describes the read/write size.
block_size_bytes uint64;
/// Describes size of partition in terms of blocks.
partition_block_count uint32;
};
@for_deprecated_c_bindings
type ReadWriteOperation = resource struct {
/// Memory object describing buffer to read into or write from.
vmo zx.handle:VMO;
/// VMO offset in bytes.
vmo_offset uint64;
/// Block # to begin operation from.
block uint32;
/// Number of blocks to read or write.
block_count uint32;
};
type WriteBytesMode = strict enum {
/// In this mode, WriteBytes() performs the following steps:
/// 1. Reads data from the minimum block range that covers the specified write range into a
/// buffer. (i.e. if 1 block contains 4 pages, then the minimum block range that covers page
/// range [3, 6] is block range [0, 1])
/// 2. Updates the buffer with input write data,
/// 3. Erase the storage in the minimum block range.
/// 4. Write the updated buffer into the minimum block range.
///
/// This mode only changes data in the specified write range on the storage, data out of the
// range remains unchanged.
READ_MODIFY_ERASE_WRITE = 1;
/// In this mode, WriteBytes() performs the following steps:
/// 1. Erase the minimum block range that covers the specified write range.
/// 2. Write new input data on the specified write range.
///
/// This mode changes data in the minmum block range w.r.t the specified write range on the
/// storage. Storage out of the specified write range will be in an erased state and available
/// for write in the future.
ERASE_WRITE = 2;
};
type WriteBytesOperation = resource struct {
/// Memory object describing buffer to write from.
vmo zx.handle:VMO;
/// VMO offset in bytes.
vmo_offset uint64;
/// Device offset in bytes to begin operation from.
/// Must be flash page aligned.
offset uint64;
/// Number of bytes to write.
/// Must be flash page aligned.
size uint64;
/// The write mode. This option does not affect WriteBytesWithoutErase().
mode WriteBytesMode;
};
/// SkipBlock is a layer on top of a raw NAND device that skips bad blocks, but provides no
/// higher-level processing like wear leveling.
///
/// Skip-block partitions are used when data needs to be accessible by the bootloader. The
/// bootloader doesn't understand the more advanced FTL partitions and this data isn't written
/// frequently enough for performance or wear-leveling to be an issue.
@for_deprecated_c_bindings
protocol SkipBlock {
/// Returns information about the skip-block partition.
///
/// The block count can shrink in the event that a bad block is grown. It is
/// recommended to call this again after a bad block is grown.
GetPartitionInfo() -> (struct {
status zx.status;
partition_info PartitionInfo;
});
/// Reads the specified blocks into the provided vmo.
Read(resource struct {
op ReadWriteOperation;
}) -> (struct {
status zx.status;
});
/// Erases and writes the specified blocks from the provided vmo.
///
/// In the event that bad block is grown, the partition will shrink and
/// `bad_block_grown` will be set to true. Since this causes the logical to
/// physical block map to change, all previously written blocks at logical
/// addresses after the section being written should be considered corrupted,
/// and rewritten if applicable.
Write(resource struct {
op ReadWriteOperation;
}) -> (struct {
status zx.status;
bad_block_grown bool;
});
/// Erases and writes the specified bytes from the provided vmo. If offset
/// and size in `op` are not aligned to `block_size_bytes` then the driver will
/// first read the partitially written blocks and combine them with the
/// provided vmo.
///
/// In the event that bad block is grown, the partition will shrink and
/// `bad_block_grown` will be set to true. Since this causes the logical to
/// physical block map to change, all previously written blocks at logical
/// addresses after the section being written should be considered corrupted,
/// and rewritten if applicable.
WriteBytes(resource struct {
op WriteBytesOperation;
}) -> (struct {
status zx.status;
bad_block_grown bool;
});
/// Similar to WriteBytes except that it does not erase before writing
/// to a block, and it will simply abort when any error, including bad block
/// grown, occurs. The service is intended to be used for fine-tune optimization to reduce
/// NAND PE cycles.
///
/// It should be noted that the caller must follow the requirements of the NAND chip.
/// Not all chips support write-without-erase, and those that do usually require writing
/// only to empty pages and in order (i.e. from the LSB page to MSB page within a block)
/// Failure to follow these requirements is undefined behavior, and may result in unexpected
/// changes to the NAND even outside the given write range and crc errors that leave the
/// storage in an unreadable state.
///
/// The safe way of using this method is to first back up the data in the minimal
/// block range that covers the write range. If the method returns failure, fall back and
/// re-write the backed-up data (can be updated with the new data) to the minimal block
/// range using either WriteBytes or Write method.
WriteBytesWithoutErase(resource struct {
op WriteBytesOperation;
}) -> (struct {
status zx.status;
});
};