openhcl_tdisp/
lib.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! This module provides resources and traits for a TDISP client device
5//! interface for OpenHCL devices.
6//!
7//! See: `vm/devices/tdisp` for more information.
8
9use std::future::Future;
10
11// Re-export the TDISP protocol types necessary for OpenHCL from top level tdisp crates
12// to avoid a direct dependency on tdisp_proto and tdisp.
13pub use tdisp::TdispGuestOperationError;
14pub use tdisp::devicereport::TdiReportStruct;
15pub use tdisp::serialize_proto::deserialize_command;
16pub use tdisp::serialize_proto::deserialize_response;
17pub use tdisp::serialize_proto::serialize_command;
18pub use tdisp::serialize_proto::serialize_response;
19pub use tdisp_proto::GuestToHostCommand;
20pub use tdisp_proto::GuestToHostCommandExt;
21pub use tdisp_proto::GuestToHostResponse;
22pub use tdisp_proto::GuestToHostResponseExt;
23pub use tdisp_proto::TdispCommandRequestGetDeviceInterfaceInfo;
24pub use tdisp_proto::TdispCommandResponseBind;
25pub use tdisp_proto::TdispCommandResponseGetDeviceInterfaceInfo;
26pub use tdisp_proto::TdispCommandResponseGetTdiReport;
27pub use tdisp_proto::TdispCommandResponseStartTdi;
28pub use tdisp_proto::TdispCommandResponseUnbind;
29pub use tdisp_proto::TdispDeviceInterfaceInfo;
30pub use tdisp_proto::TdispGuestOperationErrorCode;
31pub use tdisp_proto::TdispGuestProtocolType;
32pub use tdisp_proto::TdispGuestUnbindReason;
33pub use tdisp_proto::TdispReportType;
34
35use tdisp_proto::TdispCommandRequestBind;
36use tdisp_proto::TdispCommandRequestGetTdiReport;
37use tdisp_proto::TdispCommandRequestStartTdi;
38use tdisp_proto::TdispCommandRequestUnbind;
39use tdisp_proto::guest_to_host_command::Command;
40
41/// Represents a TDISP device assigned to a guest partition. This trait allows
42/// implementations to send TDISP commands to the host through a backing interface
43/// such as a VPCI channel.
44///
45pub trait TdispVirtualDeviceInterface: Send + Sync {
46    /// Sends a TDISP command to the device through the VPCI channel.
47    fn send_tdisp_command(
48        &self,
49        payload: GuestToHostCommand,
50    ) -> impl Future<Output = Result<GuestToHostResponse, anyhow::Error>> + Send;
51
52    /// Get the TDISP interface info for the device.
53    fn tdisp_get_device_interface_info(
54        &self,
55    ) -> impl Future<Output = anyhow::Result<TdispDeviceInterfaceInfo>> + Send;
56
57    /// Bind the device to the current partition and transition to Locked.
58    /// NOTE: While the device is in the Locked state, it can continue to
59    /// perform unencrypted operations until it is moved to the Running state.
60    /// The Locked state is a transitional state that is designed to keep
61    /// the device from modifying its resources prior to attestation.
62    fn tdisp_bind_interface(&self) -> impl Future<Output = anyhow::Result<()>> + Send;
63
64    /// Start a bound device by transitioning it to the Run state from the Locked state.
65    /// This allows for attestation and for resources to be accepted into the guest context.
66    fn tdisp_start_device(&self) -> impl Future<Output = anyhow::Result<()>> + Send;
67
68    /// Request a device report from the TDI or physical device depending on the report type.
69    fn tdisp_get_device_report(
70        &self,
71        report_type: &TdispReportType,
72    ) -> impl Future<Output = anyhow::Result<Vec<u8>>> + Send;
73
74    /// Request a TDI report from the TDI or physical device.
75    fn tdisp_get_tdi_report(&self) -> impl Future<Output = anyhow::Result<TdiReportStruct>> + Send;
76
77    /// Request the TDI device id from the vpci channel.
78    fn tdisp_get_tdi_device_id(&self) -> impl Future<Output = anyhow::Result<u64>> + Send;
79
80    /// Request to unbind the device and return to the Unlocked state.
81    fn tdisp_unbind(
82        &self,
83        reason: TdispGuestUnbindReason,
84    ) -> impl Future<Output = anyhow::Result<()>> + Send;
85}
86
87/// Creates a [`GuestToHostCommand`] for the `GetDeviceInterfaceInfo` command.
88pub fn new_get_device_interface_info_command(
89    device_id: u64,
90    guest_protocol_type: TdispGuestProtocolType,
91) -> GuestToHostCommand {
92    GuestToHostCommand {
93        device_id,
94        command: Some(Command::GetDeviceInterfaceInfo(
95            TdispCommandRequestGetDeviceInterfaceInfo {
96                guest_protocol_type: guest_protocol_type as i32,
97            },
98        )),
99    }
100}
101
102/// Creates a [`GuestToHostCommand`] for the `Bind` command.
103pub fn new_bind_command(device_id: u64) -> GuestToHostCommand {
104    GuestToHostCommand {
105        device_id,
106        command: Some(Command::Bind(TdispCommandRequestBind {})),
107    }
108}
109
110/// Creates a [`GuestToHostCommand`] for the `StartTdi` command.
111pub fn new_start_tdi_command(device_id: u64) -> GuestToHostCommand {
112    GuestToHostCommand {
113        device_id,
114        command: Some(Command::StartTdi(TdispCommandRequestStartTdi {})),
115    }
116}
117
118/// Creates a [`GuestToHostCommand`] for the `GetTdiReport` command.
119pub fn new_get_tdi_report_command(
120    device_id: u64,
121    report_type: TdispReportType,
122) -> GuestToHostCommand {
123    GuestToHostCommand {
124        device_id,
125        command: Some(Command::GetTdiReport(TdispCommandRequestGetTdiReport {
126            report_type: report_type as i32,
127        })),
128    }
129}
130
131/// Creates a [`GuestToHostCommand`] for the `Unbind` command.
132pub fn new_unbind_command(device_id: u64, reason: TdispGuestUnbindReason) -> GuestToHostCommand {
133    GuestToHostCommand {
134        device_id,
135        command: Some(Command::Unbind(TdispCommandRequestUnbind {
136            unbind_reason: reason as i32,
137        })),
138    }
139}