use num::{Num, NumCast};
use std::prelude::v1::*;
#[cfg(feature = "uefi")]
use core::prelude::rust_2021::derive;
#[cfg(feature = "uefi")]
use alloc::sync::Arc;
#[cfg(feature = "uefi")]
use spin::{Mutex, MutexGuard};
#[cfg(not(feature = "uefi"))]
use std::sync::{Arc, Mutex, MutexGuard};
use no_std_compat::time::Duration;
use crate::smbios;
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Platform {
Framework12IntelGen13,
IntelGen11,
IntelGen12,
IntelGen13,
IntelCoreUltra1,
Framework13Amd7080,
Framework13AmdAi300,
Framework16Amd7080,
Framework16AmdAi300,
FrameworkDesktopAmdAiMax300,
GenericFramework((u16, u16, u16), (u8, u8, u8)),
UnknownSystem,
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum PlatformFamily {
Framework12,
Framework13,
Framework16,
FrameworkDesktop,
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum CpuVendor {
Intel,
Amd,
}
impl Platform {
pub fn which_cpu_vendor(self) -> Option<CpuVendor> {
match self {
Platform::Framework12IntelGen13
| Platform::IntelGen11
| Platform::IntelGen12
| Platform::IntelGen13
| Platform::IntelCoreUltra1 => Some(CpuVendor::Intel),
Platform::Framework13Amd7080
| Platform::Framework13AmdAi300
| Platform::Framework16Amd7080
| Platform::Framework16AmdAi300
| Platform::FrameworkDesktopAmdAiMax300 => Some(CpuVendor::Amd),
Platform::GenericFramework(..) => None,
Platform::UnknownSystem => None,
}
}
pub fn which_family(self) -> Option<PlatformFamily> {
match self {
Platform::Framework12IntelGen13 => Some(PlatformFamily::Framework12),
Platform::IntelGen11
| Platform::IntelGen12
| Platform::IntelGen13
| Platform::IntelCoreUltra1
| Platform::Framework13Amd7080
| Platform::Framework13AmdAi300 => Some(PlatformFamily::Framework13),
Platform::Framework16Amd7080 => Some(PlatformFamily::Framework16),
Platform::Framework16AmdAi300 => Some(PlatformFamily::Framework16),
Platform::FrameworkDesktopAmdAiMax300 => Some(PlatformFamily::FrameworkDesktop),
Platform::GenericFramework(..) => None,
Platform::UnknownSystem => None,
}
}
}
#[derive(Debug)]
pub struct Config {
pub _verbose: bool,
pub platform: Platform,
}
impl Config {
pub fn set(platform: Platform) {
#[cfg(not(feature = "uefi"))]
let mut config = CONFIG.lock().unwrap();
#[cfg(feature = "uefi")]
let mut config = CONFIG.lock();
if (*config).is_none() {
*config = Some(Config {
_verbose: false,
platform,
});
}
}
pub fn is_set() -> bool {
#[cfg(not(feature = "uefi"))]
let config = CONFIG.lock().unwrap();
#[cfg(feature = "uefi")]
let config = CONFIG.lock();
(*config).is_some()
}
pub fn get() -> MutexGuard<'static, Option<Self>> {
trace!("Config::get() entry");
let unset = {
#[cfg(not(feature = "uefi"))]
let config = CONFIG.lock().unwrap();
#[cfg(feature = "uefi")]
let config = CONFIG.lock();
(*config).is_none()
};
let new_config = if unset {
smbios::get_platform().map(|platform| Config {
_verbose: false,
platform,
})
} else {
None
};
#[cfg(not(feature = "uefi"))]
let mut config = CONFIG.lock().unwrap();
#[cfg(feature = "uefi")]
let mut config = CONFIG.lock();
if new_config.is_some() {
trace!("Config::get() initializing");
*config = new_config;
}
assert!((*config).is_some());
config
}
}
lazy_static! {
static ref CONFIG: Arc<Mutex<Option<Config>>> = Arc::new(Mutex::new(None));
}
pub unsafe fn any_as_u8_slice<T: Sized>(p: &T) -> &[u8] {
let len = ::std::mem::size_of::<T>();
::std::slice::from_raw_parts((p as *const T) as *const u8, len)
}
#[cfg(feature = "rusb")]
pub unsafe fn any_as_mut_u8_slice<T: Sized>(p: &mut T) -> &mut [u8] {
let len = ::std::mem::size_of::<T>();
::std::slice::from_raw_parts_mut((p as *mut T) as *mut u8, len)
}
pub unsafe fn any_vec_as_u8_slice<T: Sized>(p: &[T]) -> &[u8] {
let len = ::std::mem::size_of_val(p);
::std::slice::from_raw_parts(p.as_ptr() as *const u8, len)
}
pub fn print_buffer(buffer: &[u8]) {
for byte in buffer {
print!("{:02x}", byte);
}
println!();
}
fn print_chunk(buffer: &[u8], newline: bool) {
for (i, byte) in buffer.iter().enumerate() {
if i % 2 == 0 {
print!(" ")
}
print!("{:02x}", byte);
}
if newline {
println!();
}
}
fn print_ascii_buffer(buffer: &[u8], newline: bool) {
for byte in buffer {
if *byte >= 32 && *byte <= 127 {
print!("{}", *byte as char);
} else {
print!(".")
}
}
if newline {
println!();
}
}
pub fn print_multiline_buffer(buffer: &[u8], offset: usize) {
let chunk_size = 16;
for (i, chunk) in buffer.chunks(chunk_size).enumerate() {
print!("{:08x}:", offset + i * chunk_size);
print_chunk(chunk, false);
if chunk.len() < 16 {
let byte_padding = 16 - chunk.len();
let space_padding = byte_padding / 2;
let padding = byte_padding * 2 + space_padding;
print!("{}", " ".repeat(padding));
}
print!(" ");
print_ascii_buffer(chunk, true);
}
}
pub fn find_sequence(haystack: &[u8], needle: &[u8]) -> Option<usize> {
haystack
.windows(needle.len())
.position(|window| window == needle)
}
pub fn assert_win_len<N: Num + std::fmt::Debug + Ord + NumCast + Copy>(left: N, right: N) {
#[cfg(windows)]
assert_eq!(left, right + NumCast::from(20).unwrap());
#[cfg(not(windows))]
assert_eq!(left, right);
}
pub fn format_duration(duration: &Duration) -> String {
let hours = duration.as_secs() / 3600;
let minutes = (duration.as_secs() % 3600) / 60;
let seconds = duration.as_secs() % 60;
format!("{:02}h {:02}m {:02}s", hours, minutes, seconds)
}