pub const EID_BASE: usize = 0x10;
pub use fid::*;
pub const UNAVAILABLE_EXTENSION: usize = 0;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, Hash)]
#[repr(transparent)]
pub struct Version {
raw: usize,
}
impl Version {
#[inline]
pub const fn from_raw(raw: usize) -> Self {
Self { raw }
}
#[inline]
pub const fn major(self) -> usize {
(self.raw >> 24) & ((1 << 7) - 1)
}
#[inline]
pub const fn minor(self) -> usize {
self.raw & ((1 << 24) - 1)
}
}
impl core::fmt::Display for Version {
#[inline]
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}.{}", self.major(), self.minor())
}
}
impl core::cmp::PartialOrd for Version {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
self.major()
.partial_cmp(&other.major())
.map(|ordering| ordering.then_with(|| self.minor().cmp(&other.minor())))
}
}
mod fid {
pub const GET_SBI_SPEC_VERSION: usize = 0x0;
pub const GET_SBI_IMPL_ID: usize = 0x1;
pub const GET_SBI_IMPL_VERSION: usize = 0x2;
pub const PROBE_EXTENSION: usize = 0x3;
pub const GET_MVENDORID: usize = 0x4;
pub const GET_MARCHID: usize = 0x5;
pub const GET_MIMPID: usize = 0x6;
}
pub mod impl_id {
pub const BBL: usize = 0;
pub const OPEN_SBI: usize = 1;
pub const XVISOR: usize = 2;
pub const KVM: usize = 3;
pub const RUST_SBI: usize = 4;
pub const DIOSIX: usize = 5;
pub const COFFER: usize = 6;
pub const XEN: usize = 7;
pub const POLARFIRE_HSS: usize = 8;
pub const COREBOOT: usize = 9;
pub const OREBOOT: usize = 10;
}
#[cfg(test)]
mod tests {
use super::Version;
#[test]
fn version_parse() {
let v1_0 = Version::from_raw(0x100_0000);
assert_eq!(v1_0.major(), 1);
assert_eq!(v1_0.minor(), 0);
let v2_0 = Version::from_raw(0x200_0000);
assert_eq!(v2_0.major(), 2);
assert_eq!(v2_0.minor(), 0);
let v2_1 = Version::from_raw(0x200_0001);
assert_eq!(v2_1.major(), 2);
assert_eq!(v2_1.minor(), 1);
let v2_max = Version::from_raw(0x2ff_ffff);
assert_eq!(v2_max.major(), 2);
assert_eq!(v2_max.minor(), 16777215);
let vmax_3 = Version::from_raw(0x7f00_0003);
assert_eq!(vmax_3.major(), 127);
assert_eq!(vmax_3.minor(), 3);
let vmax_max = Version::from_raw(0x7fff_ffff);
assert_eq!(vmax_max.major(), 127);
assert_eq!(vmax_max.minor(), 16777215);
}
#[test]
fn version_display() {
extern crate alloc;
use alloc::string::ToString;
assert_eq!("0.0", &Version::from_raw(0).to_string());
assert_eq!("0.1", &Version::from_raw(0x1).to_string());
assert_eq!("1.0", &Version::from_raw(0x100_0000).to_string());
assert_eq!("1.1", &Version::from_raw(0x100_0001).to_string());
assert_eq!("2.0", &Version::from_raw(0x200_0000).to_string());
assert_eq!("127.0", &Version::from_raw(0x7f00_0000).to_string());
assert_eq!("2.16777215", &Version::from_raw(0x2ff_ffff).to_string());
assert_eq!("127.16777215", &Version::from_raw(0x7fff_ffff).to_string());
}
#[test]
fn version_ordering() {
use core::cmp::Ordering;
let v0_0 = Version::from_raw(0x0);
let v0_3 = Version::from_raw(0x3);
let v1_0 = Version::from_raw(0x100_0000);
let v2_0 = Version::from_raw(0x200_0000);
let v2_1 = Version::from_raw(0x200_0001);
let v2_max = Version::from_raw(0x2ff_ffff);
let vmax_3 = Version::from_raw(0x7f00_0003);
let vmax_max = Version::from_raw(0x7fff_ffff);
assert!(v0_3 != v0_0);
assert!(!(v0_3 == v0_0));
assert!(v0_0 == v0_0);
assert!(vmax_max == vmax_max);
assert!(v0_3 > v0_0);
assert!(v0_3 >= v0_0);
assert!(v0_0 < v0_3);
assert!(v0_0 <= v0_3);
assert!(v0_0 >= v0_0);
assert!(v0_0 <= v0_0);
assert!(v0_3 > v0_0);
assert!(v1_0 > v0_3);
assert!(v2_0 > v1_0);
assert!(v2_1 > v2_0);
assert!(v2_max > v2_1);
assert!(vmax_3 > v2_max);
assert!(vmax_max > vmax_3);
assert_eq!(Version::partial_cmp(&v1_0, &v0_0), Some(Ordering::Greater));
assert_eq!(Version::partial_cmp(&v0_0, &v1_0), Some(Ordering::Less));
assert_eq!(Version::partial_cmp(&v0_0, &v0_0), Some(Ordering::Equal));
assert_eq!(Version::max(v0_0, v0_0), v0_0);
assert_eq!(Version::max(v1_0, v0_0), v1_0);
assert_eq!(Version::max(v0_0, v1_0), v1_0);
assert_eq!(Version::min(v0_0, v0_0), v0_0);
assert_eq!(Version::min(v1_0, v0_0), v0_0);
assert_eq!(Version::min(v0_0, v1_0), v0_0);
assert_eq!(v0_0.clamp(v0_3, v2_0), v0_3);
assert_eq!(v0_3.clamp(v0_3, v2_0), v0_3);
assert_eq!(v1_0.clamp(v0_3, v2_0), v1_0);
assert_eq!(v2_0.clamp(v0_3, v2_0), v2_0);
assert_eq!(v2_1.clamp(v0_3, v2_0), v2_0);
}
}