-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathutil.rs
More file actions
279 lines (249 loc) · 8.54 KB
/
Copy pathutil.rs
File metadata and controls
279 lines (249 loc) · 8.54 KB
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
//! Miscellaneous utility functions to use across modules
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 {
/// Framework Laptop 12
Framework12IntelGen13,
/// Framework Laptop 13 - Intel 11th Gen, Codenamed TigerLake
IntelGen11,
/// Framework Laptop 13 - Intel 12th Gen, Codenamed AlderLake
IntelGen12,
/// Framework Laptop 13 - Intel 13th Gen, Codenamed RaptorLake
IntelGen13,
/// Framework Laptop 13 - Intel Core Ultra Series 1, Codenamed MeteorLake
IntelCoreUltra1,
/// Framework Laptop 13 - Intel Core Ultra Series 3, Codenamed PantherLake
IntelCoreUltra3,
/// Framework Laptop 13 - AMD Ryzen 7080 Series
Framework13Amd7080,
/// Framework Laptop 13 - AMD Ryzen AI 300 Series
Framework13AmdAi300,
/// Framework Laptop 16 - AMD Ryzen 7080 Series
Framework16Amd7080,
/// Framework Laptop 16 - AMD Ryzen AI 300 Series
Framework16AmdAi300,
/// Framework Desktop - AMD Ryzen AI Max 300
FrameworkDesktopAmdAiMax300,
/// Generic Framework device
/// pd_addrs, pd_ports
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
| Platform::IntelCoreUltra3 => 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::IntelCoreUltra3
| 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 {
// TODO: Actually set and read this
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 {
// get_platform will call Config::get() recursively,
// can't hold the lock when calling it
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;
}
// TODO: See if we can map the Option::unwrap before returning
assert!((*config).is_some());
config
}
}
lazy_static! {
static ref CONFIG: Arc<Mutex<Option<Config>>> = Arc::new(Mutex::new(None));
}
/// Convert any type to a u8 slice (Like a C byte buffer)
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)
}
/// Convert any type to a mut u8 slice (Like a C byte buffer)
#[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)
}
/// Convert an array/slice of any type to a u8 slice (Like a C byte buffer)
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)
}
/// Print a byte buffer as a series of hex bytes
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!();
}
}
// Example:
// Input: [0x00; 0x16]
// Output: ................
// Input: [a000 0036 626e 0300 c511 8035 0000 0000]
// Output: ...6bn.....5....
fn print_ascii_buffer(buffer: &[u8], newline: bool) {
for byte in buffer {
// If printable, print, else display a dot
if *byte >= 32 && *byte <= 127 {
print!("{}", *byte as char);
} else {
print!(".")
}
}
if newline {
println!();
}
}
/// Print a big byte buffer
///
/// Because it's long it'll be printed in several lines, each 16 bytes
///
/// Example
///
/// print_multiline_buffer(&[0xa0, 0x00, 0x00, 0x36, 0x62, 0x6e, 0x03, 0x00, 0xc5, 0x11, 0x80, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], 0x2000)
/// Output:
/// 00002000: a000 0036 626e 0300 c511 8035 0000 0000 ...6bn.....5....
/// 00002010: 0000 0000 0000 0000 0000 0000 0000 00 ................
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);
// Make sure ASCII section aligns, even if less than 16 byte chunks
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);
}
}
/// Find a sequence of bytes in a long slice of bytes
pub fn find_sequence(haystack: &[u8], needle: &[u8]) -> Option<usize> {
haystack
.windows(needle.len())
.position(|window| window == needle)
}
/// Assert length of an EC response from the windows driver
/// It's always 20 more than expected. TODO: Figure out why
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)
}