|
@@ -9,10 +9,12 @@ pub const UNAVAILABLE_EXTENSION: usize = 0;
|
|
|
|
|
|
/// SBI specification version.
|
|
|
///
|
|
|
+/// In RISC-V SBI specification, the bit 31 must be 0 and is reserved for future expansion.
|
|
|
+///
|
|
|
/// Not to be confused with 'implementation version'.
|
|
|
///
|
|
|
/// Declared in §4.1.
|
|
|
-#[derive(Clone, Copy, Debug)]
|
|
|
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Ord)]
|
|
|
#[repr(transparent)]
|
|
|
pub struct Version {
|
|
|
raw: usize,
|
|
@@ -45,6 +47,15 @@ impl core::fmt::Display for Version {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+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())))
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/// Declared in §4.8
|
|
|
mod fid {
|
|
|
/// Function ID to get the current SBI specification version.
|
|
@@ -104,3 +115,100 @@ pub mod impl_id {
|
|
|
/// Oreboot.
|
|
|
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);
|
|
|
+ }
|
|
|
+}
|