From 3b822ffd0740cc4271b6e15675b185a06b2c421d Mon Sep 17 00:00:00 2001 From: "Yang, Longlong" Date: Mon, 30 Oct 2023 02:51:10 -0400 Subject: [PATCH] add tdisp to emu test. Signed-off-by: Yang, Longlong --- Cargo.lock | 15 + Cargo.toml | 2 +- .../pci_ide_km_rsp_dispatcher.rs | 2 +- tdisp/Cargo.toml | 9 +- tdisp/build.rs | 86 ++ tdisp/etc/config.json | 7 + tdisp/src/common.rs | 24 - tdisp/src/config.rs | 21 +- tdisp/src/context.rs | 110 -- tdisp/src/device.rs | 18 - tdisp/src/lib.rs | 16 +- tdisp/src/message.rs | 1042 -------------- tdisp/src/pci_tdisp.rs | 1219 +++++++++++++++++ tdisp/src/pci_tdisp_requester/mod.rs | 26 + .../pci_tdisp_req_get_capabilities.rs | 92 ++ .../pci_tdisp_req_get_interface_report.rs | 128 ++ .../pci_tdisp_req_get_interface_state.rs | 79 ++ .../pci_tdisp_req_get_version.rs | 77 ++ .../pci_tdisp_req_lock_interface.rs | 103 ++ .../pci_tdisp_req_start_interface.rs | 92 ++ .../pci_tdisp_req_stop_interface.rs | 74 + tdisp/src/pci_tdisp_responder/mod.rs | 25 + .../pci_tdisp_rsp_capabilities.rs | 184 +++ .../pci_tdisp_rsp_dispatcher.rs | 79 ++ .../pci_tdisp_rsp_error.rs | 97 ++ .../pci_tdisp_rsp_interface_report.rs | 194 +++ .../pci_tdisp_rsp_interface_state.rs | 138 ++ .../pci_tdisp_rsp_lock_interface.rs | 164 +++ .../pci_tdisp_rsp_start_interface.rs | 139 ++ .../pci_tdisp_rsp_stop_interface.rs | 133 ++ .../pci_tdisp_rsp_version.rs | 119 ++ tdisp/src/state_machine.rs | 89 -- tdisp/src/tdisp_codec.rs | 20 - .../bind_p2p_stream_request_req.rs | 77 -- .../get_device_interface_report_req.rs | 80 -- .../get_device_interface_state_req.rs | 80 -- .../get_tdisp_capabilities_req.rs | 77 -- .../tdisp_requester/get_tdisp_version_req.rs | 77 -- .../lock_interface_request_req.rs | 77 -- tdisp/src/tdisp_requester/mod.rs | 40 - .../set_mmio_attribute_request_req.rs | 77 -- .../start_interface_request_req.rs | 77 -- .../stop_interface_request_req.rs | 77 -- .../unbind_p2p_stream_request_req.rs | 77 -- tdisp/src/tdisp_requester/vdm_request.rs | 76 - .../bind_p2p_stream_request_rsp.rs | 69 - .../device_interface_report_rsp.rs | 72 - .../device_interface_state_rsp.rs | 64 - .../lock_interface_request_rsp.rs | 106 -- tdisp/src/tdisp_responder/mod.rs | 266 ---- .../set_mmio_attribute_request_rsp.rs | 69 - .../start_interface_request_rsp.rs | 78 -- .../stop_interface_request_rsp.rs | 85 -- .../tdisp_responder/tdisp_capabilities_rsp.rs | 58 - tdisp/src/tdisp_responder/tdisp_error_rsp.rs | 53 - .../src/tdisp_responder/tdisp_version_rsp.rs | 59 - .../unbind_p2p_stream_request_rsp.rs | 66 - tdisp/src/tdisp_responder/vdm_response.rs | 54 - test/spdm-requester-emu/Cargo.toml | 1 + test/spdm-requester-emu/src/main.rs | 179 ++- test/spdm-responder-emu/Cargo.toml | 2 + test/spdm-responder-emu/src/main.rs | 75 +- ...xample.rs => spdm_device_idekm_example.rs} | 2 +- .../src/spdm_device_tdisp_example.rs | 344 +++++ 64 files changed, 3891 insertions(+), 3326 deletions(-) create mode 100644 tdisp/build.rs create mode 100644 tdisp/etc/config.json delete mode 100644 tdisp/src/common.rs delete mode 100644 tdisp/src/context.rs delete mode 100644 tdisp/src/device.rs delete mode 100644 tdisp/src/message.rs create mode 100644 tdisp/src/pci_tdisp.rs create mode 100644 tdisp/src/pci_tdisp_requester/mod.rs create mode 100644 tdisp/src/pci_tdisp_requester/pci_tdisp_req_get_capabilities.rs create mode 100644 tdisp/src/pci_tdisp_requester/pci_tdisp_req_get_interface_report.rs create mode 100644 tdisp/src/pci_tdisp_requester/pci_tdisp_req_get_interface_state.rs create mode 100644 tdisp/src/pci_tdisp_requester/pci_tdisp_req_get_version.rs create mode 100644 tdisp/src/pci_tdisp_requester/pci_tdisp_req_lock_interface.rs create mode 100644 tdisp/src/pci_tdisp_requester/pci_tdisp_req_start_interface.rs create mode 100644 tdisp/src/pci_tdisp_requester/pci_tdisp_req_stop_interface.rs create mode 100644 tdisp/src/pci_tdisp_responder/mod.rs create mode 100644 tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_capabilities.rs create mode 100644 tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_dispatcher.rs create mode 100644 tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_error.rs create mode 100644 tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_interface_report.rs create mode 100644 tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_interface_state.rs create mode 100644 tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_lock_interface.rs create mode 100644 tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_start_interface.rs create mode 100644 tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_stop_interface.rs create mode 100644 tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_version.rs delete mode 100644 tdisp/src/state_machine.rs delete mode 100644 tdisp/src/tdisp_codec.rs delete mode 100644 tdisp/src/tdisp_requester/bind_p2p_stream_request_req.rs delete mode 100644 tdisp/src/tdisp_requester/get_device_interface_report_req.rs delete mode 100644 tdisp/src/tdisp_requester/get_device_interface_state_req.rs delete mode 100644 tdisp/src/tdisp_requester/get_tdisp_capabilities_req.rs delete mode 100644 tdisp/src/tdisp_requester/get_tdisp_version_req.rs delete mode 100644 tdisp/src/tdisp_requester/lock_interface_request_req.rs delete mode 100644 tdisp/src/tdisp_requester/mod.rs delete mode 100644 tdisp/src/tdisp_requester/set_mmio_attribute_request_req.rs delete mode 100644 tdisp/src/tdisp_requester/start_interface_request_req.rs delete mode 100644 tdisp/src/tdisp_requester/stop_interface_request_req.rs delete mode 100644 tdisp/src/tdisp_requester/unbind_p2p_stream_request_req.rs delete mode 100644 tdisp/src/tdisp_requester/vdm_request.rs delete mode 100644 tdisp/src/tdisp_responder/bind_p2p_stream_request_rsp.rs delete mode 100644 tdisp/src/tdisp_responder/device_interface_report_rsp.rs delete mode 100644 tdisp/src/tdisp_responder/device_interface_state_rsp.rs delete mode 100644 tdisp/src/tdisp_responder/lock_interface_request_rsp.rs delete mode 100644 tdisp/src/tdisp_responder/mod.rs delete mode 100644 tdisp/src/tdisp_responder/set_mmio_attribute_request_rsp.rs delete mode 100644 tdisp/src/tdisp_responder/start_interface_request_rsp.rs delete mode 100644 tdisp/src/tdisp_responder/stop_interface_request_rsp.rs delete mode 100644 tdisp/src/tdisp_responder/tdisp_capabilities_rsp.rs delete mode 100644 tdisp/src/tdisp_responder/tdisp_error_rsp.rs delete mode 100644 tdisp/src/tdisp_responder/tdisp_version_rsp.rs delete mode 100644 tdisp/src/tdisp_responder/unbind_p2p_stream_request_rsp.rs delete mode 100644 tdisp/src/tdisp_responder/vdm_response.rs rename test/spdm-responder-emu/src/{spdm_device_example.rs => spdm_device_idekm_example.rs} (98%) create mode 100644 test/spdm-responder-emu/src/spdm_device_tdisp_example.rs diff --git a/Cargo.lock b/Cargo.lock index 240db571..627a42ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1629,6 +1629,7 @@ dependencies = [ "spdm-emu", "spdmlib", "spin 0.9.8", + "tdisp", "tokio", ] @@ -1646,6 +1647,7 @@ dependencies = [ "spdm-emu", "spdmlib", "spin 0.9.8", + "tdisp", "tokio", "zeroize", ] @@ -1758,6 +1760,19 @@ dependencies = [ "x86_64", ] +[[package]] +name = "tdisp" +version = "0.2.0" +dependencies = [ + "bitflags 1.3.2", + "codec", + "conquer-once", + "serde", + "serde_json", + "spdmlib", + "spin 0.9.8", +] + [[package]] name = "tempfile" version = "3.8.0" diff --git a/Cargo.toml b/Cargo.toml index 74e9f9db..c3ebcfec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ members = [ "executor", "sys_time", "idekm", + "tdisp", "test/spdm-requester-emu", "test/spdm-responder-emu", "test/spdmlib-test", @@ -65,7 +66,6 @@ exclude = [ "external/ring", "external/webpki", "fuzz-target/", - "tdisp" ] resolver = "2" diff --git a/idekm/src/pci_ide_km_responder/pci_ide_km_rsp_dispatcher.rs b/idekm/src/pci_ide_km_responder/pci_ide_km_rsp_dispatcher.rs index f542a489..33e949dd 100644 --- a/idekm/src/pci_ide_km_responder/pci_ide_km_rsp_dispatcher.rs +++ b/idekm/src/pci_ide_km_responder/pci_ide_km_rsp_dispatcher.rs @@ -19,7 +19,7 @@ pub const PCI_IDE_KM_INSTANCE: VendorDefinedStruct = VendorDefinedStruct { vendor_context: 0, }; -fn pci_ide_km_rsp_dispatcher( +pub fn pci_ide_km_rsp_dispatcher( _vendor_context: usize, vendor_defined_req_payload_struct: &VendorDefinedReqPayloadStruct, ) -> SpdmResult { diff --git a/tdisp/Cargo.toml b/tdisp/Cargo.toml index 848d1a65..bb8809b1 100644 --- a/tdisp/Cargo.toml +++ b/tdisp/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "tdisp" license = "BSD-2-Clause-Patent" -version = "0.1.0" +version = "0.2.0" authors = [ "Jiewen Yao ", "Xiaoyu Lu ", @@ -12,12 +12,15 @@ edition = "2018" [dev-dependencies] [build-dependencies] +serde_json = "1.0" +serde = { version = "1.0", features = ["derive"] } +spin = { version = "0.9.8", optional = true } [dependencies] codec = { path = "../codec" } bitflags = "1.2.1" -zeroize = { version = "1.5.0", features = ["zeroize_derive"]} spdmlib = { path = "../spdmlib", default-features = false, features = ["spdm-ring"]} - +conquer-once = { version = "0.3.2", default-features = false } +spin = { version = "0.9.8" } [features] diff --git a/tdisp/build.rs b/tdisp/build.rs new file mode 100644 index 00000000..7ff8b358 --- /dev/null +++ b/tdisp/build.rs @@ -0,0 +1,86 @@ +// Copyright (c) 2023 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 or MIT + +use serde::Deserialize; +use std::env; +use std::io::Write; +use std::path::Path; +use std::{fs, fs::File}; + +#[derive(Debug, PartialEq, Deserialize)] +struct TdispConfig { + max_mmio_range_count: usize, + max_device_report_buffer_size: usize, + max_report_portion_length: usize, + max_device_specific_info_size: usize, +} + +impl TdispConfig { + fn validate_content(&self) { + // All rust fixed-size arrays require non-negative compile-time constant sizes. + // This will be checked by the compiler thus no need to check again here. + + // TODO: add more sanity checks if needed. + } +} + +macro_rules! TEMPLATE { + () => { + "// Copyright (c) 2023 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 or MIT +// +// Automatically generated by build scripts. +// It is not intended for manual editing. +// Please kindly configure via etc/config.json instead. + +pub const MAX_MMIO_RANGE_COUNT: usize = {max_mmio_range_count}; + +pub const MAX_DEVICE_SPECIFIC_INFO_LEN: usize = {max_device_specific_info_len}; + +pub const MAX_PORTION_LENGTH: usize = {max_portion_length}; + +pub const MAX_DEVICE_REPORT_BUFFER: usize = {max_device_report_buffer}; +" + }; +} + +const TDISP_CONFIG_ENV: &str = "TDISP_CONFIG"; +const TDISP_CONFIG_JSON_DEFAULT_PATH: &str = "etc/config.json"; +const TDISP_CONFIG_RS_OUT_DIR: &str = "src"; +const TDISP_CONFIG_RS_OUT_FILE_NAME: &str = "config.rs"; + +fn main() { + // Read and parse the TDISP configuration file. + let tdisp_config_json_file_path = + env::var(TDISP_CONFIG_ENV).unwrap_or_else(|_| TDISP_CONFIG_JSON_DEFAULT_PATH.to_string()); + let tdisp_config_json_file = File::open(tdisp_config_json_file_path) + .expect("The TDISP configuration file does not exist"); + let tdisp_config: TdispConfig = serde_json::from_reader(tdisp_config_json_file) + .expect("It is not a valid SPDM configuration file."); + + // Do sanity checks. + tdisp_config.validate_content(); + + // Generate config .rs file from the template and JSON inputs, then write to fs. + let mut to_generate = Vec::new(); + write!( + &mut to_generate, + TEMPLATE!(), + max_mmio_range_count = tdisp_config.max_mmio_range_count, + max_device_specific_info_len = tdisp_config.max_device_specific_info_size, + max_portion_length = tdisp_config.max_report_portion_length, + max_device_report_buffer = tdisp_config.max_device_report_buffer_size, + ) + .expect("Failed to generate configuration code from the template and JSON config"); + + let dest_path = Path::new(TDISP_CONFIG_RS_OUT_DIR).join(TDISP_CONFIG_RS_OUT_FILE_NAME); + fs::write(dest_path, to_generate).unwrap(); + + // Re-run the build script if the files at the given paths or envs have changed. + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rerun-if-changed=../Cargo.lock"); + println!("cargo:rerun-if-changed={}", TDISP_CONFIG_JSON_DEFAULT_PATH); + println!("cargo:rerun-if-env-changed={}", TDISP_CONFIG_ENV); +} diff --git a/tdisp/etc/config.json b/tdisp/etc/config.json new file mode 100644 index 00000000..27ca8638 --- /dev/null +++ b/tdisp/etc/config.json @@ -0,0 +1,7 @@ +{ + "__usage": "This helps generate compile-time constant sizes for TDISP arrays. See src/config.rs generated for details.", + "max_mmio_range_count": 4, + "max_device_report_buffer_size": 1024, + "max_report_portion_length": 256, + "max_device_specific_info_size": 256 +} diff --git a/tdisp/src/common.rs b/tdisp/src/common.rs deleted file mode 100644 index 9d810565..00000000 --- a/tdisp/src/common.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use spdmlib::message::{VendorIDStruct, MAX_SPDM_VENDOR_DEFINED_VENDOR_ID_LEN}; - -#[derive(Debug)] -pub enum InternalError { - Succ, - Unimpl, - Violation, - Unrecoverable, - - ErrStr(&'static str), - - CustomErr(T), -} - -pub type TdispResult = Result; - -pub const PCI_VENDOR_ID_STRUCT: VendorIDStruct = VendorIDStruct { - len: 0, - vendor_id: [0u8; MAX_SPDM_VENDOR_DEFINED_VENDOR_ID_LEN], -}; diff --git a/tdisp/src/config.rs b/tdisp/src/config.rs index 4962d89f..35e8218a 100644 --- a/tdisp/src/config.rs +++ b/tdisp/src/config.rs @@ -1,12 +1,15 @@ -// Copyright (c) 2022 Intel Corporation +// Copyright (c) 2023 Intel Corporation // // SPDX-License-Identifier: Apache-2.0 or MIT +// +// Automatically generated by build scripts. +// It is not intended for manual editing. +// Please kindly configure via etc/config.json instead. + +pub const MAX_MMIO_RANGE_COUNT: usize = 4; + +pub const MAX_DEVICE_SPECIFIC_INFO_LEN: usize = 256; + +pub const MAX_PORTION_LENGTH: usize = 256; -pub const MAX_VERSION_COUNT: usize = 2; -pub const MAX_MESSAGE_INTERNAL_BUFFER_SIZE: usize = 0xA000; -pub const MAX_MMIO_RANGE_COUNT: usize = 2; -pub const MAX_DEVICE_SPECIFIC_INFORMATION_LENGTH: usize = 0xA000; -pub const MAX_EXTENDED_ERROR_DATA_LENGTH: usize = 0xA000; -pub const MAX_VENDOR_ID_LEN: usize = 0x20; -pub const MAX_VENDOR_DATA_LENGTH: usize = 0xA000; -pub const MAX_TDISP_MESSAGE_SIZE: usize = 0x1000; +pub const MAX_DEVICE_REPORT_BUFFER: usize = 1024; diff --git a/tdisp/src/context.rs b/tdisp/src/context.rs deleted file mode 100644 index 3a485758..00000000 --- a/tdisp/src/context.rs +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -pub use crate::message::*; -use crate::{ - common::{InternalError, TdispResult}, - config::MAX_TDISP_MESSAGE_SIZE, - device::TdispConfiguration, - state_machine::{TDIState, TdispStateMachine}, -}; -use zeroize::{self, Zeroize}; - -#[derive(Debug)] -pub struct TdispContext<'a> { - pub version_sel: TdispVersion, - - pub tdi: InterfaceId, - - pub state_machine: TdispStateMachine, - - pub configuration: &'a mut dyn TdispConfiguration, - - pub spdm_session_id: u32, - - // volatile - pub request_message: [u8; MAX_TDISP_MESSAGE_SIZE], - pub request_code: TdispRequestResponseCode, - pub response_message: [u8; MAX_TDISP_MESSAGE_SIZE], - pub response_code: TdispRequestResponseCode, -} - -impl<'a> TdispContext<'a> { - pub fn new( - interface_id: InterfaceId, - configuration: &'a mut dyn TdispConfiguration, - spdm_session_id: u32, - ) -> Self { - let context = TdispContext { - version_sel: 0x10, - state_machine: TdispStateMachine::new(), - configuration, - spdm_session_id, - request_message: [0u8; MAX_TDISP_MESSAGE_SIZE], - request_code: TdispRequestResponseCode::Unknown(0), - response_message: [0u8; MAX_TDISP_MESSAGE_SIZE], - response_code: TdispRequestResponseCode::Unknown(0), - tdi: interface_id, - }; - context.configuration.init_config().unwrap(); // let it panic, if the device fail to init. - context - } - - pub fn zero_request_message(&mut self) { - self.request_message.zeroize(); - self.request_code = TdispRequestResponseCode::Unknown(0); - } - - pub fn zero_response_message(&mut self) { - self.response_message.zeroize(); - self.response_code = TdispRequestResponseCode::Unknown(0); - } - - pub fn zero_messages(&mut self) { - self.zero_request_message(); - self.zero_response_message(); - } - - // change the state - pub fn to_state_config_unlocked(&mut self, _from: TDIState) -> TdispResult { - if self.request_code != TdispRequestResponseCode::RequestStopInterfaceRequest { - Err(InternalError::Violation) - } else { - self.configuration.erase_confidential_config()?; - self.configuration.unlock_config()?; - - self.state_machine.to_state_config_unlocked(); - Ok(()) - } - } - - pub fn to_state_config_locked(&mut self, from: TDIState) -> TdispResult { - if from != TDIState::ConfigUnlocked - || self.request_code != TdispRequestResponseCode::RequestLockInterfaceRequest - { - Err(InternalError::Violation) - } else { - self.configuration.lock_config()?; - - self.state_machine.to_state_config_locked(); - Ok(()) - } - } - - pub fn to_state_run(&mut self, from: TDIState) -> TdispResult { - if from != TDIState::ConfigLocked - || self.request_code != TdispRequestResponseCode::RequestStartInterfaceRequest - { - Err(InternalError::Violation) - } else { - self.state_machine.to_state_run(); - Ok(()) - } - } - - pub fn to_state_error(&mut self, _from: TDIState) -> TdispResult { - self.state_machine.to_state_error(); - Ok(()) - } -} diff --git a/tdisp/src/device.rs b/tdisp/src/device.rs deleted file mode 100644 index 0d2e52dc..00000000 --- a/tdisp/src/device.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use crate::common::TdispResult; -use core::fmt::Debug; - -pub trait TdispConfiguration: Debug { - fn init_config(&mut self) -> TdispResult; - - fn lock_config(&mut self) -> TdispResult; - - fn unlock_config(&mut self) -> TdispResult; - - fn erase_confidential_config(&mut self) -> TdispResult; - - fn track_config_changes(&mut self) -> TdispResult; -} diff --git a/tdisp/src/lib.rs b/tdisp/src/lib.rs index a46361a9..e375efe8 100644 --- a/tdisp/src/lib.rs +++ b/tdisp/src/lib.rs @@ -1,16 +1,14 @@ -// Copyright (c) 2022 Intel Corporation +// Copyright (c) 2023 Intel Corporation // // SPDX-License-Identifier: Apache-2.0 or MIT +#![forbid(unsafe_code)] +#![cfg_attr(not(feature = "std"), no_std)] + #[macro_use] extern crate bitflags; -pub mod common; pub mod config; -pub mod context; -pub mod device; -pub mod message; -pub mod state_machine; -pub mod tdisp_codec; -pub mod tdisp_requester; -pub mod tdisp_responder; +pub mod pci_tdisp; +pub mod pci_tdisp_requester; +pub mod pci_tdisp_responder; diff --git a/tdisp/src/message.rs b/tdisp/src/message.rs deleted file mode 100644 index cf38afa0..00000000 --- a/tdisp/src/message.rs +++ /dev/null @@ -1,1042 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use core::fmt::Debug; - -use crate::common::{InternalError, TdispResult}; -use crate::context::TdispContext; -use crate::tdisp_codec::*; -use crate::{ - config::{ - MAX_DEVICE_SPECIFIC_INFORMATION_LENGTH, MAX_EXTENDED_ERROR_DATA_LENGTH, - MAX_MESSAGE_INTERNAL_BUFFER_SIZE, MAX_MMIO_RANGE_COUNT, MAX_VENDOR_ID_LEN, - MAX_VERSION_COUNT, - }, - state_machine::TdispStateMachine, -}; - -type ProtocolId = u8; -pub const PROTOCOL_ID: ProtocolId = 0x1; - -enum_builder! { - @U8 - EnumName: TdispRequestResponseCode; - EnumVal{ - // request codes - RequestGetTdispVersion => 0x81, // This request message must retrieve a device's TDISP version - RequestGetTdispCapabilities => 0x82, // Retrieve protocol capabilities of the device - RequestLockInterfaceRequest => 0x83, // Move TDI to CONFIG_LOCKED - RequestGetDeviceInterfaceReport => 0x84, // Obtain a TDI report - RequestGetDeviceInterfaceState => 0x85, // Obtain state of a TDI - RequestStartInterfaceRequest => 0x86, // Start a TDI - RequestStopInterfaceRequest => 0x87, // Stop and move TDI to CONFIG_UNLOCKED (if not already in CONFIG_UNLOCKED) - RequestBindP2pStreamRequest => 0x88, // Bind a P2P stream - RequestUnbindP2pStreamRequest => 0x89, // Unbind a P2P stream - RequestSetMmioAttributeRequest => 0x8A, // Update attributes of specified MMIO range - RequestVdmRequest => 0x8B, // Vendor-defined message request - - // response codes - ResponseTdispVersion => 0x01, // Version supported by device - ResponseTdispCapabilities => 0x02, // Protocol capabilities of the device - ResponseLockInterfaceResponse => 0x03, // Response to LOCK_INTERFACE_REQUEST - ResponseDeviceInterfaceReport => 0x04, // Report for a TDI - ResponseDeviceInterfaceState => 0x05, // Returns TDI state - ResponseStartInterfaceResponse => 0x06, // Response to request to move TDI to RUN - ResponseStopInterfaceResponse => 0x07, // Response to a STOP_INTERFACE_REQUEST - ResponseBindP2pStreamResponse => 0x08, // Response to bind P2P stream request - ResponseUnbindP2pStreamResponse => 0x09, // Response to unbind P2P stream request - ResponseSetMmioAttributeResponse => 0x0A, // Response to update MMIO range attributes - ResponseVdmResponse => 0x0B, // Vendor-defined message response - ResponseTdispError => 0x7F // Error in handling a request - } -} - -enum_builder! { - @U16 - EnumName: GenericErrorResponseCode; - EnumVal{ - InvalidRequest => 0x0001, // One or more request field is invalid. - Busy => 0x0003, // the Responder may be able to process the request message if the request message is sent again in the future - InvalidInterfaceState => 0x0004, // The Responder received the request while in the wrong state, or received an unexpected request - Unspecified => 0x0005, // Unspecified error occurred - UnsupportedRequest => 0x0007, // Request code is unsupporteda - VersionMismatch => 0x0041, // The version in not supported - VendorSpecificError => 0x00FF, // Vendor defined - InvalidInterface => 0x0101, // INTERFACE_ID does not exist - InvalidNonce => 0x0102, // The received nonce does not match the expected one - InsufficientEntropy => 0x0103, // The Responder fails to generate nonce - InvalidDeviceConfiguration => 0x0104 // Invalid/Unsupported device configurations - } -} - -#[derive(Debug)] -pub struct ExtendedErrorData { - pub registry_id: u8, - pub vendor_id_len: u8, - pub vendor_id: [u8; MAX_VENDOR_ID_LEN], - pub vendor_err_data: [u8; MAX_EXTENDED_ERROR_DATA_LENGTH], -} - -impl Default for ExtendedErrorData { - fn default() -> Self { - Self { - registry_id: Default::default(), - vendor_id_len: Default::default(), - vendor_id: [0u8; MAX_VENDOR_ID_LEN], - vendor_err_data: [0u8; MAX_EXTENDED_ERROR_DATA_LENGTH], - } - } -} - -#[derive(Debug, Default, Clone, Copy)] -pub struct FunctionId { - pub requester_id: u16, - requester_segment: u8, - pub requester_segment_valid: bool, -} - -impl FunctionId { - #[allow(dead_code)] - fn get_requester_segment(&self) -> Option { - if self.requester_segment_valid { - Some(self.requester_segment) - } else { - None - } - } - - #[allow(dead_code)] - fn set_requester_segment(&mut self, requester_segment: u8) -> TdispResult { - if self.requester_segment_valid { - self.requester_segment = requester_segment; - Ok(()) - } else { - Err(InternalError::ErrStr( - "requester segment is not allowed to change when RSV bit is cleared!", - )) - } - } -} - -impl TdispCodec for FunctionId { - fn tdisp_encode(&self, _context: &mut TdispContext, bytes: &mut Writer) { - self.requester_id.encode(bytes); - if self.requester_segment_valid { - self.requester_segment.encode(bytes); - 1u8.encode(bytes); // Requester Segment Valid bit - } else { - 0u16.encode(bytes); - } - } - - fn tdisp_read(_context: &mut TdispContext, r: &mut Reader) -> Option { - let requester_id = u16::read(r)?; - let requester_segment = u8::read(r)?; - let requester_segment_valid = u8::read(r)?; - if requester_segment_valid == 0x1 { - Some(FunctionId { - requester_id, - requester_segment, - requester_segment_valid: true, - }) - } else if requester_segment_valid == 0x0 { - Some(FunctionId { - requester_id, - requester_segment: 0u8, - requester_segment_valid: false, - }) - } else { - None - } - } -} - -impl Codec for FunctionId { - fn encode(&self, bytes: &mut Writer) { - self.requester_id.encode(bytes); - if self.requester_segment_valid { - self.requester_segment.encode(bytes); - 1u8.encode(bytes); // Requester Segment Valid bit - } else { - 0u16.encode(bytes); - } - } - - fn read(r: &mut Reader) -> Option { - let requester_id = u16::read(r)?; - let requester_segment = u8::read(r)?; - let requester_segment_valid = u8::read(r)?; - if requester_segment_valid == 0x1 { - Some(FunctionId { - requester_id, - requester_segment, - requester_segment_valid: true, - }) - } else if requester_segment_valid == 0x0 { - Some(FunctionId { - requester_id, - requester_segment: 0u8, - requester_segment_valid: false, - }) - } else { - None - } - } -} - -#[derive(Debug, Default, Clone, Copy)] -pub struct InterfaceId { - pub function_id: FunctionId, -} - -impl TdispCodec for InterfaceId { - fn tdisp_encode(&self, context: &mut TdispContext, bytes: &mut Writer) { - self.function_id.tdisp_encode(context, bytes); - 0u32.encode(bytes); // reserved - } - - fn tdisp_read(context: &mut TdispContext, r: &mut Reader) -> Option { - let function_id = FunctionId::tdisp_read(context, r)?; - let _ = u32::read(r)?; - - Some(InterfaceId { function_id }) - } -} - -impl Codec for InterfaceId { - fn encode(&self, bytes: &mut Writer) { - self.function_id.encode(bytes); - 0u32.encode(bytes); // reserved - } - - fn read(r: &mut Reader) -> Option { - let function_id = FunctionId::read(r)?; - let _ = u32::read(r)?; - - Some(InterfaceId { function_id }) - } -} - -pub type TdispVersion = u8; - -#[derive(Debug, Default)] -pub struct TdispMessageHeader { - pub tdisp_version: TdispVersion, - pub message_type: TdispRequestResponseCode, - pub interface_id: InterfaceId, -} - -impl TdispCodec for TdispMessageHeader { - fn tdisp_encode(&self, context: &mut TdispContext, bytes: &mut Writer) { - self.tdisp_version.encode(bytes); - self.message_type.encode(bytes); - 0u16.encode(bytes); // reserved - self.interface_id.tdisp_encode(context, bytes); - } - - fn tdisp_read(context: &mut TdispContext, r: &mut Reader) -> Option { - let tdisp_version = TdispVersion::read(r)?; - let message_type = TdispRequestResponseCode::read(r)?; - u16::read(r)?; - let interface_id = InterfaceId::tdisp_read(context, r)?; - - Some(TdispMessageHeader { - tdisp_version, - message_type, - interface_id, - }) - } -} - -impl Codec for TdispMessageHeader { - fn encode(&self, bytes: &mut Writer) { - self.tdisp_version.encode(bytes); - self.message_type.encode(bytes); - 0u16.encode(bytes); // reserved - self.interface_id.encode(bytes); - } - - fn read(r: &mut Reader) -> Option { - let tdisp_version = TdispVersion::read(r)?; - let message_type = TdispRequestResponseCode::read(r)?; - u16::read(r)?; - let interface_id = InterfaceId::read(r)?; - - Some(TdispMessageHeader { - tdisp_version, - message_type, - interface_id, - }) - } - - fn read_bytes(bytes: &[u8]) -> Option { - let mut rd = Reader::init(bytes); - Self::read(&mut rd) - } -} - -#[derive(Debug, Default)] -pub struct MessagePayloadDummy {} - -impl TdispCodec for MessagePayloadDummy { - fn tdisp_encode(&self, _context: &mut TdispContext, _bytes: &mut Writer) {} - - fn tdisp_read(_context: &mut TdispContext, _: &mut Reader) -> Option { - Some(MessagePayloadDummy {}) - } -} - -impl Codec for MessagePayloadDummy { - fn encode(&self, _bytes: &mut Writer) {} - - fn read(_: &mut Reader) -> Option { - Some(MessagePayloadDummy {}) - } -} - -#[derive(Debug, Default)] -pub struct TdispMessage -where - T: TdispCodec + Default + Debug, -{ - pub tdisp_message_header: TdispMessageHeader, - pub tdisp_message_payload: T, -} - -impl TdispCodec for TdispMessage -where - T: TdispCodec + Default + Debug, -{ - fn tdisp_encode(&self, context: &mut TdispContext, bytes: &mut Writer) { - PROTOCOL_ID.encode(bytes); - self.tdisp_message_header.tdisp_encode(context, bytes); - self.tdisp_message_payload.tdisp_encode(context, bytes); - } - - fn tdisp_read(context: &mut TdispContext, r: &mut Reader) -> Option { - let _ = ProtocolId::read(r)?; // protocol id - let tdisp_message_header = TdispMessageHeader::tdisp_read(context, r)?; - let tdisp_message_payload = T::tdisp_read(context, r)?; - - Some(TdispMessage { - tdisp_message_header, - tdisp_message_payload, - }) - } -} - -#[derive(Debug, Default)] -pub struct MessagePayloadRequestGetVersion {} - -impl TdispCodec for MessagePayloadRequestGetVersion { - fn tdisp_encode(&self, _context: &mut TdispContext, _bytes: &mut Writer) {} - - fn tdisp_read(_context: &mut TdispContext, _: &mut Reader) -> Option { - Some(MessagePayloadRequestGetVersion {}) - } -} - -#[derive(Debug, Default)] -pub struct MessagePayloadResponseVersion { - pub version_num_count: u8, - pub version_num_entry: [TdispVersion; MAX_VERSION_COUNT], -} - -impl TdispCodec for MessagePayloadResponseVersion { - fn tdisp_encode(&self, _context: &mut TdispContext, bytes: &mut Writer) { - self.version_num_count.encode(bytes); - for version in self - .version_num_entry - .iter() - .take(self.version_num_count as usize) - { - version.encode(bytes); - } - } - - fn tdisp_read(_context: &mut TdispContext, r: &mut Reader) -> Option { - let version_num_count = u8::read(r)?; - let mut version_num_entry: [TdispVersion; MAX_VERSION_COUNT] = [0u8; MAX_VERSION_COUNT]; - for version in version_num_entry - .iter_mut() - .take(version_num_count as usize) - { - *version = TdispVersion::read(r)?; - } - - Some(MessagePayloadResponseVersion { - version_num_count, - version_num_entry, - }) - } -} - -#[derive(Debug, Default)] -pub struct MessagePayloadRequestGetCapabilities { - tsm_caps: u32, -} - -impl TdispCodec for MessagePayloadRequestGetCapabilities { - fn tdisp_encode(&self, _context: &mut TdispContext, bytes: &mut Writer) { - self.tsm_caps.encode(bytes); - } - - fn tdisp_read(_context: &mut TdispContext, r: &mut Reader) -> Option { - let tsm_caps = u32::read(r)?; - - Some(MessagePayloadRequestGetCapabilities { tsm_caps }) - } -} - -#[derive(Debug, Default)] -pub struct MessagePayloadResponseCapabilities { - pub dsm_caps: u32, - pub req_msgs_supported: u128, - pub lock_interface_flags_supported: u16, - pub dev_addr_width: u8, - pub num_req_this: u8, - pub num_req_all: u8, -} - -impl TdispCodec for MessagePayloadResponseCapabilities { - fn tdisp_encode(&self, _context: &mut TdispContext, bytes: &mut Writer) { - self.dsm_caps.encode(bytes); - self.req_msgs_supported.encode(bytes); - self.lock_interface_flags_supported.encode(bytes); - u24::new(0).encode(bytes); // reserved - self.dev_addr_width.encode(bytes); - self.num_req_this.encode(bytes); - self.num_req_all.encode(bytes); - } - - fn tdisp_read(_context: &mut TdispContext, r: &mut Reader) -> Option { - let dsm_caps = u32::read(r)?; - let req_msgs_supported = u128::read(r)?; - let lock_interface_flags_supported = u16::read(r)?; - let _ = u24::read(r)?; // reserved - let dev_addr_width = u8::read(r)?; - let num_req_this = u8::read(r)?; - let num_req_all = u8::read(r)?; - - Some(MessagePayloadResponseCapabilities { - dsm_caps, - req_msgs_supported, - lock_interface_flags_supported, - dev_addr_width, - num_req_this, - num_req_all, - }) - } -} - -bitflags! { - #[derive(Default)] - pub struct LockInterfaceFlag: u16 { - const NO_FW_UPDATE = 0b0000_0000_0000_0001; - const SYSTEM_CACHE_LINE_SIZE = 0b0000_0000_0000_0010; - const LOCK_MSIX = 0b0000_0000_0000_0100; - const BIND_P2P = 0b0000_0000_0000_1000; - const ALL_REQUEST_REDIRECT = 0b0000_0000_0001_0000; - } -} - -impl TdispCodec for LockInterfaceFlag { - fn tdisp_encode(&self, _context: &mut TdispContext, bytes: &mut Writer) { - self.bits().encode(bytes); - } - - fn tdisp_read(_context: &mut TdispContext, r: &mut Reader) -> Option { - let bits = u16::read(r)?; - - LockInterfaceFlag::from_bits(bits) - } -} - -#[derive(Debug, Default)] -pub struct MessagePayloadRequestLockInterface { - pub flags: LockInterfaceFlag, - pub stream_id_for_default_stream: u8, - pub mmio_reporting_offset: u64, - pub bind_p2p_address_mask: u64, -} - -impl TdispCodec for MessagePayloadRequestLockInterface { - fn tdisp_encode(&self, context: &mut TdispContext, bytes: &mut Writer) { - self.flags.tdisp_encode(context, bytes); - self.stream_id_for_default_stream.encode(bytes); - 0u8.encode(bytes); // reserved - self.mmio_reporting_offset.encode(bytes); - self.bind_p2p_address_mask.encode(bytes); - } - - fn tdisp_read(context: &mut TdispContext, r: &mut Reader) -> Option { - let flags = LockInterfaceFlag::tdisp_read(context, r)?; - let stream_id_for_default_stream = u8::read(r)?; - let _ = u8::read(r)?; // reserved - let mmio_reporting_offset = u64::read(r)?; - let bind_p2p_address_mask = u64::read(r)?; - Some(MessagePayloadRequestLockInterface { - flags, - stream_id_for_default_stream, - mmio_reporting_offset, - bind_p2p_address_mask, - }) - } -} - -#[derive(Debug, Default)] -pub struct MessagePayloadResponseLockInterface { - pub start_interface_nonce: u128, -} - -impl TdispCodec for MessagePayloadResponseLockInterface { - fn tdisp_encode(&self, _context: &mut TdispContext, bytes: &mut Writer) { - self.start_interface_nonce.encode(bytes); - } - - fn tdisp_read(_context: &mut TdispContext, r: &mut Reader) -> Option { - let start_interface_nonce = u128::read(r)?; - Some(MessagePayloadResponseLockInterface { - start_interface_nonce, - }) - } -} - -#[derive(Debug, Default)] -pub struct MessagePayloadRequestGetDeviceInterfaceReport { - pub offset: u16, - pub length: u16, -} - -impl TdispCodec for MessagePayloadRequestGetDeviceInterfaceReport { - fn tdisp_encode(&self, _context: &mut TdispContext, bytes: &mut Writer) { - self.offset.encode(bytes); - self.length.encode(bytes); - } - - fn tdisp_read(_context: &mut TdispContext, r: &mut Reader) -> Option { - let offset = u16::read(r)?; - let length = u16::read(r)?; - Some(MessagePayloadRequestGetDeviceInterfaceReport { offset, length }) - } -} - -#[derive(Debug)] -pub struct MessagePayloadResponseDeviceInterfaceReport { - pub portion_length: u16, - pub reminder_length: u16, - pub report_bytes: [u8; MAX_MESSAGE_INTERNAL_BUFFER_SIZE], -} - -impl TdispCodec for MessagePayloadResponseDeviceInterfaceReport { - fn tdisp_encode(&self, _context: &mut TdispContext, bytes: &mut Writer) { - self.portion_length.encode(bytes); - self.reminder_length.encode(bytes); - for b in self.report_bytes.iter().take(self.portion_length as usize) { - b.encode(bytes); - } - } - - fn tdisp_read(_context: &mut TdispContext, r: &mut Reader) -> Option { - let portion_length = u16::read(r)?; - let reminder_length = u16::read(r)?; - let mut report_bytes: [u8; MAX_MESSAGE_INTERNAL_BUFFER_SIZE] = - [0u8; MAX_MESSAGE_INTERNAL_BUFFER_SIZE]; - for b in report_bytes.iter_mut().take(portion_length as usize) { - *b = u8::read(r)?; - } - - Some(MessagePayloadResponseDeviceInterfaceReport { - portion_length, - reminder_length, - report_bytes, - }) - } -} - -impl Default for MessagePayloadResponseDeviceInterfaceReport { - fn default() -> Self { - Self { - portion_length: Default::default(), - reminder_length: Default::default(), - report_bytes: [0u8; MAX_MESSAGE_INTERNAL_BUFFER_SIZE], - } - } -} - -bitflags! { - #[derive(Default)] - pub struct InterfaceInfo: u16 { - const DEVICE_FIRMWARE_UPDATES_NOT_PERMITTED = 0b0000_0000_0000_0001; - const DMA_REQUESTS_WITHOUT_PASID = 0b0000_0000_0000_0010; - const DMA_REQUESTS_WITH_PASID = 0b0000_0000_0000_0100; - const ATS_SUPPORTED_ENABLED = 0b0000_0000_0000_1000; - const PRS_SUPPORTED_ENABLED = 0b0000_0000_0001_0000; - } -} - -impl TdispCodec for InterfaceInfo { - fn tdisp_encode(&self, _context: &mut TdispContext, bytes: &mut Writer) { - self.bits().encode(bytes); - } - - fn tdisp_read(_context: &mut TdispContext, r: &mut Reader) -> Option { - let bits = u16::read(r)?; - - InterfaceInfo::from_bits(bits) - } -} - -bitflags! { - #[derive(Default)] - pub struct MMIORangeAttribute: u16 { - const MSI_X_TABLE = 0b0000_0000_0000_0001; - const MSI_X_PBA = 0b0000_0000_0000_0010; - const IS_NON_TEE_MEM = 0b0000_0000_0000_0100; - const IS_MEM_ATTR_UPDATABLE = 0b0000_0000_0000_1000; - const PRS_SUPPORTED_ENABLED = 0b0000_0000_0001_0000; - } -} - -impl TdispCodec for MMIORangeAttribute { - fn tdisp_encode(&self, _context: &mut TdispContext, bytes: &mut Writer) { - self.bits().encode(bytes); - } - - fn tdisp_read(_context: &mut TdispContext, r: &mut Reader) -> Option { - let bits = u16::read(r)?; - - MMIORangeAttribute::from_bits(bits) - } -} - -#[derive(Debug, Default, Clone, Copy)] -pub struct MMIORange { - pub first_4k_page_with_offset_added: u64, - pub number_of_4k_pages: u32, - pub range_attribute: MMIORangeAttribute, - pub range_id: u16, -} - -impl TdispCodec for MMIORange { - fn tdisp_encode(&self, context: &mut TdispContext, bytes: &mut Writer) { - self.first_4k_page_with_offset_added.encode(bytes); - self.number_of_4k_pages.encode(bytes); - self.range_attribute.tdisp_encode(context, bytes); - self.range_id.encode(bytes); - } - - fn tdisp_read(context: &mut TdispContext, r: &mut Reader) -> Option { - let first_4k_page_with_offset_added = u64::read(r)?; - let number_of_4k_pages = u32::read(r)?; - let range_attribute = MMIORangeAttribute::tdisp_read(context, r)?; - let range_id = u16::read(r)?; - - Some(MMIORange { - first_4k_page_with_offset_added, - number_of_4k_pages, - range_attribute, - range_id, - }) - } -} - -#[derive(Debug)] -pub struct TDIReport { - pub interface_info: InterfaceInfo, - pub msi_x_message_control: u16, - pub lnr_control: u16, - pub tph_control: u32, - pub mmio_range_count: u32, - pub mmio_range: [MMIORange; MAX_MMIO_RANGE_COUNT], - pub device_specific_info_len: u32, - pub device_specific_info: [u8; MAX_DEVICE_SPECIFIC_INFORMATION_LENGTH], -} - -impl TdispCodec for TDIReport { - fn tdisp_encode(&self, context: &mut TdispContext, bytes: &mut Writer) { - self.interface_info.tdisp_encode(context, bytes); - self.msi_x_message_control.encode(bytes); - self.lnr_control.encode(bytes); - self.tph_control.encode(bytes); - self.mmio_range_count.encode(bytes); - for m in self.mmio_range.iter().take(self.mmio_range_count as usize) { - m.tdisp_encode(context, bytes); - } - self.device_specific_info_len.encode(bytes); - for d in self - .device_specific_info - .iter() - .take(self.device_specific_info_len as usize) - { - d.encode(bytes); - } - } - - fn tdisp_read(context: &mut TdispContext, r: &mut Reader) -> Option { - let interface_info = InterfaceInfo::tdisp_read(context, r)?; - let msi_x_message_control = u16::read(r)?; - let lnr_control = u16::read(r)?; - let tph_control = u32::read(r)?; - let mmio_range_count = u32::read(r)?; - let mut mmio_range: [MMIORange; MAX_MMIO_RANGE_COUNT] = - [MMIORange::default(); MAX_MMIO_RANGE_COUNT]; - for m in mmio_range.iter_mut().take(mmio_range_count as usize) { - *m = MMIORange::tdisp_read(context, r)?; - } - let device_specific_info_len = u32::read(r)?; - let mut device_specific_info: [u8; MAX_DEVICE_SPECIFIC_INFORMATION_LENGTH] = - [0u8; MAX_DEVICE_SPECIFIC_INFORMATION_LENGTH]; - for d in device_specific_info - .iter_mut() - .take(device_specific_info_len as usize) - { - *d = u8::read(r)?; - } - - Some(TDIReport { - interface_info, - msi_x_message_control, - lnr_control, - tph_control, - mmio_range_count, - mmio_range, - device_specific_info_len, - device_specific_info, - }) - } -} - -impl Default for TDIReport { - fn default() -> Self { - Self { - interface_info: Default::default(), - msi_x_message_control: Default::default(), - lnr_control: Default::default(), - tph_control: Default::default(), - mmio_range_count: Default::default(), - mmio_range: Default::default(), - device_specific_info_len: Default::default(), - device_specific_info: [0u8; MAX_DEVICE_SPECIFIC_INFORMATION_LENGTH], - } - } -} - -#[derive(Debug, Default)] -pub struct MessagePayloadRequestGetDeviceInterfaceState {} - -impl TdispCodec for MessagePayloadRequestGetDeviceInterfaceState { - fn tdisp_encode(&self, _context: &mut TdispContext, _bytes: &mut Writer) {} - - fn tdisp_read(_context: &mut TdispContext, _: &mut Reader) -> Option { - Some(MessagePayloadRequestGetDeviceInterfaceState {}) - } -} - -#[derive(Debug, Default)] -pub struct MessagePayloadResponseDeviceInterfaceState { - pub tdi_state: TdispStateMachine, -} - -impl TdispCodec for MessagePayloadResponseDeviceInterfaceState { - fn tdisp_encode(&self, _context: &mut TdispContext, bytes: &mut Writer) { - self.tdi_state.encode(bytes); - } - - fn tdisp_read(_context: &mut TdispContext, r: &mut Reader) -> Option { - let tdi_state = TdispStateMachine::read(r)?; - Some(MessagePayloadResponseDeviceInterfaceState { tdi_state }) - } -} - -pub const NONCE_LENGTH: usize = 32; // specification defined - -#[derive(Debug, Default)] -pub struct MessagePayloadRequestStartInterface { - pub start_interface_nonce: [u8; NONCE_LENGTH], -} - -impl TdispCodec for MessagePayloadRequestStartInterface { - fn tdisp_encode(&self, _context: &mut TdispContext, bytes: &mut Writer) { - for b in self.start_interface_nonce.iter().take(NONCE_LENGTH) { - b.encode(bytes); - } - } - - fn tdisp_read(_context: &mut TdispContext, r: &mut Reader) -> Option { - let mut start_interface_nonce: [u8; NONCE_LENGTH] = [0u8; NONCE_LENGTH]; - for b in start_interface_nonce.iter_mut().take(NONCE_LENGTH) { - *b = u8::read(r)?; - } - Some(MessagePayloadRequestStartInterface { - start_interface_nonce, - }) - } -} - -#[derive(Debug, Default)] -pub struct MessagePayloadResponseStartInterface {} - -impl TdispCodec for MessagePayloadResponseStartInterface { - fn tdisp_encode(&self, _context: &mut TdispContext, _bytes: &mut Writer) {} - - fn tdisp_read(_context: &mut TdispContext, _: &mut Reader) -> Option { - Some(MessagePayloadResponseStartInterface {}) - } -} - -#[derive(Debug, Default)] -pub struct MessagePayloadRequestStopInterface {} - -impl TdispCodec for MessagePayloadRequestStopInterface { - fn tdisp_encode(&self, _context: &mut TdispContext, _bytes: &mut Writer) {} - - fn tdisp_read(_context: &mut TdispContext, _: &mut Reader) -> Option { - Some(MessagePayloadRequestStopInterface {}) - } -} - -#[derive(Debug, Default)] -pub struct MessagePayloadResponseStopInterface {} - -impl TdispCodec for MessagePayloadResponseStopInterface { - fn tdisp_encode(&self, _context: &mut TdispContext, _bytes: &mut Writer) {} - - fn tdisp_read(_context: &mut TdispContext, _: &mut Reader) -> Option { - Some(MessagePayloadResponseStopInterface {}) - } -} - -#[derive(Debug, Default)] -pub struct MessagePayloadRequestBindP2pStream { - pub p2p_stream_id: u8, -} - -impl TdispCodec for MessagePayloadRequestBindP2pStream { - fn tdisp_encode(&self, _context: &mut TdispContext, bytes: &mut Writer) { - self.p2p_stream_id.encode(bytes); - } - - fn tdisp_read(_context: &mut TdispContext, r: &mut Reader) -> Option { - let p2p_stream_id = u8::read(r)?; - Some(MessagePayloadRequestBindP2pStream { p2p_stream_id }) - } -} - -#[derive(Debug, Default)] -pub struct MessagePayloadResponseBindP2pStream {} - -impl TdispCodec for MessagePayloadResponseBindP2pStream { - fn tdisp_encode(&self, _context: &mut TdispContext, _bytes: &mut Writer) {} - - fn tdisp_read(_context: &mut TdispContext, _: &mut Reader) -> Option { - Some(MessagePayloadResponseBindP2pStream {}) - } -} - -#[derive(Debug, Default)] -pub struct MessagePayloadRequestUnbindP2pStream { - pub p2p_stream_id: u8, -} - -impl TdispCodec for MessagePayloadRequestUnbindP2pStream { - fn tdisp_encode(&self, _context: &mut TdispContext, bytes: &mut Writer) { - self.p2p_stream_id.encode(bytes); - } - - fn tdisp_read(_context: &mut TdispContext, r: &mut Reader) -> Option { - let p2p_stream_id = u8::read(r)?; - Some(MessagePayloadRequestUnbindP2pStream { p2p_stream_id }) - } -} - -#[derive(Debug, Default)] -pub struct MessagePayloadResponseUnbindP2pStream {} - -impl TdispCodec for MessagePayloadResponseUnbindP2pStream { - fn tdisp_encode(&self, _context: &mut TdispContext, _bytes: &mut Writer) {} - - fn tdisp_read(_context: &mut TdispContext, _: &mut Reader) -> Option { - Some(MessagePayloadResponseUnbindP2pStream {}) - } -} - -#[derive(Debug, Default)] -pub struct MessagePayloadRequestSetMmioAttribute { - pub mmio_range: MMIORange, -} - -impl TdispCodec for MessagePayloadRequestSetMmioAttribute { - fn tdisp_encode(&self, context: &mut TdispContext, bytes: &mut Writer) { - self.mmio_range.tdisp_encode(context, bytes); - } - - fn tdisp_read(context: &mut TdispContext, r: &mut Reader) -> Option { - let mmio_range = MMIORange::tdisp_read(context, r)?; - Some(MessagePayloadRequestSetMmioAttribute { mmio_range }) - } -} - -#[derive(Debug, Default)] -pub struct MessagePayloadResponseSetMmioAttribute {} - -impl TdispCodec for MessagePayloadResponseSetMmioAttribute { - fn tdisp_encode(&self, _context: &mut TdispContext, _bytes: &mut Writer) {} - - fn tdisp_read(_context: &mut TdispContext, _: &mut Reader) -> Option { - Some(MessagePayloadResponseSetMmioAttribute {}) - } -} - -#[derive(Debug)] -pub struct MessagePayloadResponseTdispError { - pub error_code: GenericErrorResponseCode, - pub error_data: u32, - pub extended_error_data: ExtendedErrorData, -} - -impl TdispCodec for MessagePayloadResponseTdispError { - fn tdisp_encode(&self, _context: &mut TdispContext, bytes: &mut Writer) { - (self.error_code.get_u16() as u32).encode(bytes); - self.error_data.encode(bytes); - if self.error_code == GenericErrorResponseCode::VendorSpecificError { - self.extended_error_data.registry_id.encode(bytes); - self.extended_error_data.vendor_id_len.encode(bytes); - for b in self - .extended_error_data - .vendor_id - .iter() - .take(self.extended_error_data.vendor_id_len as usize) - { - b.encode(bytes); - } - for b in self - .extended_error_data - .vendor_err_data - .iter() - .take(self.error_data as usize) - { - b.encode(bytes); - } - } - } - - fn tdisp_read(_context: &mut TdispContext, r: &mut Reader) -> Option { - let error_code = u32::read(r)?; - let error_data = u32::read(r)?; - let mut extended_error_data = ExtendedErrorData::default(); - - if GenericErrorResponseCode::VendorSpecificError.get_u16() as u32 == error_code { - extended_error_data.registry_id = u8::read(r)?; - extended_error_data.vendor_id_len = u8::read(r)?; - for b in extended_error_data - .vendor_id - .iter_mut() - .take(extended_error_data.vendor_id_len as usize) - { - *b = u8::read(r)?; - } - for b in extended_error_data - .vendor_err_data - .iter_mut() - .take(error_data as usize) - { - *b = u8::read(r)?; - } - } - let error_code = GenericErrorResponseCode::read_bytes(&error_code.to_le_bytes())?; - - Some(MessagePayloadResponseTdispError { - error_code, - error_data, - extended_error_data, - }) - } -} - -#[derive(Debug)] -pub struct MessagePayloadRequestVDM { - pub registry_id: u8, - pub vendor_id_len: u8, - pub vendor_id: [u8; MAX_VENDOR_ID_LEN], - //pub vendor_data: [u8; MAX_EXTENDED_ERROR_DATA_LENGTH], -} - -impl Default for MessagePayloadRequestVDM { - fn default() -> Self { - Self { - registry_id: Default::default(), - vendor_id_len: Default::default(), - vendor_id: [0u8; MAX_VENDOR_ID_LEN], - } - } -} - -impl TdispCodec for MessagePayloadRequestVDM { - fn tdisp_encode(&self, _context: &mut TdispContext, bytes: &mut Writer) { - self.registry_id.encode(bytes); - self.vendor_id_len.encode(bytes); - for b in self.vendor_id.iter().take(self.vendor_id_len as usize) { - b.encode(bytes); - } - } - - fn tdisp_read(_context: &mut TdispContext, r: &mut Reader) -> Option { - let registry_id = u8::read(r)?; - let vendor_id_len = u8::read(r)?; - let mut vendor_id: [u8; MAX_VENDOR_ID_LEN] = [0u8; MAX_VENDOR_ID_LEN]; - for b in vendor_id.iter_mut().take(vendor_id_len as usize) { - *b = u8::read(r)?; - } - - Some(MessagePayloadRequestVDM { - registry_id, - vendor_id_len, - vendor_id, - }) - } -} - -#[derive(Debug)] -pub struct MessagePayloadResponseVDM { - pub registry_id: u8, - pub vendor_id_len: u8, - pub vendor_id: [u8; MAX_VENDOR_ID_LEN], - // pub vendor_data: [u8; MAX_EXTENDED_ERROR_DATA_LENGTH], -} - -impl Default for MessagePayloadResponseVDM { - fn default() -> Self { - Self { - registry_id: Default::default(), - vendor_id_len: Default::default(), - vendor_id: [0u8; MAX_VENDOR_ID_LEN], - } - } -} - -impl TdispCodec for MessagePayloadResponseVDM { - fn tdisp_encode(&self, _context: &mut TdispContext, bytes: &mut Writer) { - self.registry_id.encode(bytes); - self.vendor_id_len.encode(bytes); - for b in self.vendor_id.iter().take(self.vendor_id_len as usize) { - b.encode(bytes); - } - } - - fn tdisp_read(_context: &mut TdispContext, r: &mut Reader) -> Option { - let registry_id = u8::read(r)?; - let vendor_id_len = u8::read(r)?; - let mut vendor_id: [u8; MAX_VENDOR_ID_LEN] = [0u8; MAX_VENDOR_ID_LEN]; - for b in vendor_id.iter_mut().take(vendor_id_len as usize) { - *b = u8::read(r)?; - } - - Some(MessagePayloadResponseVDM { - registry_id, - vendor_id_len, - vendor_id, - }) - } -} diff --git a/tdisp/src/pci_tdisp.rs b/tdisp/src/pci_tdisp.rs new file mode 100644 index 00000000..e1321bd0 --- /dev/null +++ b/tdisp/src/pci_tdisp.rs @@ -0,0 +1,1219 @@ +// Copyright (c) 2023 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 or MIT + +use codec::{u24, Codec}; +use core::convert::TryFrom; +use spdmlib::message::{ + RegistryOrStandardsBodyID, VendorIDStruct, MAX_SPDM_VENDOR_DEFINED_VENDOR_ID_LEN, +}; + +use crate::config::{MAX_DEVICE_SPECIFIC_INFO_LEN, MAX_MMIO_RANGE_COUNT, MAX_PORTION_LENGTH}; + +pub const TDISP_PROTOCOL_ID: u8 = 1; + +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)] +pub struct FunctionId { + pub requester_id: u16, + pub requester_segment: u8, + pub requester_segment_valid: bool, +} + +impl Codec for FunctionId { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + let mut function_id = 0u32; + function_id |= self.requester_id as u32; + if self.requester_segment_valid { + function_id |= (self.requester_segment as u32) << 16; + } + function_id |= (self.requester_segment_valid as u32) << 24; + + function_id.encode(bytes) + } + + fn read(r: &mut codec::Reader) -> Option { + let function_id = u32::read(r)?; + + let requester_id = (function_id & 0x0000FFFF) as u16; + let requester_segment = ((function_id & 0x00FF0000) >> 16) as u8; + let requester_segment_valid = function_id & (1 << 24) != 0; + + if !requester_segment_valid && requester_segment != 0 { + return None; + } + + Some(Self { + requester_id, + requester_segment, + requester_segment_valid, + }) + } +} + +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)] +pub struct InterfaceId { + pub function_id: FunctionId, +} + +impl Codec for InterfaceId { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + let mut cnt = 0; + + cnt += self.function_id.encode(bytes)?; + cnt += 0u64.encode(bytes)?; + + Ok(cnt) + } + + fn read(r: &mut codec::Reader) -> Option { + let function_id = FunctionId::read(r)?; + let _ = u64::read(r)?; + + Some(Self { function_id }) + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[allow(non_camel_case_types)] +pub enum TdiState { + RUN, + ERROR, + CONFIG_LOCKED, + CONFIG_UNLOCKED, +} + +impl From for u8 { + fn from(ts: TdiState) -> Self { + match ts { + TdiState::RUN => 2, + TdiState::ERROR => 3, + TdiState::CONFIG_LOCKED => 1, + TdiState::CONFIG_UNLOCKED => 0, + } + } +} + +impl From<&TdiState> for u8 { + fn from(ts: &TdiState) -> Self { + u8::from(*ts) + } +} + +impl TryFrom for TdiState { + type Error = (); + fn try_from(uts: u8) -> Result>::Error> { + match uts { + 0 => Ok(Self::CONFIG_UNLOCKED), + 1 => Ok(Self::CONFIG_LOCKED), + 2 => Ok(Self::RUN), + 3 => Ok(Self::ERROR), + 4_u8..=u8::MAX => Err(()), + } + } +} + +impl Default for TdiState { + fn default() -> Self { + Self::CONFIG_UNLOCKED + } +} + +impl Codec for TdiState { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + u8::from(self).encode(bytes) + } + + fn read(r: &mut codec::Reader) -> Option { + let tdi_state = u8::read(r)?; + Self::try_from(tdi_state).ok() + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[allow(non_camel_case_types)] +pub enum TdispRequestResponseCode { + // Request + GET_TDISP_VERSION, + GET_TDISP_CAPABILITIES, + LOCK_INTERFACE_REQUEST, + GET_DEVICE_INTERFACE_REPORT, + GET_DEVICE_INTERFACE_STATE, + START_INTERFACE_REQUEST, + STOP_INTERFACE_REQUEST, + BIND_P2P_STREAM_REQUEST, + UNBIND_P2P_STREAM_REQUEST, + SET_MMIO_ATTRIBUTE_REQUEST, + VDM_REQUEST, + + // Response + TDISP_VERSION, + TDISP_CAPABILITIES, + LOCK_INTERFACE_RESPONSE, + DEVICE_INTERFACE_REPORT, + DEVICE_INTERFACE_STATE, + START_INTERFACE_RESPONSE, + STOP_INTERFACE_RESPONSE, + BIND_P2P_STREAM_RESPONSE, + UNBIND_P2P_STREAM_RESPONSE, + SET_MMIO_ATTRIBUTE_RESPONSE, + VDM_RESPONSE, + TDISP_ERROR, +} + +impl From for u8 { + fn from(trrc: TdispRequestResponseCode) -> Self { + match trrc { + TdispRequestResponseCode::GET_TDISP_VERSION => 0x81, + TdispRequestResponseCode::GET_TDISP_CAPABILITIES => 0x82, + TdispRequestResponseCode::LOCK_INTERFACE_REQUEST => 0x83, + TdispRequestResponseCode::GET_DEVICE_INTERFACE_REPORT => 0x84, + TdispRequestResponseCode::GET_DEVICE_INTERFACE_STATE => 0x85, + TdispRequestResponseCode::START_INTERFACE_REQUEST => 0x86, + TdispRequestResponseCode::STOP_INTERFACE_REQUEST => 0x87, + TdispRequestResponseCode::BIND_P2P_STREAM_REQUEST => 0x88, + TdispRequestResponseCode::UNBIND_P2P_STREAM_REQUEST => 0x89, + TdispRequestResponseCode::SET_MMIO_ATTRIBUTE_REQUEST => 0x8A, + TdispRequestResponseCode::VDM_REQUEST => 0x8B, + TdispRequestResponseCode::TDISP_VERSION => 0x01, + TdispRequestResponseCode::TDISP_CAPABILITIES => 0x02, + TdispRequestResponseCode::LOCK_INTERFACE_RESPONSE => 0x03, + TdispRequestResponseCode::DEVICE_INTERFACE_REPORT => 0x04, + TdispRequestResponseCode::DEVICE_INTERFACE_STATE => 0x05, + TdispRequestResponseCode::START_INTERFACE_RESPONSE => 0x06, + TdispRequestResponseCode::STOP_INTERFACE_RESPONSE => 0x07, + TdispRequestResponseCode::BIND_P2P_STREAM_RESPONSE => 0x08, + TdispRequestResponseCode::UNBIND_P2P_STREAM_RESPONSE => 0x09, + TdispRequestResponseCode::SET_MMIO_ATTRIBUTE_RESPONSE => 0x0A, + TdispRequestResponseCode::VDM_RESPONSE => 0x0B, + TdispRequestResponseCode::TDISP_ERROR => 0x7F, + } + } +} + +impl From<&TdispRequestResponseCode> for u8 { + fn from(trrc: &TdispRequestResponseCode) -> Self { + u8::from(*trrc) + } +} + +impl TryFrom for TdispRequestResponseCode { + type Error = (); + fn try_from(utrrc: u8) -> Result>::Error> { + match utrrc { + 0x81 => Ok(TdispRequestResponseCode::GET_TDISP_VERSION), + 0x82 => Ok(TdispRequestResponseCode::GET_TDISP_CAPABILITIES), + 0x83 => Ok(TdispRequestResponseCode::LOCK_INTERFACE_REQUEST), + 0x84 => Ok(TdispRequestResponseCode::GET_DEVICE_INTERFACE_REPORT), + 0x85 => Ok(TdispRequestResponseCode::GET_DEVICE_INTERFACE_STATE), + 0x86 => Ok(TdispRequestResponseCode::START_INTERFACE_REQUEST), + 0x87 => Ok(TdispRequestResponseCode::STOP_INTERFACE_REQUEST), + 0x88 => Ok(TdispRequestResponseCode::BIND_P2P_STREAM_REQUEST), + 0x89 => Ok(TdispRequestResponseCode::UNBIND_P2P_STREAM_REQUEST), + 0x8A => Ok(TdispRequestResponseCode::SET_MMIO_ATTRIBUTE_REQUEST), + 0x8B => Ok(TdispRequestResponseCode::VDM_REQUEST), + 0x01 => Ok(TdispRequestResponseCode::TDISP_VERSION), + 0x02 => Ok(TdispRequestResponseCode::TDISP_CAPABILITIES), + 0x03 => Ok(TdispRequestResponseCode::LOCK_INTERFACE_RESPONSE), + 0x04 => Ok(TdispRequestResponseCode::DEVICE_INTERFACE_REPORT), + 0x05 => Ok(TdispRequestResponseCode::DEVICE_INTERFACE_STATE), + 0x06 => Ok(TdispRequestResponseCode::START_INTERFACE_RESPONSE), + 0x07 => Ok(TdispRequestResponseCode::STOP_INTERFACE_RESPONSE), + 0x08 => Ok(TdispRequestResponseCode::BIND_P2P_STREAM_RESPONSE), + 0x09 => Ok(TdispRequestResponseCode::UNBIND_P2P_STREAM_RESPONSE), + 0x0A => Ok(TdispRequestResponseCode::SET_MMIO_ATTRIBUTE_RESPONSE), + 0x0B => Ok(TdispRequestResponseCode::VDM_RESPONSE), + 0x7F => Ok(TdispRequestResponseCode::TDISP_ERROR), + _ => Err(()), + } + } +} + +impl Codec for TdispRequestResponseCode { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + u8::from(self).encode(bytes) + } + + fn read(r: &mut codec::Reader) -> Option { + let req_rsp_code = u8::read(r)?; + Self::try_from(req_rsp_code).ok() + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub struct TdispVersion { + pub major_version: u8, + pub minor_version: u8, +} + +impl Default for TdispVersion { + fn default() -> Self { + Self { + major_version: 1, + minor_version: 0, + } + } +} + +impl PartialOrd for TdispVersion { + fn partial_cmp(&self, tv: &TdispVersion) -> Option { + if self.major_version > tv.major_version { + Some(core::cmp::Ordering::Greater) + } else if self.major_version < tv.major_version { + Some(core::cmp::Ordering::Less) + } else if self.minor_version > tv.minor_version { + Some(core::cmp::Ordering::Greater) + } else if self.minor_version < tv.minor_version { + Some(core::cmp::Ordering::Less) + } else { + Some(core::cmp::Ordering::Equal) + } + } +} + +impl Codec for TdispVersion { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + (self.major_version << 4 | self.minor_version).encode(bytes) + } + + fn read(r: &mut codec::Reader) -> Option { + let tdisp_version = u8::read(r)?; + + let major_version = (tdisp_version & 0xF0) >> 4; + let minor_version = tdisp_version & 0x0F; + + Some(Self { + major_version, + minor_version, + }) + } +} + +#[derive(Debug, Copy, Clone)] +pub struct TdispMessageHeader { + pub tdisp_version: TdispVersion, + pub message_type: TdispRequestResponseCode, + pub interface_id: InterfaceId, +} + +impl Codec for TdispMessageHeader { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + let mut cnt = 0; + + cnt += TDISP_PROTOCOL_ID.encode(bytes)?; + cnt += self.tdisp_version.encode(bytes)?; + cnt += self.message_type.encode(bytes)?; + cnt += 0u16.encode(bytes)?; // reserved + cnt += self.interface_id.encode(bytes)?; + + Ok(cnt) + } + + fn read(r: &mut codec::Reader) -> Option { + let protocol_id = u8::read(r)?; + if protocol_id != TDISP_PROTOCOL_ID { + return None; + } + let tdisp_version = TdispVersion::read(r)?; + let message_type = TdispRequestResponseCode::read(r)?; + u16::read(r)?; // reserved + let interface_id = InterfaceId::read(r)?; + + Some(Self { + tdisp_version, + message_type, + interface_id, + }) + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[allow(non_camel_case_types)] +pub enum TdispErrorCode { + INVALID_REQUEST, + BUSY, + INVALID_INTERFACE_STATE, + UNSPECIFIED, + UNSUPPORTED_REQUEST, + VERSION_MISMATCH, + VENDOR_SPECIFIC_ERROR, + INVALID_INTERFACE, + INVALID_NONCE, + INSUFFICIENT_ENTROPY, + INVALID_DEVICE_CONFIGURATION, +} + +impl From for u32 { + fn from(ec: TdispErrorCode) -> Self { + match ec { + TdispErrorCode::INVALID_REQUEST => 0x0001, + TdispErrorCode::BUSY => 0x0003, + TdispErrorCode::INVALID_INTERFACE_STATE => 0x0004, + TdispErrorCode::UNSPECIFIED => 0x0005, + TdispErrorCode::UNSUPPORTED_REQUEST => 0x0007, + TdispErrorCode::VERSION_MISMATCH => 0x0041, + TdispErrorCode::VENDOR_SPECIFIC_ERROR => 0x00FF, + TdispErrorCode::INVALID_INTERFACE => 0x0101, + TdispErrorCode::INVALID_NONCE => 0x0102, + TdispErrorCode::INSUFFICIENT_ENTROPY => 0x0103, + TdispErrorCode::INVALID_DEVICE_CONFIGURATION => 0x0104, + } + } +} + +impl From<&TdispErrorCode> for u32 { + fn from(ec: &TdispErrorCode) -> Self { + u32::from(*ec) + } +} + +impl TryFrom for TdispErrorCode { + type Error = (); + fn try_from(uec: u32) -> Result>::Error> { + match uec { + 0x0001 => Ok(Self::INVALID_REQUEST), + 0x0003 => Ok(Self::BUSY), + 0x0004 => Ok(Self::INVALID_INTERFACE_STATE), + 0x0005 => Ok(Self::UNSPECIFIED), + 0x0007 => Ok(Self::UNSUPPORTED_REQUEST), + 0x0041 => Ok(Self::VERSION_MISMATCH), + 0x00FF => Ok(Self::VENDOR_SPECIFIC_ERROR), + 0x0101 => Ok(Self::INVALID_INTERFACE), + 0x0102 => Ok(Self::INVALID_NONCE), + 0x0103 => Ok(Self::INSUFFICIENT_ENTROPY), + 0x0104 => Ok(Self::INVALID_DEVICE_CONFIGURATION), + _ => Err(()), + } + } +} + +impl Codec for TdispErrorCode { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + u32::from(self).encode(bytes) + } + + fn read(r: &mut codec::Reader) -> Option { + let errcode = u32::read(r)?; + Self::try_from(errcode).ok() + } +} + +#[derive(Debug, Copy, Clone)] +pub struct ReqGetTdispVersion { + pub interface_id: InterfaceId, +} + +impl Codec for ReqGetTdispVersion { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + TdispMessageHeader { + tdisp_version: TdispVersion { + major_version: 1, + minor_version: 0, + }, + message_type: TdispRequestResponseCode::GET_TDISP_VERSION, + interface_id: self.interface_id, + } + .encode(bytes) + } + + fn read(r: &mut codec::Reader) -> Option { + let message_header = TdispMessageHeader::read(r)?; + + if message_header.tdisp_version.major_version != 1 { + return None; + } + + if message_header.message_type != TdispRequestResponseCode::GET_TDISP_VERSION { + return None; + } + + Some(Self { + interface_id: message_header.interface_id, + }) + } +} + +#[derive(Debug, Copy, Clone)] +pub struct RspTdispVersion { + pub interface_id: InterfaceId, + pub version_num_count: u8, + pub version_num_entry: [TdispVersion; u8::MAX as usize], +} + +impl Codec for RspTdispVersion { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + let mut cnt = 0; + + cnt += TdispMessageHeader { + tdisp_version: TdispVersion { + major_version: 1, + minor_version: 0, + }, + message_type: TdispRequestResponseCode::TDISP_VERSION, + interface_id: self.interface_id, + } + .encode(bytes)?; + cnt += self.version_num_count.encode(bytes)?; + for version in self + .version_num_entry + .iter() + .take(self.version_num_count as usize) + { + cnt += version.encode(bytes)?; + } + + Ok(cnt) + } + + fn read(r: &mut codec::Reader) -> Option { + let message_header = TdispMessageHeader::read(r)?; + + if message_header.tdisp_version.major_version != 1 { + return None; + } + + if message_header.message_type != TdispRequestResponseCode::TDISP_VERSION { + return None; + } + + let version_num_count = u8::read(r)?; + let mut version_num_entry = [TdispVersion::default(); u8::MAX as usize]; + for version in version_num_entry + .iter_mut() + .take(version_num_count as usize) + { + *version = TdispVersion::read(r)?; + } + + Some(Self { + interface_id: message_header.interface_id, + version_num_count, + version_num_entry, + }) + } +} + +#[derive(Debug, Copy, Clone)] +pub struct ReqGetTdispCapabilities { + pub message_header: TdispMessageHeader, + pub tsm_caps: u32, +} + +impl Codec for ReqGetTdispCapabilities { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + let mut cnt = 0; + + cnt += self.message_header.encode(bytes)?; + cnt += self.tsm_caps.encode(bytes)?; + + Ok(cnt) + } + + fn read(r: &mut codec::Reader) -> Option { + let message_header = TdispMessageHeader::read(r)?; + let tsm_caps = u32::read(r)?; + + Some(Self { + message_header, + tsm_caps, + }) + } +} + +bitflags! { + #[derive(Default)] + pub struct LockInterfaceFlag: u16 { + const NO_FW_UPDATE = 0b0000_0000_0000_0001; + const SYSTEM_CACHE_LINE_SIZE = 0b0000_0000_0000_0010; + const LOCK_MSIX = 0b0000_0000_0000_0100; + const BIND_P2P = 0b0000_0000_0000_1000; + const ALL_REQUEST_REDIRECT = 0b0000_0000_0001_0000; + } +} + +impl Codec for LockInterfaceFlag { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + self.bits().encode(bytes) + } + + fn read(r: &mut codec::Reader) -> Option { + let bits = u16::read(r)?; + Some(Self { bits }) + } +} + +#[derive(Debug, Copy, Clone)] +pub struct RspTdispCapabilities { + pub message_header: TdispMessageHeader, + pub dsm_caps: u32, + pub req_msgs_supported: [u8; 16], + pub lock_interface_flags_supported: LockInterfaceFlag, + pub dev_addr_width: u8, + pub num_req_this: u8, + pub num_req_all: u8, +} + +impl Codec for RspTdispCapabilities { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + let mut cnt = 0; + + cnt += self.message_header.encode(bytes)?; + cnt += self.dsm_caps.encode(bytes)?; + cnt += self.req_msgs_supported.encode(bytes)?; + cnt += self.lock_interface_flags_supported.encode(bytes)?; + cnt += u24::new(0).encode(bytes)?; // reserved + cnt += self.dev_addr_width.encode(bytes)?; + cnt += self.num_req_this.encode(bytes)?; + cnt += self.num_req_all.encode(bytes)?; + + Ok(cnt) + } + + fn read(r: &mut codec::Reader) -> Option { + let message_header = TdispMessageHeader::read(r)?; + let dsm_caps = u32::read(r)?; + let req_msgs_supported = <[u8; 16]>::read(r)?; + let lock_interface_flags_supported = LockInterfaceFlag::read(r)?; + u24::read(r)?; // reserved + let dev_addr_width = u8::read(r)?; + let num_req_this = u8::read(r)?; + let num_req_all = u8::read(r)?; + + Some(Self { + message_header, + dsm_caps, + req_msgs_supported, + lock_interface_flags_supported, + dev_addr_width, + num_req_this, + num_req_all, + }) + } +} + +#[derive(Debug, Copy, Clone)] +#[allow(non_snake_case)] +pub struct ReqLockInterfaceRequest { + pub message_header: TdispMessageHeader, + pub flags: LockInterfaceFlag, + pub default_stream_id: u8, + pub mmio_reporting_offset: u64, + pub bind_p2p_address_mask: u64, +} + +impl Codec for ReqLockInterfaceRequest { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + let mut cnt = 0; + + cnt += self.message_header.encode(bytes)?; + cnt += self.flags.encode(bytes)?; + cnt += self.default_stream_id.encode(bytes)?; + cnt += 0u8.encode(bytes)?; //reserved + cnt += self.mmio_reporting_offset.encode(bytes)?; + cnt += self.bind_p2p_address_mask.encode(bytes)?; + + Ok(cnt) + } + + fn read(r: &mut codec::Reader) -> Option { + let message_header = TdispMessageHeader::read(r)?; + let flags = LockInterfaceFlag::read(r)?; + let default_stream_id = u8::read(r)?; + u8::read(r)?; // reserved + let mmio_reporting_offset = u64::read(r)?; + let bind_p2p_address_mask = u64::read(r)?; + + Some(Self { + message_header, + flags, + default_stream_id, + mmio_reporting_offset, + bind_p2p_address_mask, + }) + } +} + +pub const START_INTERFACE_NONCE_LEN: usize = 32; + +#[derive(Debug, Copy, Clone)] +#[allow(non_snake_case)] +pub struct RspLockInterfaceResponse { + pub message_header: TdispMessageHeader, + pub start_interface_nonce: [u8; START_INTERFACE_NONCE_LEN], +} + +impl Codec for RspLockInterfaceResponse { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + let mut cnt = 0; + + cnt += self.message_header.encode(bytes)?; + cnt += self.start_interface_nonce.encode(bytes)?; + + Ok(cnt) + } + + fn read(r: &mut codec::Reader) -> Option { + let message_header = TdispMessageHeader::read(r)?; + let start_interface_nonce = <[u8; START_INTERFACE_NONCE_LEN]>::read(r)?; + + Some(Self { + message_header, + start_interface_nonce, + }) + } +} + +#[derive(Debug, Copy, Clone)] +#[allow(non_snake_case)] +pub struct ReqGetDeviceInterfaceReport { + pub message_header: TdispMessageHeader, + pub offset: u16, + pub length: u16, +} + +impl Codec for ReqGetDeviceInterfaceReport { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + let mut cnt = 0; + + cnt += self.message_header.encode(bytes)?; + cnt += self.offset.encode(bytes)?; + cnt += self.length.encode(bytes)?; + + Ok(cnt) + } + + fn read(r: &mut codec::Reader) -> Option { + let message_header = TdispMessageHeader::read(r)?; + let offset = u16::read(r)?; + let length = u16::read(r)?; + + Some(Self { + message_header, + offset, + length, + }) + } +} + +bitflags! { + #[derive(Default)] + pub struct InterfaceInfo: u16 { + const DEVICE_FIRMWARE_UPDATES_NOT_PERMITTED = 0b0000_0000_0000_0001; + const DMA_REQUESTS_WITHOUT_PASID = 0b0000_0000_0000_0010; + const DMA_REQUESTS_WITH_PASID = 0b0000_0000_0000_0100; + const ATS_SUPPORTED_ENABLED = 0b0000_0000_0000_1000; + const PRS_SUPPORTED_ENABLED = 0b0000_0000_0001_0000; + } +} + +impl Codec for InterfaceInfo { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + self.bits().encode(bytes) + } + + fn read(r: &mut codec::Reader) -> Option { + let bits = u16::read(r)?; + Some(Self { bits }) + } +} + +bitflags! { + #[derive(Default)] + pub struct MMIORangeAttribute: u16 { + const MSI_X_TABLE = 0b0000_0000_0000_0001; + const MSI_X_PBA = 0b0000_0000_0000_0010; + const IS_NON_TEE_MEM = 0b0000_0000_0000_0100; + const IS_MEM_ATTR_UPDATABLE = 0b0000_0000_0000_1000; + const PRS_SUPPORTED_ENABLED = 0b0000_0000_0001_0000; + } +} + +impl Codec for MMIORangeAttribute { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + self.bits().encode(bytes) + } + + fn read(r: &mut codec::Reader) -> Option { + let bits = u16::read(r)?; + Some(Self { bits }) + } +} + +#[derive(Debug, Copy, Clone)] +pub struct TdispMmioRange { + pub first_page_with_offset_added: u64, + pub number_of_pages: u32, + pub range_attributes: MMIORangeAttribute, +} + +impl Default for TdispMmioRange { + fn default() -> Self { + Self { + first_page_with_offset_added: 0, + number_of_pages: 0, + range_attributes: MMIORangeAttribute::empty(), + } + } +} + +impl Codec for TdispMmioRange { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + let mut cnt = 0; + + cnt += self.first_page_with_offset_added.encode(bytes)?; + cnt += self.number_of_pages.encode(bytes)?; + cnt += self.range_attributes.encode(bytes)?; + + Ok(cnt) + } + + fn read(r: &mut codec::Reader) -> Option { + let first_page_with_offset_added = u64::read(r)?; + let number_of_pages = u32::read(r)?; + let range_attributes = MMIORangeAttribute::read(r)?; + + Some(Self { + first_page_with_offset_added, + number_of_pages, + range_attributes, + }) + } +} + +#[derive(Debug, Copy, Clone)] +pub struct TdiReportStructure { + pub interface_info: InterfaceInfo, + pub msi_x_message_control: u16, + pub lnr_control: u16, + pub tph_control: u32, + pub mmio_range_count: u32, + pub mmio_range: [TdispMmioRange; MAX_MMIO_RANGE_COUNT], + pub device_specific_info_len: u32, + pub device_specific_info: [u8; MAX_DEVICE_SPECIFIC_INFO_LEN], +} + +impl Default for TdiReportStructure { + fn default() -> Self { + Self { + interface_info: InterfaceInfo::default(), + msi_x_message_control: 0u16, + lnr_control: 0u16, + tph_control: 0u32, + mmio_range_count: 0u32, + mmio_range: [TdispMmioRange::default(); MAX_MMIO_RANGE_COUNT], + device_specific_info_len: 0u32, + device_specific_info: [0u8; MAX_DEVICE_SPECIFIC_INFO_LEN], + } + } +} + +pub const TDISP_REPORT_STRUCTURE_BUFFER_SIZE: usize = + 16 + MAX_MMIO_RANGE_COUNT * 16 + 4 + MAX_DEVICE_SPECIFIC_INFO_LEN; + +impl Codec for TdiReportStructure { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + let mut cnt = 0; + + cnt += self.interface_info.encode(bytes)?; + cnt += 0u16.encode(bytes)?; + cnt += self.msi_x_message_control.encode(bytes)?; + cnt += self.lnr_control.encode(bytes)?; + cnt += self.tph_control.encode(bytes)?; + cnt += self.mmio_range_count.encode(bytes)?; + for mr in self.mmio_range.iter().take(self.mmio_range_count as usize) { + cnt += mr.encode(bytes)?; + } + cnt += self.device_specific_info_len.encode(bytes)?; + for dsi in self + .device_specific_info + .iter() + .take(self.device_specific_info_len as usize) + { + cnt += dsi.encode(bytes)?; + } + + Ok(cnt) + } + + fn read(r: &mut codec::Reader) -> Option { + let interface_info = InterfaceInfo::read(r)?; + u16::read(r)?; + let msi_x_message_control = u16::read(r)?; + let lnr_control = u16::read(r)?; + let tph_control = u32::read(r)?; + let mmio_range_count = u32::read(r)?; + if mmio_range_count as usize > MAX_MMIO_RANGE_COUNT { + return None; + } + let mut mmio_range = [TdispMmioRange::default(); MAX_MMIO_RANGE_COUNT]; + for mr in mmio_range.iter_mut().take(mmio_range_count as usize) { + *mr = TdispMmioRange::read(r)?; + } + let device_specific_info_len = u32::read(r)?; + if device_specific_info_len as usize > MAX_DEVICE_SPECIFIC_INFO_LEN { + return None; + } + let mut device_specific_info = [0u8; MAX_DEVICE_SPECIFIC_INFO_LEN]; + for dsi in device_specific_info + .iter_mut() + .take(device_specific_info_len as usize) + { + *dsi = u8::read(r)?; + } + + Some(Self { + interface_info, + msi_x_message_control, + lnr_control, + tph_control, + mmio_range_count, + mmio_range, + device_specific_info_len, + device_specific_info, + }) + } +} + +#[derive(Debug, Copy, Clone)] +#[allow(non_snake_case)] +pub struct RspDeviceInterfaceReport { + pub message_header: TdispMessageHeader, + pub portion_length: u16, + pub remainder_length: u16, + pub report: [u8; MAX_PORTION_LENGTH], +} + +impl Codec for RspDeviceInterfaceReport { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + let mut cnt = 0; + + cnt += self.message_header.encode(bytes)?; + cnt += self.portion_length.encode(bytes)?; + cnt += self.remainder_length.encode(bytes)?; + cnt += self.report.encode(bytes)?; + + Ok(cnt) + } + + fn read(r: &mut codec::Reader) -> Option { + let message_header = TdispMessageHeader::read(r)?; + let portion_length = u16::read(r)?; + let remainder_length = u16::read(r)?; + let mut report = [0u8; MAX_PORTION_LENGTH]; + if portion_length as usize > MAX_PORTION_LENGTH { + return None; + } + for rp in report.iter_mut().take(portion_length as usize) { + *rp = u8::read(r)?; + } + + Some(Self { + message_header, + portion_length, + remainder_length, + report, + }) + } +} + +#[derive(Debug, Copy, Clone)] +pub struct ReqGetDeviceInterfaceState { + pub message_header: TdispMessageHeader, +} + +impl Codec for ReqGetDeviceInterfaceState { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + self.message_header.encode(bytes) + } + + fn read(r: &mut codec::Reader) -> Option { + let message_header = TdispMessageHeader::read(r)?; + + Some(Self { message_header }) + } +} + +#[derive(Debug, Copy, Clone)] +#[allow(non_snake_case)] +pub struct RspDeviceInterfaceState { + pub message_header: TdispMessageHeader, + pub tdi_state: TdiState, +} + +impl Codec for RspDeviceInterfaceState { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + let mut cnt = 0; + + cnt += self.message_header.encode(bytes)?; + cnt += self.tdi_state.encode(bytes)?; + + Ok(cnt) + } + + fn read(r: &mut codec::Reader) -> Option { + let message_header = TdispMessageHeader::read(r)?; + let tdi_state = TdiState::read(r)?; + + Some(Self { + message_header, + tdi_state, + }) + } +} + +#[derive(Debug, Copy, Clone)] +pub struct ReqStartInterfaceRequest { + pub message_header: TdispMessageHeader, + pub start_interface_nonce: [u8; START_INTERFACE_NONCE_LEN], +} + +impl Codec for ReqStartInterfaceRequest { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + let mut cnt = 0; + + cnt += self.message_header.encode(bytes)?; + cnt += self.start_interface_nonce.encode(bytes)?; + + Ok(cnt) + } + + fn read(r: &mut codec::Reader) -> Option { + let message_header = TdispMessageHeader::read(r)?; + let start_interface_nonce = <[u8; START_INTERFACE_NONCE_LEN]>::read(r)?; + + Some(Self { + message_header, + start_interface_nonce, + }) + } +} + +#[derive(Debug, Copy, Clone)] +pub struct RspStartInterfaceResponse { + pub message_header: TdispMessageHeader, +} + +impl Codec for RspStartInterfaceResponse { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + self.message_header.encode(bytes) + } + + fn read(r: &mut codec::Reader) -> Option { + let message_header = TdispMessageHeader::read(r)?; + + Some(Self { message_header }) + } +} + +#[derive(Debug, Copy, Clone)] +pub struct ReqStopInterfaceRequest { + pub message_header: TdispMessageHeader, +} + +impl Codec for ReqStopInterfaceRequest { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + self.message_header.encode(bytes) + } + + fn read(r: &mut codec::Reader) -> Option { + let message_header = TdispMessageHeader::read(r)?; + + Some(Self { message_header }) + } +} + +#[derive(Debug, Copy, Clone)] +pub struct RspStopInterfaceResponse { + pub message_header: TdispMessageHeader, +} + +impl Codec for RspStopInterfaceResponse { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + self.message_header.encode(bytes) + } + + fn read(r: &mut codec::Reader) -> Option { + let message_header = TdispMessageHeader::read(r)?; + + Some(Self { message_header }) + } +} + +#[derive(Debug, Copy, Clone)] +pub struct ReqBindP2PStreamRequest { + pub message_header: TdispMessageHeader, + pub p2p_stream_id: u8, +} + +impl Codec for ReqBindP2PStreamRequest { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + let mut cnt = 0; + + cnt += self.message_header.encode(bytes)?; + cnt += self.p2p_stream_id.encode(bytes)?; + + Ok(cnt) + } + + fn read(r: &mut codec::Reader) -> Option { + let message_header = TdispMessageHeader::read(r)?; + let p2p_stream_id = u8::read(r)?; + + Some(Self { + message_header, + p2p_stream_id, + }) + } +} + +#[derive(Debug, Copy, Clone)] +pub struct RspBindP2PStreamResponse { + pub message_header: TdispMessageHeader, +} + +impl Codec for RspBindP2PStreamResponse { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + self.message_header.encode(bytes) + } + + fn read(r: &mut codec::Reader) -> Option { + let message_header = TdispMessageHeader::read(r)?; + + Some(Self { message_header }) + } +} + +#[derive(Debug, Copy, Clone)] +pub struct ReqUnBindP2PStreamRequest { + pub message_header: TdispMessageHeader, + pub p2p_stream_id: u8, +} + +impl Codec for ReqUnBindP2PStreamRequest { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + let mut cnt = 0; + + cnt += self.message_header.encode(bytes)?; + cnt += self.p2p_stream_id.encode(bytes)?; + + Ok(cnt) + } + + fn read(r: &mut codec::Reader) -> Option { + let message_header = TdispMessageHeader::read(r)?; + let p2p_stream_id = u8::read(r)?; + + Some(Self { + message_header, + p2p_stream_id, + }) + } +} + +#[derive(Debug, Copy, Clone)] +pub struct RspUnBindP2PStreamResponse { + pub message_header: TdispMessageHeader, +} + +impl Codec for RspUnBindP2PStreamResponse { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + self.message_header.encode(bytes) + } + + fn read(r: &mut codec::Reader) -> Option { + let message_header = TdispMessageHeader::read(r)?; + + Some(Self { message_header }) + } +} + +#[derive(Debug, Copy, Clone)] +pub struct ReqSetMmioAttributeRequest { + pub message_header: TdispMessageHeader, + pub mmio_range: TdispMmioRange, +} + +impl Codec for ReqSetMmioAttributeRequest { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + let mut cnt = 0; + + cnt += self.message_header.encode(bytes)?; + cnt += self.mmio_range.encode(bytes)?; + + Ok(cnt) + } + + fn read(r: &mut codec::Reader) -> Option { + let message_header = TdispMessageHeader::read(r)?; + let mmio_range = TdispMmioRange::read(r)?; + + Some(Self { + message_header, + mmio_range, + }) + } +} + +#[derive(Debug, Copy, Clone)] +pub struct RspSetMmioAttributeResponse { + pub message_header: TdispMessageHeader, +} + +impl Codec for RspSetMmioAttributeResponse { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + self.message_header.encode(bytes) + } + + fn read(r: &mut codec::Reader) -> Option { + let message_header = TdispMessageHeader::read(r)?; + + Some(Self { message_header }) + } +} + +#[derive(Debug, Copy, Clone)] +pub struct RspTdispError { + pub message_header: TdispMessageHeader, + pub error_code: TdispErrorCode, + pub error_data: u32, +} + +impl Codec for RspTdispError { + fn encode(&self, bytes: &mut codec::Writer) -> Result { + let mut cnt = 0; + + cnt += self.message_header.encode(bytes)?; + cnt += self.error_code.encode(bytes)?; + cnt += self.error_data.encode(bytes)?; + + Ok(cnt) + } + + fn read(r: &mut codec::Reader) -> Option { + let message_header = TdispMessageHeader::read(r)?; + if message_header.message_type != TdispRequestResponseCode::TDISP_ERROR { + return None; + } + let error_code = TdispErrorCode::read(r)?; + let error_data = u32::read(r)?; + + Some(Self { + message_header, + error_code, + error_data, + }) + } +} + +pub const STANDARD_ID: RegistryOrStandardsBodyID = RegistryOrStandardsBodyID::PCISIG; + +#[inline] +pub const fn vendor_id() -> VendorIDStruct { + let mut vendor_idstruct = VendorIDStruct { + len: 2, + vendor_id: [0u8; MAX_SPDM_VENDOR_DEFINED_VENDOR_ID_LEN], + }; + + vendor_idstruct.vendor_id[0] = 0x01; + + vendor_idstruct +} diff --git a/tdisp/src/pci_tdisp_requester/mod.rs b/tdisp/src/pci_tdisp_requester/mod.rs new file mode 100644 index 00000000..4c6fb037 --- /dev/null +++ b/tdisp/src/pci_tdisp_requester/mod.rs @@ -0,0 +1,26 @@ +// Copyright (c) 2023 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 or MIT + +use crate::pci_tdisp::{InterfaceId, TdispVersion}; + +pub mod pci_tdisp_req_get_version; +pub use pci_tdisp_req_get_version::*; + +pub mod pci_tdisp_req_get_capabilities; +pub use pci_tdisp_req_get_capabilities::*; + +pub mod pci_tdisp_req_lock_interface; +pub use pci_tdisp_req_lock_interface::*; + +pub mod pci_tdisp_req_get_interface_report; +pub use pci_tdisp_req_get_interface_report::*; + +pub mod pci_tdisp_req_get_interface_state; +pub use pci_tdisp_req_get_interface_state::*; + +pub mod pci_tdisp_req_start_interface; +pub use pci_tdisp_req_start_interface::*; + +pub mod pci_tdisp_req_stop_interface; +pub use pci_tdisp_req_stop_interface::*; diff --git a/tdisp/src/pci_tdisp_requester/pci_tdisp_req_get_capabilities.rs b/tdisp/src/pci_tdisp_requester/pci_tdisp_req_get_capabilities.rs new file mode 100644 index 00000000..d6d9199e --- /dev/null +++ b/tdisp/src/pci_tdisp_requester/pci_tdisp_req_get_capabilities.rs @@ -0,0 +1,92 @@ +// Copyright (c) 2023 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 or MIT + +use codec::Codec; +use codec::Writer; +use spdmlib::error::SPDM_STATUS_BUFFER_FULL; +use spdmlib::error::SPDM_STATUS_INVALID_MSG_FIELD; +use spdmlib::{ + error::SpdmResult, + message::{VendorDefinedReqPayloadStruct, MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE}, + requester::RequesterContext, +}; + +use crate::pci_tdisp::vendor_id; +use crate::pci_tdisp::InterfaceId; +use crate::pci_tdisp::LockInterfaceFlag; +use crate::pci_tdisp::ReqGetTdispCapabilities; +use crate::pci_tdisp::RspTdispCapabilities; +use crate::pci_tdisp::TdispMessageHeader; +use crate::pci_tdisp::TdispRequestResponseCode; +use crate::pci_tdisp::TdispVersion; +use crate::pci_tdisp::STANDARD_ID; + +#[allow(clippy::too_many_arguments)] +pub async fn pci_tdisp_req_get_capabilities( + // IN + spdm_requester: &mut RequesterContext, + session_id: u32, + tsm_caps: u32, + negotiated_version: TdispVersion, + interface_id: InterfaceId, + // OUT + dsm_caps: &mut u32, + lock_interface_flags_supported: &mut LockInterfaceFlag, + dev_addr_width: &mut u8, + num_req_this: &mut u8, + num_req_all: &mut u8, + req_msgs_supported: &mut [u8; 16], +) -> SpdmResult { + let mut vendor_defined_req_payload_struct = VendorDefinedReqPayloadStruct { + req_length: 0, + vendor_defined_req_payload: [0u8; MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], + }; + + let mut writer = + Writer::init(&mut vendor_defined_req_payload_struct.vendor_defined_req_payload); + + vendor_defined_req_payload_struct.req_length = ReqGetTdispCapabilities { + message_header: TdispMessageHeader { + interface_id, + message_type: TdispRequestResponseCode::GET_TDISP_CAPABILITIES, + tdisp_version: negotiated_version, + }, + tsm_caps, + } + .encode(&mut writer) + .map_err(|_| SPDM_STATUS_BUFFER_FULL)? + as u16; + let vendor_defined_rsp_payload_struct = spdm_requester + .send_spdm_vendor_defined_request( + Some(session_id), + STANDARD_ID, + vendor_id(), + vendor_defined_req_payload_struct, + ) + .await?; + + let rsp_tdisp_capabilities = RspTdispCapabilities::read_bytes( + &vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload + [..vendor_defined_rsp_payload_struct.rsp_length as usize], + ) + .ok_or(SPDM_STATUS_INVALID_MSG_FIELD)?; + + if rsp_tdisp_capabilities.message_header.tdisp_version != negotiated_version + || rsp_tdisp_capabilities.message_header.message_type + != TdispRequestResponseCode::TDISP_CAPABILITIES + || rsp_tdisp_capabilities.message_header.interface_id != interface_id + { + return Err(SPDM_STATUS_INVALID_MSG_FIELD); + } + + *dsm_caps = rsp_tdisp_capabilities.dsm_caps; + req_msgs_supported.copy_from_slice(&rsp_tdisp_capabilities.req_msgs_supported); + *lock_interface_flags_supported = rsp_tdisp_capabilities.lock_interface_flags_supported; + *lock_interface_flags_supported = rsp_tdisp_capabilities.lock_interface_flags_supported; + *dev_addr_width = rsp_tdisp_capabilities.dev_addr_width; + *num_req_this = rsp_tdisp_capabilities.num_req_this; + *num_req_all = rsp_tdisp_capabilities.num_req_all; + + Ok(()) +} diff --git a/tdisp/src/pci_tdisp_requester/pci_tdisp_req_get_interface_report.rs b/tdisp/src/pci_tdisp_requester/pci_tdisp_req_get_interface_report.rs new file mode 100644 index 00000000..7705d77d --- /dev/null +++ b/tdisp/src/pci_tdisp_requester/pci_tdisp_req_get_interface_report.rs @@ -0,0 +1,128 @@ +// Copyright (c) 2023 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 or MIT + +use codec::Codec; +use codec::Writer; +use spdmlib::error::SPDM_STATUS_BUFFER_FULL; +use spdmlib::error::SPDM_STATUS_ERROR_PEER; +use spdmlib::error::SPDM_STATUS_INVALID_MSG_FIELD; +use spdmlib::{ + error::SpdmResult, + message::{VendorDefinedReqPayloadStruct, MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE}, + requester::RequesterContext, +}; + +use crate::config::MAX_DEVICE_REPORT_BUFFER; +use crate::config::MAX_PORTION_LENGTH; +use crate::pci_tdisp::vendor_id; +use crate::pci_tdisp::InterfaceId; +use crate::pci_tdisp::ReqGetDeviceInterfaceReport; +use crate::pci_tdisp::RspDeviceInterfaceReport; +use crate::pci_tdisp::RspTdispError; +use crate::pci_tdisp::TdiReportStructure; +use crate::pci_tdisp::TdispErrorCode; +use crate::pci_tdisp::TdispMessageHeader; +use crate::pci_tdisp::TdispRequestResponseCode; +use crate::pci_tdisp::STANDARD_ID; +use crate::pci_tdisp_requester::TdispVersion; + +pub async fn pci_tdisp_req_get_interface_report( + // IN + spdm_requester: &mut RequesterContext, + session_id: u32, + negotiated_version: TdispVersion, + interface_id: InterfaceId, + // OUT + report: &mut TdiReportStructure, + tdisp_error_code: &mut Option, +) -> SpdmResult { + let mut offset = 0u16; + let length = MAX_PORTION_LENGTH as u16; + let mut report_buffer = [0u8; MAX_DEVICE_REPORT_BUFFER]; + let mut report_buffer_walker = 0usize; + + loop { + let mut vendor_defined_req_payload_struct = VendorDefinedReqPayloadStruct { + req_length: 0, + vendor_defined_req_payload: [0u8; MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], + }; + + let mut writer = + Writer::init(&mut vendor_defined_req_payload_struct.vendor_defined_req_payload); + + vendor_defined_req_payload_struct.req_length = ReqGetDeviceInterfaceReport { + message_header: TdispMessageHeader { + interface_id, + message_type: TdispRequestResponseCode::GET_DEVICE_INTERFACE_REPORT, + tdisp_version: negotiated_version, + }, + offset, + length, + } + .encode(&mut writer) + .map_err(|_| SPDM_STATUS_BUFFER_FULL)? + as u16; + + let vendor_defined_rsp_payload_struct = spdm_requester + .send_spdm_vendor_defined_request( + Some(session_id), + STANDARD_ID, + vendor_id(), + vendor_defined_req_payload_struct, + ) + .await?; + + if let Ok(tdisp_error) = RspTdispError::read_bytes( + &vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload + [..vendor_defined_rsp_payload_struct.rsp_length as usize], + ) + .ok_or(SPDM_STATUS_INVALID_MSG_FIELD) + { + *tdisp_error_code = Some(tdisp_error.error_code); + return Err(SPDM_STATUS_ERROR_PEER); + } + + let rsp_device_interface_report = RspDeviceInterfaceReport::read_bytes( + &vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload + [..vendor_defined_rsp_payload_struct.rsp_length as usize], + ) + .ok_or(SPDM_STATUS_INVALID_MSG_FIELD)?; + + if rsp_device_interface_report.message_header.tdisp_version != negotiated_version + || rsp_device_interface_report.message_header.message_type + != TdispRequestResponseCode::DEVICE_INTERFACE_REPORT + || rsp_device_interface_report.message_header.interface_id != interface_id + { + return Err(SPDM_STATUS_INVALID_MSG_FIELD); + } + + if report_buffer_walker + + rsp_device_interface_report.portion_length as usize + + rsp_device_interface_report.remainder_length as usize + > MAX_DEVICE_REPORT_BUFFER + { + return Err(SPDM_STATUS_BUFFER_FULL); + } + + report_buffer[report_buffer_walker + ..report_buffer_walker + rsp_device_interface_report.portion_length as usize] + .copy_from_slice( + &rsp_device_interface_report.report + [..rsp_device_interface_report.portion_length as usize], + ); + report_buffer_walker += rsp_device_interface_report.portion_length as usize; + + if rsp_device_interface_report.remainder_length != 0 { + offset += rsp_device_interface_report.portion_length; + continue; + } else { + break; + } + } + + *report = TdiReportStructure::read_bytes(&report_buffer[..report_buffer_walker]) + .ok_or(SPDM_STATUS_INVALID_MSG_FIELD)?; + + Ok(()) +} diff --git a/tdisp/src/pci_tdisp_requester/pci_tdisp_req_get_interface_state.rs b/tdisp/src/pci_tdisp_requester/pci_tdisp_req_get_interface_state.rs new file mode 100644 index 00000000..1955cead --- /dev/null +++ b/tdisp/src/pci_tdisp_requester/pci_tdisp_req_get_interface_state.rs @@ -0,0 +1,79 @@ +// Copyright (c) 2023 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 or MIT + +use codec::Codec; +use codec::Writer; +use spdmlib::error::SPDM_STATUS_BUFFER_FULL; +use spdmlib::error::SPDM_STATUS_INVALID_MSG_FIELD; +use spdmlib::{ + error::SpdmResult, + message::{VendorDefinedReqPayloadStruct, MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE}, + requester::RequesterContext, +}; + +use crate::pci_tdisp::vendor_id; +use crate::pci_tdisp::InterfaceId; +use crate::pci_tdisp::ReqGetDeviceInterfaceState; +use crate::pci_tdisp::RspDeviceInterfaceState; +use crate::pci_tdisp::TdiState; +use crate::pci_tdisp::TdispMessageHeader; +use crate::pci_tdisp::TdispRequestResponseCode; +use crate::pci_tdisp::TdispVersion; +use crate::pci_tdisp::STANDARD_ID; + +pub async fn pci_tdisp_req_get_interface_state( + // IN + spdm_requester: &mut RequesterContext, + session_id: u32, + negotiated_version: TdispVersion, + interface_id: InterfaceId, + // OUT + tdi_state: &mut TdiState, +) -> SpdmResult { + let mut vendor_defined_req_payload_struct = VendorDefinedReqPayloadStruct { + req_length: 0, + vendor_defined_req_payload: [0u8; MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], + }; + + let mut writer = + Writer::init(&mut vendor_defined_req_payload_struct.vendor_defined_req_payload); + + vendor_defined_req_payload_struct.req_length = ReqGetDeviceInterfaceState { + message_header: TdispMessageHeader { + interface_id, + message_type: TdispRequestResponseCode::GET_DEVICE_INTERFACE_STATE, + tdisp_version: negotiated_version, + }, + } + .encode(&mut writer) + .map_err(|_| SPDM_STATUS_BUFFER_FULL)? + as u16; + + let vendor_defined_rsp_payload_struct = spdm_requester + .send_spdm_vendor_defined_request( + Some(session_id), + STANDARD_ID, + vendor_id(), + vendor_defined_req_payload_struct, + ) + .await?; + + let rsp_device_interface_state = RspDeviceInterfaceState::read_bytes( + &vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload + [..vendor_defined_rsp_payload_struct.rsp_length as usize], + ) + .ok_or(SPDM_STATUS_INVALID_MSG_FIELD)?; + + if rsp_device_interface_state.message_header.tdisp_version != negotiated_version + || rsp_device_interface_state.message_header.message_type + != TdispRequestResponseCode::DEVICE_INTERFACE_STATE + || rsp_device_interface_state.message_header.interface_id != interface_id + { + return Err(SPDM_STATUS_INVALID_MSG_FIELD); + } + + *tdi_state = rsp_device_interface_state.tdi_state; + + Ok(()) +} diff --git a/tdisp/src/pci_tdisp_requester/pci_tdisp_req_get_version.rs b/tdisp/src/pci_tdisp_requester/pci_tdisp_req_get_version.rs new file mode 100644 index 00000000..41a1b62d --- /dev/null +++ b/tdisp/src/pci_tdisp_requester/pci_tdisp_req_get_version.rs @@ -0,0 +1,77 @@ +// Copyright (c) 2023 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 or MIT + +use codec::Codec; +use codec::Writer; +use spdmlib::error::SPDM_STATUS_BUFFER_FULL; +use spdmlib::error::SPDM_STATUS_INVALID_MSG_FIELD; +use spdmlib::{ + error::SpdmResult, + message::{VendorDefinedReqPayloadStruct, MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE}, + requester::RequesterContext, +}; + +use crate::pci_tdisp::vendor_id; +use crate::pci_tdisp::RspTdispVersion; +use crate::pci_tdisp::STANDARD_ID; +use crate::pci_tdisp::{ReqGetTdispVersion, TdispVersion}; +use crate::pci_tdisp_requester::InterfaceId; + +pub async fn pci_tdisp_req_get_version( + // IN + spdm_requester: &mut RequesterContext, + session_id: u32, + interface_id: InterfaceId, + // OUT + negotiated_version: &mut Option, +) -> SpdmResult { + let mut vendor_defined_req_payload_struct = VendorDefinedReqPayloadStruct { + req_length: 0, + vendor_defined_req_payload: [0u8; MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], + }; + + let mut writer = + Writer::init(&mut vendor_defined_req_payload_struct.vendor_defined_req_payload); + + vendor_defined_req_payload_struct.req_length = ReqGetTdispVersion { interface_id } + .encode(&mut writer) + .map_err(|_| SPDM_STATUS_BUFFER_FULL)? + as u16; + + let vendor_defined_rsp_payload_struct = spdm_requester + .send_spdm_vendor_defined_request( + Some(session_id), + STANDARD_ID, + vendor_id(), + vendor_defined_req_payload_struct, + ) + .await?; + + let rsp_tdisp_version = RspTdispVersion::read_bytes( + &vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload + [..vendor_defined_rsp_payload_struct.rsp_length as usize], + ) + .ok_or(SPDM_STATUS_INVALID_MSG_FIELD)?; + + if rsp_tdisp_version.interface_id != interface_id { + return Err(SPDM_STATUS_INVALID_MSG_FIELD); + } + + if rsp_tdisp_version.version_num_count == 1 + && rsp_tdisp_version.version_num_entry[0] + == (TdispVersion { + major_version: 1, + minor_version: 0, + }) + { + *negotiated_version = Some(TdispVersion { + major_version: 1, + minor_version: 0, + }); + Ok(()) + } else { + *negotiated_version = None; + Err(SPDM_STATUS_INVALID_MSG_FIELD) + } +} diff --git a/tdisp/src/pci_tdisp_requester/pci_tdisp_req_lock_interface.rs b/tdisp/src/pci_tdisp_requester/pci_tdisp_req_lock_interface.rs new file mode 100644 index 00000000..7c8e6ef1 --- /dev/null +++ b/tdisp/src/pci_tdisp_requester/pci_tdisp_req_lock_interface.rs @@ -0,0 +1,103 @@ +// Copyright (c) 2023 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 or MIT + +use codec::Codec; +use codec::Writer; +use spdmlib::error::SPDM_STATUS_BUFFER_FULL; +use spdmlib::error::SPDM_STATUS_ERROR_PEER; +use spdmlib::error::SPDM_STATUS_INVALID_MSG_FIELD; +use spdmlib::{ + error::SpdmResult, + message::{VendorDefinedReqPayloadStruct, MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE}, + requester::RequesterContext, +}; + +use crate::pci_tdisp::vendor_id; +use crate::pci_tdisp::InterfaceId; +use crate::pci_tdisp::LockInterfaceFlag; +use crate::pci_tdisp::ReqLockInterfaceRequest; +use crate::pci_tdisp::RspLockInterfaceResponse; +use crate::pci_tdisp::RspTdispError; +use crate::pci_tdisp::TdispErrorCode; +use crate::pci_tdisp::TdispMessageHeader; +use crate::pci_tdisp::TdispRequestResponseCode; +use crate::pci_tdisp::STANDARD_ID; +use crate::pci_tdisp::START_INTERFACE_NONCE_LEN; +use crate::pci_tdisp_requester::TdispVersion; + +#[allow(clippy::too_many_arguments)] +pub async fn pci_tdisp_req_lock_interface( + // IN + spdm_requester: &mut RequesterContext, + session_id: u32, + negotiated_version: TdispVersion, + interface_id: InterfaceId, + flags: LockInterfaceFlag, + default_stream_id: u8, + mmio_reporting_offset: u64, + bind_p2p_address_mask: u64, + // OUT + start_interface_nonce: &mut [u8; START_INTERFACE_NONCE_LEN], + tdisp_error_code: &mut Option, +) -> SpdmResult { + let mut vendor_defined_req_payload_struct = VendorDefinedReqPayloadStruct { + req_length: 0, + vendor_defined_req_payload: [0u8; MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], + }; + + let mut writer = + Writer::init(&mut vendor_defined_req_payload_struct.vendor_defined_req_payload); + + vendor_defined_req_payload_struct.req_length = ReqLockInterfaceRequest { + message_header: TdispMessageHeader { + interface_id, + message_type: TdispRequestResponseCode::LOCK_INTERFACE_REQUEST, + tdisp_version: negotiated_version, + }, + flags, + default_stream_id, + mmio_reporting_offset, + bind_p2p_address_mask, + } + .encode(&mut writer) + .map_err(|_| SPDM_STATUS_BUFFER_FULL)? + as u16; + + let vendor_defined_rsp_payload_struct = spdm_requester + .send_spdm_vendor_defined_request( + Some(session_id), + STANDARD_ID, + vendor_id(), + vendor_defined_req_payload_struct, + ) + .await?; + + if let Ok(tdisp_error) = RspTdispError::read_bytes( + &vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload + [..vendor_defined_rsp_payload_struct.rsp_length as usize], + ) + .ok_or(SPDM_STATUS_INVALID_MSG_FIELD) + { + *tdisp_error_code = Some(tdisp_error.error_code); + return Err(SPDM_STATUS_ERROR_PEER); + } + + let rsp_lock_interface_response = RspLockInterfaceResponse::read_bytes( + &vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload + [..vendor_defined_rsp_payload_struct.rsp_length as usize], + ) + .ok_or(SPDM_STATUS_INVALID_MSG_FIELD)?; + + if rsp_lock_interface_response.message_header.tdisp_version != negotiated_version + || rsp_lock_interface_response.message_header.message_type + != TdispRequestResponseCode::LOCK_INTERFACE_RESPONSE + || rsp_lock_interface_response.message_header.interface_id != interface_id + { + return Err(SPDM_STATUS_INVALID_MSG_FIELD); + } + + start_interface_nonce.copy_from_slice(&rsp_lock_interface_response.start_interface_nonce); + + Ok(()) +} diff --git a/tdisp/src/pci_tdisp_requester/pci_tdisp_req_start_interface.rs b/tdisp/src/pci_tdisp_requester/pci_tdisp_req_start_interface.rs new file mode 100644 index 00000000..ef333e9f --- /dev/null +++ b/tdisp/src/pci_tdisp_requester/pci_tdisp_req_start_interface.rs @@ -0,0 +1,92 @@ +// Copyright (c) 2023 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 or MIT + +use codec::Codec; +use codec::Writer; +use spdmlib::error::SPDM_STATUS_BUFFER_FULL; +use spdmlib::error::SPDM_STATUS_ERROR_PEER; +use spdmlib::error::SPDM_STATUS_INVALID_MSG_FIELD; +use spdmlib::{ + error::SpdmResult, + message::{VendorDefinedReqPayloadStruct, MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE}, + requester::RequesterContext, +}; + +use crate::pci_tdisp::vendor_id; +use crate::pci_tdisp::InterfaceId; +use crate::pci_tdisp::ReqStartInterfaceRequest; +use crate::pci_tdisp::RspStartInterfaceResponse; +use crate::pci_tdisp::RspTdispError; +use crate::pci_tdisp::TdispErrorCode; +use crate::pci_tdisp::TdispMessageHeader; +use crate::pci_tdisp::TdispRequestResponseCode; +use crate::pci_tdisp::TdispVersion; +use crate::pci_tdisp::STANDARD_ID; +use crate::pci_tdisp::START_INTERFACE_NONCE_LEN; + +pub async fn pci_tdisp_req_start_interface( + // IN + spdm_requester: &mut RequesterContext, + session_id: u32, + negotiated_version: TdispVersion, + interface_id: InterfaceId, + start_interface_nonce: &[u8; START_INTERFACE_NONCE_LEN], + // OUT + tdisp_error_code: &mut Option, +) -> SpdmResult { + let mut vendor_defined_req_payload_struct = VendorDefinedReqPayloadStruct { + req_length: 0, + vendor_defined_req_payload: [0u8; MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], + }; + + let mut writer = + Writer::init(&mut vendor_defined_req_payload_struct.vendor_defined_req_payload); + + vendor_defined_req_payload_struct.req_length = ReqStartInterfaceRequest { + message_header: TdispMessageHeader { + interface_id, + message_type: TdispRequestResponseCode::START_INTERFACE_REQUEST, + tdisp_version: negotiated_version, + }, + start_interface_nonce: *start_interface_nonce, + } + .encode(&mut writer) + .map_err(|_| SPDM_STATUS_BUFFER_FULL)? + as u16; + + let vendor_defined_rsp_payload_struct = spdm_requester + .send_spdm_vendor_defined_request( + Some(session_id), + STANDARD_ID, + vendor_id(), + vendor_defined_req_payload_struct, + ) + .await?; + + if let Ok(tdisp_error) = RspTdispError::read_bytes( + &vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload + [..vendor_defined_rsp_payload_struct.rsp_length as usize], + ) + .ok_or(SPDM_STATUS_INVALID_MSG_FIELD) + { + *tdisp_error_code = Some(tdisp_error.error_code); + return Err(SPDM_STATUS_ERROR_PEER); + } + + let rsp_start_interface_response = RspStartInterfaceResponse::read_bytes( + &vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload + [..vendor_defined_rsp_payload_struct.rsp_length as usize], + ) + .ok_or(SPDM_STATUS_INVALID_MSG_FIELD)?; + + if rsp_start_interface_response.message_header.tdisp_version != negotiated_version + || rsp_start_interface_response.message_header.message_type + != TdispRequestResponseCode::START_INTERFACE_RESPONSE + || rsp_start_interface_response.message_header.interface_id != interface_id + { + return Err(SPDM_STATUS_INVALID_MSG_FIELD); + } + + Ok(()) +} diff --git a/tdisp/src/pci_tdisp_requester/pci_tdisp_req_stop_interface.rs b/tdisp/src/pci_tdisp_requester/pci_tdisp_req_stop_interface.rs new file mode 100644 index 00000000..d33694cb --- /dev/null +++ b/tdisp/src/pci_tdisp_requester/pci_tdisp_req_stop_interface.rs @@ -0,0 +1,74 @@ +// Copyright (c) 2023 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 or MIT + +use codec::Codec; +use codec::Writer; +use spdmlib::error::SPDM_STATUS_BUFFER_FULL; +use spdmlib::error::SPDM_STATUS_INVALID_MSG_FIELD; +use spdmlib::{ + error::SpdmResult, + message::{VendorDefinedReqPayloadStruct, MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE}, + requester::RequesterContext, +}; + +use crate::pci_tdisp::vendor_id; +use crate::pci_tdisp::InterfaceId; +use crate::pci_tdisp::ReqStopInterfaceRequest; +use crate::pci_tdisp::RspStopInterfaceResponse; +use crate::pci_tdisp::TdispMessageHeader; +use crate::pci_tdisp::TdispRequestResponseCode; +use crate::pci_tdisp::TdispVersion; +use crate::pci_tdisp::STANDARD_ID; + +pub async fn pci_tdisp_req_stop_interface( + // IN + spdm_requester: &mut RequesterContext, + session_id: u32, + negotiated_version: TdispVersion, + interface_id: InterfaceId, +) -> SpdmResult { + let mut vendor_defined_req_payload_struct = VendorDefinedReqPayloadStruct { + req_length: 0, + vendor_defined_req_payload: [0u8; MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], + }; + + let mut writer = + Writer::init(&mut vendor_defined_req_payload_struct.vendor_defined_req_payload); + + vendor_defined_req_payload_struct.req_length = ReqStopInterfaceRequest { + message_header: TdispMessageHeader { + interface_id, + message_type: TdispRequestResponseCode::STOP_INTERFACE_REQUEST, + tdisp_version: negotiated_version, + }, + } + .encode(&mut writer) + .map_err(|_| SPDM_STATUS_BUFFER_FULL)? + as u16; + + let vendor_defined_rsp_payload_struct = spdm_requester + .send_spdm_vendor_defined_request( + Some(session_id), + STANDARD_ID, + vendor_id(), + vendor_defined_req_payload_struct, + ) + .await?; + + let rsp_stop_interface_response = RspStopInterfaceResponse::read_bytes( + &vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload + [..vendor_defined_rsp_payload_struct.rsp_length as usize], + ) + .ok_or(SPDM_STATUS_INVALID_MSG_FIELD)?; + + if rsp_stop_interface_response.message_header.tdisp_version != negotiated_version + || rsp_stop_interface_response.message_header.message_type + != TdispRequestResponseCode::STOP_INTERFACE_RESPONSE + || rsp_stop_interface_response.message_header.interface_id != interface_id + { + return Err(SPDM_STATUS_INVALID_MSG_FIELD); + } + + Ok(()) +} diff --git a/tdisp/src/pci_tdisp_responder/mod.rs b/tdisp/src/pci_tdisp_responder/mod.rs new file mode 100644 index 00000000..39579279 --- /dev/null +++ b/tdisp/src/pci_tdisp_responder/mod.rs @@ -0,0 +1,25 @@ +// Copyright (c) 2023 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 or MIT + +pub const MAX_TDISP_VERSION_COUNT: usize = u8::MAX as usize; + +pub mod pci_tdisp_rsp_dispatcher; +pub use pci_tdisp_rsp_dispatcher::*; + +pub mod pci_tdisp_rsp_version; + +pub mod pci_tdisp_rsp_capabilities; + +pub mod pci_tdisp_rsp_lock_interface; + +pub mod pci_tdisp_rsp_interface_report; + +pub mod pci_tdisp_rsp_interface_state; + +pub mod pci_tdisp_rsp_start_interface; + +pub mod pci_tdisp_rsp_stop_interface; + +pub mod pci_tdisp_rsp_error; +pub use pci_tdisp_rsp_error::*; diff --git a/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_capabilities.rs b/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_capabilities.rs new file mode 100644 index 00000000..6df376ed --- /dev/null +++ b/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_capabilities.rs @@ -0,0 +1,184 @@ +// Copyright (c) 2023 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 or MIT + +use codec::{Codec, Writer}; +use conquer_once::spin::OnceCell; +use spdmlib::{ + error::{ + SpdmResult, SPDM_STATUS_BUFFER_FULL, SPDM_STATUS_INVALID_MSG_FIELD, + SPDM_STATUS_INVALID_STATE_LOCAL, + }, + message::{ + VendorDefinedReqPayloadStruct, VendorDefinedRspPayloadStruct, + MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE, + }, +}; + +use crate::pci_tdisp::{ + InterfaceId, LockInterfaceFlag, ReqGetTdispCapabilities, RspTdispCapabilities, TdispErrorCode, + TdispMessageHeader, TdispRequestResponseCode, TdispVersion, +}; + +use super::write_error; + +static PCI_TDISP_DEVICE_CAPABILITIES_INSTANCE: OnceCell = + OnceCell::uninit(); + +#[derive(Clone)] +pub struct PciTdispDeviceCapabilities { + #[allow(clippy::type_complexity)] + pub pci_tdisp_device_capabilities_cb: fn( + // IN + vendor_context: usize, + tsm_caps: u32, + // OUT + negotiated_version: &mut TdispVersion, + interface_id: &mut InterfaceId, + dsm_caps: &mut u32, + req_msgs_supported: &mut [u8; 16], + lock_interface_flags_supported: &mut LockInterfaceFlag, + dev_addr_width: &mut u8, + num_req_this: &mut u8, + num_req_all: &mut u8, + tdisp_error_code: &mut Option, + ) -> SpdmResult, +} + +pub fn register(context: PciTdispDeviceCapabilities) -> bool { + PCI_TDISP_DEVICE_CAPABILITIES_INSTANCE + .try_init_once(|| context) + .is_ok() +} + +static UNIMPLETEMTED: PciTdispDeviceCapabilities = PciTdispDeviceCapabilities { + pci_tdisp_device_capabilities_cb: |// IN + _vendor_context: usize, + _tsm_caps: u32, + // OUT + _negotiated_version: &mut TdispVersion, + _interface_id: &mut InterfaceId, + _dsm_caps: &mut u32, + _req_msgs_supported: &mut [u8; 16], + _lock_interface_flags_supported: &mut LockInterfaceFlag, + _dev_addr_width: &mut u8, + _num_req_this: &mut u8, + _num_req_all: &mut u8, + _tdisp_error_code: &mut Option| + -> SpdmResult { unimplemented!() }, +}; + +#[allow(clippy::too_many_arguments)] +pub(crate) fn pci_tdisp_device_capabilities( + // IN + vendor_context: usize, + tsm_caps: u32, + // OUT + negotiated_version: &mut TdispVersion, + interface_id: &mut InterfaceId, + dsm_caps: &mut u32, + req_msgs_supported: &mut [u8; 16], + lock_interface_flags_supported: &mut LockInterfaceFlag, + dev_addr_width: &mut u8, + num_req_this: &mut u8, + num_req_all: &mut u8, + tdisp_error_code: &mut Option, +) -> SpdmResult { + (PCI_TDISP_DEVICE_CAPABILITIES_INSTANCE + .try_get_or_init(|| UNIMPLETEMTED.clone()) + .ok() + .ok_or(SPDM_STATUS_INVALID_STATE_LOCAL)? + .pci_tdisp_device_capabilities_cb)( + // IN + vendor_context, + tsm_caps, + // OUT + negotiated_version, + interface_id, + dsm_caps, + req_msgs_supported, + lock_interface_flags_supported, + dev_addr_width, + num_req_this, + num_req_all, + tdisp_error_code, + ) +} + +pub(crate) fn pci_tdisp_rsp_capabilities( + vendor_context: usize, + vendor_defined_req_payload_struct: &VendorDefinedReqPayloadStruct, +) -> SpdmResult { + let req_get_tdisp_capabilities = ReqGetTdispCapabilities::read_bytes( + &vendor_defined_req_payload_struct.vendor_defined_req_payload + [..vendor_defined_req_payload_struct.req_length as usize], + ) + .ok_or(SPDM_STATUS_INVALID_MSG_FIELD)?; + + let mut negotiated_version = TdispVersion::default(); + let mut interface_id = InterfaceId::default(); + let mut dsm_caps = 0u32; + let mut req_msgs_supported = [0u8; 16]; + let mut lock_interface_flags_supported = LockInterfaceFlag::empty(); + let mut dev_addr_width = 0u8; + let mut num_req_this = 0u8; + let mut num_req_all = 0u8; + let mut tdisp_error_code = None; + + pci_tdisp_device_capabilities( + vendor_context, + req_get_tdisp_capabilities.tsm_caps, + &mut negotiated_version, + &mut interface_id, + &mut dsm_caps, + &mut req_msgs_supported, + &mut lock_interface_flags_supported, + &mut dev_addr_width, + &mut num_req_this, + &mut num_req_all, + &mut tdisp_error_code, + )?; + + let mut vendor_defined_rsp_payload_struct = VendorDefinedRspPayloadStruct { + rsp_length: 0, + vendor_defined_rsp_payload: [0u8; MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], + }; + + if let Some(tdisp_error_code) = tdisp_error_code { + let len = write_error( + vendor_context, + tdisp_error_code, + 0, + &[], + &mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload, + )?; + vendor_defined_rsp_payload_struct.rsp_length = len as u16; + return Ok(vendor_defined_rsp_payload_struct); + } + + let mut writer = + Writer::init(&mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload); + + let cnt = RspTdispCapabilities { + message_header: TdispMessageHeader { + interface_id, + message_type: TdispRequestResponseCode::TDISP_CAPABILITIES, + tdisp_version: negotiated_version, + }, + dsm_caps, + req_msgs_supported, + lock_interface_flags_supported, + dev_addr_width, + num_req_this, + num_req_all, + } + .encode(&mut writer) + .map_err(|_| SPDM_STATUS_BUFFER_FULL)?; + + if cnt > u16::MAX as usize { + Err(SPDM_STATUS_INVALID_STATE_LOCAL) + } else { + vendor_defined_rsp_payload_struct.rsp_length = cnt as u16; + Ok(vendor_defined_rsp_payload_struct) + } +} diff --git a/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_dispatcher.rs b/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_dispatcher.rs new file mode 100644 index 00000000..17cc48ff --- /dev/null +++ b/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_dispatcher.rs @@ -0,0 +1,79 @@ +// Copyright (c) 2023 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 or MIT + +use core::convert::TryFrom; +use spdmlib::{ + error::{SpdmResult, SPDM_STATUS_INVALID_MSG_FIELD}, + message::{ + VendorDefinedReqPayloadStruct, VendorDefinedRspPayloadStruct, + MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE, + }, +}; + +use crate::pci_tdisp::{TdispErrorCode, TdispRequestResponseCode}; + +use super::{ + pci_tdisp_rsp_capabilities::pci_tdisp_rsp_capabilities, + pci_tdisp_rsp_interface_report::pci_tdisp_rsp_interface_report, + pci_tdisp_rsp_interface_state::pci_tdisp_rsp_interface_state, + pci_tdisp_rsp_lock_interface::pci_tdisp_rsp_lock_interface, + pci_tdisp_rsp_start_interface::pci_tdisp_rsp_start_interface, + pci_tdisp_rsp_stop_interface::pci_tdisp_rsp_stop_interface, + pci_tdisp_rsp_version::pci_tdisp_rsp_version, write_error, +}; + +pub fn pci_tdisp_rsp_dispatcher( + vendor_context: usize, + vendor_defined_req_payload_struct: &VendorDefinedReqPayloadStruct, +) -> SpdmResult { + if vendor_defined_req_payload_struct.req_length < 3 { + return Err(SPDM_STATUS_INVALID_MSG_FIELD); + } + + if let Ok(request_response_code) = TdispRequestResponseCode::try_from( + vendor_defined_req_payload_struct.vendor_defined_req_payload[2], + ) { + match request_response_code { + TdispRequestResponseCode::GET_TDISP_VERSION => { + pci_tdisp_rsp_version(vendor_context, vendor_defined_req_payload_struct) + } + TdispRequestResponseCode::GET_TDISP_CAPABILITIES => { + pci_tdisp_rsp_capabilities(vendor_context, vendor_defined_req_payload_struct) + } + TdispRequestResponseCode::LOCK_INTERFACE_REQUEST => { + pci_tdisp_rsp_lock_interface(vendor_context, vendor_defined_req_payload_struct) + } + TdispRequestResponseCode::GET_DEVICE_INTERFACE_REPORT => { + pci_tdisp_rsp_interface_report(vendor_context, vendor_defined_req_payload_struct) + } + TdispRequestResponseCode::GET_DEVICE_INTERFACE_STATE => { + pci_tdisp_rsp_interface_state(vendor_context, vendor_defined_req_payload_struct) + } + TdispRequestResponseCode::START_INTERFACE_REQUEST => { + pci_tdisp_rsp_start_interface(vendor_context, vendor_defined_req_payload_struct) + } + TdispRequestResponseCode::STOP_INTERFACE_REQUEST => { + pci_tdisp_rsp_stop_interface(vendor_context, vendor_defined_req_payload_struct) + } + _ => { + let mut vendor_defined_rsp_payload_struct = VendorDefinedRspPayloadStruct { + rsp_length: 0, + vendor_defined_rsp_payload: [0u8; MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], + }; + + let len = write_error( + vendor_context, + TdispErrorCode::UNSUPPORTED_REQUEST, + 0, + &[], + &mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload, + )?; + vendor_defined_rsp_payload_struct.rsp_length = len as u16; + Ok(vendor_defined_rsp_payload_struct) + } + } + } else { + Err(SPDM_STATUS_INVALID_MSG_FIELD) + } +} diff --git a/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_error.rs b/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_error.rs new file mode 100644 index 00000000..20f384b3 --- /dev/null +++ b/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_error.rs @@ -0,0 +1,97 @@ +// Copyright (c) 2023 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 or MIT + +use codec::{Codec, Writer}; +use conquer_once::spin::OnceCell; +use spdmlib::{ + error::{SpdmResult, SPDM_STATUS_BUFFER_FULL, SPDM_STATUS_INVALID_STATE_LOCAL}, + message::MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE, +}; + +use crate::pci_tdisp::{ + InterfaceId, RspTdispError, TdispErrorCode, TdispMessageHeader, TdispRequestResponseCode, + TdispVersion, +}; + +static PCI_TDISP_DEVICE_ERROR_INSTANCE: OnceCell = OnceCell::uninit(); + +#[derive(Clone)] +pub struct PciTdispDeviceError { + #[allow(clippy::type_complexity)] + pub pci_tdisp_device_error_cb: fn( + // IN + vendor_context: usize, + // OUT + negotiated_version: &mut TdispVersion, + interface_id: &mut InterfaceId, + ) -> SpdmResult, +} + +pub fn register(context: PciTdispDeviceError) -> bool { + PCI_TDISP_DEVICE_ERROR_INSTANCE + .try_init_once(|| context) + .is_ok() +} + +static UNIMPLETEMTED: PciTdispDeviceError = PciTdispDeviceError { + pci_tdisp_device_error_cb: |// IN + _vendor_context: usize, + // OUT + _negotiated_version: &mut TdispVersion, + _interface_id: &mut InterfaceId| + -> SpdmResult { unimplemented!() }, +}; + +pub(crate) fn pci_tdisp_device_error( + // IN + vendor_context: usize, + // OUT + negotiated_version: &mut TdispVersion, + interface_id: &mut InterfaceId, +) -> SpdmResult { + (PCI_TDISP_DEVICE_ERROR_INSTANCE + .try_get_or_init(|| UNIMPLETEMTED.clone()) + .ok() + .ok_or(SPDM_STATUS_INVALID_STATE_LOCAL)? + .pci_tdisp_device_error_cb)( + // IN + vendor_context, + // OUT + negotiated_version, + interface_id, + ) +} + +pub(crate) fn write_error( + vendor_context: usize, + error_code: TdispErrorCode, + error_data: u32, + ext_error_data: &[u8], + vendor_defined_rsp_payload: &mut [u8; MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], +) -> SpdmResult { + let mut writer = Writer::init(vendor_defined_rsp_payload); + + let mut negotiated_version = TdispVersion::default(); + let mut interface_id = InterfaceId::default(); + + pci_tdisp_device_error(vendor_context, &mut negotiated_version, &mut interface_id)?; + + let len1 = RspTdispError { + message_header: TdispMessageHeader { + interface_id, + message_type: TdispRequestResponseCode::TDISP_ERROR, + tdisp_version: negotiated_version, + }, + error_code, + error_data, + } + .encode(&mut writer) + .map_err(|_| SPDM_STATUS_BUFFER_FULL)?; + + if let Some(len2) = writer.extend_from_slice(ext_error_data) { + Ok(len1 + len2) + } else { + Err(SPDM_STATUS_BUFFER_FULL) + } +} diff --git a/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_interface_report.rs b/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_interface_report.rs new file mode 100644 index 00000000..c86db872 --- /dev/null +++ b/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_interface_report.rs @@ -0,0 +1,194 @@ +// Copyright (c) 2023 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 or MIT + +use codec::{Codec, Writer}; +use conquer_once::spin::OnceCell; +use spdmlib::{ + error::{ + SpdmResult, SPDM_STATUS_BUFFER_FULL, SPDM_STATUS_INVALID_MSG_FIELD, + SPDM_STATUS_INVALID_STATE_LOCAL, + }, + message::{ + VendorDefinedReqPayloadStruct, VendorDefinedRspPayloadStruct, + MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE, + }, +}; + +use crate::{ + config::MAX_PORTION_LENGTH, + pci_tdisp::{ + InterfaceId, ReqGetDeviceInterfaceReport, RspDeviceInterfaceReport, TdiReportStructure, + TdispErrorCode, TdispMessageHeader, TdispRequestResponseCode, TdispVersion, + TDISP_REPORT_STRUCTURE_BUFFER_SIZE, + }, +}; + +use super::write_error; + +static PCI_TDISP_DEVICE_INTERFACE_REPORT_INSTANCE: OnceCell = + OnceCell::uninit(); + +#[derive(Clone)] +pub struct PciTdispDeviceInterfaceReport { + pub pci_tdisp_device_interface_report_cb: fn( + // INT + vendor_context: usize, + // OUT + negotiated_version: &mut TdispVersion, + interface_id: &mut InterfaceId, + tdi_report: &mut TdiReportStructure, + tdisp_error_code: &mut Option, + ) -> SpdmResult, +} + +pub fn register(context: PciTdispDeviceInterfaceReport) -> bool { + PCI_TDISP_DEVICE_INTERFACE_REPORT_INSTANCE + .try_init_once(|| context) + .is_ok() +} + +static UNIMPLETEMTED: PciTdispDeviceInterfaceReport = PciTdispDeviceInterfaceReport { + pci_tdisp_device_interface_report_cb: |_: usize, + _: &mut TdispVersion, + _: &mut InterfaceId, + _: &mut TdiReportStructure, + _: &mut Option| + -> SpdmResult { unimplemented!() }, +}; + +pub(crate) fn pci_tdisp_device_interface_report( + // INT + vendor_context: usize, + // OUT + negotiated_version: &mut TdispVersion, + interface_id: &mut InterfaceId, + tdi_report: &mut TdiReportStructure, + tdisp_error_code: &mut Option, +) -> SpdmResult { + (PCI_TDISP_DEVICE_INTERFACE_REPORT_INSTANCE + .try_get_or_init(|| UNIMPLETEMTED.clone()) + .ok() + .ok_or(SPDM_STATUS_INVALID_STATE_LOCAL)? + .pci_tdisp_device_interface_report_cb)( + vendor_context, + negotiated_version, + interface_id, + tdi_report, + tdisp_error_code, + ) +} + +pub(crate) fn pci_tdisp_rsp_interface_report( + vendor_context: usize, + vendor_defined_req_payload_struct: &VendorDefinedReqPayloadStruct, +) -> SpdmResult { + let req_get_device_interface_report = ReqGetDeviceInterfaceReport::read_bytes( + &vendor_defined_req_payload_struct.vendor_defined_req_payload + [..vendor_defined_req_payload_struct.req_length as usize], + ) + .ok_or(SPDM_STATUS_INVALID_MSG_FIELD)?; + + let mut negotiated_version = TdispVersion::default(); + let mut interface_id = InterfaceId::default(); + let mut tdi_report = TdiReportStructure::default(); + let mut tdisp_error_code_code = None; + + // device need to check tdi state + pci_tdisp_device_interface_report( + vendor_context, + &mut negotiated_version, + &mut interface_id, + &mut tdi_report, + &mut tdisp_error_code_code, + )?; + + let mut vendor_defined_rsp_payload_struct = VendorDefinedRspPayloadStruct { + rsp_length: 0, + vendor_defined_rsp_payload: [0u8; MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], + }; + + if let Some(tdisp_error_code_code) = tdisp_error_code_code { + let len = write_error( + vendor_context, + tdisp_error_code_code, + 0, + &[], + &mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload, + )?; + vendor_defined_rsp_payload_struct.rsp_length = len as u16; + return Ok(vendor_defined_rsp_payload_struct); + } + + let mut internal_report_buffer = [0u8; TDISP_REPORT_STRUCTURE_BUFFER_SIZE]; + let mut writer = Writer::init(&mut internal_report_buffer); + let total_report_size = tdi_report + .encode(&mut writer) + .map_err(|_| SPDM_STATUS_BUFFER_FULL)?; + + if req_get_device_interface_report.offset as usize >= total_report_size { + let len = write_error( + vendor_context, + TdispErrorCode::INVALID_REQUEST, + 0, + &[], + &mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload, + )?; + vendor_defined_rsp_payload_struct.rsp_length = len as u16; + return Ok(vendor_defined_rsp_payload_struct); + } + + let portion_length = if req_get_device_interface_report.length as usize > MAX_PORTION_LENGTH { + MAX_PORTION_LENGTH as u16 + } else { + req_get_device_interface_report.length + }; + + let portion_length = if req_get_device_interface_report.offset as usize + + portion_length as usize + > total_report_size + { + (total_report_size - req_get_device_interface_report.offset as usize) as u16 + } else { + portion_length + }; + + let remainder_length = if total_report_size + > req_get_device_interface_report.offset as usize + portion_length as usize + { + (total_report_size + - req_get_device_interface_report.offset as usize + - portion_length as usize) as u16 + } else { + 0 + }; + + let mut writer = + Writer::init(&mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload); + + let mut report = [0u8; MAX_PORTION_LENGTH]; + report[..portion_length as usize].copy_from_slice( + &internal_report_buffer[req_get_device_interface_report.offset as usize + ..req_get_device_interface_report.offset as usize + portion_length as usize], + ); + + let cnt = RspDeviceInterfaceReport { + message_header: TdispMessageHeader { + interface_id, + message_type: TdispRequestResponseCode::DEVICE_INTERFACE_REPORT, + tdisp_version: negotiated_version, + }, + portion_length, + remainder_length, + report, + } + .encode(&mut writer) + .map_err(|_| SPDM_STATUS_BUFFER_FULL)?; + + if cnt > u16::MAX as usize { + Err(SPDM_STATUS_INVALID_STATE_LOCAL) + } else { + vendor_defined_rsp_payload_struct.rsp_length = cnt as u16; + Ok(vendor_defined_rsp_payload_struct) + } +} diff --git a/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_interface_state.rs b/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_interface_state.rs new file mode 100644 index 00000000..fb6aaf6a --- /dev/null +++ b/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_interface_state.rs @@ -0,0 +1,138 @@ +// Copyright (c) 2023 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 or MIT + +use codec::{Codec, Writer}; +use conquer_once::spin::OnceCell; +use spdmlib::{ + error::{ + SpdmResult, SPDM_STATUS_BUFFER_FULL, SPDM_STATUS_INVALID_MSG_FIELD, + SPDM_STATUS_INVALID_STATE_LOCAL, + }, + message::{ + VendorDefinedReqPayloadStruct, VendorDefinedRspPayloadStruct, + MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE, + }, +}; + +use crate::pci_tdisp::{ + InterfaceId, ReqGetDeviceInterfaceState, RspDeviceInterfaceState, TdiState, TdispErrorCode, + TdispMessageHeader, TdispRequestResponseCode, TdispVersion, +}; + +use super::write_error; + +static PCI_TDISP_DEVICE_INTERFACE_STATE_INSTANCE: OnceCell = + OnceCell::uninit(); + +#[derive(Clone)] +pub struct PciTdispDeviceInterfaceState { + pub pci_tdisp_device_interface_state_cb: fn( + // IN + vendor_context: usize, + // OUT + negotiated_version: &mut TdispVersion, + interface_id: &mut InterfaceId, + tdi_state: &mut TdiState, + tdisp_error_code: &mut Option, + ) -> SpdmResult, +} + +pub fn register(context: PciTdispDeviceInterfaceState) -> bool { + PCI_TDISP_DEVICE_INTERFACE_STATE_INSTANCE + .try_init_once(|| context) + .is_ok() +} + +static UNIMPLETEMTED: PciTdispDeviceInterfaceState = PciTdispDeviceInterfaceState { + pci_tdisp_device_interface_state_cb: |_: usize, + _: &mut TdispVersion, + _: &mut InterfaceId, + _: &mut TdiState, + _: &mut Option| + -> SpdmResult { unimplemented!() }, +}; + +pub(crate) fn pci_tdisp_device_interface_state( + // IN + vendor_context: usize, + // OUT + negotiated_version: &mut TdispVersion, + interface_id: &mut InterfaceId, + tdi_state: &mut TdiState, + tdisp_error_code: &mut Option, +) -> SpdmResult { + (PCI_TDISP_DEVICE_INTERFACE_STATE_INSTANCE + .try_get_or_init(|| UNIMPLETEMTED.clone()) + .ok() + .ok_or(SPDM_STATUS_INVALID_STATE_LOCAL)? + .pci_tdisp_device_interface_state_cb)( + vendor_context, + negotiated_version, + interface_id, + tdi_state, + tdisp_error_code, + ) +} + +pub(crate) fn pci_tdisp_rsp_interface_state( + vendor_context: usize, + vendor_defined_req_payload_struct: &VendorDefinedReqPayloadStruct, +) -> SpdmResult { + let _ = ReqGetDeviceInterfaceState::read_bytes( + &vendor_defined_req_payload_struct.vendor_defined_req_payload + [..vendor_defined_req_payload_struct.req_length as usize], + ) + .ok_or(SPDM_STATUS_INVALID_MSG_FIELD)?; + + let mut negotiated_version = TdispVersion::default(); + let mut interface_id = InterfaceId::default(); + let mut tdi_state = TdiState::ERROR; + let mut tdisp_error_code = None; + + pci_tdisp_device_interface_state( + vendor_context, + &mut negotiated_version, + &mut interface_id, + &mut tdi_state, + &mut tdisp_error_code, + )?; + + let mut vendor_defined_rsp_payload_struct = VendorDefinedRspPayloadStruct { + rsp_length: 0, + vendor_defined_rsp_payload: [0u8; MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], + }; + + if let Some(tdisp_error_code) = tdisp_error_code { + let len = write_error( + vendor_context, + tdisp_error_code, + 0, + &[], + &mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload, + )?; + vendor_defined_rsp_payload_struct.rsp_length = len as u16; + return Ok(vendor_defined_rsp_payload_struct); + } + + let mut writer = + Writer::init(&mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload); + + let cnt = RspDeviceInterfaceState { + message_header: TdispMessageHeader { + interface_id, + message_type: TdispRequestResponseCode::DEVICE_INTERFACE_STATE, + tdisp_version: negotiated_version, + }, + tdi_state, + } + .encode(&mut writer) + .map_err(|_| SPDM_STATUS_BUFFER_FULL)?; + + if cnt > u16::MAX as usize { + Err(SPDM_STATUS_INVALID_STATE_LOCAL) + } else { + vendor_defined_rsp_payload_struct.rsp_length = cnt as u16; + Ok(vendor_defined_rsp_payload_struct) + } +} diff --git a/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_lock_interface.rs b/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_lock_interface.rs new file mode 100644 index 00000000..0c323fd7 --- /dev/null +++ b/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_lock_interface.rs @@ -0,0 +1,164 @@ +// Copyright (c) 2023 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 or MIT + +use codec::{Codec, Writer}; +use conquer_once::spin::OnceCell; +use spdmlib::{ + error::{ + SpdmResult, SPDM_STATUS_BUFFER_FULL, SPDM_STATUS_INVALID_MSG_FIELD, + SPDM_STATUS_INVALID_STATE_LOCAL, + }, + message::{ + VendorDefinedReqPayloadStruct, VendorDefinedRspPayloadStruct, + MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE, + }, +}; + +use crate::pci_tdisp::{ + InterfaceId, LockInterfaceFlag, ReqLockInterfaceRequest, RspLockInterfaceResponse, + TdispErrorCode, TdispMessageHeader, TdispRequestResponseCode, TdispVersion, + START_INTERFACE_NONCE_LEN, +}; + +use super::write_error; + +static PCI_TDISP_DEVICE_LOCK_INTERFACE_INSTANCE: OnceCell = + OnceCell::uninit(); + +#[derive(Clone)] +pub struct PciTdispDeviceLockInterface { + #[allow(clippy::type_complexity)] + pub pci_tdisp_device_lock_interface_cb: fn( + // IN + vendor_context: usize, + flags: &LockInterfaceFlag, + default_stream_id: u8, + mmio_reporting_offset: u64, + bind_p2p_address_mask: u64, + // OUT + negotiated_version: &mut TdispVersion, + interface_id: &mut InterfaceId, + start_interface_nonce: &mut [u8; START_INTERFACE_NONCE_LEN], + tdisp_error_code: &mut Option, + ) -> SpdmResult, +} + +pub fn register(context: PciTdispDeviceLockInterface) -> bool { + PCI_TDISP_DEVICE_LOCK_INTERFACE_INSTANCE + .try_init_once(|| context) + .is_ok() +} + +static UNIMPLETEMTED: PciTdispDeviceLockInterface = PciTdispDeviceLockInterface { + pci_tdisp_device_lock_interface_cb: + |// IN + _vendor_context: usize, + _flags: &LockInterfaceFlag, + _default_stream_id: u8, + _mmio_reporting_offset: u64, + _bind_p2p_address_mask: u64, + // OUT + _negotiated_version: &mut TdispVersion, + _interface_id: &mut InterfaceId, + _start_interface_nonce: &mut [u8; START_INTERFACE_NONCE_LEN], + _tdisp_error_code: &mut Option| + -> SpdmResult { unimplemented!() }, +}; + +#[allow(clippy::too_many_arguments)] +pub(crate) fn pci_tdisp_device_lock_interface( + // IN + vendor_context: usize, + flags: &LockInterfaceFlag, + default_stream_id: u8, + mmio_reporting_offset: u64, + bind_p2p_address_mask: u64, + // OUT + negotiated_version: &mut TdispVersion, + interface_id: &mut InterfaceId, + start_interface_nonce: &mut [u8; START_INTERFACE_NONCE_LEN], + tdisp_error_code: &mut Option, +) -> SpdmResult { + (PCI_TDISP_DEVICE_LOCK_INTERFACE_INSTANCE + .try_get_or_init(|| UNIMPLETEMTED.clone()) + .ok() + .ok_or(SPDM_STATUS_INVALID_STATE_LOCAL)? + .pci_tdisp_device_lock_interface_cb)( + vendor_context, + flags, + default_stream_id, + mmio_reporting_offset, + bind_p2p_address_mask, + negotiated_version, + interface_id, + start_interface_nonce, + tdisp_error_code, + ) +} + +pub(crate) fn pci_tdisp_rsp_lock_interface( + vendor_context: usize, + vendor_defined_req_payload_struct: &VendorDefinedReqPayloadStruct, +) -> SpdmResult { + let req_lock_interface_request = ReqLockInterfaceRequest::read_bytes( + &vendor_defined_req_payload_struct.vendor_defined_req_payload + [..vendor_defined_req_payload_struct.req_length as usize], + ) + .ok_or(SPDM_STATUS_INVALID_MSG_FIELD)?; + + let mut vendor_defined_rsp_payload_struct = VendorDefinedRspPayloadStruct { + rsp_length: 0, + vendor_defined_rsp_payload: [0u8; MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], + }; + + let mut negotiated_version = TdispVersion::default(); + let mut interface_id = InterfaceId::default(); + let mut start_interface_nonce = [0u8; START_INTERFACE_NONCE_LEN]; + let mut tdisp_error_code = None; + + pci_tdisp_device_lock_interface( + vendor_context, + &req_lock_interface_request.flags, + req_lock_interface_request.default_stream_id, + req_lock_interface_request.mmio_reporting_offset, + req_lock_interface_request.bind_p2p_address_mask, + &mut negotiated_version, + &mut interface_id, + &mut start_interface_nonce, + &mut tdisp_error_code, + )?; + + if let Some(tdisp_error_code) = tdisp_error_code { + let len = write_error( + vendor_context, + tdisp_error_code, + 0, + &[], + &mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload, + )?; + vendor_defined_rsp_payload_struct.rsp_length = len as u16; + return Ok(vendor_defined_rsp_payload_struct); + } + + let mut writer = + Writer::init(&mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload); + + let cnt = RspLockInterfaceResponse { + message_header: TdispMessageHeader { + interface_id, + message_type: TdispRequestResponseCode::LOCK_INTERFACE_RESPONSE, + tdisp_version: negotiated_version, + }, + start_interface_nonce, + } + .encode(&mut writer) + .map_err(|_| SPDM_STATUS_BUFFER_FULL)?; + + if cnt > u16::MAX as usize { + Err(SPDM_STATUS_INVALID_STATE_LOCAL) + } else { + vendor_defined_rsp_payload_struct.rsp_length = cnt as u16; + Ok(vendor_defined_rsp_payload_struct) + } +} diff --git a/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_start_interface.rs b/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_start_interface.rs new file mode 100644 index 00000000..74cecc79 --- /dev/null +++ b/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_start_interface.rs @@ -0,0 +1,139 @@ +// Copyright (c) 2023 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 or MIT + +use codec::{Codec, Writer}; +use conquer_once::spin::OnceCell; +use spdmlib::{ + error::{ + SpdmResult, SPDM_STATUS_BUFFER_FULL, SPDM_STATUS_INVALID_MSG_FIELD, + SPDM_STATUS_INVALID_STATE_LOCAL, + }, + message::{ + VendorDefinedReqPayloadStruct, VendorDefinedRspPayloadStruct, + MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE, + }, +}; + +use crate::pci_tdisp::{ + InterfaceId, ReqStartInterfaceRequest, RspStartInterfaceResponse, TdispErrorCode, + TdispMessageHeader, TdispRequestResponseCode, TdispVersion, START_INTERFACE_NONCE_LEN, +}; + +use super::write_error; + +static PCI_TDISP_DEVICE_START_INTERFACE_INSTANCE: OnceCell = + OnceCell::uninit(); + +#[derive(Clone)] +pub struct PciTdispDeviceStartInterface { + pub pci_tdisp_device_start_interface_cb: fn( + //IN + vendor_context: usize, + start_interface_nonce: &[u8; START_INTERFACE_NONCE_LEN], + //OUT + negotiated_version: &mut TdispVersion, + interface_id: &mut InterfaceId, + tdisp_error_code: &mut Option, + ) -> SpdmResult, +} + +pub fn register(context: PciTdispDeviceStartInterface) -> bool { + PCI_TDISP_DEVICE_START_INTERFACE_INSTANCE + .try_init_once(|| context) + .is_ok() +} + +static UNIMPLETEMTED: PciTdispDeviceStartInterface = PciTdispDeviceStartInterface { + pci_tdisp_device_start_interface_cb: + |//IN + _vendor_context: usize, + _start_interface_nonce: &[u8; START_INTERFACE_NONCE_LEN], + //OUT + _negotiated_version: &mut TdispVersion, + _interface_id: &mut InterfaceId, + _tdisp_error_code: &mut Option| + -> SpdmResult { unimplemented!() }, +}; + +pub(crate) fn pci_tdisp_device_start_interface( + //IN + vendor_context: usize, + start_interface_nonce: &[u8; START_INTERFACE_NONCE_LEN], + //OUT + negotiated_version: &mut TdispVersion, + interface_id: &mut InterfaceId, + tdisp_error_code: &mut Option, +) -> SpdmResult { + (PCI_TDISP_DEVICE_START_INTERFACE_INSTANCE + .try_get_or_init(|| UNIMPLETEMTED.clone()) + .ok() + .ok_or(SPDM_STATUS_INVALID_STATE_LOCAL)? + .pci_tdisp_device_start_interface_cb)( + vendor_context, + start_interface_nonce, + negotiated_version, + interface_id, + tdisp_error_code, + ) +} + +pub(crate) fn pci_tdisp_rsp_start_interface( + vendor_context: usize, + vendor_defined_req_payload_struct: &VendorDefinedReqPayloadStruct, +) -> SpdmResult { + let req_start_interface_request = ReqStartInterfaceRequest::read_bytes( + &vendor_defined_req_payload_struct.vendor_defined_req_payload + [..vendor_defined_req_payload_struct.req_length as usize], + ) + .ok_or(SPDM_STATUS_INVALID_MSG_FIELD)?; + + let mut negotiated_version = TdispVersion::default(); + let mut interface_id = InterfaceId::default(); + let mut tdisp_error_code = None; + + pci_tdisp_device_start_interface( + vendor_context, + &req_start_interface_request.start_interface_nonce, + &mut negotiated_version, + &mut interface_id, + &mut tdisp_error_code, + )?; + + let mut vendor_defined_rsp_payload_struct = VendorDefinedRspPayloadStruct { + rsp_length: 0, + vendor_defined_rsp_payload: [0u8; MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], + }; + + if let Some(tdisp_error_code) = tdisp_error_code { + let len = write_error( + vendor_context, + tdisp_error_code, + 0, + &[], + &mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload, + )?; + vendor_defined_rsp_payload_struct.rsp_length = len as u16; + return Ok(vendor_defined_rsp_payload_struct); + } + + let mut writer = + Writer::init(&mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload); + + let cnt = RspStartInterfaceResponse { + message_header: TdispMessageHeader { + interface_id, + message_type: TdispRequestResponseCode::START_INTERFACE_RESPONSE, + tdisp_version: negotiated_version, + }, + } + .encode(&mut writer) + .map_err(|_| SPDM_STATUS_BUFFER_FULL)?; + + if cnt > u16::MAX as usize { + Err(SPDM_STATUS_INVALID_STATE_LOCAL) + } else { + vendor_defined_rsp_payload_struct.rsp_length = cnt as u16; + Ok(vendor_defined_rsp_payload_struct) + } +} diff --git a/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_stop_interface.rs b/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_stop_interface.rs new file mode 100644 index 00000000..6b3e30eb --- /dev/null +++ b/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_stop_interface.rs @@ -0,0 +1,133 @@ +// Copyright (c) 2023 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 or MIT + +use codec::{Codec, Writer}; +use conquer_once::spin::OnceCell; +use spdmlib::{ + error::{ + SpdmResult, SPDM_STATUS_BUFFER_FULL, SPDM_STATUS_INVALID_MSG_FIELD, + SPDM_STATUS_INVALID_STATE_LOCAL, + }, + message::{ + VendorDefinedReqPayloadStruct, VendorDefinedRspPayloadStruct, + MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE, + }, +}; + +use crate::pci_tdisp::{ + InterfaceId, ReqStopInterfaceRequest, RspStartInterfaceResponse, TdispErrorCode, + TdispMessageHeader, TdispRequestResponseCode, TdispVersion, +}; + +use super::write_error; + +static PCI_TDISP_DEVICE_STOP_INTERFACE_INSTANCE: OnceCell = + OnceCell::uninit(); + +#[derive(Clone)] +pub struct PciTdispDeviceStopInterface { + pub pci_tdisp_device_stop_interface_cb: fn( + // IN + vendor_context: usize, + // OUT + negotiated_version: &mut TdispVersion, + interface_id: &mut InterfaceId, + tdisp_error_code: &mut Option, + ) -> SpdmResult, +} + +pub fn register(context: PciTdispDeviceStopInterface) -> bool { + PCI_TDISP_DEVICE_STOP_INTERFACE_INSTANCE + .try_init_once(|| context) + .is_ok() +} + +static UNIMPLETEMTED: PciTdispDeviceStopInterface = PciTdispDeviceStopInterface { + pci_tdisp_device_stop_interface_cb: |// IN + _vendor_context: usize, + // OUT + _negotiated_version: &mut TdispVersion, + _interface_id: &mut InterfaceId, + _tdisp_error_code: &mut Option| + -> SpdmResult { unimplemented!() }, +}; + +pub(crate) fn pci_tdisp_device_stop_interface( + // IN + vendor_context: usize, + // OUT + negotiated_version: &mut TdispVersion, + interface_id: &mut InterfaceId, + tdisp_error_code: &mut Option, +) -> SpdmResult { + (PCI_TDISP_DEVICE_STOP_INTERFACE_INSTANCE + .try_get_or_init(|| UNIMPLETEMTED.clone()) + .ok() + .ok_or(SPDM_STATUS_INVALID_STATE_LOCAL)? + .pci_tdisp_device_stop_interface_cb)( + vendor_context, + negotiated_version, + interface_id, + tdisp_error_code, + ) +} + +pub(crate) fn pci_tdisp_rsp_stop_interface( + vendor_context: usize, + vendor_defined_req_payload_struct: &VendorDefinedReqPayloadStruct, +) -> SpdmResult { + let _ = ReqStopInterfaceRequest::read_bytes( + &vendor_defined_req_payload_struct.vendor_defined_req_payload + [..vendor_defined_req_payload_struct.req_length as usize], + ) + .ok_or(SPDM_STATUS_INVALID_MSG_FIELD)?; + + let mut negotiated_version = TdispVersion::default(); + let mut interface_id = InterfaceId::default(); + let mut tdisp_error_code = None; + + pci_tdisp_device_stop_interface( + vendor_context, + &mut negotiated_version, + &mut interface_id, + &mut tdisp_error_code, + )?; + + let mut vendor_defined_rsp_payload_struct = VendorDefinedRspPayloadStruct { + rsp_length: 0, + vendor_defined_rsp_payload: [0u8; MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], + }; + + if let Some(tdisp_error_code) = tdisp_error_code { + let len = write_error( + vendor_context, + tdisp_error_code, + 0, + &[], + &mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload, + )?; + vendor_defined_rsp_payload_struct.rsp_length = len as u16; + return Ok(vendor_defined_rsp_payload_struct); + } + + let mut writer = + Writer::init(&mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload); + + let cnt = RspStartInterfaceResponse { + message_header: TdispMessageHeader { + interface_id, + message_type: TdispRequestResponseCode::STOP_INTERFACE_RESPONSE, + tdisp_version: negotiated_version, + }, + } + .encode(&mut writer) + .map_err(|_| SPDM_STATUS_BUFFER_FULL)?; + + if cnt > u16::MAX as usize { + Err(SPDM_STATUS_INVALID_STATE_LOCAL) + } else { + vendor_defined_rsp_payload_struct.rsp_length = cnt as u16; + Ok(vendor_defined_rsp_payload_struct) + } +} diff --git a/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_version.rs b/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_version.rs new file mode 100644 index 00000000..9ead092b --- /dev/null +++ b/tdisp/src/pci_tdisp_responder/pci_tdisp_rsp_version.rs @@ -0,0 +1,119 @@ +// Copyright (c) 2023 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 or MIT + +use codec::{Codec, Writer}; +use conquer_once::spin::OnceCell; +use spdmlib::{ + error::{ + SpdmResult, SPDM_STATUS_BUFFER_FULL, SPDM_STATUS_INVALID_MSG_FIELD, + SPDM_STATUS_INVALID_STATE_LOCAL, + }, + message::{ + VendorDefinedReqPayloadStruct, VendorDefinedRspPayloadStruct, + MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE, + }, +}; + +use crate::pci_tdisp::{InterfaceId, ReqGetTdispVersion, RspTdispVersion, TdispVersion}; + +use super::MAX_TDISP_VERSION_COUNT; + +static PCI_TDISP_DEVICE_VERSIONI_INSTANCE: OnceCell = OnceCell::uninit(); + +#[derive(Clone)] +pub struct PciTdispDeviceVersion { + #[allow(clippy::type_complexity)] + pub pci_tdisp_device_version_cb: fn( + // IN + vendor_context: usize, + // OUT + interface_id: &mut InterfaceId, + version_num_count: &mut u8, + version_num_entry: &mut [TdispVersion; MAX_TDISP_VERSION_COUNT], + ) -> SpdmResult, +} + +pub fn register(context: PciTdispDeviceVersion) -> bool { + PCI_TDISP_DEVICE_VERSIONI_INSTANCE + .try_init_once(|| context) + .is_ok() +} + +static UNIMPLETEMTED: PciTdispDeviceVersion = PciTdispDeviceVersion { + pci_tdisp_device_version_cb: |// IN + _vendor_context: usize, + // OUT + _interface_id: &mut InterfaceId, + _version_num_count: &mut u8, + _version_num_entry: &mut [TdispVersion; + MAX_TDISP_VERSION_COUNT]| + -> SpdmResult { unimplemented!() }, +}; + +pub(crate) fn pci_tdisp_device_version( + // IN + vendor_context: usize, + // OUT + interface_id: &mut InterfaceId, + version_num_count: &mut u8, + version_num_entry: &mut [TdispVersion; MAX_TDISP_VERSION_COUNT], +) -> SpdmResult { + (PCI_TDISP_DEVICE_VERSIONI_INSTANCE + .try_get_or_init(|| UNIMPLETEMTED.clone()) + .ok() + .ok_or(SPDM_STATUS_INVALID_STATE_LOCAL)? + .pci_tdisp_device_version_cb)( + // IN + vendor_context, + // OUT + interface_id, + version_num_count, + version_num_entry, + ) +} + +pub(crate) fn pci_tdisp_rsp_version( + vendor_context: usize, + vendor_defined_req_payload_struct: &VendorDefinedReqPayloadStruct, +) -> SpdmResult { + let _ = ReqGetTdispVersion::read_bytes( + &vendor_defined_req_payload_struct.vendor_defined_req_payload + [..vendor_defined_req_payload_struct.req_length as usize], + ) + .ok_or(SPDM_STATUS_INVALID_MSG_FIELD)?; + + let mut interface_id = InterfaceId::default(); + let mut version_num_count = 0u8; + let mut version_num_entry = [TdispVersion::default(); MAX_TDISP_VERSION_COUNT]; + + pci_tdisp_device_version( + vendor_context, + &mut interface_id, + &mut version_num_count, + &mut version_num_entry, + )?; + + let mut vendor_defined_rsp_payload_struct = VendorDefinedRspPayloadStruct { + rsp_length: 0, + vendor_defined_rsp_payload: [0u8; MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], + }; + + let mut writer = + Writer::init(&mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload); + + let cnt = RspTdispVersion { + interface_id, + version_num_count, + version_num_entry, + } + .encode(&mut writer) + .map_err(|_| SPDM_STATUS_BUFFER_FULL)?; + + if cnt > u16::MAX as usize { + Err(SPDM_STATUS_INVALID_STATE_LOCAL) + } else { + vendor_defined_rsp_payload_struct.rsp_length = cnt as u16; + Ok(vendor_defined_rsp_payload_struct) + } +} diff --git a/tdisp/src/state_machine.rs b/tdisp/src/state_machine.rs deleted file mode 100644 index 32118156..00000000 --- a/tdisp/src/state_machine.rs +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use ::codec::*; - -enum_builder! { - @U8 - EnumName: TDIState; - EnumVal{ - // 1. In CONFIG_UNLOCKED the VMM configures the TDI to be assigned to a TVM. - // 2. TVMs should not place confidential data into a TDI in this state. - // 3. Memory Requests originating within a TVM must be rejected. - // 4. Transitions to by STOP_INTERFACE_REQUEST message. - // 5. DSM ensure no data leaked outside of device. - ConfigUnlocked => 0x00, - - // 1. Transitions to after TDI configuration is finalized by the VMM. - // 2. Transitions to by LOCK_INTERFACE_REQUEST message. - // 3. Memory Requests originating within a TVM must be rejected. - // 4. DSM must perform all necessary actions to lock the TDI configuration. - // 5. DSM must start tracking the TDI for [changes](need clarify) that affect the configuration or the security of the TDI - // 6. Transitions to ERROR when Changes are detected. - // 7. If applicable, verify that an IDE stream has been established by the TSM between the host and the device. - // 8. If the TVM approves of the device, the TVM may request the TSM to transition the TDI to RUN. - ConfigLocked => 0x01, - - // 1. TDI resources are operational and permitted to be accessed and managed by the TVM. - // 2. DSM must continue tracking the TDI for changes that affect the configuration or the security of the TDI - // 3. Transitions to ERROR when Changes are detected. - Run => 0x02, - - // 1. The TDI must not expose confidential TVM data. - // 2. Memory Requests originating within a TVM must be rejected. - // 3. The TDI must restrict TLP operations - // 4. Before transition to CONFIG_UNLOCKED, all TVM confidential data must be cleared. - Error => 0x03 - } -} - -#[derive(Debug, Default)] -pub struct TdispStateMachine { - pub current_state: TDIState, -} - -impl Codec for TdispStateMachine { - fn encode(&self, bytes: &mut Writer) { - self.current_state.encode(bytes); - } - - fn read(r: &mut Reader) -> Option { - let current_state = TDIState::read(r)?; - - Some(TdispStateMachine { current_state }) - } -} - -impl TdispStateMachine { - pub fn new() -> Self { - TdispStateMachine { - current_state: TDIState::ConfigUnlocked, - } - } - - #[inline] - pub fn to_state_config_unlocked(&mut self) { - self.current_state = TDIState::ConfigUnlocked; - } - - #[inline] - pub fn to_state_config_locked(&mut self) { - self.current_state = TDIState::ConfigLocked; - } - - #[inline] - pub fn to_state_run(&mut self) { - self.current_state = TDIState::Run; - } - - #[inline] - pub fn to_state_error(&mut self) { - self.current_state = TDIState::Error; - } - - #[inline] - pub fn reset(&mut self) { - self.to_state_config_unlocked(); - } -} diff --git a/tdisp/src/tdisp_codec.rs b/tdisp/src/tdisp_codec.rs deleted file mode 100644 index 71319ad6..00000000 --- a/tdisp/src/tdisp_codec.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -pub use crate::context; -pub use ::codec::*; -use core::fmt::Debug; - -use self::context::TdispContext; - -pub trait TdispCodec: Debug + Sized { - fn tdisp_encode(&self, _context: &mut TdispContext, _bytes: &mut Writer); - - fn tdisp_read(_context: &mut TdispContext, _: &mut Reader) -> Option; - - fn tdisp_read_bytes(context: &mut TdispContext, bytes: &[u8]) -> Option { - let mut rd = Reader::init(bytes); - Self::tdisp_read(context, &mut rd) - } -} diff --git a/tdisp/src/tdisp_requester/bind_p2p_stream_request_req.rs b/tdisp/src/tdisp_requester/bind_p2p_stream_request_req.rs deleted file mode 100644 index 46396f91..00000000 --- a/tdisp/src/tdisp_requester/bind_p2p_stream_request_req.rs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use codec::Writer; -use core::convert::TryInto; -use spdmlib::{ - message::{ - RegistryOrStandardsBodyID, VendorDefinedReqPayloadStruct, VendorDefinedRspPayloadStruct, - }, - requester::RequesterContext, -}; - -use crate::{ - common::{InternalError, TdispResult, PCI_VENDOR_ID_STRUCT}, - context::{MessagePayloadRequestBindP2pStream, TdispMessage, TdispRequestResponseCode}, - tdisp_codec::TdispCodec, -}; - -use super::*; - -impl<'a> TdispRequester<'a> { - pub fn send_receive_bind_p2p_stream( - &mut self, - spdm_requester: &mut RequesterContext, - ) -> TdispResult { - let mut tdisp_message = TdispMessage::::default(); - tdisp_message.tdisp_message_header.interface_id = self.tdisp_requester_context.tdi; - tdisp_message.tdisp_message_header.tdisp_version = self.tdisp_requester_context.version_sel; - let mut vendor_defined_req_payload = - [0u8; spdmlib::config::MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE]; - let mut writer = Writer::init(&mut vendor_defined_req_payload); - tdisp_message.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - let req_length: u16 = writer.used().try_into().unwrap(); - - let vdrp = VendorDefinedReqPayloadStruct { - req_length, - vendor_defined_req_payload, - }; - - self.tdisp_requester_context - .request_message - .copy_from_slice(&vendor_defined_req_payload); - self.tdisp_requester_context.request_code = - TdispRequestResponseCode::RequestBindP2pStreamRequest; - - match spdm_requester.send_spdm_vendor_defined_request( - self.tdisp_requester_context.spdm_session_id, - RegistryOrStandardsBodyID::PCISIG, - PCI_VENDOR_ID_STRUCT, - vdrp, - ) { - Ok(vdrp) => { - let VendorDefinedRspPayloadStruct { - rsp_length: _, - vendor_defined_rsp_payload, - } = vdrp; - - self.tdisp_requester_context.response_code = - TdispRequestResponseCode::ResponseBindP2pStreamResponse; - self.tdisp_requester_context - .response_message - .copy_from_slice(&vendor_defined_rsp_payload); - - self.handle_bind_p2p_stream_response(spdm_requester) - } - Err(_) => Err(InternalError::Unrecoverable), - } - } - - fn handle_bind_p2p_stream_response( - &mut self, - _spdm_requester: &mut RequesterContext, - ) -> TdispResult { - Ok(()) - } -} diff --git a/tdisp/src/tdisp_requester/get_device_interface_report_req.rs b/tdisp/src/tdisp_requester/get_device_interface_report_req.rs deleted file mode 100644 index b2af6ad0..00000000 --- a/tdisp/src/tdisp_requester/get_device_interface_report_req.rs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use codec::Writer; -use core::convert::TryInto; -use spdmlib::{ - message::{ - RegistryOrStandardsBodyID, VendorDefinedReqPayloadStruct, VendorDefinedRspPayloadStruct, - }, - requester::RequesterContext, -}; - -use crate::{ - common::{InternalError, TdispResult, PCI_VENDOR_ID_STRUCT}, - context::{ - MessagePayloadRequestGetDeviceInterfaceReport, TdispMessage, TdispRequestResponseCode, - }, - tdisp_codec::TdispCodec, -}; - -use super::*; - -impl<'a> TdispRequester<'a> { - pub fn send_receive_get_device_interface_report( - &mut self, - spdm_requester: &mut RequesterContext, - ) -> TdispResult { - let mut tdisp_message = - TdispMessage::::default(); - tdisp_message.tdisp_message_header.interface_id = self.tdisp_requester_context.tdi; - tdisp_message.tdisp_message_header.tdisp_version = self.tdisp_requester_context.version_sel; - let mut vendor_defined_req_payload = - [0u8; spdmlib::config::MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE]; - let mut writer = Writer::init(&mut vendor_defined_req_payload); - tdisp_message.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - let req_length: u16 = writer.used().try_into().unwrap(); - - let vdrp = VendorDefinedReqPayloadStruct { - req_length, - vendor_defined_req_payload, - }; - - self.tdisp_requester_context - .request_message - .copy_from_slice(&vendor_defined_req_payload); - self.tdisp_requester_context.request_code = - TdispRequestResponseCode::RequestGetDeviceInterfaceReport; - - match spdm_requester.send_spdm_vendor_defined_request( - self.tdisp_requester_context.spdm_session_id, - RegistryOrStandardsBodyID::PCISIG, - PCI_VENDOR_ID_STRUCT, - vdrp, - ) { - Ok(vdrp) => { - let VendorDefinedRspPayloadStruct { - rsp_length: _, - vendor_defined_rsp_payload, - } = vdrp; - - self.tdisp_requester_context.response_code = - TdispRequestResponseCode::ResponseDeviceInterfaceReport; - self.tdisp_requester_context - .response_message - .copy_from_slice(&vendor_defined_rsp_payload); - - self.handle_get_device_interface_report_response(spdm_requester) - } - Err(_) => Err(InternalError::Unrecoverable), - } - } - - fn handle_get_device_interface_report_response( - &mut self, - _spdm_requester: &mut RequesterContext, - ) -> TdispResult { - Ok(()) - } -} diff --git a/tdisp/src/tdisp_requester/get_device_interface_state_req.rs b/tdisp/src/tdisp_requester/get_device_interface_state_req.rs deleted file mode 100644 index 89620fb1..00000000 --- a/tdisp/src/tdisp_requester/get_device_interface_state_req.rs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use codec::Writer; -use core::convert::TryInto; -use spdmlib::{ - message::{ - RegistryOrStandardsBodyID, VendorDefinedReqPayloadStruct, VendorDefinedRspPayloadStruct, - }, - requester::RequesterContext, -}; - -use crate::{ - common::{InternalError, TdispResult, PCI_VENDOR_ID_STRUCT}, - context::{ - MessagePayloadRequestGetDeviceInterfaceState, TdispMessage, TdispRequestResponseCode, - }, - tdisp_codec::TdispCodec, -}; - -use super::*; - -impl<'a> TdispRequester<'a> { - pub fn send_receive_get_device_interface_state( - &mut self, - spdm_requester: &mut RequesterContext, - ) -> TdispResult { - let mut tdisp_message = - TdispMessage::::default(); - tdisp_message.tdisp_message_header.interface_id = self.tdisp_requester_context.tdi; - tdisp_message.tdisp_message_header.tdisp_version = self.tdisp_requester_context.version_sel; - let mut vendor_defined_req_payload = - [0u8; spdmlib::config::MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE]; - let mut writer = Writer::init(&mut vendor_defined_req_payload); - tdisp_message.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - let req_length: u16 = writer.used().try_into().unwrap(); - - let vdrp = VendorDefinedReqPayloadStruct { - req_length, - vendor_defined_req_payload, - }; - - self.tdisp_requester_context - .request_message - .copy_from_slice(&vendor_defined_req_payload); - self.tdisp_requester_context.request_code = - TdispRequestResponseCode::RequestGetDeviceInterfaceState; - - match spdm_requester.send_spdm_vendor_defined_request( - self.tdisp_requester_context.spdm_session_id, - RegistryOrStandardsBodyID::PCISIG, - PCI_VENDOR_ID_STRUCT, - vdrp, - ) { - Ok(vdrp) => { - let VendorDefinedRspPayloadStruct { - rsp_length: _, - vendor_defined_rsp_payload, - } = vdrp; - - self.tdisp_requester_context.response_code = - TdispRequestResponseCode::ResponseDeviceInterfaceState; - self.tdisp_requester_context - .response_message - .copy_from_slice(&vendor_defined_rsp_payload); - - self.handle_get_device_interface_state_response(spdm_requester) - } - Err(_) => Err(InternalError::Unrecoverable), - } - } - - fn handle_get_device_interface_state_response( - &mut self, - _spdm_requester: &mut RequesterContext, - ) -> TdispResult { - Ok(()) - } -} diff --git a/tdisp/src/tdisp_requester/get_tdisp_capabilities_req.rs b/tdisp/src/tdisp_requester/get_tdisp_capabilities_req.rs deleted file mode 100644 index 2f88dc89..00000000 --- a/tdisp/src/tdisp_requester/get_tdisp_capabilities_req.rs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use codec::Writer; -use core::convert::TryInto; -use spdmlib::{ - message::{ - RegistryOrStandardsBodyID, VendorDefinedReqPayloadStruct, VendorDefinedRspPayloadStruct, - }, - requester::RequesterContext, -}; - -use crate::{ - common::{InternalError, TdispResult, PCI_VENDOR_ID_STRUCT}, - context::{MessagePayloadRequestGetCapabilities, TdispMessage, TdispRequestResponseCode}, - tdisp_codec::TdispCodec, -}; - -use super::*; - -impl<'a> TdispRequester<'a> { - pub fn send_receive_get_tdisp_capabilities( - &mut self, - spdm_requester: &mut RequesterContext, - ) -> TdispResult { - let mut tdisp_message = TdispMessage::::default(); - tdisp_message.tdisp_message_header.interface_id = self.tdisp_requester_context.tdi; - tdisp_message.tdisp_message_header.tdisp_version = self.tdisp_requester_context.version_sel; - let mut vendor_defined_req_payload = - [0u8; spdmlib::config::MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE]; - let mut writer = Writer::init(&mut vendor_defined_req_payload); - tdisp_message.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - let req_length: u16 = writer.used().try_into().unwrap(); - - let vdrp = VendorDefinedReqPayloadStruct { - req_length, - vendor_defined_req_payload, - }; - - self.tdisp_requester_context - .request_message - .copy_from_slice(&vendor_defined_req_payload); - self.tdisp_requester_context.request_code = - TdispRequestResponseCode::RequestGetTdispCapabilities; - - match spdm_requester.send_spdm_vendor_defined_request( - self.tdisp_requester_context.spdm_session_id, - RegistryOrStandardsBodyID::PCISIG, - PCI_VENDOR_ID_STRUCT, - vdrp, - ) { - Ok(vdrp) => { - let VendorDefinedRspPayloadStruct { - rsp_length: _, - vendor_defined_rsp_payload, - } = vdrp; - - self.tdisp_requester_context.response_code = - TdispRequestResponseCode::ResponseTdispCapabilities; - self.tdisp_requester_context - .response_message - .copy_from_slice(&vendor_defined_rsp_payload); - - self.handle_get_tdisp_capabilities_response(spdm_requester) - } - Err(_) => Err(InternalError::Unrecoverable), - } - } - - fn handle_get_tdisp_capabilities_response( - &mut self, - _spdm_requester: &mut RequesterContext, - ) -> TdispResult { - Ok(()) - } -} diff --git a/tdisp/src/tdisp_requester/get_tdisp_version_req.rs b/tdisp/src/tdisp_requester/get_tdisp_version_req.rs deleted file mode 100644 index c05b714d..00000000 --- a/tdisp/src/tdisp_requester/get_tdisp_version_req.rs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use codec::Writer; -use core::convert::TryInto; -use spdmlib::{ - message::{ - RegistryOrStandardsBodyID, VendorDefinedReqPayloadStruct, VendorDefinedRspPayloadStruct, - }, - requester::RequesterContext, -}; - -use crate::{ - common::{InternalError, TdispResult, PCI_VENDOR_ID_STRUCT}, - context::{MessagePayloadRequestGetVersion, TdispMessage, TdispRequestResponseCode}, - tdisp_codec::TdispCodec, -}; - -use super::*; - -impl<'a> TdispRequester<'a> { - pub fn send_receive_get_tdisp_version( - &mut self, - spdm_requester: &mut RequesterContext, - ) -> TdispResult { - let mut tdisp_message = TdispMessage::::default(); - tdisp_message.tdisp_message_header.interface_id = self.tdisp_requester_context.tdi; - tdisp_message.tdisp_message_header.tdisp_version = self.tdisp_requester_context.version_sel; - let mut vendor_defined_req_payload = - [0u8; spdmlib::config::MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE]; - let mut writer = Writer::init(&mut vendor_defined_req_payload); - tdisp_message.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - let req_length: u16 = writer.used().try_into().unwrap(); - - let vdrp = VendorDefinedReqPayloadStruct { - req_length, - vendor_defined_req_payload, - }; - - self.tdisp_requester_context - .request_message - .copy_from_slice(&vendor_defined_req_payload); - self.tdisp_requester_context.request_code = - TdispRequestResponseCode::RequestGetTdispVersion; - - match spdm_requester.send_spdm_vendor_defined_request( - self.tdisp_requester_context.spdm_session_id, - RegistryOrStandardsBodyID::PCISIG, - PCI_VENDOR_ID_STRUCT, - vdrp, - ) { - Ok(vdrp) => { - let VendorDefinedRspPayloadStruct { - rsp_length: _, - vendor_defined_rsp_payload, - } = vdrp; - - self.tdisp_requester_context.response_code = - TdispRequestResponseCode::ResponseTdispVersion; - self.tdisp_requester_context - .response_message - .copy_from_slice(&vendor_defined_rsp_payload); - - self.handle_get_tdisp_version_response(spdm_requester) - } - Err(_) => Err(InternalError::Unrecoverable), - } - } - - fn handle_get_tdisp_version_response( - &mut self, - _spdm_requester: &mut RequesterContext, - ) -> TdispResult { - Ok(()) - } -} diff --git a/tdisp/src/tdisp_requester/lock_interface_request_req.rs b/tdisp/src/tdisp_requester/lock_interface_request_req.rs deleted file mode 100644 index 1c0f26b1..00000000 --- a/tdisp/src/tdisp_requester/lock_interface_request_req.rs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use codec::Writer; -use core::convert::TryInto; -use spdmlib::{ - message::{ - RegistryOrStandardsBodyID, VendorDefinedReqPayloadStruct, VendorDefinedRspPayloadStruct, - }, - requester::RequesterContext, -}; - -use crate::{ - common::{InternalError, TdispResult, PCI_VENDOR_ID_STRUCT}, - context::{MessagePayloadRequestLockInterface, TdispMessage, TdispRequestResponseCode}, - tdisp_codec::TdispCodec, -}; - -use super::*; - -impl<'a> TdispRequester<'a> { - pub fn send_receive_lock_interface_request( - &mut self, - spdm_requester: &mut RequesterContext, - ) -> TdispResult { - let mut tdisp_message = TdispMessage::::default(); - tdisp_message.tdisp_message_header.interface_id = self.tdisp_requester_context.tdi; - tdisp_message.tdisp_message_header.tdisp_version = self.tdisp_requester_context.version_sel; - let mut vendor_defined_req_payload = - [0u8; spdmlib::config::MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE]; - let mut writer = Writer::init(&mut vendor_defined_req_payload); - tdisp_message.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - let req_length: u16 = writer.used().try_into().unwrap(); - - let vdrp = VendorDefinedReqPayloadStruct { - req_length, - vendor_defined_req_payload, - }; - - self.tdisp_requester_context - .request_message - .copy_from_slice(&vendor_defined_req_payload); - self.tdisp_requester_context.request_code = - TdispRequestResponseCode::RequestLockInterfaceRequest; - - match spdm_requester.send_spdm_vendor_defined_request( - self.tdisp_requester_context.spdm_session_id, - RegistryOrStandardsBodyID::PCISIG, - PCI_VENDOR_ID_STRUCT, - vdrp, - ) { - Ok(vdrp) => { - let VendorDefinedRspPayloadStruct { - rsp_length: _, - vendor_defined_rsp_payload, - } = vdrp; - - self.tdisp_requester_context.response_code = - TdispRequestResponseCode::ResponseLockInterfaceResponse; - self.tdisp_requester_context - .response_message - .copy_from_slice(&vendor_defined_rsp_payload); - - self.handle_lock_interface_request_response(spdm_requester) - } - Err(_) => Err(InternalError::Unrecoverable), - } - } - - fn handle_lock_interface_request_response( - &mut self, - _spdm_requester: &mut RequesterContext, - ) -> TdispResult { - Ok(()) - } -} diff --git a/tdisp/src/tdisp_requester/mod.rs b/tdisp/src/tdisp_requester/mod.rs deleted file mode 100644 index 8b8d9c02..00000000 --- a/tdisp/src/tdisp_requester/mod.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use crate::{ - context::{InterfaceId, TdispContext}, - device::TdispConfiguration, -}; - -pub struct TdispRequester<'a> { - pub tdisp_requester_context: TdispContext<'a>, -} - -impl<'a> TdispRequester<'a> { - pub fn new( - interface_id: InterfaceId, - configuration: &'a mut dyn TdispConfiguration, - spdm_session_id: u32, - ) -> Self { - TdispRequester { - tdisp_requester_context: TdispContext::new( - interface_id, - configuration, - spdm_session_id, - ), - } - } -} - -pub mod bind_p2p_stream_request_req; -pub mod get_device_interface_report_req; -pub mod get_device_interface_state_req; -pub mod get_tdisp_capabilities_req; -pub mod get_tdisp_version_req; -pub mod lock_interface_request_req; -pub mod set_mmio_attribute_request_req; -pub mod start_interface_request_req; -pub mod stop_interface_request_req; -pub mod unbind_p2p_stream_request_req; -pub mod vdm_request; diff --git a/tdisp/src/tdisp_requester/set_mmio_attribute_request_req.rs b/tdisp/src/tdisp_requester/set_mmio_attribute_request_req.rs deleted file mode 100644 index 8f0e27cc..00000000 --- a/tdisp/src/tdisp_requester/set_mmio_attribute_request_req.rs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use codec::Writer; -use core::convert::TryInto; -use spdmlib::{ - message::{ - RegistryOrStandardsBodyID, VendorDefinedReqPayloadStruct, VendorDefinedRspPayloadStruct, - }, - requester::RequesterContext, -}; - -use crate::{ - common::{InternalError, TdispResult, PCI_VENDOR_ID_STRUCT}, - context::{MessagePayloadRequestSetMmioAttribute, TdispMessage, TdispRequestResponseCode}, - tdisp_codec::TdispCodec, -}; - -use super::*; - -impl<'a> TdispRequester<'a> { - pub fn send_receive_set_mmio_attribute( - &mut self, - spdm_requester: &mut RequesterContext, - ) -> TdispResult { - let mut tdisp_message = TdispMessage::::default(); - tdisp_message.tdisp_message_header.interface_id = self.tdisp_requester_context.tdi; - tdisp_message.tdisp_message_header.tdisp_version = self.tdisp_requester_context.version_sel; - let mut vendor_defined_req_payload = - [0u8; spdmlib::config::MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE]; - let mut writer = Writer::init(&mut vendor_defined_req_payload); - tdisp_message.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - let req_length: u16 = writer.used().try_into().unwrap(); - - let vdrp = VendorDefinedReqPayloadStruct { - req_length, - vendor_defined_req_payload, - }; - - self.tdisp_requester_context - .request_message - .copy_from_slice(&vendor_defined_req_payload); - self.tdisp_requester_context.request_code = - TdispRequestResponseCode::RequestSetMmioAttributeRequest; - - match spdm_requester.send_spdm_vendor_defined_request( - self.tdisp_requester_context.spdm_session_id, - RegistryOrStandardsBodyID::PCISIG, - PCI_VENDOR_ID_STRUCT, - vdrp, - ) { - Ok(vdrp) => { - let VendorDefinedRspPayloadStruct { - rsp_length: _, - vendor_defined_rsp_payload, - } = vdrp; - - self.tdisp_requester_context.response_code = - TdispRequestResponseCode::ResponseSetMmioAttributeResponse; - self.tdisp_requester_context - .response_message - .copy_from_slice(&vendor_defined_rsp_payload); - - self.handle_set_mmio_attribute_response(spdm_requester) - } - Err(_) => Err(InternalError::Unrecoverable), - } - } - - fn handle_set_mmio_attribute_response( - &mut self, - _spdm_requester: &mut RequesterContext, - ) -> TdispResult { - Ok(()) - } -} diff --git a/tdisp/src/tdisp_requester/start_interface_request_req.rs b/tdisp/src/tdisp_requester/start_interface_request_req.rs deleted file mode 100644 index bbad7361..00000000 --- a/tdisp/src/tdisp_requester/start_interface_request_req.rs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use codec::Writer; -use core::convert::TryInto; -use spdmlib::{ - message::{ - RegistryOrStandardsBodyID, VendorDefinedReqPayloadStruct, VendorDefinedRspPayloadStruct, - }, - requester::RequesterContext, -}; - -use crate::{ - common::{InternalError, TdispResult, PCI_VENDOR_ID_STRUCT}, - context::{MessagePayloadRequestStartInterface, TdispMessage, TdispRequestResponseCode}, - tdisp_codec::TdispCodec, -}; - -use super::*; - -impl<'a> TdispRequester<'a> { - pub fn send_receive_start_interface( - &mut self, - spdm_requester: &mut RequesterContext, - ) -> TdispResult { - let mut tdisp_message = TdispMessage::::default(); - tdisp_message.tdisp_message_header.interface_id = self.tdisp_requester_context.tdi; - tdisp_message.tdisp_message_header.tdisp_version = self.tdisp_requester_context.version_sel; - let mut vendor_defined_req_payload = - [0u8; spdmlib::config::MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE]; - let mut writer = Writer::init(&mut vendor_defined_req_payload); - tdisp_message.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - let req_length: u16 = writer.used().try_into().unwrap(); - - let vdrp = VendorDefinedReqPayloadStruct { - req_length, - vendor_defined_req_payload, - }; - - self.tdisp_requester_context - .request_message - .copy_from_slice(&vendor_defined_req_payload); - self.tdisp_requester_context.request_code = - TdispRequestResponseCode::RequestStartInterfaceRequest; - - match spdm_requester.send_spdm_vendor_defined_request( - self.tdisp_requester_context.spdm_session_id, - RegistryOrStandardsBodyID::PCISIG, - PCI_VENDOR_ID_STRUCT, - vdrp, - ) { - Ok(vdrp) => { - let VendorDefinedRspPayloadStruct { - rsp_length: _, - vendor_defined_rsp_payload, - } = vdrp; - - self.tdisp_requester_context.response_code = - TdispRequestResponseCode::ResponseStartInterfaceResponse; - self.tdisp_requester_context - .response_message - .copy_from_slice(&vendor_defined_rsp_payload); - - self.handle_start_interface_response(spdm_requester) - } - Err(_) => Err(InternalError::Unrecoverable), - } - } - - fn handle_start_interface_response( - &mut self, - _spdm_requester: &mut RequesterContext, - ) -> TdispResult { - Ok(()) - } -} diff --git a/tdisp/src/tdisp_requester/stop_interface_request_req.rs b/tdisp/src/tdisp_requester/stop_interface_request_req.rs deleted file mode 100644 index d1c3aad9..00000000 --- a/tdisp/src/tdisp_requester/stop_interface_request_req.rs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use codec::Writer; -use core::convert::TryInto; -use spdmlib::{ - message::{ - RegistryOrStandardsBodyID, VendorDefinedReqPayloadStruct, VendorDefinedRspPayloadStruct, - }, - requester::RequesterContext, -}; - -use crate::{ - common::{InternalError, TdispResult, PCI_VENDOR_ID_STRUCT}, - context::{MessagePayloadRequestStopInterface, TdispMessage, TdispRequestResponseCode}, - tdisp_codec::TdispCodec, -}; - -use super::*; - -impl<'a> TdispRequester<'a> { - pub fn send_receive_stop_interface( - &mut self, - spdm_requester: &mut RequesterContext, - ) -> TdispResult { - let mut tdisp_message = TdispMessage::::default(); - tdisp_message.tdisp_message_header.interface_id = self.tdisp_requester_context.tdi; - tdisp_message.tdisp_message_header.tdisp_version = self.tdisp_requester_context.version_sel; - let mut vendor_defined_req_payload = - [0u8; spdmlib::config::MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE]; - let mut writer = Writer::init(&mut vendor_defined_req_payload); - tdisp_message.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - let req_length: u16 = writer.used().try_into().unwrap(); - - let vdrp = VendorDefinedReqPayloadStruct { - req_length, - vendor_defined_req_payload, - }; - - self.tdisp_requester_context - .request_message - .copy_from_slice(&vendor_defined_req_payload); - self.tdisp_requester_context.request_code = - TdispRequestResponseCode::RequestStopInterfaceRequest; - - match spdm_requester.send_spdm_vendor_defined_request( - self.tdisp_requester_context.spdm_session_id, - RegistryOrStandardsBodyID::PCISIG, - PCI_VENDOR_ID_STRUCT, - vdrp, - ) { - Ok(vdrp) => { - let VendorDefinedRspPayloadStruct { - rsp_length: _, - vendor_defined_rsp_payload, - } = vdrp; - - self.tdisp_requester_context.response_code = - TdispRequestResponseCode::ResponseStopInterfaceResponse; - self.tdisp_requester_context - .response_message - .copy_from_slice(&vendor_defined_rsp_payload); - - self.handle_stop_interface_response(spdm_requester) - } - Err(_) => Err(InternalError::Unrecoverable), - } - } - - fn handle_stop_interface_response( - &mut self, - _spdm_requester: &mut RequesterContext, - ) -> TdispResult { - Ok(()) - } -} diff --git a/tdisp/src/tdisp_requester/unbind_p2p_stream_request_req.rs b/tdisp/src/tdisp_requester/unbind_p2p_stream_request_req.rs deleted file mode 100644 index 235cd037..00000000 --- a/tdisp/src/tdisp_requester/unbind_p2p_stream_request_req.rs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use codec::Writer; -use core::convert::TryInto; -use spdmlib::{ - message::{ - RegistryOrStandardsBodyID, VendorDefinedReqPayloadStruct, VendorDefinedRspPayloadStruct, - }, - requester::RequesterContext, -}; - -use crate::{ - common::{InternalError, TdispResult, PCI_VENDOR_ID_STRUCT}, - context::{MessagePayloadRequestUnbindP2pStream, TdispMessage, TdispRequestResponseCode}, - tdisp_codec::TdispCodec, -}; - -use super::*; - -impl<'a> TdispRequester<'a> { - pub fn send_receive_unbind_p2p_stream( - &mut self, - spdm_requester: &mut RequesterContext, - ) -> TdispResult { - let mut tdisp_message = TdispMessage::::default(); - tdisp_message.tdisp_message_header.interface_id = self.tdisp_requester_context.tdi; - tdisp_message.tdisp_message_header.tdisp_version = self.tdisp_requester_context.version_sel; - let mut vendor_defined_req_payload = - [0u8; spdmlib::config::MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE]; - let mut writer = Writer::init(&mut vendor_defined_req_payload); - tdisp_message.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - let req_length: u16 = writer.used().try_into().unwrap(); - - let vdrp = VendorDefinedReqPayloadStruct { - req_length, - vendor_defined_req_payload, - }; - - self.tdisp_requester_context - .request_message - .copy_from_slice(&vendor_defined_req_payload); - self.tdisp_requester_context.request_code = - TdispRequestResponseCode::RequestUnbindP2pStreamRequest; - - match spdm_requester.send_spdm_vendor_defined_request( - self.tdisp_requester_context.spdm_session_id, - RegistryOrStandardsBodyID::PCISIG, - PCI_VENDOR_ID_STRUCT, - vdrp, - ) { - Ok(vdrp) => { - let VendorDefinedRspPayloadStruct { - rsp_length: _, - vendor_defined_rsp_payload, - } = vdrp; - - self.tdisp_requester_context.response_code = - TdispRequestResponseCode::ResponseUnbindP2pStreamResponse; - self.tdisp_requester_context - .response_message - .copy_from_slice(&vendor_defined_rsp_payload); - - self.handle_unbind_p2p_stream_response(spdm_requester) - } - Err(_) => Err(InternalError::Unrecoverable), - } - } - - fn handle_unbind_p2p_stream_response( - &mut self, - _spdm_requester: &mut RequesterContext, - ) -> TdispResult { - Ok(()) - } -} diff --git a/tdisp/src/tdisp_requester/vdm_request.rs b/tdisp/src/tdisp_requester/vdm_request.rs deleted file mode 100644 index 46c6c53c..00000000 --- a/tdisp/src/tdisp_requester/vdm_request.rs +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use codec::Writer; -use core::convert::TryInto; -use spdmlib::{ - message::{ - RegistryOrStandardsBodyID, VendorDefinedReqPayloadStruct, VendorDefinedRspPayloadStruct, - }, - requester::RequesterContext, -}; - -use crate::{ - common::{InternalError, TdispResult, PCI_VENDOR_ID_STRUCT}, - context::{MessagePayloadRequestVDM, TdispMessage, TdispRequestResponseCode}, - tdisp_codec::TdispCodec, -}; - -use super::*; - -impl<'a> TdispRequester<'a> { - pub fn send_receive_vdm_request( - &mut self, - spdm_requester: &mut RequesterContext, - ) -> TdispResult { - let mut tdisp_message = TdispMessage::::default(); - tdisp_message.tdisp_message_header.interface_id = self.tdisp_requester_context.tdi; - tdisp_message.tdisp_message_header.tdisp_version = self.tdisp_requester_context.version_sel; - let mut vendor_defined_req_payload = - [0u8; spdmlib::config::MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE]; - let mut writer = Writer::init(&mut vendor_defined_req_payload); - tdisp_message.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - let req_length: u16 = writer.used().try_into().unwrap(); - - let vdrp = VendorDefinedReqPayloadStruct { - req_length, - vendor_defined_req_payload, - }; - - self.tdisp_requester_context - .request_message - .copy_from_slice(&vendor_defined_req_payload); - self.tdisp_requester_context.request_code = TdispRequestResponseCode::RequestVdmRequest; - - match spdm_requester.send_spdm_vendor_defined_request( - self.tdisp_requester_context.spdm_session_id, - RegistryOrStandardsBodyID::PCISIG, - PCI_VENDOR_ID_STRUCT, - vdrp, - ) { - Ok(vdrp) => { - let VendorDefinedRspPayloadStruct { - rsp_length: _, - vendor_defined_rsp_payload, - } = vdrp; - - self.tdisp_requester_context.response_code = - TdispRequestResponseCode::ResponseVdmResponse; - self.tdisp_requester_context - .response_message - .copy_from_slice(&vendor_defined_rsp_payload); - - self.handle_spdm_version_response(spdm_requester) - } - Err(_) => Err(InternalError::Unrecoverable), - } - } - - fn handle_spdm_version_response( - &mut self, - _spdm_requester: &mut RequesterContext, - ) -> TdispResult { - Ok(()) - } -} diff --git a/tdisp/src/tdisp_responder/bind_p2p_stream_request_rsp.rs b/tdisp/src/tdisp_responder/bind_p2p_stream_request_rsp.rs deleted file mode 100644 index 9653c073..00000000 --- a/tdisp/src/tdisp_responder/bind_p2p_stream_request_rsp.rs +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use spdmlib::error::*; - -use crate::{ - context::{MessagePayloadRequestBindP2pStream, MessagePayloadResponseBindP2pStream}, - state_machine::TDIState, -}; - -use super::*; - -// security check -// Interface ID in the request is not hosted by the device -// TDI does not support binding peer-to-peer streams -// DONE - TDI is not in RUN -// Stream ID specified does not have IDE keys programmed for all sub streams -// All IDE keys of the stream identified by the Stream ID were not configured over the SPDM session on which the LOCK_INTERFACE_REQUEST was received -// Multiple IDE configuration registers have been programmed with the same stream ID -// IDE configuration register for this stream is configured as the default stream -// Address and/or RID association registers of this streams IDE configuration registers overlap with other IDE configuration registers -impl<'a> TdispResponder<'a> { - pub fn handle_bind_p2p_stream_request( - &mut self, - vendor_defined_req_payload_struct: &VendorDefinedReqPayloadStruct, - ) -> SpdmResult { - let mut reader = - Reader::init(&vendor_defined_req_payload_struct.vendor_defined_req_payload); - let tmh = TdispMessageHeader::tdisp_read(&mut self.tdisp_requester_context, &mut reader); - let mpr = MessagePayloadRequestBindP2pStream::tdisp_read( - &mut self.tdisp_requester_context, - &mut reader, - ); - if tmh.is_none() || mpr.is_none() { - self.handle_tdisp_error( - vendor_defined_req_payload_struct, - MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_REQUEST, - ) - } else if self.tdisp_requester_context.state_machine.current_state != TDIState::Run { - self.handle_tdisp_error( - vendor_defined_req_payload_struct, - MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_INTERFACE_STATE, - ) - } else { - let mut vendor_defined_rsp_payload_struct: VendorDefinedRspPayloadStruct = - VendorDefinedRspPayloadStruct { - rsp_length: 0, - vendor_defined_rsp_payload: [0u8; - spdmlib::config::MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], - }; - let mut writer = - Writer::init(&mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload); - - let tmhr = TdispMessageHeader { - tdisp_version: self.tdisp_requester_context.version_sel, - message_type: TdispRequestResponseCode::ResponseBindP2pStreamResponse, - interface_id: self.tdisp_requester_context.tdi, - }; - - let mprr = MessagePayloadResponseBindP2pStream::default(); - - tmhr.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - mprr.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - - Ok(vendor_defined_rsp_payload_struct) - } - } -} diff --git a/tdisp/src/tdisp_responder/device_interface_report_rsp.rs b/tdisp/src/tdisp_responder/device_interface_report_rsp.rs deleted file mode 100644 index acd58f1f..00000000 --- a/tdisp/src/tdisp_responder/device_interface_report_rsp.rs +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use spdmlib::error::*; - -use crate::{ - context::{ - MessagePayloadRequestGetDeviceInterfaceReport, MessagePayloadResponseDeviceInterfaceReport, - }, - state_machine::TDIState, -}; - -use super::*; - -// security check -// Interface ID in the request is not hosted by the device -// DONE - TDI is not in CONFIG_LOCKED or RUN -// Invalid offset specified - -impl<'a> TdispResponder<'a> { - pub fn handle_device_interface_report( - &mut self, - vendor_defined_req_payload_struct: &VendorDefinedReqPayloadStruct, - ) -> SpdmResult { - let mut reader = - Reader::init(&vendor_defined_req_payload_struct.vendor_defined_req_payload); - let tmh = TdispMessageHeader::tdisp_read(&mut self.tdisp_requester_context, &mut reader); - let mpr = MessagePayloadRequestGetDeviceInterfaceReport::tdisp_read( - &mut self.tdisp_requester_context, - &mut reader, - ); - if tmh.is_none() || mpr.is_none() { - self.handle_tdisp_error( - vendor_defined_req_payload_struct, - MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_REQUEST, - ) - } else if self.tdisp_requester_context.state_machine.current_state != TDIState::Run - || self.tdisp_requester_context.state_machine.current_state != TDIState::ConfigLocked - { - self.handle_tdisp_error( - vendor_defined_req_payload_struct, - MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_INTERFACE_STATE, - ) - } else { - let mut vendor_defined_rsp_payload_struct: VendorDefinedRspPayloadStruct = - VendorDefinedRspPayloadStruct { - rsp_length: 0, - vendor_defined_rsp_payload: [0u8; - spdmlib::config::MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], - }; - let mut writer = - Writer::init(&mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload); - - let tmhr = TdispMessageHeader { - tdisp_version: self.tdisp_requester_context.version_sel, - message_type: TdispRequestResponseCode::ResponseDeviceInterfaceReport, - interface_id: self.tdisp_requester_context.tdi, - }; - - let mprr = MessagePayloadResponseDeviceInterfaceReport::default(); - // mprr.portion_length - // mprr.reminder_length - // mprr.report_bytes - - tmhr.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - mprr.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - - Ok(vendor_defined_rsp_payload_struct) - } - } -} diff --git a/tdisp/src/tdisp_responder/device_interface_state_rsp.rs b/tdisp/src/tdisp_responder/device_interface_state_rsp.rs deleted file mode 100644 index a2443be9..00000000 --- a/tdisp/src/tdisp_responder/device_interface_state_rsp.rs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use spdmlib::error::*; - -use crate::{ - context::{ - MessagePayloadRequestGetDeviceInterfaceState, MessagePayloadResponseDeviceInterfaceState, - }, - state_machine::TdispStateMachine, -}; - -use super::*; - -// security check -// Interface ID in the request is not hosted by the device. - -impl<'a> TdispResponder<'a> { - pub fn handle_device_interface_state( - &mut self, - vendor_defined_req_payload_struct: &VendorDefinedReqPayloadStruct, - ) -> SpdmResult { - let mut reader = - Reader::init(&vendor_defined_req_payload_struct.vendor_defined_req_payload); - let tmh = TdispMessageHeader::tdisp_read(&mut self.tdisp_requester_context, &mut reader); - let mpr = MessagePayloadRequestGetDeviceInterfaceState::tdisp_read( - &mut self.tdisp_requester_context, - &mut reader, - ); - if tmh.is_none() || mpr.is_none() { - self.handle_tdisp_error( - vendor_defined_req_payload_struct, - MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_REQUEST, - ) - } else { - let mut vendor_defined_rsp_payload_struct: VendorDefinedRspPayloadStruct = - VendorDefinedRspPayloadStruct { - rsp_length: 0, - vendor_defined_rsp_payload: [0u8; - spdmlib::config::MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], - }; - let mut writer = - Writer::init(&mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload); - - let tmhr = TdispMessageHeader { - tdisp_version: self.tdisp_requester_context.version_sel, - message_type: TdispRequestResponseCode::ResponseDeviceInterfaceState, - interface_id: self.tdisp_requester_context.tdi, - }; - - let mprr = MessagePayloadResponseDeviceInterfaceState { - tdi_state: TdispStateMachine { - current_state: self.tdisp_requester_context.state_machine.current_state, - }, - }; - - tmhr.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - mprr.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - - Ok(vendor_defined_rsp_payload_struct) - } - } -} diff --git a/tdisp/src/tdisp_responder/lock_interface_request_rsp.rs b/tdisp/src/tdisp_responder/lock_interface_request_rsp.rs deleted file mode 100644 index 849993bb..00000000 --- a/tdisp/src/tdisp_responder/lock_interface_request_rsp.rs +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use spdmlib::error::*; - -use crate::{ - context::{MessagePayloadRequestLockInterface, MessagePayloadResponseLockInterface}, - state_machine::TDIState, -}; - -use super::*; - -// security check -// Interface ID specified in the request is not hosted by the device. -// DONE - TDI is not in CONFIG_UNLOCKED. -// For TDIs where IDE is required: -// The default Stream does not match the Stream ID indicated -// The default stream does not have IDE keys programmed for all sub-streams -// All IDE keys of the default stream were not configured over the SPDM session on which the LOCK_INTERFACE_REQUEST was received -// Multiple IDE configuration registers in the device have been configured as the default stream -// The default Stream is associated with a TC other than TC0 -// Phantom Functions Enabled -// Device PF BARs configured with overlapping addresses -// Expansion ROM base address, if supported, configured t// overlap with a BAR -// Resizable BAR control registers programmed with an unsupported BAR size -// VF BARs are configured with address overlapping another VF BAR, a PF BAR or Expansion ROM BAR -// Unsupported system page size is configured in the system page size register of SR-IOV capability -// Cache Line Size configured for LN requester capability (deprecated in PCIe Revision 6.0), if supported and enabled, does not match the system cache line size specified in the LOCK_INTERFACE_REQUEST or is configured t// a value not supported by the device. -// ST mode selected in TPH Requester Extended Capability, if supported and enabled, does not correspond t// a mode supported by the function hosting the TDI. -// Other device determined errors in the device or TDI configurations - -// The LOCK_INTERFACE_REQUEST binds and configures the following parameters into the TDI -// MMIO_REPORTING_OFFSET -// NO_FW_UPDATE -// System cache line size -// MSI-X table and PBA -// BIND_P2P -// ALL_REQUEST_REDIRECT -impl<'a> TdispResponder<'a> { - pub fn handle_lock_interface_request( - &mut self, - vendor_defined_req_payload_struct: &VendorDefinedReqPayloadStruct, - ) -> SpdmResult { - let mut reader = - Reader::init(&vendor_defined_req_payload_struct.vendor_defined_req_payload); - let tmh = TdispMessageHeader::tdisp_read(&mut self.tdisp_requester_context, &mut reader); - let mpr = MessagePayloadRequestLockInterface::tdisp_read( - &mut self.tdisp_requester_context, - &mut reader, - ); - if tmh.is_none() || mpr.is_none() { - self.handle_tdisp_error( - vendor_defined_req_payload_struct, - MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_REQUEST, - ) - } else if self.tdisp_requester_context.state_machine.current_state - != TDIState::ConfigUnlocked - { - self.handle_tdisp_error( - vendor_defined_req_payload_struct, - MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_INTERFACE_STATE, - ) - } else { - let mut vendor_defined_rsp_payload_struct: VendorDefinedRspPayloadStruct = - VendorDefinedRspPayloadStruct { - rsp_length: 0, - vendor_defined_rsp_payload: [0u8; - spdmlib::config::MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], - }; - let mut writer = - Writer::init(&mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload); - - let tmhr = TdispMessageHeader { - tdisp_version: self.tdisp_requester_context.version_sel, - message_type: TdispRequestResponseCode::ResponseLockInterfaceResponse, - interface_id: self.tdisp_requester_context.tdi, - }; - - let mprr = MessagePayloadResponseLockInterface::default(); - // mprr.start_interface_nonce - - tmhr.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - mprr.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - - match self.tdisp_requester_context.configuration.init_config() { - Ok(_) => match self.tdisp_requester_context.configuration.lock_config() { - Ok(_) => { - self.tdisp_requester_context - .state_machine - .to_state_config_locked(); - Ok(vendor_defined_rsp_payload_struct) - } - Err(_) => self.handle_tdisp_error( - vendor_defined_req_payload_struct, - MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_DEVICE_CONFIGURATION, - ), - }, - Err(_) => self.handle_tdisp_error( - vendor_defined_req_payload_struct, - MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_DEVICE_CONFIGURATION, - ), - } - } - } -} diff --git a/tdisp/src/tdisp_responder/mod.rs b/tdisp/src/tdisp_responder/mod.rs deleted file mode 100644 index b37fafd2..00000000 --- a/tdisp/src/tdisp_responder/mod.rs +++ /dev/null @@ -1,266 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -pub use crate::tdisp_codec::*; -pub use ::codec::*; -use spdmlib::{ - error::*, - message::{VendorDefinedReqPayloadStruct, VendorDefinedRspPayloadStruct}, -}; - -use crate::{ - config::{MAX_EXTENDED_ERROR_DATA_LENGTH, MAX_VENDOR_ID_LEN}, - context::{TdispContext, TdispMessageHeader, TdispRequestResponseCode}, - device::TdispConfiguration, -}; - -use core::mem; - -use self::context::{ - ExtendedErrorData, GenericErrorResponseCode, InterfaceId, MessagePayloadResponseTdispError, -}; - -pub mod bind_p2p_stream_request_rsp; -pub mod device_interface_report_rsp; -pub mod device_interface_state_rsp; -pub mod lock_interface_request_rsp; -pub mod set_mmio_attribute_request_rsp; -pub mod start_interface_request_rsp; -pub mod stop_interface_request_rsp; -pub mod tdisp_capabilities_rsp; -pub mod tdisp_error_rsp; -pub mod tdisp_version_rsp; -pub mod unbind_p2p_stream_request_rsp; -pub mod vdm_response; - -pub static mut TDISP_RESPONDER: Option = None; - -pub struct TdispResponder<'a> { - pub tdisp_requester_context: TdispContext<'a>, -} - -pub fn vendor_defined_request_handler( - vendor_defined_req_payload_struct: &VendorDefinedReqPayloadStruct, -) -> SpdmResult { - let VendorDefinedReqPayloadStruct { - req_length, - vendor_defined_req_payload, - } = vendor_defined_req_payload_struct; - - if (*req_length as usize) < mem::size_of::() { - Err(SPDM_STATUS_INVALID_MSG_FIELD) - } else if unsafe { TDISP_RESPONDER.is_none() } { - Err(SPDM_STATUS_INVALID_MSG_FIELD) - } else { - let tdisp_message_header = TdispMessageHeader::read_bytes(vendor_defined_req_payload); - match tdisp_message_header { - Some(tmh) => match tmh.message_type { - TdispRequestResponseCode::RequestGetTdispVersion => unsafe { - TDISP_RESPONDER - .as_mut() - .unwrap() - .handle_tdisp_version(vendor_defined_req_payload_struct) - }, - TdispRequestResponseCode::RequestGetTdispCapabilities => unsafe { - TDISP_RESPONDER - .as_mut() - .unwrap() - .handle_tdisp_capabilities(vendor_defined_req_payload_struct) - }, - TdispRequestResponseCode::RequestLockInterfaceRequest => unsafe { - TDISP_RESPONDER - .as_mut() - .unwrap() - .handle_lock_interface_request(vendor_defined_req_payload_struct) - }, - TdispRequestResponseCode::RequestGetDeviceInterfaceReport => unsafe { - TDISP_RESPONDER - .as_mut() - .unwrap() - .handle_device_interface_report(vendor_defined_req_payload_struct) - }, - TdispRequestResponseCode::RequestGetDeviceInterfaceState => unsafe { - TDISP_RESPONDER - .as_mut() - .unwrap() - .handle_device_interface_state(vendor_defined_req_payload_struct) - }, - TdispRequestResponseCode::RequestStartInterfaceRequest => unsafe { - TDISP_RESPONDER - .as_mut() - .unwrap() - .handle_start_interface_request(vendor_defined_req_payload_struct) - }, - TdispRequestResponseCode::RequestStopInterfaceRequest => unsafe { - TDISP_RESPONDER - .as_mut() - .unwrap() - .handle_stop_interface_request(vendor_defined_req_payload_struct) - }, - TdispRequestResponseCode::RequestBindP2pStreamRequest => unsafe { - TDISP_RESPONDER - .as_mut() - .unwrap() - .handle_bind_p2p_stream_request(vendor_defined_req_payload_struct) - }, - TdispRequestResponseCode::RequestUnbindP2pStreamRequest => unsafe { - TDISP_RESPONDER - .as_mut() - .unwrap() - .handle_unbind_p2p_stream_request(vendor_defined_req_payload_struct) - }, - TdispRequestResponseCode::RequestSetMmioAttributeRequest => unsafe { - TDISP_RESPONDER - .as_mut() - .unwrap() - .handle_set_mmio_attribute_request(vendor_defined_req_payload_struct) - }, - TdispRequestResponseCode::RequestVdmRequest => unsafe { - TDISP_RESPONDER - .as_mut() - .unwrap() - .handle_vdm_request(vendor_defined_req_payload_struct) - }, - _ => Err(SPDM_STATUS_INVALID_MSG_FIELD), - }, - None => Err(SPDM_STATUS_INVALID_MSG_FIELD), - } - } -} - -impl<'a> TdispResponder<'a> { - pub fn new( - interface_id: InterfaceId, - configuration: &'a mut dyn TdispConfiguration, - spdm_session_id: u32, - ) -> Self { - TdispResponder { - tdisp_requester_context: TdispContext::new( - interface_id, - configuration, - spdm_session_id, - ), - } - } -} - -pub const MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_REQUEST: MessagePayloadResponseTdispError = - MessagePayloadResponseTdispError { - error_code: GenericErrorResponseCode::InvalidRequest, - error_data: 0, - extended_error_data: ExtendedErrorData { - registry_id: 0, - vendor_id_len: 0, - vendor_id: [0u8; MAX_VENDOR_ID_LEN], - vendor_err_data: [0u8; MAX_EXTENDED_ERROR_DATA_LENGTH], - }, - }; - -pub const MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_BUSY: MessagePayloadResponseTdispError = - MessagePayloadResponseTdispError { - error_code: GenericErrorResponseCode::Busy, - error_data: 0, - extended_error_data: ExtendedErrorData { - registry_id: 0, - vendor_id_len: 0, - vendor_id: [0u8; MAX_VENDOR_ID_LEN], - vendor_err_data: [0u8; MAX_EXTENDED_ERROR_DATA_LENGTH], - }, - }; - -pub const MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_INTERFACE_STATE: - MessagePayloadResponseTdispError = MessagePayloadResponseTdispError { - error_code: GenericErrorResponseCode::InvalidInterfaceState, - error_data: 0, - extended_error_data: ExtendedErrorData { - registry_id: 0, - vendor_id_len: 0, - vendor_id: [0u8; MAX_VENDOR_ID_LEN], - vendor_err_data: [0u8; MAX_EXTENDED_ERROR_DATA_LENGTH], - }, -}; - -pub const MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_UNSPECIFIED: MessagePayloadResponseTdispError = - MessagePayloadResponseTdispError { - error_code: GenericErrorResponseCode::Unspecified, - error_data: 0, - extended_error_data: ExtendedErrorData { - registry_id: 0, - vendor_id_len: 0, - vendor_id: [0u8; MAX_VENDOR_ID_LEN], - vendor_err_data: [0u8; MAX_EXTENDED_ERROR_DATA_LENGTH], - }, - }; - -pub const MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_UNSUPPORTED_REQUEST: - MessagePayloadResponseTdispError = MessagePayloadResponseTdispError { - error_code: GenericErrorResponseCode::UnsupportedRequest, - error_data: 0, - extended_error_data: ExtendedErrorData { - registry_id: 0, - vendor_id_len: 0, - vendor_id: [0u8; MAX_VENDOR_ID_LEN], - vendor_err_data: [0u8; MAX_EXTENDED_ERROR_DATA_LENGTH], - }, -}; - -pub const MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_VERSION_MISMATCH: MessagePayloadResponseTdispError = - MessagePayloadResponseTdispError { - error_code: GenericErrorResponseCode::VersionMismatch, - error_data: 0, - extended_error_data: ExtendedErrorData { - registry_id: 0, - vendor_id_len: 0, - vendor_id: [0u8; MAX_VENDOR_ID_LEN], - vendor_err_data: [0u8; MAX_EXTENDED_ERROR_DATA_LENGTH], - }, - }; - -pub const MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_INTERFACE: MessagePayloadResponseTdispError = - MessagePayloadResponseTdispError { - error_code: GenericErrorResponseCode::InvalidInterface, - error_data: 0, - extended_error_data: ExtendedErrorData { - registry_id: 0, - vendor_id_len: 0, - vendor_id: [0u8; MAX_VENDOR_ID_LEN], - vendor_err_data: [0u8; MAX_EXTENDED_ERROR_DATA_LENGTH], - }, - }; - -pub const MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_NONCE: MessagePayloadResponseTdispError = - MessagePayloadResponseTdispError { - error_code: GenericErrorResponseCode::InvalidNonce, - error_data: 0, - extended_error_data: ExtendedErrorData { - registry_id: 0, - vendor_id_len: 0, - vendor_id: [0u8; MAX_VENDOR_ID_LEN], - vendor_err_data: [0u8; MAX_EXTENDED_ERROR_DATA_LENGTH], - }, - }; - -pub const MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INSUFFICIENT_ENTROPY: - MessagePayloadResponseTdispError = MessagePayloadResponseTdispError { - error_code: GenericErrorResponseCode::InsufficientEntropy, - error_data: 0, - extended_error_data: ExtendedErrorData { - registry_id: 0, - vendor_id_len: 0, - vendor_id: [0u8; MAX_VENDOR_ID_LEN], - vendor_err_data: [0u8; MAX_EXTENDED_ERROR_DATA_LENGTH], - }, -}; - -pub const MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_DEVICE_CONFIGURATION: - MessagePayloadResponseTdispError = MessagePayloadResponseTdispError { - error_code: GenericErrorResponseCode::InvalidDeviceConfiguration, - error_data: 0, - extended_error_data: ExtendedErrorData { - registry_id: 0, - vendor_id_len: 0, - vendor_id: [0u8; MAX_VENDOR_ID_LEN], - vendor_err_data: [0u8; MAX_EXTENDED_ERROR_DATA_LENGTH], - }, -}; diff --git a/tdisp/src/tdisp_responder/set_mmio_attribute_request_rsp.rs b/tdisp/src/tdisp_responder/set_mmio_attribute_request_rsp.rs deleted file mode 100644 index 30b7cf68..00000000 --- a/tdisp/src/tdisp_responder/set_mmio_attribute_request_rsp.rs +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use spdmlib::error::*; - -use crate::{ - context::{MessagePayloadRequestSetMmioAttribute, MessagePayloadResponseSetMmioAttribute}, - state_machine::TDIState, -}; - -use super::*; - -// security check -// Interface ID in the request is not hosted by the device -// TDI does not support updateable MMIO attributes -// TDI does not support updateable MMIO attributes for the requested MMIO range -// TDI does not support the specified attribute for the requested MMIO range -// TDI does not support the value specified for the attribute -// DONE - TDI is not in RUN -// The MMIO range specified in the request is not associated with TDI - -impl<'a> TdispResponder<'a> { - pub fn handle_set_mmio_attribute_request( - &mut self, - vendor_defined_req_payload_struct: &VendorDefinedReqPayloadStruct, - ) -> SpdmResult { - let mut reader = - Reader::init(&vendor_defined_req_payload_struct.vendor_defined_req_payload); - let tmh = TdispMessageHeader::tdisp_read(&mut self.tdisp_requester_context, &mut reader); - let mpr = MessagePayloadRequestSetMmioAttribute::tdisp_read( - &mut self.tdisp_requester_context, - &mut reader, - ); - if tmh.is_none() || mpr.is_none() { - self.handle_tdisp_error( - vendor_defined_req_payload_struct, - MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_REQUEST, - ) - } else if self.tdisp_requester_context.state_machine.current_state != TDIState::Run { - self.handle_tdisp_error( - vendor_defined_req_payload_struct, - MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_INTERFACE_STATE, - ) - } else { - let mut vendor_defined_rsp_payload_struct: VendorDefinedRspPayloadStruct = - VendorDefinedRspPayloadStruct { - rsp_length: 0, - vendor_defined_rsp_payload: [0u8; - spdmlib::config::MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], - }; - let mut writer = - Writer::init(&mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload); - - let tmhr = TdispMessageHeader { - tdisp_version: self.tdisp_requester_context.version_sel, - message_type: TdispRequestResponseCode::ResponseSetMmioAttributeResponse, - interface_id: self.tdisp_requester_context.tdi, - }; - - let mprr = MessagePayloadResponseSetMmioAttribute::default(); - - tmhr.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - mprr.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - - Ok(vendor_defined_rsp_payload_struct) - } - } -} diff --git a/tdisp/src/tdisp_responder/start_interface_request_rsp.rs b/tdisp/src/tdisp_responder/start_interface_request_rsp.rs deleted file mode 100644 index 32d69e30..00000000 --- a/tdisp/src/tdisp_responder/start_interface_request_rsp.rs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use spdmlib::error::*; - -use crate::{ - context::{MessagePayloadRequestStartInterface, MessagePayloadResponseStartInterface}, - state_machine::TDIState, -}; - -use super::*; - -// If the interface ID in the request is not hosted by the device. -// START_INTERFACE_NONCE in the request is not valid i.e., does not match the nonce generated by the device in the LOCK_INTERFACE_RESPONSE. -// DONE - TDI is not in CONFIG_LOCKED. - -impl<'a> TdispResponder<'a> { - pub fn handle_start_interface_request( - &mut self, - vendor_defined_req_payload_struct: &VendorDefinedReqPayloadStruct, - ) -> SpdmResult { - let mut reader = - Reader::init(&vendor_defined_req_payload_struct.vendor_defined_req_payload); - let tmh = TdispMessageHeader::tdisp_read(&mut self.tdisp_requester_context, &mut reader); - let mpr = MessagePayloadRequestStartInterface::tdisp_read( - &mut self.tdisp_requester_context, - &mut reader, - ); - if tmh.is_none() || mpr.is_none() { - self.handle_tdisp_error( - vendor_defined_req_payload_struct, - MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_REQUEST, - ) - } else if self.tdisp_requester_context.state_machine.current_state != TDIState::ConfigLocked - { - self.handle_tdisp_error( - vendor_defined_req_payload_struct, - MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_INTERFACE_STATE, - ) - } else { - let mut vendor_defined_rsp_payload_struct: VendorDefinedRspPayloadStruct = - VendorDefinedRspPayloadStruct { - rsp_length: 0, - vendor_defined_rsp_payload: [0u8; - spdmlib::config::MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], - }; - let mut writer = - Writer::init(&mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload); - - let tmhr = TdispMessageHeader { - tdisp_version: self.tdisp_requester_context.version_sel, - message_type: TdispRequestResponseCode::ResponseStartInterfaceResponse, - interface_id: self.tdisp_requester_context.tdi, - }; - - let mprr = MessagePayloadResponseStartInterface::default(); - - tmhr.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - mprr.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - - match self - .tdisp_requester_context - .configuration - .track_config_changes() - { - Ok(_) => { - self.tdisp_requester_context.state_machine.to_state_run(); - Ok(vendor_defined_rsp_payload_struct) - } - Err(_) => self.handle_tdisp_error( - vendor_defined_req_payload_struct, - MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_DEVICE_CONFIGURATION, - ), - } - } - } -} diff --git a/tdisp/src/tdisp_responder/stop_interface_request_rsp.rs b/tdisp/src/tdisp_responder/stop_interface_request_rsp.rs deleted file mode 100644 index 0485b5fc..00000000 --- a/tdisp/src/tdisp_responder/stop_interface_request_rsp.rs +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use spdmlib::error::*; - -use crate::context::{MessagePayloadRequestStopInterface, MessagePayloadResponseStopInterface}; - -use super::*; - -// security check -// If the interface ID in the request is not hosted by the device. - -// Abort all in-flight and accepted operations that are being performed by the TDI -// Wait for outstanding responses for the aborted operations -// All DMA read and write operations by the TDI are aborted or completed -// All interrupts from the TDI have been generated -// If function hosting the TDI is capable of Address Translation Service (ATS), all ATS requests by the TDI have completed or aborted. All translations cached in the device for ATS requests generated by this TDI have been invalidated. -// If function hosting the TDI is capable of Page Request Interface Service (PRI), no more page requests will be generated by the TDI. Additionally, either page responses have been received for all page requests generated by the TDI or the TDI will discard page responses for outstanding page requests. -// Scrub internal state of the device to remove secrets associated with the TDI such that those secrets will not be accessible. -// Reclaim and scrub private resources (e.g., memory encryption keys for device attached memories, etc.) assigned to the TDI - -impl<'a> TdispResponder<'a> { - pub fn handle_stop_interface_request( - &mut self, - vendor_defined_req_payload_struct: &VendorDefinedReqPayloadStruct, - ) -> SpdmResult { - let mut reader = - Reader::init(&vendor_defined_req_payload_struct.vendor_defined_req_payload); - let tmh = TdispMessageHeader::tdisp_read(&mut self.tdisp_requester_context, &mut reader); - let mpr = MessagePayloadRequestStopInterface::tdisp_read( - &mut self.tdisp_requester_context, - &mut reader, - ); - if tmh.is_none() || mpr.is_none() { - self.handle_tdisp_error( - vendor_defined_req_payload_struct, - MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_REQUEST, - ) - } else { - let mut vendor_defined_rsp_payload_struct: VendorDefinedRspPayloadStruct = - VendorDefinedRspPayloadStruct { - rsp_length: 0, - vendor_defined_rsp_payload: [0u8; - spdmlib::config::MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], - }; - let mut writer = - Writer::init(&mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload); - - let tmhr = TdispMessageHeader { - tdisp_version: self.tdisp_requester_context.version_sel, - message_type: TdispRequestResponseCode::ResponseStopInterfaceResponse, - interface_id: self.tdisp_requester_context.tdi, - }; - - let mprr = MessagePayloadResponseStopInterface::default(); - - tmhr.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - mprr.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - - match self - .tdisp_requester_context - .configuration - .erase_confidential_config() - { - Ok(_) => match self.tdisp_requester_context.configuration.unlock_config() { - Ok(_) => { - self.tdisp_requester_context - .state_machine - .to_state_config_unlocked(); - Ok(vendor_defined_rsp_payload_struct) - } - Err(_) => self.handle_tdisp_error( - vendor_defined_req_payload_struct, - MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_DEVICE_CONFIGURATION, - ), - }, - Err(_) => self.handle_tdisp_error( - vendor_defined_req_payload_struct, - MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_DEVICE_CONFIGURATION, - ), - } - } - } -} diff --git a/tdisp/src/tdisp_responder/tdisp_capabilities_rsp.rs b/tdisp/src/tdisp_responder/tdisp_capabilities_rsp.rs deleted file mode 100644 index 5750ac36..00000000 --- a/tdisp/src/tdisp_responder/tdisp_capabilities_rsp.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use spdmlib::error::*; - -use crate::context::{MessagePayloadRequestGetCapabilities, MessagePayloadResponseCapabilities}; - -use super::*; - -impl<'a> TdispResponder<'a> { - pub fn handle_tdisp_capabilities( - &mut self, - vendor_defined_req_payload_struct: &VendorDefinedReqPayloadStruct, - ) -> SpdmResult { - let mut reader = - Reader::init(&vendor_defined_req_payload_struct.vendor_defined_req_payload); - let tmh = TdispMessageHeader::tdisp_read(&mut self.tdisp_requester_context, &mut reader); - let mpr = MessagePayloadRequestGetCapabilities::tdisp_read( - &mut self.tdisp_requester_context, - &mut reader, - ); - if tmh.is_none() || mpr.is_none() { - self.handle_tdisp_error( - vendor_defined_req_payload_struct, - MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_REQUEST, - ) - } else { - let mut vendor_defined_rsp_payload_struct: VendorDefinedRspPayloadStruct = - VendorDefinedRspPayloadStruct { - rsp_length: 0, - vendor_defined_rsp_payload: [0u8; - spdmlib::config::MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], - }; - let mut writer = - Writer::init(&mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload); - - let tmhr = TdispMessageHeader { - tdisp_version: self.tdisp_requester_context.version_sel, - message_type: TdispRequestResponseCode::ResponseTdispCapabilities, - interface_id: self.tdisp_requester_context.tdi, - }; - - let mprr = MessagePayloadResponseCapabilities::default(); - // mprr.dev_addr_width - // mprr.dsm_caps - // mprr.lock_interface_flags_supported - // mprr.num_req_all - // mprr.num_req_this - // mprr.req_msgs_supported - - tmhr.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - mprr.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - - Ok(vendor_defined_rsp_payload_struct) - } - } -} diff --git a/tdisp/src/tdisp_responder/tdisp_error_rsp.rs b/tdisp/src/tdisp_responder/tdisp_error_rsp.rs deleted file mode 100644 index 60ef96e7..00000000 --- a/tdisp/src/tdisp_responder/tdisp_error_rsp.rs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use spdmlib::error::*; - -use crate::{context::MessagePayloadResponseTdispError, tdisp_codec::TdispCodec}; - -use super::*; - -impl<'a> TdispResponder<'a> { - pub fn handle_tdisp_error( - &mut self, - vendor_defined_req_payload_struct: &VendorDefinedReqPayloadStruct, - message_payload_response_tdisp_error: MessagePayloadResponseTdispError, - ) -> SpdmResult { - let mut reader = - Reader::init(&vendor_defined_req_payload_struct.vendor_defined_req_payload); - let _tmh = TdispMessageHeader::tdisp_read(&mut self.tdisp_requester_context, &mut reader); - - let mut vendor_defined_rsp_payload_struct: VendorDefinedRspPayloadStruct = - VendorDefinedRspPayloadStruct { - rsp_length: 0, - vendor_defined_rsp_payload: [0u8; - spdmlib::config::MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], - }; - let mut writer = - Writer::init(&mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload); - - let tmhr = TdispMessageHeader { - tdisp_version: self.tdisp_requester_context.version_sel, - message_type: TdispRequestResponseCode::ResponseTdispError, - interface_id: self.tdisp_requester_context.tdi, - }; - - tmhr.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - - message_payload_response_tdisp_error - .tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - - match self - .tdisp_requester_context - .configuration - .erase_confidential_config() - { - Ok(_) => { - self.tdisp_requester_context.state_machine.to_state_error(); - Ok(vendor_defined_rsp_payload_struct) - } - Err(_) => panic!("Confidential data leaking"), - } - } -} diff --git a/tdisp/src/tdisp_responder/tdisp_version_rsp.rs b/tdisp/src/tdisp_responder/tdisp_version_rsp.rs deleted file mode 100644 index 12933f21..00000000 --- a/tdisp/src/tdisp_responder/tdisp_version_rsp.rs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use spdmlib::error::*; - -use crate::{ - config::MAX_VERSION_COUNT, - context::{MessagePayloadRequestGetVersion, MessagePayloadResponseVersion}, - tdisp_codec::TdispCodec, -}; - -use super::*; - -impl<'a> TdispResponder<'a> { - pub fn handle_tdisp_version( - &mut self, - vendor_defined_req_payload_struct: &VendorDefinedReqPayloadStruct, - ) -> SpdmResult { - let mut reader = - Reader::init(&vendor_defined_req_payload_struct.vendor_defined_req_payload); - let tmh = TdispMessageHeader::tdisp_read(&mut self.tdisp_requester_context, &mut reader); - let mpr = MessagePayloadRequestGetVersion::tdisp_read( - &mut self.tdisp_requester_context, - &mut reader, - ); - if tmh.is_none() || mpr.is_none() { - self.handle_tdisp_error( - vendor_defined_req_payload_struct, - MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_REQUEST, - ) - } else { - let mut vendor_defined_rsp_payload_struct: VendorDefinedRspPayloadStruct = - VendorDefinedRspPayloadStruct { - rsp_length: 0, - vendor_defined_rsp_payload: [0u8; - spdmlib::config::MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], - }; - let mut writer = - Writer::init(&mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload); - - let tmhr = TdispMessageHeader { - tdisp_version: self.tdisp_requester_context.version_sel, - message_type: TdispRequestResponseCode::ResponseTdispVersion, - interface_id: self.tdisp_requester_context.tdi, - }; - - let mprr = MessagePayloadResponseVersion { - version_num_count: 1, - version_num_entry: [self.tdisp_requester_context.version_sel; MAX_VERSION_COUNT], - }; - - tmhr.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - mprr.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - - Ok(vendor_defined_rsp_payload_struct) - } - } -} diff --git a/tdisp/src/tdisp_responder/unbind_p2p_stream_request_rsp.rs b/tdisp/src/tdisp_responder/unbind_p2p_stream_request_rsp.rs deleted file mode 100644 index 2dbf5b66..00000000 --- a/tdisp/src/tdisp_responder/unbind_p2p_stream_request_rsp.rs +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use spdmlib::error::*; - -use crate::{ - context::{MessagePayloadRequestUnbindP2pStream, MessagePayloadResponseUnbindP2pStream}, - state_machine::TDIState, -}; - -use super::*; - -// security check -// Interface ID in the request is not hosted by the device -// TDI does not support binding peer-to-peer streams -// DONE - TDI is not in RUN -// Stream ID specified was not previously bound to this TDI - -impl<'a> TdispResponder<'a> { - pub fn handle_unbind_p2p_stream_request( - &mut self, - vendor_defined_req_payload_struct: &VendorDefinedReqPayloadStruct, - ) -> SpdmResult { - let mut reader = - Reader::init(&vendor_defined_req_payload_struct.vendor_defined_req_payload); - let tmh = TdispMessageHeader::tdisp_read(&mut self.tdisp_requester_context, &mut reader); - let mpr = MessagePayloadRequestUnbindP2pStream::tdisp_read( - &mut self.tdisp_requester_context, - &mut reader, - ); - if tmh.is_none() || mpr.is_none() { - self.handle_tdisp_error( - vendor_defined_req_payload_struct, - MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_REQUEST, - ) - } else if self.tdisp_requester_context.state_machine.current_state != TDIState::Run { - self.handle_tdisp_error( - vendor_defined_req_payload_struct, - MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_INTERFACE_STATE, - ) - } else { - let mut vendor_defined_rsp_payload_struct: VendorDefinedRspPayloadStruct = - VendorDefinedRspPayloadStruct { - rsp_length: 0, - vendor_defined_rsp_payload: [0u8; - spdmlib::config::MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], - }; - let mut writer = - Writer::init(&mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload); - - let tmhr = TdispMessageHeader { - tdisp_version: self.tdisp_requester_context.version_sel, - message_type: TdispRequestResponseCode::ResponseUnbindP2pStreamResponse, - interface_id: self.tdisp_requester_context.tdi, - }; - - let mprr = MessagePayloadResponseUnbindP2pStream::default(); - - tmhr.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - mprr.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - - Ok(vendor_defined_rsp_payload_struct) - } - } -} diff --git a/tdisp/src/tdisp_responder/vdm_response.rs b/tdisp/src/tdisp_responder/vdm_response.rs deleted file mode 100644 index ab714bfd..00000000 --- a/tdisp/src/tdisp_responder/vdm_response.rs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2022 Intel Corporation -// -// SPDX-License-Identifier: Apache-2.0 or MIT - -use spdmlib::error::*; - -use crate::context::{MessagePayloadRequestVDM, MessagePayloadResponseVDM}; - -use super::*; - -impl<'a> TdispResponder<'a> { - pub fn handle_vdm_request( - &mut self, - vendor_defined_req_payload_struct: &VendorDefinedReqPayloadStruct, - ) -> SpdmResult { - let mut reader = - Reader::init(&vendor_defined_req_payload_struct.vendor_defined_req_payload); - let tmh = TdispMessageHeader::tdisp_read(&mut self.tdisp_requester_context, &mut reader); - let mpr = - MessagePayloadRequestVDM::tdisp_read(&mut self.tdisp_requester_context, &mut reader); - if tmh.is_none() || mpr.is_none() { - self.handle_tdisp_error( - vendor_defined_req_payload_struct, - MESSAGE_PAYLOAD_RESPONSE_TDISP_ERROR_INVALID_REQUEST, - ) - } else { - let mut vendor_defined_rsp_payload_struct: VendorDefinedRspPayloadStruct = - VendorDefinedRspPayloadStruct { - rsp_length: 0, - vendor_defined_rsp_payload: [0u8; - spdmlib::config::MAX_SPDM_VENDOR_DEFINED_PAYLOAD_SIZE], - }; - let mut writer = - Writer::init(&mut vendor_defined_rsp_payload_struct.vendor_defined_rsp_payload); - - let tmhr = TdispMessageHeader { - tdisp_version: self.tdisp_requester_context.version_sel, - message_type: TdispRequestResponseCode::ResponseVdmResponse, - interface_id: self.tdisp_requester_context.tdi, - }; - - let mprr = MessagePayloadResponseVDM::default(); - // mprr.registry_id - // mprr.vendor_id - // mprr.vendor_id_len - // vendor_data - - tmhr.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - mprr.tdisp_encode(&mut self.tdisp_requester_context, &mut writer); - - Ok(vendor_defined_rsp_payload_struct) - } - } -} diff --git a/test/spdm-requester-emu/Cargo.toml b/test/spdm-requester-emu/Cargo.toml index 9da878ad..c3677ced 100644 --- a/test/spdm-requester-emu/Cargo.toml +++ b/test/spdm-requester-emu/Cargo.toml @@ -10,6 +10,7 @@ edition = "2018" spdm-emu = { path = "../spdm-emu", default-features = false } spdmlib = { path = "../../spdmlib", default-features = false } idekm = { path = "../../idekm", default-features = false } +tdisp = { path = "../../tdisp", default-features = false } codec = { path = "../../codec" } mctp_transport = { path = "../../mctp_transport" } pcidoe_transport = { path = "../../pcidoe_transport" } diff --git a/test/spdm-requester-emu/src/main.rs b/test/spdm-requester-emu/src/main.rs index 040f9ec2..800925d7 100644 --- a/test/spdm-requester-emu/src/main.rs +++ b/test/spdm-requester-emu/src/main.rs @@ -39,6 +39,19 @@ use pcidoe_transport::PciDoeTransportEncap; use spdm_emu::socket_io_transport::SocketIoTransport; use spdm_emu::spdm_emu::*; use std::net::TcpStream; +use tdisp::pci_tdisp::FunctionId; +use tdisp::pci_tdisp::InterfaceId; +use tdisp::pci_tdisp::LockInterfaceFlag; +use tdisp::pci_tdisp::TdiReportStructure; +use tdisp::pci_tdisp::TdiState; +use tdisp::pci_tdisp::START_INTERFACE_NONCE_LEN; +use tdisp::pci_tdisp_requester::pci_tdisp_req_get_capabilities; +use tdisp::pci_tdisp_requester::pci_tdisp_req_get_interface_report; +use tdisp::pci_tdisp_requester::pci_tdisp_req_get_interface_state; +use tdisp::pci_tdisp_requester::pci_tdisp_req_get_version; +use tdisp::pci_tdisp_requester::pci_tdisp_req_lock_interface; +use tdisp::pci_tdisp_requester::pci_tdisp_req_start_interface; +use tdisp::pci_tdisp_requester::pci_tdisp_req_stop_interface; use tokio::runtime::Runtime; @@ -402,7 +415,7 @@ async fn test_spdm( } } -async fn test_idekm( +async fn test_idekm_tdisp( socket_io_transport: Arc>, transport_encap: Arc>, ) { @@ -1080,6 +1093,168 @@ async fn test_idekm( .unwrap(); println!("Successful KEY_SET_STOP at Key Set 0 | TX | CPL!"); + // tdisp test + let interface_id = InterfaceId { + function_id: FunctionId { + requester_id: 0x1234, + requester_segment: 0, + requester_segment_valid: false, + }, + }; + + let mut negotiated_version = None; + + pci_tdisp_req_get_version( + &mut context, + session_id, + interface_id, + &mut negotiated_version, + ) + .await + .unwrap(); + println!("Successful Get Tdisp Version!"); + + assert!(negotiated_version.is_some()); + assert_eq!( + negotiated_version.unwrap(), + tdisp::pci_tdisp::TdispVersion { + major_version: 1, + minor_version: 0 + } + ); + let negotiated_version = negotiated_version.unwrap(); + + let tsm_caps = 0; + let mut dsm_caps = 0u32; + let mut lock_interface_flags_supported = LockInterfaceFlag::empty(); + let mut dev_addr_width = 0u8; + let mut num_req_this = 0u8; + let mut num_req_all = 0u8; + let mut req_msgs_supported = [0u8; 16]; + pci_tdisp_req_get_capabilities( + &mut context, + session_id, + tsm_caps, + negotiated_version, + interface_id, + &mut dsm_caps, + &mut lock_interface_flags_supported, + &mut dev_addr_width, + &mut num_req_this, + &mut num_req_all, + &mut req_msgs_supported, + ) + .await + .unwrap(); + println!("Successful Get Tdisp Capabilities!"); + + let mut tdi_state = TdiState::ERROR; + pci_tdisp_req_get_interface_state( + &mut context, + session_id, + negotiated_version, + interface_id, + &mut tdi_state, + ) + .await + .unwrap(); + assert_eq!(tdi_state, TdiState::CONFIG_UNLOCKED); + println!("Successful Get Tdisp State: {:X?}!", tdi_state); + + let flags = LockInterfaceFlag::NO_FW_UPDATE; + let default_stream_id = 0; + let mmio_reporting_offset = 0xFFFFFF00; + let bind_p2p_address_mask = 0; + let mut start_interface_nonce = [0u8; START_INTERFACE_NONCE_LEN]; + let mut tdisp_error_code = None; + pci_tdisp_req_lock_interface( + &mut context, + session_id, + negotiated_version, + interface_id, + flags, + default_stream_id, + mmio_reporting_offset, + bind_p2p_address_mask, + &mut start_interface_nonce, + &mut tdisp_error_code, + ) + .await + .unwrap(); + assert!(tdisp_error_code.is_none()); + println!( + "Successful Lock Interface, start_interface_nonce: {:X?}!", + start_interface_nonce + ); + + pci_tdisp_req_get_interface_state( + &mut context, + session_id, + negotiated_version, + interface_id, + &mut tdi_state, + ) + .await + .unwrap(); + assert_eq!(tdi_state, TdiState::CONFIG_LOCKED); + println!("Successful Get Tdisp State: {:X?}!", tdi_state); + + let mut report = TdiReportStructure::default(); + pci_tdisp_req_get_interface_report( + &mut context, + session_id, + negotiated_version, + interface_id, + &mut report, + &mut tdisp_error_code, + ) + .await + .unwrap(); + assert!(tdisp_error_code.is_none()); + println!("Successful Get Interface Report, report: {:X?}!", report); + + pci_tdisp_req_start_interface( + &mut context, + session_id, + negotiated_version, + interface_id, + &start_interface_nonce, + &mut tdisp_error_code, + ) + .await + .unwrap(); + assert!(tdisp_error_code.is_none()); + println!("Successful Start Interface!"); + + pci_tdisp_req_get_interface_state( + &mut context, + session_id, + negotiated_version, + interface_id, + &mut tdi_state, + ) + .await + .unwrap(); + assert_eq!(tdi_state, TdiState::RUN); + println!("Successful Get Tdisp State: {:X?}!", tdi_state); + + pci_tdisp_req_stop_interface(&mut context, session_id, negotiated_version, interface_id) + .await + .unwrap(); + println!("Successful Stop Interface!"); + + pci_tdisp_req_get_interface_state( + &mut context, + session_id, + negotiated_version, + interface_id, + &mut tdi_state, + ) + .await + .unwrap(); + assert_eq!(tdi_state, TdiState::CONFIG_UNLOCKED); + println!("Successful Get Tdisp State: {:X?}!", tdi_state); + // end spdm session context.end_session(session_id).await.unwrap(); } @@ -1153,7 +1328,7 @@ fn emu_main() { transport_encap.clone(), )); - rt.block_on(test_idekm( + rt.block_on(test_idekm_tdisp( socket_io_transport.clone(), transport_encap.clone(), )); diff --git a/test/spdm-responder-emu/Cargo.toml b/test/spdm-responder-emu/Cargo.toml index 7aeb44dd..886d108f 100644 --- a/test/spdm-responder-emu/Cargo.toml +++ b/test/spdm-responder-emu/Cargo.toml @@ -10,6 +10,7 @@ edition = "2018" spdm-emu = { path = "../spdm-emu", default-features = false } spdmlib = { path = "../../spdmlib", default-features = false } idekm = { path = "../../idekm", default-features = false } +tdisp = { path = "../../tdisp", default-features = false } codec = { path = "../../codec" } mctp_transport = { path = "../../mctp_transport" } pcidoe_transport = { path = "../../pcidoe_transport" } @@ -20,6 +21,7 @@ spin = { version = "0.9.8" } tokio = { version = "1.30.0", features = ["full"] } zeroize = { version = "1.5.0", features = ["zeroize_derive"]} + [features] mut-auth = ["spdm-emu/mut-auth"] mandatory-mut-auth = ["mut-auth", "spdm-emu/mandatory-mut-auth"] diff --git a/test/spdm-responder-emu/src/main.rs b/test/spdm-responder-emu/src/main.rs index 8b8e7d2c..47ecf62c 100644 --- a/test/spdm-responder-emu/src/main.rs +++ b/test/spdm-responder-emu/src/main.rs @@ -2,17 +2,28 @@ // // SPDX-License-Identifier: Apache-2.0 or MIT -#![forbid(unsafe_code)] +mod spdm_device_idekm_example; +use idekm::pci_ide_km_responder::pci_ide_km_rsp_dispatcher; +use idekm::pci_idekm::IDE_PROTOCOL_ID; +use spdm_device_idekm_example::init_device_idekm_instance; -mod spdm_device_example; -use spdm_device_example::init_device_instance; +mod spdm_device_tdisp_example; +use spdm_device_tdisp_example::init_device_tdisp_instance; -use idekm::pci_ide_km_responder::PCI_IDE_KM_INSTANCE; use log::LevelFilter; use simple_logger::SimpleLogger; use spdm_emu::watchdog_impl_sample::init_watchdog; use spdmlib::common::{SecuredMessageVersion, SpdmOpaqueSupport}; use spdmlib::config::{MAX_ROOT_CERT_SUPPORT, RECEIVER_BUFFER_SIZE}; +use spdmlib::error::{SpdmResult, SPDM_STATUS_INVALID_MSG_FIELD}; +use spdmlib::message::{ + VendorDefinedReqPayloadStruct, VendorDefinedRspPayloadStruct, VendorDefinedStruct, +}; +use tdisp::pci_tdisp::{ + FunctionId, InterfaceId, LockInterfaceFlag, TdiState, START_INTERFACE_NONCE_LEN, + TDISP_PROTOCOL_ID, +}; +use tdisp::pci_tdisp_responder::pci_tdisp_rsp_dispatcher; use std::net::{TcpListener, TcpStream}; use std::u32; @@ -36,6 +47,8 @@ extern crate alloc; use alloc::sync::Arc; use core::ops::DerefMut; +use crate::spdm_device_tdisp_example::DeviceContext; + async fn process_socket_message( stream: Arc>, transport_encap: Arc>, @@ -263,7 +276,37 @@ async fn handle_message( }; spdmlib::secret::asym_sign::register(SECRET_ASYM_IMPL_INSTANCE.clone()); - spdmlib::message::vendor::register_vendor_defined_struct(PCI_IDE_KM_INSTANCE); + let tdisp_rsp_context = DeviceContext { + bus: 0x2a, + device: 0x00, + function: 0x00, + negotiated_version: None, + interface_id: InterfaceId { + function_id: FunctionId { + requester_id: 0x1234, + requester_segment: 0, + requester_segment_valid: false, + }, + }, + dsm_caps: 0, + dev_addr_width: 52, + num_req_this: 1, + num_req_all: 1, + flags: LockInterfaceFlag::empty(), + tdi_state: TdiState::CONFIG_UNLOCKED, + default_stream_id: 0, + mmio_reporting_offset: 0, + bind_p2p_address_mask: 0, + start_interface_nonce: [0u8; START_INTERFACE_NONCE_LEN], + }; + + let device_context_handle = &tdisp_rsp_context as *const DeviceContext as usize; + + spdmlib::message::vendor::register_vendor_defined_struct(VendorDefinedStruct { + vendor_defined_request_handler: pci_idekm_tdisp_rsp_dispatcher, + vendor_context: device_context_handle, + }); + init_watchdog(); let mut context = responder::ResponderContext::new( socket_io_transport, @@ -421,9 +464,29 @@ pub async fn send_pci_discovery( true } +fn pci_idekm_tdisp_rsp_dispatcher( + vendor_context: usize, + vendor_defined_req_payload_struct: &VendorDefinedReqPayloadStruct, +) -> SpdmResult { + if vendor_defined_req_payload_struct.req_length < 1 { + return Err(SPDM_STATUS_INVALID_MSG_FIELD); + } + + match vendor_defined_req_payload_struct.vendor_defined_req_payload[0] { + IDE_PROTOCOL_ID => { + pci_ide_km_rsp_dispatcher(vendor_context, vendor_defined_req_payload_struct) + } + TDISP_PROTOCOL_ID => { + pci_tdisp_rsp_dispatcher(vendor_context, vendor_defined_req_payload_struct) + } + _ => Err(SPDM_STATUS_INVALID_MSG_FIELD), + } +} + fn main() { use std::thread; - init_device_instance(); + init_device_idekm_instance(); + init_device_tdisp_instance(); thread::Builder::new() .stack_size(EMU_STACK_SIZE) diff --git a/test/spdm-responder-emu/src/spdm_device_example.rs b/test/spdm-responder-emu/src/spdm_device_idekm_example.rs similarity index 98% rename from test/spdm-responder-emu/src/spdm_device_example.rs rename to test/spdm-responder-emu/src/spdm_device_idekm_example.rs index 1077eda3..91cd1ac1 100644 --- a/test/spdm-responder-emu/src/spdm_device_example.rs +++ b/test/spdm-responder-emu/src/spdm_device_idekm_example.rs @@ -73,7 +73,7 @@ fn pci_ide_km_device_query( Ok(()) } -pub fn init_device_instance() { +pub fn init_device_idekm_instance() { pci_ide_km_rsp_key_prog::register(PciIdeKmDeviceKeyProg { pci_ide_km_device_key_prog_cb: pci_ide_km_device_key_prog, }); diff --git a/test/spdm-responder-emu/src/spdm_device_tdisp_example.rs b/test/spdm-responder-emu/src/spdm_device_tdisp_example.rs new file mode 100644 index 00000000..0a385d4a --- /dev/null +++ b/test/spdm-responder-emu/src/spdm_device_tdisp_example.rs @@ -0,0 +1,344 @@ +// Copyright (c) 2023 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 or MIT + +use spdmlib::error::{SpdmResult, SPDM_STATUS_INVALID_STATE_PEER}; +use tdisp::{ + config::{MAX_DEVICE_SPECIFIC_INFO_LEN, MAX_MMIO_RANGE_COUNT}, + pci_tdisp::{ + InterfaceId, InterfaceInfo, LockInterfaceFlag, MMIORangeAttribute, TdiReportStructure, + TdiState, TdispErrorCode, TdispMmioRange, TdispVersion, START_INTERFACE_NONCE_LEN, + }, + pci_tdisp_responder::{ + pci_tdisp_rsp_capabilities::{self, PciTdispDeviceCapabilities}, + pci_tdisp_rsp_error, + pci_tdisp_rsp_interface_report::{self, PciTdispDeviceInterfaceReport}, + pci_tdisp_rsp_interface_state::{self, PciTdispDeviceInterfaceState}, + pci_tdisp_rsp_lock_interface::{self, PciTdispDeviceLockInterface}, + pci_tdisp_rsp_start_interface::{self, PciTdispDeviceStartInterface}, + pci_tdisp_rsp_stop_interface::{self, PciTdispDeviceStopInterface}, + pci_tdisp_rsp_version::{self, PciTdispDeviceVersion}, + PciTdispDeviceError, MAX_TDISP_VERSION_COUNT, + }, +}; + +#[derive(Debug, Clone)] +pub struct DeviceContext { + pub bus: u8, + pub device: u8, + pub function: u8, + pub negotiated_version: Option, + pub interface_id: InterfaceId, + pub dsm_caps: u32, + pub dev_addr_width: u8, + pub num_req_this: u8, + pub num_req_all: u8, + pub flags: LockInterfaceFlag, + pub tdi_state: TdiState, + pub default_stream_id: u8, + pub mmio_reporting_offset: u64, + pub bind_p2p_address_mask: u64, + pub start_interface_nonce: [u8; START_INTERFACE_NONCE_LEN], +} + +#[allow(clippy::too_many_arguments)] +fn pci_tdisp_device_capabilities( + // IN + vendor_context: usize, + _tsm_caps: u32, + // OUT + negotiated_version: &mut TdispVersion, + interface_id: &mut InterfaceId, + dsm_caps: &mut u32, + req_msgs_supported: &mut [u8; 16], + lock_interface_flags_supported: &mut LockInterfaceFlag, + dev_addr_width: &mut u8, + num_req_this: &mut u8, + num_req_all: &mut u8, + tdisp_error_code: &mut Option, +) -> SpdmResult { + let device_context = vendor_context as *mut DeviceContext; + + let device_context = unsafe { &*device_context as &DeviceContext }; + + *negotiated_version = if let Some(negotiated_version) = device_context.negotiated_version { + negotiated_version + } else { + *tdisp_error_code = Some(TdispErrorCode::UNSPECIFIED); + return Ok(()); + }; + + *interface_id = device_context.interface_id; + *dsm_caps = device_context.dsm_caps; + req_msgs_supported[0] = 0x7f; + *lock_interface_flags_supported = device_context.flags; + *dev_addr_width = device_context.dev_addr_width; + *num_req_this = device_context.num_req_this; + *num_req_all = device_context.num_req_all; + + *tdisp_error_code = None; + Ok(()) +} + +fn pci_tdisp_device_error( + // IN + vendor_context: usize, + // OUT + negotiated_version: &mut TdispVersion, + interface_id: &mut InterfaceId, +) -> SpdmResult { + let device_context = vendor_context as *mut DeviceContext; + + let device_context = unsafe { &mut *device_context as &mut DeviceContext }; + + *negotiated_version = if let Some(negotiated_version) = device_context.negotiated_version { + negotiated_version + } else { + return Err(SPDM_STATUS_INVALID_STATE_PEER); + }; + + *interface_id = device_context.interface_id; + + device_context.tdi_state = TdiState::ERROR; + + Ok(()) +} + +fn pci_tdisp_device_interface_report( + // INT + vendor_context: usize, + // OUT + negotiated_version: &mut TdispVersion, + interface_id: &mut InterfaceId, + tdi_report: &mut TdiReportStructure, + tdisp_error_code: &mut Option, +) -> SpdmResult { + let device_context = vendor_context as *mut DeviceContext; + + let device_context = unsafe { &mut *device_context as &mut DeviceContext }; + + if device_context.tdi_state != TdiState::CONFIG_LOCKED + && device_context.tdi_state != TdiState::RUN + { + *tdisp_error_code = Some(TdispErrorCode::INVALID_INTERFACE_STATE); + } else { + *negotiated_version = if let Some(negotiated_version) = device_context.negotiated_version { + negotiated_version + } else { + return Err(SPDM_STATUS_INVALID_STATE_PEER); + }; + + *interface_id = device_context.interface_id; + *tdi_report = TdiReportStructure { + interface_info: InterfaceInfo::DEVICE_FIRMWARE_UPDATES_NOT_PERMITTED, + msi_x_message_control: 0u16, + lnr_control: 0u16, + tph_control: 0u32, + mmio_range_count: 1, + mmio_range: [TdispMmioRange { + first_page_with_offset_added: 0x12340000 + device_context.mmio_reporting_offset, + number_of_pages: 32, + range_attributes: MMIORangeAttribute::empty(), + }; MAX_MMIO_RANGE_COUNT], + device_specific_info_len: 6, + device_specific_info: [6u8; MAX_DEVICE_SPECIFIC_INFO_LEN], + }; + *tdisp_error_code = None; + } + + Ok(()) +} + +fn pci_tdisp_device_interface_state( + // IN + vendor_context: usize, + // OUT + negotiated_version: &mut TdispVersion, + interface_id: &mut InterfaceId, + tdi_state: &mut TdiState, + tdisp_error_code: &mut Option, +) -> SpdmResult { + let device_context = vendor_context as *mut DeviceContext; + + let device_context = unsafe { &mut *device_context as &mut DeviceContext }; + + *negotiated_version = if let Some(negotiated_version) = device_context.negotiated_version { + negotiated_version + } else { + *tdisp_error_code = Some(TdispErrorCode::UNSPECIFIED); + return Ok(()); + }; + + *interface_id = device_context.interface_id; + *tdi_state = device_context.tdi_state; + + *tdisp_error_code = None; + Ok(()) +} + +#[allow(clippy::too_many_arguments)] +fn pci_tdisp_device_lock_interface( + // IN + vendor_context: usize, + flags: &LockInterfaceFlag, + default_stream_id: u8, + mmio_reporting_offset: u64, + bind_p2p_address_mask: u64, + // OUT + negotiated_version: &mut TdispVersion, + interface_id: &mut InterfaceId, + start_interface_nonce: &mut [u8; START_INTERFACE_NONCE_LEN], + tdisp_error_code: &mut Option, +) -> SpdmResult { + let device_context = vendor_context as *mut DeviceContext; + + let device_context = unsafe { &mut *device_context as &mut DeviceContext }; + + if device_context.tdi_state != TdiState::CONFIG_UNLOCKED { + *tdisp_error_code = Some(TdispErrorCode::INVALID_INTERFACE_STATE); + } else { + *tdisp_error_code = None; + *negotiated_version = if let Some(negotiated_version) = device_context.negotiated_version { + negotiated_version + } else { + *tdisp_error_code = Some(TdispErrorCode::UNSPECIFIED); + return Ok(()); + }; + *interface_id = device_context.interface_id; + + device_context.flags = *flags; + device_context.default_stream_id = default_stream_id; + device_context.mmio_reporting_offset = mmio_reporting_offset; + device_context.bind_p2p_address_mask = bind_p2p_address_mask; + + if spdmlib::crypto::rand::get_random(start_interface_nonce).is_err() { + *tdisp_error_code = Some(TdispErrorCode::INSUFFICIENT_ENTROPY); + return Ok(()); + } + + device_context + .start_interface_nonce + .copy_from_slice(start_interface_nonce); + + device_context.tdi_state = TdiState::CONFIG_LOCKED; + } + + Ok(()) +} + +fn pci_tdisp_device_start_interface( + //IN + vendor_context: usize, + start_interface_nonce: &[u8; START_INTERFACE_NONCE_LEN], + //OUT + negotiated_version: &mut TdispVersion, + interface_id: &mut InterfaceId, + tdisp_error_code: &mut Option, +) -> SpdmResult { + let device_context = vendor_context as *mut DeviceContext; + + let device_context = unsafe { &mut *device_context as &mut DeviceContext }; + + if device_context.tdi_state != TdiState::CONFIG_LOCKED { + *tdisp_error_code = Some(TdispErrorCode::INVALID_INTERFACE_STATE); + } else if start_interface_nonce != &device_context.start_interface_nonce { + *tdisp_error_code = Some(TdispErrorCode::INVALID_NONCE); + } else { + *tdisp_error_code = None; + *negotiated_version = if let Some(negotiated_version) = device_context.negotiated_version { + negotiated_version + } else { + return Err(SPDM_STATUS_INVALID_STATE_PEER); + }; + *interface_id = device_context.interface_id; + + device_context.tdi_state = TdiState::RUN; + } + + Ok(()) +} + +fn pci_tdisp_device_stop_interface( + // IN + vendor_context: usize, + // OUT + negotiated_version: &mut TdispVersion, + interface_id: &mut InterfaceId, + tdisp_error_code: &mut Option, +) -> SpdmResult { + let device_context = vendor_context as *mut DeviceContext; + + let device_context = unsafe { &mut *device_context as &mut DeviceContext }; + + if device_context.tdi_state != TdiState::RUN { + *tdisp_error_code = Some(TdispErrorCode::INVALID_INTERFACE_STATE); + return Ok(()); + } else { + *tdisp_error_code = None; + *negotiated_version = if let Some(negotiated_version) = device_context.negotiated_version { + negotiated_version + } else { + *tdisp_error_code = Some(TdispErrorCode::UNSPECIFIED); + return Ok(()); + }; + *interface_id = device_context.interface_id; + + device_context.tdi_state = TdiState::CONFIG_UNLOCKED; + } + + Ok(()) +} + +fn pci_tdisp_device_version( + // IN + vendor_context: usize, + // OUT + interface_id: &mut InterfaceId, + version_num_count: &mut u8, + version_num_entry: &mut [TdispVersion; MAX_TDISP_VERSION_COUNT], +) -> SpdmResult { + let device_context = vendor_context as *mut DeviceContext; + + let device_context = unsafe { &mut *device_context as &mut DeviceContext }; + + *interface_id = device_context.interface_id; + *version_num_count = 1; + version_num_entry[0] = TdispVersion { + major_version: 1, + minor_version: 0, + }; + + device_context.negotiated_version = Some(TdispVersion { + major_version: 1, + minor_version: 0, + }); + + Ok(()) +} + +pub fn init_device_tdisp_instance() { + pci_tdisp_rsp_capabilities::register(PciTdispDeviceCapabilities { + pci_tdisp_device_capabilities_cb: pci_tdisp_device_capabilities, + }); + pci_tdisp_rsp_error::register(PciTdispDeviceError { + pci_tdisp_device_error_cb: pci_tdisp_device_error, + }); + pci_tdisp_rsp_interface_report::register(PciTdispDeviceInterfaceReport { + pci_tdisp_device_interface_report_cb: pci_tdisp_device_interface_report, + }); + pci_tdisp_rsp_interface_state::register(PciTdispDeviceInterfaceState { + pci_tdisp_device_interface_state_cb: pci_tdisp_device_interface_state, + }); + pci_tdisp_rsp_lock_interface::register(PciTdispDeviceLockInterface { + pci_tdisp_device_lock_interface_cb: pci_tdisp_device_lock_interface, + }); + pci_tdisp_rsp_start_interface::register(PciTdispDeviceStartInterface { + pci_tdisp_device_start_interface_cb: pci_tdisp_device_start_interface, + }); + pci_tdisp_rsp_stop_interface::register(PciTdispDeviceStopInterface { + pci_tdisp_device_stop_interface_cb: pci_tdisp_device_stop_interface, + }); + pci_tdisp_rsp_version::register(PciTdispDeviceVersion { + pci_tdisp_device_version_cb: pci_tdisp_device_version, + }); +}