riscfetch_core/
hardware.rs1use crate::parsing::parse_vector_from_isa;
4use crate::types::HardwareIds;
5use std::fmt::Write;
6use std::fs;
7use sysinfo::System;
8
9#[must_use]
11pub fn get_isa_string() -> String {
12 if let Ok(content) = fs::read_to_string("/proc/cpuinfo") {
13 for line in content.lines() {
14 if line.starts_with("isa") {
15 if let Some(isa) = line.split(':').nth(1) {
16 return isa.trim().to_string();
17 }
18 }
19 }
20 }
21 "unknown".to_string()
22}
23
24#[must_use]
26pub fn get_hardware_ids() -> HardwareIds {
27 let mut ids = HardwareIds::default();
28
29 if let Ok(content) = fs::read_to_string("/proc/cpuinfo") {
30 for line in content.lines() {
31 if line.starts_with("mvendorid") {
32 if let Some(val) = line.split(':').nth(1) {
33 let val = val.trim();
34 if !val.is_empty() && val != "0x0" {
35 ids.mvendorid = val.to_string();
36 }
37 }
38 } else if line.starts_with("marchid") {
39 if let Some(val) = line.split(':').nth(1) {
40 let val = val.trim();
41 if !val.is_empty() && val != "0x0" {
42 ids.marchid = val.to_string();
43 }
44 }
45 } else if line.starts_with("mimpid") {
46 if let Some(val) = line.split(':').nth(1) {
47 let val = val.trim();
48 if !val.is_empty() && val != "0x0" {
49 ids.mimpid = val.to_string();
50 }
51 }
52 }
53 }
54 }
55
56 ids
57}
58
59#[must_use]
61pub fn get_hart_count() -> String {
62 if let Ok(content) = fs::read_to_string("/proc/cpuinfo") {
63 let count = content
64 .lines()
65 .filter(|line| line.starts_with("processor"))
66 .count();
67 if count > 0 {
68 return format!("{count} hart{}", if count > 1 { "s" } else { "" });
69 }
70 }
71
72 let mut sys = System::new();
73 sys.refresh_cpu_all();
74 let count = sys.cpus().len();
75 format!("{count} hart{}", if count > 1 { "s" } else { "" })
76}
77
78#[must_use]
80pub fn get_hart_count_num() -> usize {
81 if let Ok(content) = fs::read_to_string("/proc/cpuinfo") {
82 let count = content
83 .lines()
84 .filter(|line| line.starts_with("processor"))
85 .count();
86 if count > 0 {
87 return count;
88 }
89 }
90
91 let mut sys = System::new();
92 sys.refresh_cpu_all();
93 sys.cpus().len()
94}
95
96#[must_use]
98pub fn get_cache_info() -> String {
99 let mut cache_parts = Vec::new();
100
101 if let Ok(l1d_size) = fs::read_to_string("/sys/devices/system/cpu/cpu0/cache/index0/size") {
102 let size = l1d_size.trim();
103 if !size.is_empty() {
104 cache_parts.push(format!("L1D:{size}"));
105 }
106 }
107
108 if let Ok(l1i_size) = fs::read_to_string("/sys/devices/system/cpu/cpu0/cache/index1/size") {
109 let size = l1i_size.trim();
110 if !size.is_empty() {
111 cache_parts.push(format!("L1I:{size}"));
112 }
113 }
114
115 if let Ok(l2_size) = fs::read_to_string("/sys/devices/system/cpu/cpu0/cache/index2/size") {
116 let size = l2_size.trim();
117 if !size.is_empty() {
118 cache_parts.push(format!("L2:{size}"));
119 }
120 }
121
122 if let Ok(l3_size) = fs::read_to_string("/sys/devices/system/cpu/cpu0/cache/index3/size") {
123 let size = l3_size.trim();
124 if !size.is_empty() {
125 cache_parts.push(format!("L3:{size}"));
126 }
127 }
128
129 cache_parts.join(" ")
130}
131
132#[must_use]
134pub fn get_board_info() -> String {
135 if let Ok(content) = fs::read_to_string("/proc/device-tree/model") {
136 let model = content.trim_matches('\0').trim();
137 if !model.is_empty() {
138 return model.to_string();
139 }
140 }
141
142 if let Ok(content) = fs::read_to_string("/proc/device-tree/compatible") {
143 let parts: Vec<&str> = content.split('\0').collect();
144 if let Some(&first) = parts.first() {
145 if !first.is_empty() {
146 return first.to_string();
147 }
148 }
149 }
150
151 String::new()
152}
153
154#[must_use]
156pub fn get_vector_detail() -> String {
157 let isa = get_isa_string();
158 let mut result = parse_vector_from_isa(&isa).unwrap_or_default();
159
160 if !result.is_empty() {
162 if let Ok(vlen) = fs::read_to_string("/sys/devices/system/cpu/cpu0/riscv/vlen") {
163 let _ = write!(result, ", VLEN={}", vlen.trim());
164 }
165 }
166
167 result
168}