1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
use core::fmt; /// A globally unique identifier /// /// GUIDs are used by UEFI to identify protocols and other objects. They are /// mostly like variant 2 UUIDs as specified by RFC 4122, but differ from them /// in that the first 3 fields are little endian instead of big endian. /// /// The `Display` formatter prints GUIDs in the canonical format defined by /// RFC 4122, which is also used by UEFI. #[derive(Debug, Copy, Clone, Eq, PartialEq)] #[repr(C)] pub struct Guid { /// The low field of the timestamp. a: u32, /// The middle field of the timestamp. b: u16, /// The high field of the timestamp multiplexed with the version number. c: u16, /// Contains, in this order: /// - The high field of the clock sequence multiplexed with the variant. /// - The low field of the clock sequence. /// - The spatially unique node identifier. d: [u8; 8], } impl Guid { /// Creates a new GUID from its canonical representation // // FIXME: An unwieldy array of bytes must be used for the node ID until one // can assert that an u64 has its high 16-bits cleared in a const fn. // Once that is done, we can take an u64 to be even closer to the // canonical UUID/GUID format. // pub const fn from_values( time_low: u32, time_mid: u16, time_high_and_version: u16, clock_seq_and_variant: u16, node: [u8; 6], ) -> Self { Guid { a: time_low, b: time_mid, c: time_high_and_version, d: [ (clock_seq_and_variant / 0x100) as u8, (clock_seq_and_variant % 0x100) as u8, node[0], node[1], node[2], node[3], node[4], node[5], ], } } } impl fmt::Display for Guid { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let d = { let (low, high) = (u16::from(self.d[0]), u16::from(self.d[1])); (low << 8) | high }; // Extract and reverse byte order. let e = self.d[2..8].iter().enumerate().fold(0, |acc, (i, &elem)| { acc | { let shift = (5 - i) * 8; u64::from(elem) << shift } }); write!( fmt, "{:08x}-{:04x}-{:04x}-{:04x}-{:012x}", self.a, self.b, self.c, d, e ) } } /// Several entities in the UEFI specification can be referred to by their GUID, /// this trait is a building block to interface them in uefi-rs. /// /// You should never need to use the `Identify` trait directly, but instead go /// for more specific traits such as `Protocol` or `FileProtocolInfo`, which /// indicate in which circumstances an `Identify`-tagged type should be used. /// /// Implementing `Identify` is unsafe because attaching an incorrect GUID to a /// type can lead to type unsafety on both the Rust and UEFI side. /// /// You can derive `Identify` for a type using the `unsafe_guid` procedural /// macro, which is exported by this module. This macro mostly works like a /// custom derive, but also supports type aliases. It takes a GUID in canonical /// textual format as an argument, and is used in the following way: /// /// ``` /// #[unsafe_guid("12345678-9abc-def0-1234-56789abcdef0")] /// type Emptiness = (); /// ``` pub unsafe trait Identify { /// Unique protocol identifier. const GUID: Guid; } pub use uefi_macros::unsafe_guid;