1 use core::fmt; 2 3 /// A revision of the UEFI specification. 4 /// 5 /// The major revision number is incremented on major, API-incompatible changes. 6 /// 7 /// The minor revision number is incremented on minor changes, 8 /// it is stored as a two-digit binary-coded decimal. 9 /// 10 /// # Display format 11 /// 12 /// For major revision 2 and later, if the lower minor digit is zero, 13 /// the revision is formatted as "major.minor-upper". Otherwise it's 14 /// formatted as "major.minor-upper.minor-lower". This format is 15 /// described in the "EFI System Table" section of the UEFI 16 /// Specification. 17 /// 18 /// Prior to major version 2, the revision is always formatted as 19 /// "major.minor", with minor left-padded with zero if minor-upper is 20 /// zero. 21 /// 22 /// Examples: 23 /// 24 /// ``` 25 /// # use uefi_raw::table::Revision; 26 /// assert_eq!(Revision::EFI_1_02.to_string(), "1.02"); 27 /// assert_eq!(Revision::EFI_1_10.to_string(), "1.10"); 28 /// assert_eq!(Revision::EFI_2_00.to_string(), "2.0"); 29 /// assert_eq!(Revision::EFI_2_30.to_string(), "2.3"); 30 /// assert_eq!(Revision::EFI_2_31.to_string(), "2.3.1"); 31 /// assert_eq!(Revision::EFI_2_100.to_string(), "2.10"); 32 /// ``` 33 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] 34 #[repr(transparent)] 35 pub struct Revision(pub u32); 36 37 // Allow missing docs, there's nothing useful to document about these 38 // constants. 39 #[allow(missing_docs)] 40 impl Revision { 41 pub const EFI_1_02: Self = Self::new(1, 2); 42 pub const EFI_1_10: Self = Self::new(1, 10); 43 pub const EFI_2_00: Self = Self::new(2, 00); 44 pub const EFI_2_10: Self = Self::new(2, 10); 45 pub const EFI_2_20: Self = Self::new(2, 20); 46 pub const EFI_2_30: Self = Self::new(2, 30); 47 pub const EFI_2_31: Self = Self::new(2, 31); 48 pub const EFI_2_40: Self = Self::new(2, 40); 49 pub const EFI_2_50: Self = Self::new(2, 50); 50 pub const EFI_2_60: Self = Self::new(2, 60); 51 pub const EFI_2_70: Self = Self::new(2, 70); 52 pub const EFI_2_80: Self = Self::new(2, 80); 53 pub const EFI_2_90: Self = Self::new(2, 90); 54 pub const EFI_2_100: Self = Self::new(2, 100); 55 } 56 57 impl Revision { 58 /// Creates a new revision. 59 #[must_use] new(major: u16, minor: u16) -> Self60 pub const fn new(major: u16, minor: u16) -> Self { 61 let major = major as u32; 62 let minor = minor as u32; 63 let value = (major << 16) | minor; 64 Self(value) 65 } 66 67 /// Returns the major revision. 68 #[must_use] major(self) -> u1669 pub const fn major(self) -> u16 { 70 (self.0 >> 16) as u16 71 } 72 73 /// Returns the minor revision. 74 #[must_use] minor(self) -> u1675 pub const fn minor(self) -> u16 { 76 self.0 as u16 77 } 78 } 79 80 impl fmt::Display for Revision { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result81 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 82 let (major, minor) = (self.major(), self.minor()); 83 84 if major < 2 { 85 write!(f, "{major}.{minor:02}") 86 } else { 87 let (minor, patch) = (minor / 10, minor % 10); 88 if patch == 0 { 89 write!(f, "{major}.{minor}") 90 } else { 91 write!(f, "{major}.{minor}.{patch}") 92 } 93 } 94 } 95 } 96 97 #[cfg(test)] 98 mod tests { 99 use super::*; 100 101 #[test] test_revision()102 fn test_revision() { 103 let rev = Revision::EFI_2_31; 104 assert_eq!(rev.major(), 2); 105 assert_eq!(rev.minor(), 31); 106 assert_eq!(rev.0, 0x0002_001f); 107 108 assert!(Revision::EFI_1_10 < Revision::EFI_2_00); 109 } 110 } 111