Skip to main content

max / everycycle

3.2 KB · 98 lines History Blame Raw
1 //! Run Vulkan enumeration on the current host and print the resulting
2 //! `BoxReportPayload` skeleton as pretty JSON.
3 //!
4 //! No measurements, no signing. The goal at this stage is to confirm
5 //! that the discrete-compute filter sees the right cards and skips
6 //! everything else, and that the host-identity reads return something
7 //! useful on the target platform.
8
9 use std::time::{SystemTime, UNIX_EPOCH};
10
11 use everycycle_appraise::enumerate::{EnumeratedDevice, enumerate};
12
13 const PROBE_SUITE: &str = env!("CARGO_PKG_VERSION");
14
15 fn main() {
16 let host = match enumerate() {
17 Ok(h) => h,
18 Err(e) => {
19 eprintln!("enumeration failed: {e}");
20 std::process::exit(1);
21 }
22 };
23
24 eprintln!("host: {}", host.host.hostname);
25 if let Some(dmi) = &host.host.dmi_string {
26 eprintln!("dmi: {dmi}");
27 }
28 eprintln!("cpu: {}", host.host.cpu_model);
29 eprintln!("devices: {}", host.devices.len());
30 for d in &host.devices {
31 print_device(d);
32 }
33 eprintln!();
34
35 let payload = host.into_box_payload(rough_rfc3339_now(), 0.0, PROBE_SUITE);
36 match serde_json::to_string_pretty(&payload) {
37 Ok(s) => println!("{s}"),
38 Err(e) => {
39 eprintln!("could not serialize box payload: {e}");
40 std::process::exit(1);
41 }
42 }
43 }
44
45 #[allow(clippy::cast_precision_loss)]
46 fn print_device(d: &EnumeratedDevice) {
47 eprintln!(
48 " - {} @ {} pci_ids={} driver={} vram={:.1} GiB",
49 d.device_name,
50 d.bus_address,
51 d.pci_ids,
52 d.driver_version,
53 d.physical_bytes as f64 / (1024.0 * 1024.0 * 1024.0),
54 );
55 }
56
57 /// A placeholder RFC 3339 timestamp using the system clock at second
58 /// resolution. Replaced by a real time source once a probe lands that
59 /// needs one.
60 #[allow(clippy::cast_possible_wrap)]
61 fn rough_rfc3339_now() -> String {
62 let Ok(d) = SystemTime::now().duration_since(UNIX_EPOCH) else {
63 return "1970-01-01T00:00:00Z".to_string();
64 };
65 let secs = d.as_secs() as i64;
66 let (y, mo, da, h, mi, s) = civil_from_unix(secs);
67 format!("{y:04}-{mo:02}-{da:02}T{h:02}:{mi:02}:{s:02}Z")
68 }
69
70 /// Trivial UTC unix-seconds to civil-date converter. Good enough for
71 /// timestamp recording; will be replaced by a real time crate when we
72 /// need timezone correctness for anything user-facing.
73 #[allow(
74 clippy::cast_possible_truncation,
75 clippy::cast_sign_loss,
76 clippy::many_single_char_names
77 )]
78 fn civil_from_unix(secs: i64) -> (i32, u32, u32, u32, u32, u32) {
79 // Howard Hinnant's date algorithm, public domain.
80 let z = secs.div_euclid(86_400);
81 let day_secs = secs.rem_euclid(86_400);
82 let h = (day_secs / 3600) as u32;
83 let mi = ((day_secs / 60) % 60) as u32;
84 let s = (day_secs % 60) as u32;
85
86 let z = z + 719_468;
87 let era = if z >= 0 { z } else { z - 146_096 } / 146_097;
88 let doe = (z - era * 146_097) as u32;
89 let yoe = (doe - doe / 1460 + doe / 36_524 - doe / 146_096) / 365;
90 let y = i64::from(yoe) + era * 400;
91 let doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
92 let mp = (5 * doy + 2) / 153;
93 let d = doy - (153 * mp + 2) / 5 + 1;
94 let m = if mp < 10 { mp + 3 } else { mp - 9 };
95 let y = y + i64::from(m <= 2);
96 (y as i32, m, d, h, mi, s)
97 }
98