[block] Add FIDL protocol for block devices

These bindings have parity with the remaining ioctl declarations.
For direct comparison, refer to: system/public/zircon/device/block.h

Test: Declarations only; bindings utilized in subsequent patches.

Change-Id: I6cfba4834b3d4688e1be92c04da20bd945df4afc
diff --git a/system/fidl/fuchsia-hardware-block-partition/partition.fidl b/system/fidl/fuchsia-hardware-block-partition/partition.fidl
new file mode 100644
index 0000000..f8442cd
--- /dev/null
+++ b/system/fidl/fuchsia-hardware-block-partition/partition.fidl
@@ -0,0 +1,33 @@
+// 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.hardware.block.partition;
+using zx;
+using fuchsia.hardware.block as block;
+
+const uint32 GUID_LENGTH = 16;
+const uint32 NAME_LENGTH = 24;
+
+// A Globally Unique IDentifier, which may be utilized to identify
+// a partition.
+struct GUID {
+    array<uint8>:GUID_LENGTH value;
+};
+
+// Partition describes a region of one or more block devices, labelled
+// with distinguishing identifiers.
+[Layout = "Simple", FragileBase]
+interface Partition : block.Block {
+    // Gets the type GUID of the partition (if one exists).
+    // If the partition has no type GUID, ZX_ERR_NOT_SUPPORTED is returned.
+    GetTypeGuid() -> (zx.status status, GUID? guid);
+
+    // Gets the instance GUID of the partition (if one exists).
+    // If the partition has no instance GUID, ZX_ERR_NOT_SUPPORTED is returned.
+    GetInstanceGuid() -> (zx.status status, GUID? guid);
+
+    // Gets the name of the partition (if one exists).
+    // If the partition has no name, ZX_ERR_NOT_SUPPORTED is returned.
+    GetName() -> (zx.status status, string:NAME_LENGTH? name);
+};
diff --git a/system/fidl/fuchsia-hardware-block-partition/rules.mk b/system/fidl/fuchsia-hardware-block-partition/rules.mk
new file mode 100644
index 0000000..065672b
--- /dev/null
+++ b/system/fidl/fuchsia-hardware-block-partition/rules.mk
@@ -0,0 +1,21 @@
+# 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.
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+MODULE := $(LOCAL_DIR)
+
+MODULE_TYPE := fidl
+
+MODULE_PACKAGE := fidl
+
+MODULE_FIDL_LIBRARY := fuchsia.hardware.block.partition
+
+MODULE_SRCS += \
+    $(LOCAL_DIR)/partition.fidl \
+
+MODULE_FIDL_DEPS := \
+    system/fidl/fuchsia-hardware-block \
+
+include make/module.mk
diff --git a/system/fidl/fuchsia-hardware-block-volume/rules.mk b/system/fidl/fuchsia-hardware-block-volume/rules.mk
new file mode 100644
index 0000000..308fc9e
--- /dev/null
+++ b/system/fidl/fuchsia-hardware-block-volume/rules.mk
@@ -0,0 +1,22 @@
+# 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.
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+MODULE := $(LOCAL_DIR)
+
+MODULE_TYPE := fidl
+
+MODULE_PACKAGE := fidl
+
+MODULE_FIDL_LIBRARY := fuchsia.hardware.block.volume
+
+MODULE_SRCS += \
+    $(LOCAL_DIR)/volume.fidl \
+
+MODULE_FIDL_DEPS := \
+    system/fidl/fuchsia-hardware-block \
+    system/fidl/fuchsia-hardware-block-partition \
+
+include make/module.mk
diff --git a/system/fidl/fuchsia-hardware-block-volume/volume.fidl b/system/fidl/fuchsia-hardware-block-volume/volume.fidl
new file mode 100644
index 0000000..a33dddf
--- /dev/null
+++ b/system/fidl/fuchsia-hardware-block-volume/volume.fidl
@@ -0,0 +1,102 @@
+// 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.hardware.block.volume;
+using zx;
+using fuchsia.hardware.block.partition as partition;
+
+// VolumeInfo describes characteristics of either a single Volume, or all
+// Volumes combined.
+struct VolumeInfo {
+    // Size of a single slice, in bytes.
+    uint64 slice_size;
+
+    // Number of addressable slices.
+    uint64 vslice_count;
+
+    // Total number of allocatable slices.
+    uint64 pslice_total_count;
+
+    // Total number of currently allocated slices.
+    uint64 pslice_allocated_count;
+};
+
+// Indicates that the partition should be created as inactive, implying that it
+// will be destroyed on reboot (unless activated by a call to "Activate").
+const uint32 AllocatePartitionFlagInactive = 0x00000001;
+
+// VolumeManager controls a collection of Volumes.
+[Layout = "Simple"]
+interface VolumeManager {
+    // Allocates a virtual partition with the requested features.
+    //
+    // |slice_count| is the number of slices initially allocated to the partition, at
+    // offset zero. The number of slices allocated to a new partition must be at least one.
+    // |type| and |value| indicate type and instance GUIDs for the partition, respectively.
+    // |name| indicates the name of the new partition.
+    AllocatePartition(uint64 slice_count, partition.GUID type,
+                      partition.GUID instance, string:partition.NAME_LENGTH name,
+                      uint32 flags) -> (zx.status status);
+
+    // Gets slice size information about all volumes.
+    Query() -> (zx.status status, VolumeInfo? info);
+
+    // Atomically marks a vpartition (by instance GUID) as inactive, while finding
+    // another partition (by instance GUID) and marking it as active.
+    //
+    // If the "old" partition does not exist, the GUID is ignored.
+    // If the "old" partition is the same as the "new" partition, the "old"
+    // GUID is ignored.
+    // If the "new" partition does not exist, |ZX_ERR_NOT_FOUND| is returned.
+    //
+    // This function does not destroy the "old" partition, it just marks it as
+    // inactive -- to reclaim that space, the "old" partition must be explicitly
+    // destroyed.  This destruction can also occur automatically when the FVM driver
+    // is rebound (i.e., on reboot).
+    //
+    // This function may be useful for A/B updates within the FVM,
+    // since it will allow activating updated partitions.
+    Activate(partition.GUID old_guid, partition.GUID new_guid) -> (zx.status status);
+};
+
+// An arbitrary cap on the number of slices which may be requested when querying
+// for allocation information from a volume.
+const uint32 MAX_SLICE_REQUESTS = 16;
+
+// VsliceRange describes a range of virtual slices: start, length, and allocated status.
+//
+// These ranges are returned in an ordered container, which implicitly describes the
+// starting offset, starting from the "index zero" slice.
+struct VsliceRange {
+    // True if the virtual slices are allocated, false otherwise.
+    bool allocated;
+
+    // The number of contiguous virtual slices.
+    uint64 count;
+};
+
+// Volume is a partition which may access virtually-mapped blocks within a device.
+[Layout = "Simple"]
+interface Volume : partition.Partition {
+    // Gets slice size information about the parent volume.
+    Query() -> (zx.status status, VolumeInfo? info);
+
+    // Returns the number of contiguous allocated (or unallocated) vslices
+    // starting from each vslice.
+    //
+    // TODO(smklein): Replace array with vector; doing so would be non-simple.
+    QuerySlices(vector<uint64>:MAX_SLICE_REQUESTS start_slices)
+      -> (zx.status status, array<VsliceRange>:MAX_SLICE_REQUESTS response, uint64 response_count);
+
+    // Extends the mapping of this partition.
+    Extend(uint64 start_slice, uint64 slice_count) -> (zx.status status);
+
+    // Shrinks a virtual partition. Returns |ZX_OK| if ANY slices are
+    // freed, even if part of the requested range contains unallocated slices.
+    Shrink(uint64 start_slice, uint64 slice_count) -> (zx.status status);
+
+    // Destroys the current partition, removing it from the VolumeManager, and
+    // freeing all underlying storage.
+    Destroy() -> (zx.status status);
+};
diff --git a/system/fidl/fuchsia-hardware-block/block.fidl b/system/fidl/fuchsia-hardware-block/block.fidl
new file mode 100644
index 0000000..c1a5b66
--- /dev/null
+++ b/system/fidl/fuchsia-hardware-block/block.fidl
@@ -0,0 +1,105 @@
+// 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.hardware.block;
+using zx;
+
+// All writes to the block device will fail.
+const uint32 FLAG_READONLY = 0x00000001;
+
+// The block device may be removed from the device during operation.
+const uint32 FLAG_REMOVABLE = 0x00000002;
+
+// The device has a bootdata partition map.
+const uint32 FLAG_BOOTPART = 0x00000004;
+
+// The maximum value for a transfer size, identifying that there
+// effectively exists no maximum for a single operation.
+const uint32 MAX_TRANSFER_UNBOUNDED = 0xFFFFFFFF;
+
+// Describes metatadata about a block device.
+struct BlockInfo {
+    // The number of blocks in this block device.
+    uint64 block_count;
+
+    // The size of a single block.
+    uint32 block_size;
+
+    // The maximum size, in bytes, of a transfer.
+    // Set to MAX_TRANSFER_UNBOUNDED if no such maximum exists.
+    uint32 max_transfer_size;
+
+    // Identifiers about the device; refer to the "FLAG_*" documentation above.
+    uint32 flags;
+
+    uint32 reserved;
+};
+
+// Describes statistics about the operations on the block device since boot.
+struct BlockStats {
+    // The total number of operations which have been processed.
+    int64 ops;
+
+    // The total number of blocks which have been acted upon.
+    int64 blocks;
+
+    // The total number of requests to read from the device.
+    int64 reads;
+
+    // The total number of blocks which have been read from the device.
+    int64 blocks_read;
+
+    // The total number of requests to write to the device.
+    int64 writes;
+
+    // The total number of blocks which have been written to the device.
+    int64 blocks_written;
+};
+
+// A client-identifier to a VMO.
+// This value may be utilized by clients to refer to a VMO which is being held
+// by a block device server.
+struct VmoID {
+    uint16 id;
+};
+
+// Dummy value reserved for "invalid" VmoID. Will never be allocated by the server,
+// and may be utilized as a local value for an unallocated ID.
+const uint16 VMOID_INVALID = 0;
+
+// Defines access to a device which is accessible in block-granularity chunks
+// for reading and writing.
+[Layout = "Simple", FragileBase]
+interface Block {
+    // Get information about the underlying block device.
+    GetInfo() -> (zx.status status, BlockInfo? info);
+
+    // Returns stats about the block device on the provided buffer and optionally
+    // clears the counters.
+    GetStats(bool clear) -> (zx.status status, BlockStats? stats);
+
+    // Sets up a FIFO-based server on the block device; acquire the handle to it.
+    GetFifo() -> (zx.status status, handle<fifo> fifo);
+
+    // Attaches a VMO to the currently running FIFO server.
+    AttachVmo(handle<vmo> vmo) -> (zx.status status, VmoID? vmoid);
+
+    // Shuts down the fifo server, waiting for it to be ready to be started again.
+    //
+    // When this method returns, a client may safely invoke GetFifo to acquire
+    // a new connection to the block server, without being told that a server
+    // is already serving requests on a different fifo.
+    //
+    // If, instead of invoking "CloseFifo", a client merely closes their fifo,
+    // the server automatically cleans up all resources anyway. In this case,
+    // however, the client will have no guarantee that the next invocation of
+    // "GetFifo" will return a connection successfully.
+    CloseFifo() -> (zx.status status);
+
+    // Rebinds the block device (if supported).
+    //
+    // WARNING: This is only added for parity with block device ioctls;
+    // this is going to move into the device FIDL API.
+    RebindDevice() -> (zx.status status);
+};
diff --git a/system/fidl/fuchsia-hardware-block/rules.mk b/system/fidl/fuchsia-hardware-block/rules.mk
index 731eb3d..7c729be 100644
--- a/system/fidl/fuchsia-hardware-block/rules.mk
+++ b/system/fidl/fuchsia-hardware-block/rules.mk
@@ -13,6 +13,7 @@
 MODULE_FIDL_LIBRARY := fuchsia.hardware.block
 
 MODULE_SRCS += \
+    $(LOCAL_DIR)/block.fidl \
     $(LOCAL_DIR)/ftl.fidl \
 
 include make/module.mk