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 109 110
use core::fmt;
/// A revision of the UEFI specification.
///
/// The major revision number is incremented on major, API-incompatible changes.
///
/// The minor revision number is incremented on minor changes,
/// it is stored as a two-digit binary-coded decimal.
///
/// # Display format
///
/// For major revision 2 and later, if the lower minor digit is zero,
/// the revision is formatted as "major.minor-upper". Otherwise it's
/// formatted as "major.minor-upper.minor-lower". This format is
/// described in the "EFI System Table" section of the UEFI
/// Specification.
///
/// Prior to major version 2, the revision is always formatted as
/// "major.minor", with minor left-padded with zero if minor-upper is
/// zero.
///
/// Examples:
///
/// ```
/// # use uefi_raw::table::Revision;
/// assert_eq!(Revision::EFI_1_02.to_string(), "1.02");
/// assert_eq!(Revision::EFI_1_10.to_string(), "1.10");
/// assert_eq!(Revision::EFI_2_00.to_string(), "2.0");
/// assert_eq!(Revision::EFI_2_30.to_string(), "2.3");
/// assert_eq!(Revision::EFI_2_31.to_string(), "2.3.1");
/// assert_eq!(Revision::EFI_2_100.to_string(), "2.10");
/// ```
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct Revision(pub u32);
// Allow missing docs, there's nothing useful to document about these
// constants.
#[allow(missing_docs)]
impl Revision {
pub const EFI_1_02: Self = Self::new(1, 2);
pub const EFI_1_10: Self = Self::new(1, 10);
pub const EFI_2_00: Self = Self::new(2, 00);
pub const EFI_2_10: Self = Self::new(2, 10);
pub const EFI_2_20: Self = Self::new(2, 20);
pub const EFI_2_30: Self = Self::new(2, 30);
pub const EFI_2_31: Self = Self::new(2, 31);
pub const EFI_2_40: Self = Self::new(2, 40);
pub const EFI_2_50: Self = Self::new(2, 50);
pub const EFI_2_60: Self = Self::new(2, 60);
pub const EFI_2_70: Self = Self::new(2, 70);
pub const EFI_2_80: Self = Self::new(2, 80);
pub const EFI_2_90: Self = Self::new(2, 90);
pub const EFI_2_100: Self = Self::new(2, 100);
}
impl Revision {
/// Creates a new revision.
#[must_use]
pub const fn new(major: u16, minor: u16) -> Self {
let major = major as u32;
let minor = minor as u32;
let value = (major << 16) | minor;
Self(value)
}
/// Returns the major revision.
#[must_use]
pub const fn major(self) -> u16 {
(self.0 >> 16) as u16
}
/// Returns the minor revision.
#[must_use]
pub const fn minor(self) -> u16 {
self.0 as u16
}
}
impl fmt::Display for Revision {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let (major, minor) = (self.major(), self.minor());
if major < 2 {
write!(f, "{major}.{minor:02}")
} else {
let (minor, patch) = (minor / 10, minor % 10);
if patch == 0 {
write!(f, "{major}.{minor}")
} else {
write!(f, "{major}.{minor}.{patch}")
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_revision() {
let rev = Revision::EFI_2_31;
assert_eq!(rev.major(), 2);
assert_eq!(rev.minor(), 31);
assert_eq!(rev.0, 0x0002_001f);
assert!(Revision::EFI_1_10 < Revision::EFI_2_00);
}
}