Skip to main content

uefi_raw/protocol/
nvme.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3use super::device_path::DevicePathProtocol;
4use crate::{Status, newtype_enum};
5use core::ffi::c_void;
6use uguid::{Guid, guid};
7
8bitflags::bitflags! {
9    /// In an NVMe command, the `flags` field specifies which cdw (command specific word)
10    /// contains a value.
11    #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
12    #[repr(transparent)]
13    pub struct NvmExpressCommandCdwValidity: u8 {
14        const CDW_2  = 0x01;
15        const CDW_3  = 0x02;
16        const CDW_10 = 0x04;
17        const CDW_11 = 0x08;
18        const CDW_12 = 0x10;
19        const CDW_13 = 0x20;
20        const CDW_14 = 0x40;
21        const CDW_15 = 0x80;
22    }
23
24    /// Represents the `EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_*` defines from the UEFI specification.
25    ///
26    /// # UEFI Specification Description
27    /// Tells if the interface is for physical NVM Express controllers or logical NVM Express controllers.
28    ///
29    /// Drivers for non-RAID NVM Express controllers will set both the `PHYSICAL` and the `LOGICAL` bit.
30    ///
31    /// Drivers for RAID controllers that allow access to the underlying physical controllers will produces
32    /// two protocol instances. One where the `LOGICAL` bit is set (representing the logical RAID volume),
33    /// and one where the `PHYSICAL` bit is set, which can be used to access the underlying NVMe controllers.
34    ///
35    /// Drivers for RAID controllers that do not allow access of the underlying NVMe controllers will only
36    /// produce one protocol instance for the logical RAID volume with the `LOGICAL` bit set.
37    #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
38    #[repr(transparent)]
39    pub struct NvmExpressPassThruAttributes: u32 {
40        /// If this bit is set, the interface is for directly addressable namespaces.
41        const PHYSICAL = 0x0001;
42
43        /// If this bit is set, the interface is for a single logical namespace comprising multiple namespaces.
44        const LOGICAL = 0x0002;
45
46        /// If this bit is set, the interface supports both blocking and non-blocking I/O.
47        /// - All interfaces must support blocking I/O, but this bit indicates that non-blocking I/O is also supported.
48        const NONBLOCKIO = 0x0004;
49
50        /// If this bit is set, the interface supports the NVM Express command set.
51        const CMD_SET_NVM = 0x0008;
52    }
53}
54
55#[derive(Clone, Debug)]
56#[repr(C)]
57pub struct NvmExpressPassThruMode {
58    pub attributes: NvmExpressPassThruAttributes,
59    pub io_align: u32,
60    pub nvme_version: u32,
61}
62
63/// This structure maps to the NVM Express specification Submission Queue Entry
64#[derive(Debug, Default)]
65#[repr(C)]
66pub struct NvmExpressCommand {
67    pub cdw0: u32,
68    pub flags: u8,
69    pub nsid: u32,
70    pub cdw2: u32,
71    pub cdw3: u32,
72    pub cdw10: u32,
73    pub cdw11: u32,
74    pub cdw12: u32,
75    pub cdw13: u32,
76    pub cdw14: u32,
77    pub cdw15: u32,
78}
79
80newtype_enum! {
81    /// Type of queues an NVMe command can be placed into
82    /// (Which queue a command should be placed into depends on the command)
83    #[derive(Default)]
84    pub enum NvmExpressQueueType: u8  => {
85        /// Admin Submission Queue
86        ADMIN = 0,
87        /// 1) I/O Submission Queue
88        IO = 1,
89    }
90}
91
92/// This structure maps to the NVM Express specification Completion Queue Entry
93#[derive(Debug, Default)]
94#[repr(C)]
95pub struct NvmExpressCompletion {
96    pub dw0: u32,
97    pub dw1: u32,
98    pub dw2: u32,
99    pub dw3: u32,
100}
101
102#[derive(Debug)]
103#[repr(C)]
104pub struct NvmExpressPassThruCommandPacket {
105    pub command_timeout: u64,
106    pub transfer_buffer: *mut c_void,
107    pub transfer_length: u32,
108    pub meta_data_buffer: *mut c_void,
109    pub meta_data_length: u32,
110    pub queue_type: NvmExpressQueueType,
111    pub nvme_cmd: *const NvmExpressCommand,
112    pub nvme_completion: *mut NvmExpressCompletion,
113}
114
115#[derive(Debug)]
116#[repr(C)]
117pub struct NvmExpressPassThruProtocol {
118    pub mode: *const NvmExpressPassThruMode,
119    pub pass_thru: unsafe extern "efiapi" fn(
120        this: *mut Self,
121        namespace_id: u32,
122        packet: *mut NvmExpressPassThruCommandPacket,
123        event: *mut c_void,
124    ) -> Status,
125    pub get_next_namespace:
126        unsafe extern "efiapi" fn(this: *const Self, namespace_id: *mut u32) -> Status,
127    pub build_device_path: unsafe extern "efiapi" fn(
128        this: *const Self,
129        namespace_id: u32,
130        device_path: *mut *const DevicePathProtocol,
131    ) -> Status,
132    pub get_namespace: unsafe extern "efiapi" fn(
133        this: *const Self,
134        device_path: *const DevicePathProtocol,
135        namespace_id: *mut u32,
136    ) -> Status,
137}
138
139impl NvmExpressPassThruProtocol {
140    pub const GUID: Guid = guid!("52c78312-8edc-4233-98f2-1a1aa5e388a5");
141}