uefi/
guid.rs

1// SPDX-License-Identifier: MIT
2
3//! # Globally Unique Identifier
4//!
5//! GUIDs are Microsoft's variant of [UUIDs][wiki]. The first 3 groups are
6//! stored in the native endianness of the platform.
7//!
8//! ## References
9//!
10//! - [UEFI Specification, Version 2.10][UEFI Spec]: Appendix A - GUID and Time
11//!   Formats
12//! - [RFC 9562: Universally Unique IDentifiers (UUIDs)][rfc9562]
13//! - [Microsoft GUID structure][guiddef]
14//!
15//! [wiki]: https://en.wikipedia.org/wiki/Universally_unique_identifier
16//! [guiddef]: https://docs.microsoft.com/en-us/windows/win32/api/guiddef/ns-guiddef-guid
17//! [rfc9562]: https://www.rfc-editor.org/rfc/rfc9562.html
18//! [UEFI Spec]: https://uefi.org/sites/default/files/resources/UEFI_Spec_2_10_Aug29.pdf
19
20use core::fmt;
21
22#[macro_export]
23macro_rules! guid {
24    ($guid_str:literal) => {
25        $crate::guid::Guid::parse_str($guid_str)
26    };
27}
28
29/// String length of a GUID with hyphens.
30const HYPHENATED_LEN: usize = 36;
31
32#[deprecated(note = "use `Guid::NULL`")]
33pub const NULL_GUID: Guid = guid!("00000000-0000-0000-0000-000000000000");
34pub const MPS_TABLE_GUID: Guid = guid!("eb9d2d2f-2d88-11d3-9a16-0090273fc14d");
35pub const ACPI_TABLE_GUID: Guid = guid!("eb9d2d30-2d88-11d3-9a16-0090273fc14d");
36pub const ACPI_20_TABLE_GUID: Guid = guid!("8868e871-e4f1-11d3-bc22-0080c73c8881");
37pub const SMBIOS_TABLE_GUID: Guid = guid!("eb9d2d31-2d88-11d3-9a16-0090273fc14d");
38pub const SMBIOS3_TABLE_GUID: Guid = guid!("f2fd1544-9794-4a2c-992e-e5bbcf20e394");
39pub const SAL_SYSTEM_TABLE_GUID: Guid = guid!("eb9d2d32-2d88-11d3-9a16-0090273fc14d");
40pub const HCDP_TABLE_GUID: Guid = guid!("f951938d-620b-42ef-8279-a84b79617898");
41pub const UGA_IO_PROTOCOL_GUID: Guid = guid!("61a4d49e-6f68-4f1b-b922-a86eed0b07a2");
42#[deprecated(note = "use `TextOutput::GUID`")]
43pub const SIMPLE_TEXT_OUTPUT_GUID: Guid = guid!("387477c2-69c7-11d2-8e39-00a0c969723b");
44pub const GLOBAL_VARIABLE_GUID: Guid = guid!("8be4df61-93ca-11d2-aa0d-00e098032b8c");
45pub const UV_SYSTEM_TABLE_GUID: Guid = guid!("3b13a7d4-633e-11dd-93ec-da2556d89593");
46pub const LINUX_EFI_CRASH_GUID: Guid = guid!("cfc8fc79-be2e-4ddc-97f0-9f98bfe298a0");
47#[deprecated(note = "use `LoadedImage::GUID`")]
48pub const LOADED_IMAGE_PROTOCOL_GUID: Guid = guid!("5b1b31a1-9562-11d2-8e3f-00a0c969723b");
49pub const LOADED_IMAGE_DEVICE_PATH_GUID: Guid = guid!("bc62157e-3e33-4fec-9920-2d3b36d750df");
50#[deprecated(note = "use `GraphicsOutput::GUID`")]
51pub const GRAPHICS_OUTPUT_PROTOCOL_GUID: Guid = guid!("9042a9de-23dc-4a38-96fb-7aded080516a");
52pub const UGA_PROTOCOL_GUID: Guid = guid!("982c298b-f4fa-41cb-b838-77aa688fb839");
53pub const PCI_IO_PROTOCOL_GUID: Guid = guid!("4cf5b200-68b8-4ca5-9eec-b23e3f50029a");
54#[deprecated(note = "use `FileInfo::ID`")]
55pub const FILE_INFO_ID: Guid = guid!("09576e92-6d3f-11d2-8e39-00a0c969723b");
56pub const SYSTEM_RESOURCE_TABLE_GUID: Guid = guid!("b122a263-3661-4f68-9929-78f8b0d62180");
57#[deprecated(note = "use `BlockIo::GUID`")]
58pub const BLOCK_IO_GUID: Guid = guid!("964e5b21-6459-11d2-8e39-00a0c969723b");
59#[deprecated(note = "use `SimplFileSystem::GUID`")]
60pub const FILE_SYSTEM_GUID: Guid = guid!("964e5b22-6459-11d2-8e39-00a0c969723b");
61pub const LOAD_FILE_GUID: Guid = guid!("56ec3091-954c-11d2-8e3f-00a0c969723b");
62#[deprecated(note = "use `DevicePath::GUID`")]
63pub const DEVICE_PATH_GUID: Guid = guid!("09576e91-6d3f-11d2-8e39-00a0c969723b");
64pub const DEVICE_TREE_GUID: Guid = guid!("b1b621d5-f19c-41a5-830b-d9152c69aae0");
65pub const PROPERTIES_TABLE_GUID: Guid = guid!("880aaca3-4adc-4a04-9079-b747340825e5");
66pub const RNG_PROTOCOL_GUID: Guid = guid!("3152bca5-eade-433d-862e-c01cdc291f44");
67pub const RNG_ALGORITHM_RAW: Guid = guid!("e43176d7-b6e8-4827-b784-7ffdc4b68561");
68pub const MEMORY_ATTRIBUTES_TABLE_GUID: Guid = guid!("dcfa911d-26eb-469f-a220-38b7dc461220");
69pub const CONSOLE_OUT_DEVICE_GUID: Guid = guid!("d3b36f2c-d551-11d4-9a46-0090273fc14d");
70pub const SECTION_TIANO_COMPRESS_GUID: Guid = guid!("a31280ad-481e-41b6-95e8-127f4c984779");
71pub const SECTION_LZMA_COMPRESS_GUID: Guid = guid!("ee4e5898-3914-4259-9d6e-dc7bd79403cf");
72pub const DXE_SERVICES_TABLE_GUID: Guid = guid!("05ad34ba-6f02-4214-952e-4da0398e2bb9");
73pub const HOB_LIST_GUID: Guid = guid!("7739f24c-93d7-11d4-9a3a-0090273fc14d");
74pub const MEMORY_TYPE_INFORMATION_GUID: Guid = guid!("4c19049f-4137-4dd3-9c10-8b97a83ffdfa");
75pub const DEBUG_IMAGE_INFO_TABLE_GUID: Guid = guid!("49152e77-1ada-4764-b7a2-7afefed95e8b");
76#[deprecated(note = "use `Shell::GUID`")]
77pub const SHELL_GUID: Guid = guid!("6302d008-7f9b-4f30-87ac-60c9fef5da4e");
78#[deprecated(note = "use `ShellParameters::GUID`")]
79pub const SHELL_PARAMETERS_GUID: Guid = guid!("752f3136-4e16-4fdc-a22a-e5f46812f4ca");
80#[deprecated(note = "use `SimplePointer::GUID`")]
81pub const SIMPLE_POINTER_GUID: Guid = guid!("31878c87-0b75-11d5-9a4f-0090273fc14d");
82#[deprecated(note = "use `HiiDatabase::GUID`")]
83pub const HII_DATABASE_GUID: Guid = guid!("ef9fc172-a1b2-4693-b327-6d32fc416042");
84#[deprecated(note = "use `ComponentName::GUID`")]
85pub const COMPONENT_NAME2_GUID: Guid = guid!("6a7a5cff-e8d9-4f70-bada-75ab3025ce14");
86
87#[derive(Copy, Clone, Debug, Eq, PartialEq)]
88#[repr(C)]
89pub struct Guid(pub u32, pub u16, pub u16, pub [u8; 8]);
90
91#[deprecated(note = "use `Guid` directly")]
92#[derive(Copy, Clone, Debug, Eq, PartialEq)]
93pub enum GuidKind {
94    Null,
95    Mps,
96    Acpi,
97    Acpi2,
98    Smbios,
99    Smbios3,
100    SalSystem,
101    Hcdp,
102    UgaIo,
103    GlobalVariable,
104    SimpleTextOutput,
105    UvSystem,
106    LinuxEfiCrash,
107    LoadedImage,
108    GraphicsOutput,
109    Uga,
110    PciIo,
111    FileInfo,
112    SystemResource,
113    BlockIo,
114    FileSystem,
115    LoadFile,
116    DevicePath,
117    DeviceTree,
118    Properties,
119    Rng,
120    RngAlrorithm,
121    MemoryAttributes,
122    ConsoleOut,
123    SectionTianoCompress,
124    SectionLzmaCompress,
125    DxeServices,
126    HobList,
127    MemoryTypeInformation,
128    DebugImageInfo,
129    Shell,
130    ShellParameters,
131    SimplePointer,
132    HiiDatabase,
133    ComponentName2,
134    Unknown,
135}
136
137impl Guid {
138    /// A GUID that has all bits set to 0.
139    pub const NIL: Self = guid!("00000000-0000-0000-0000-000000000000");
140    /// An alias for [Guid::NIL].
141    pub const NULL: Self = Self::NIL;
142    /// A GUID that has all bits set to 1.
143    pub const MAX: Self = guid!("ffffffff-ffff-ffff-ffff-ffffffffffff");
144
145    /// Converts a string literal to a GUID.
146    ///
147    /// The string must be in the form "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX".
148    /// Hex digits may be either upper case or lower case.
149    ///
150    /// # Panics
151    ///
152    /// Panics if the string literal is not in the standard form or contains
153    /// a value that is not a hex digit.
154    pub const fn parse_str(literal: &str) -> Self {
155        if literal.len() != HYPHENATED_LEN {
156            panic!("invalid GUID length");
157        }
158
159        let bytes = literal.as_bytes();
160
161        // Check hyphens
162        if bytes[8] != b'-' || bytes[13] != b'-' || bytes[18] != b'-' || bytes[23] != b'-' {
163            panic!("invalid GUID format");
164        }
165
166        let mut raw = [0u8; 16];
167
168        let mut i = 0;
169        let mut j = 0;
170        while i < HYPHENATED_LEN {
171            if i == 8 || i == 13 || i == 18 || i == 23 {
172                // Already checked hyphens; skip
173                i += 1;
174            }
175
176            let hi = hex_to_u8(bytes[i]);
177            let lo = hex_to_u8(bytes[i + 1]);
178
179            let b = hi << 4 | lo;
180            raw[j] = b;
181
182            i += 2;
183            j += 1;
184        }
185
186        let d1 = u32::from_be_bytes([raw[0], raw[1], raw[2], raw[3]]);
187        let d2 = u16::from_be_bytes([raw[4], raw[5]]);
188        let d3 = u16::from_be_bytes([raw[6], raw[7]]);
189        let d4 = [
190            raw[8], raw[9], raw[10], raw[11], raw[12], raw[13], raw[14], raw[15],
191        ];
192
193        Self(d1, d2, d3, d4)
194    }
195
196    #[allow(deprecated)]
197    #[deprecated(note = "compare `Guid`s directly")]
198    pub fn kind(&self) -> GuidKind {
199        match *self {
200            NULL_GUID => GuidKind::Null,
201            MPS_TABLE_GUID => GuidKind::Mps,
202            ACPI_TABLE_GUID => GuidKind::Acpi,
203            ACPI_20_TABLE_GUID => GuidKind::Acpi2,
204            SMBIOS_TABLE_GUID => GuidKind::Smbios,
205            SMBIOS3_TABLE_GUID => GuidKind::Smbios3,
206            SAL_SYSTEM_TABLE_GUID => GuidKind::SalSystem,
207            HCDP_TABLE_GUID => GuidKind::Hcdp,
208            UGA_IO_PROTOCOL_GUID => GuidKind::UgaIo,
209            GLOBAL_VARIABLE_GUID => GuidKind::GlobalVariable,
210            SIMPLE_TEXT_OUTPUT_GUID => GuidKind::SimpleTextOutput,
211            UV_SYSTEM_TABLE_GUID => GuidKind::UvSystem,
212            LINUX_EFI_CRASH_GUID => GuidKind::LinuxEfiCrash,
213            LOADED_IMAGE_PROTOCOL_GUID => GuidKind::LoadedImage,
214            GRAPHICS_OUTPUT_PROTOCOL_GUID => GuidKind::GraphicsOutput,
215            UGA_PROTOCOL_GUID => GuidKind::Uga,
216            PCI_IO_PROTOCOL_GUID => GuidKind::PciIo,
217            FILE_INFO_ID => GuidKind::FileInfo,
218            SYSTEM_RESOURCE_TABLE_GUID => GuidKind::SystemResource,
219            BLOCK_IO_GUID => GuidKind::BlockIo,
220            FILE_SYSTEM_GUID => GuidKind::FileSystem,
221            LOAD_FILE_GUID => GuidKind::LoadFile,
222            DEVICE_PATH_GUID => GuidKind::DevicePath,
223            DEVICE_TREE_GUID => GuidKind::DeviceTree,
224            PROPERTIES_TABLE_GUID => GuidKind::Properties,
225            RNG_PROTOCOL_GUID => GuidKind::Rng,
226            RNG_ALGORITHM_RAW => GuidKind::RngAlrorithm,
227            MEMORY_ATTRIBUTES_TABLE_GUID => GuidKind::MemoryAttributes,
228            CONSOLE_OUT_DEVICE_GUID => GuidKind::ConsoleOut,
229            SECTION_TIANO_COMPRESS_GUID => GuidKind::SectionTianoCompress,
230            SECTION_LZMA_COMPRESS_GUID => GuidKind::SectionLzmaCompress,
231            DXE_SERVICES_TABLE_GUID => GuidKind::DxeServices,
232            HOB_LIST_GUID => GuidKind::HobList,
233            MEMORY_TYPE_INFORMATION_GUID => GuidKind::MemoryTypeInformation,
234            DEBUG_IMAGE_INFO_TABLE_GUID => GuidKind::DebugImageInfo,
235            SHELL_GUID => GuidKind::Shell,
236            SHELL_PARAMETERS_GUID => GuidKind::ShellParameters,
237            SIMPLE_POINTER_GUID => GuidKind::SimplePointer,
238            HII_DATABASE_GUID => GuidKind::HiiDatabase,
239            COMPONENT_NAME2_GUID => GuidKind::ComponentName2,
240            _ => GuidKind::Unknown,
241        }
242    }
243}
244
245/// Converts a hex character to its integer value.
246/// Panics on invalid values.
247#[doc(hidden)]
248const fn hex_to_u8(hex: u8) -> u8 {
249    match hex {
250        b'0'..=b'9' => hex - b'0',
251        b'A'..=b'F' => hex - b'A' + 10,
252        b'a'..=b'f' => hex - b'a' + 10,
253        _ => panic!("invalid hex value in GUID"),
254    }
255}
256
257impl fmt::Display for Guid {
258    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
259        // Per RFC 4122, hex digits are output as lower case characters.
260        write!(f, "{:x}", &self)
261    }
262}
263
264impl fmt::LowerHex for Guid {
265    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
266        write!(
267            f,
268            "{:08x}-{:04x}-{:04x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
269            // Group 1
270            self.0,
271            // Group 2
272            self.1,
273            // Group 3
274            self.2,
275            // Group 4
276            self.3[0],
277            self.3[1],
278            // Group 5
279            self.3[2],
280            self.3[3],
281            self.3[4],
282            self.3[5],
283            self.3[6],
284            self.3[7],
285        )
286    }
287}
288
289impl fmt::UpperHex for Guid {
290    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
291        write!(
292            f,
293            "{:08X}-{:04X}-{:04X}-{:02X}{:02X}-{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}",
294            // Group 1
295            self.0,
296            // Group 2
297            self.1,
298            // Group 3
299            self.2,
300            // Group 4
301            self.3[0],
302            self.3[1],
303            // Group 5
304            self.3[2],
305            self.3[3],
306            self.3[4],
307            self.3[5],
308            self.3[6],
309            self.3[7],
310        )
311    }
312}