xref: /DragonOS/kernel/src/driver/acpi/sysfs.rs (revision fbe6becd6dd3cd72643707e0088f20364ac1b166)
1 use acpi::sdt::SdtHeader;
2 use alloc::{
3     string::{String, ToString},
4     sync::Arc,
5     vec::Vec,
6 };
7 
8 use crate::{
9     driver::{
10         acpi::acpi_manager,
11         base::{kobject::KObject, kset::KSet},
12     },
13     filesystem::{
14         sysfs::{file::sysfs_emit_str, sysfs_instance, Attribute, BinAttribute, SysFSOpsSupport},
15         vfs::syscall::ModeType,
16     },
17     libs::rwlock::RwLock,
18     syscall::SystemError,
19 };
20 
21 use super::{acpi_kset, AcpiManager};
22 
23 static mut __HOTPLUG_KSET_INSTANCE: Option<Arc<KSet>> = None;
24 static mut __ACPI_TABLES_KSET_INSTANCE: Option<Arc<KSet>> = None;
25 static mut __ACPI_TABLES_DATA_KSET_INSTANCE: Option<Arc<KSet>> = None;
26 static mut __ACPI_TABLES_DYNAMIC_KSET_INSTANCE: Option<Arc<KSet>> = None;
27 static mut __ACPI_TABLE_ATTR_LIST: Option<RwLock<Vec<Arc<AttrAcpiTable>>>> = None;
28 
29 const ACPI_MAX_TABLE_INSTANCES: usize = 999;
30 
31 #[inline(always)]
32 #[allow(dead_code)]
33 pub fn hotplug_kset() -> Arc<KSet> {
34     unsafe { __HOTPLUG_KSET_INSTANCE.clone().unwrap() }
35 }
36 
37 #[inline(always)]
38 pub fn acpi_tables_kset() -> Arc<KSet> {
39     unsafe { __ACPI_TABLES_KSET_INSTANCE.clone().unwrap() }
40 }
41 
42 #[inline(always)]
43 #[allow(dead_code)]
44 pub fn acpi_tables_data_kset() -> Arc<KSet> {
45     unsafe { __ACPI_TABLES_DATA_KSET_INSTANCE.clone().unwrap() }
46 }
47 
48 #[inline(always)]
49 #[allow(dead_code)]
50 pub fn acpi_tables_dynamic_kset() -> Arc<KSet> {
51     unsafe { __ACPI_TABLES_DYNAMIC_KSET_INSTANCE.clone().unwrap() }
52 }
53 
54 #[inline(always)]
55 fn acpi_table_attr_list() -> &'static RwLock<Vec<Arc<AttrAcpiTable>>> {
56     unsafe {
57         return __ACPI_TABLE_ATTR_LIST.as_ref().unwrap();
58     }
59 }
60 
61 impl AcpiManager {
62     pub(super) fn acpi_sysfs_init(&self) -> Result<(), SystemError> {
63         unsafe {
64             __ACPI_TABLE_ATTR_LIST = Some(RwLock::new(Vec::new()));
65         }
66         self.acpi_tables_sysfs_init()?;
67 
68         let hotplug_kset = KSet::new("hotplug".to_string());
69         hotplug_kset.register(Some(acpi_kset()))?;
70 
71         unsafe {
72             __HOTPLUG_KSET_INSTANCE = Some(hotplug_kset.clone());
73         }
74 
75         let hotplug_kobj = hotplug_kset as Arc<dyn KObject>;
76         sysfs_instance().create_file(&hotplug_kobj, &AttrForceRemove)?;
77 
78         return Ok(());
79     }
80 
81     /// 在 sysfs 中创建 ACPI 表目录
82     ///
83     /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/sysfs.c?fi=acpi_sysfs_init#488
84     fn acpi_tables_sysfs_init(&self) -> Result<(), SystemError> {
85         // 创建 `/sys/firmware/acpi/tables` 目录
86         let acpi_tables_kset = KSet::new("tables".to_string());
87         acpi_tables_kset.register(Some(acpi_kset()))?;
88         unsafe {
89             __ACPI_TABLES_KSET_INSTANCE = Some(acpi_tables_kset.clone());
90         }
91 
92         // 创建 `/sys/firmware/acpi/tables/data` 目录
93         let acpi_tables_data_kset = KSet::new("data".to_string());
94         acpi_tables_data_kset.register(Some(acpi_tables_kset.clone()))?;
95         unsafe {
96             __ACPI_TABLES_DATA_KSET_INSTANCE = Some(acpi_tables_data_kset);
97         }
98 
99         // 创建 `/sys/firmware/acpi/tables/dynamic` 目录
100         let acpi_tables_dynamic_kset = KSet::new("dynamic".to_string());
101         acpi_tables_dynamic_kset.register(Some(acpi_tables_kset.clone()))?;
102         unsafe {
103             __ACPI_TABLES_DYNAMIC_KSET_INSTANCE = Some(acpi_tables_dynamic_kset);
104         }
105 
106         // todo: get acpi tables.
107         let tables = self.tables().unwrap();
108         let headers = tables.headers();
109         for header in headers {
110             kdebug!("ACPI header: {:?}", header);
111             let attr = AttrAcpiTable::new(&header)?;
112             acpi_table_attr_list().write().push(attr);
113             self.acpi_table_data_init(&header)?;
114         }
115 
116         return Ok(());
117     }
118 
119     /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/sysfs.c?fi=acpi_sysfs_init#469
120     fn acpi_table_data_init(&self, _header: &SdtHeader) -> Result<(), SystemError> {
121         // todo!("AcpiManager::acpi_table_data_init()")
122         return Ok(());
123     }
124 }
125 
126 #[derive(Debug)]
127 struct AttrForceRemove;
128 
129 impl Attribute for AttrForceRemove {
130     fn name(&self) -> &str {
131         "force_remove"
132     }
133 
134     fn mode(&self) -> ModeType {
135         return ModeType::from_bits_truncate(0o444);
136     }
137 
138     fn support(&self) -> SysFSOpsSupport {
139         return SysFSOpsSupport::SHOW;
140     }
141 
142     fn show(&self, _kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
143         return sysfs_emit_str(buf, "0\n");
144     }
145 }
146 
147 /// ACPI 表在 sysfs 中的属性
148 #[derive(Debug)]
149 struct AttrAcpiTable {
150     name: String,
151     filename: String,
152     instance: isize,
153     size: usize,
154 }
155 
156 impl AttrAcpiTable {
157     pub fn new(header: &SdtHeader) -> Result<Arc<Self>, SystemError> {
158         let mut r = Self {
159             name: header.signature.to_string(),
160             filename: "".to_string(),
161             instance: 0,
162             size: header.length as usize,
163         };
164 
165         for attr in acpi_table_attr_list().read().iter() {
166             if attr.name == r.name {
167                 r.instance = attr.instance;
168             }
169         }
170         // 将当前实例的序号加1
171         r.instance += 1;
172         if r.instance > ACPI_MAX_TABLE_INSTANCES as isize {
173             kwarn!("too many table instances. name: {}", r.name);
174             return Err(SystemError::ERANGE);
175         }
176 
177         let mut has_multiple_instances: bool = false;
178         let mut tmpcnt = 0;
179         for h in acpi_manager().tables().unwrap().headers() {
180             if h.signature == header.signature {
181                 tmpcnt += 1;
182                 if tmpcnt > 1 {
183                     has_multiple_instances = true;
184                     break;
185                 }
186             }
187         }
188 
189         if r.instance > 1 || (r.instance == 1 && has_multiple_instances) {
190             r.filename = format!("{}{}", r.name, r.instance);
191         } else {
192             r.filename = r.name.clone();
193         }
194 
195         let result = Arc::new(r);
196         sysfs_instance().create_bin_file(
197             &(acpi_tables_kset() as Arc<dyn KObject>),
198             &(result.clone() as Arc<dyn BinAttribute>),
199         )?;
200         return Ok(result);
201     }
202 }
203 
204 impl Attribute for AttrAcpiTable {
205     fn show(&self, _kobj: Arc<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> {
206         return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
207     }
208 
209     fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
210         return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
211     }
212 
213     fn name(&self) -> &str {
214         return &self.filename;
215     }
216 
217     fn mode(&self) -> ModeType {
218         return ModeType::from_bits_truncate(0o400);
219     }
220 
221     fn support(&self) -> SysFSOpsSupport {
222         return SysFSOpsSupport::empty();
223     }
224 }
225 
226 impl BinAttribute for AttrAcpiTable {
227     fn support_battr(&self) -> SysFSOpsSupport {
228         return SysFSOpsSupport::READ;
229     }
230     fn write(
231         &self,
232         _kobj: Arc<dyn KObject>,
233         _buf: &[u8],
234         _offset: usize,
235     ) -> Result<usize, SystemError> {
236         return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
237     }
238 
239     /// 展示 ACPI 表的内容
240     ///
241     /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/sysfs.c?fi=acpi_sysfs_init#320
242     fn read(
243         &self,
244         _kobj: Arc<dyn KObject>,
245         buf: &mut [u8],
246         offset: usize,
247     ) -> Result<usize, SystemError> {
248         macro_rules! copy_data {
249             ($table:expr) => {
250                 let from = unsafe {
251                     core::slice::from_raw_parts(
252                         $table.virtual_start().as_ptr() as *const u8,
253                         $table.region_length(),
254                     )
255                 };
256                 if offset >= from.len() {
257                     return Ok(0);
258                 }
259                 let mut count = buf.len();
260                 if count > from.len() - offset {
261                     count = from.len() - offset;
262                 }
263                 buf[0..count].copy_from_slice(&from[offset..offset + count]);
264                 return Ok(count);
265             };
266         }
267 
268         macro_rules! define_struct {
269             ($name:ident) => {
270                 #[repr(transparent)]
271                 #[allow(non_snake_case)]
272                 #[allow(non_camel_case_types)]
273                 struct $name {
274                     header: SdtHeader,
275                 }
276 
277                 unsafe impl acpi::AcpiTable for $name {
278                     const SIGNATURE: acpi::sdt::Signature = acpi::sdt::Signature::$name;
279                     fn header(&self) -> &acpi::sdt::SdtHeader {
280                         return &self.header;
281                     }
282                 }
283             };
284         }
285 
286         macro_rules! handle {
287             ($name: ident, $tables: expr) => {
288                 define_struct!($name);
289                 let table = $tables.find_entire_table::<$name>().map_err(|e| {
290                     kwarn!(
291                         "AttrAcpiTable::read(): failed to find table. name: {}, error: {:?}",
292                         self.name,
293                         e
294                     );
295                     SystemError::ENODEV
296                 })?;
297 
298                 copy_data!(table);
299             };
300         }
301 
302         let tables = acpi_manager().tables().unwrap();
303         match self.name.as_str() {
304             "RSDT" => {
305                 handle!(RSDT, tables);
306             }
307             "XSDT" => {
308                 handle!(XSDT, tables);
309             }
310             "FACP" => {
311                 handle!(FADT, tables);
312             }
313             "HPET" => {
314                 handle!(HPET, tables);
315             }
316             "APIC" => {
317                 handle!(MADT, tables);
318             }
319             "MCFG" => {
320                 handle!(MCFG, tables);
321             }
322             "SSDT" => {
323                 handle!(SSDT, tables);
324             }
325             "BERT" => {
326                 handle!(BERT, tables);
327             }
328             "BGRT" => {
329                 handle!(BGRT, tables);
330             }
331             "CPEP" => {
332                 handle!(CPEP, tables);
333             }
334             "DSDT" => {
335                 handle!(DSDT, tables);
336             }
337             "ECDT" => {
338                 handle!(ECDT, tables);
339             }
340             "EINJ" => {
341                 handle!(EINJ, tables);
342             }
343             "ERST" => {
344                 handle!(ERST, tables);
345             }
346             "FACS" => {
347                 handle!(FACS, tables);
348             }
349             "FPDT" => {
350                 handle!(FPDT, tables);
351             }
352             "GTDT" => {
353                 handle!(GTDT, tables);
354             }
355             "HEST" => {
356                 handle!(HEST, tables);
357             }
358             "MSCT" => {
359                 handle!(MSCT, tables);
360             }
361             "MPST" => {
362                 handle!(MPST, tables);
363             }
364             "NFIT" => {
365                 handle!(NFIT, tables);
366             }
367             "PCCT" => {
368                 handle!(PCCT, tables);
369             }
370             "PHAT" => {
371                 handle!(PHAT, tables);
372             }
373             "PMTT" => {
374                 handle!(PMTT, tables);
375             }
376             "PSDT" => {
377                 handle!(PSDT, tables);
378             }
379             "RASF" => {
380                 handle!(RASF, tables);
381             }
382             "SBST" => {
383                 handle!(SBST, tables);
384             }
385             "SDEV" => {
386                 handle!(SDEV, tables);
387             }
388             "SLIT" => {
389                 handle!(SLIT, tables);
390             }
391             "SRAT" => {
392                 handle!(SRAT, tables);
393             }
394             "AEST" => {
395                 handle!(AEST, tables);
396             }
397             "BDAT" => {
398                 handle!(BDAT, tables);
399             }
400             "CDIT" => {
401                 handle!(CDIT, tables);
402             }
403             "CEDT" => {
404                 handle!(CEDT, tables);
405             }
406             "CRAT" => {
407                 handle!(CRAT, tables);
408             }
409             "CSRT" => {
410                 handle!(CSRT, tables);
411             }
412             "DBGP" => {
413                 handle!(DBGP, tables);
414             }
415             "DBG2" => {
416                 handle!(DBG2, tables);
417             }
418             "DMAR" => {
419                 handle!(DMAR, tables);
420             }
421             "DRTM" => {
422                 handle!(DRTM, tables);
423             }
424             "ETDT" => {
425                 handle!(ETDT, tables);
426             }
427             "IBFT" => {
428                 handle!(IBFT, tables);
429             }
430             "IORT" => {
431                 handle!(IORT, tables);
432             }
433             "IVRS" => {
434                 handle!(IVRS, tables);
435             }
436             "LPIT" => {
437                 handle!(LPIT, tables);
438             }
439             "MCHI" => {
440                 handle!(MCHI, tables);
441             }
442             "MPAM" => {
443                 handle!(MPAM, tables);
444             }
445             "MSDM" => {
446                 handle!(MSDM, tables);
447             }
448             "PRMT" => {
449                 handle!(PRMT, tables);
450             }
451             "RGRT" => {
452                 handle!(RGRT, tables);
453             }
454             "SDEI" => {
455                 handle!(SDEI, tables);
456             }
457             "SLIC" => {
458                 handle!(SLIC, tables);
459             }
460             "SPCR" => {
461                 handle!(SPCR, tables);
462             }
463             "SPMI" => {
464                 handle!(SPMI, tables);
465             }
466             "STAO" => {
467                 handle!(STAO, tables);
468             }
469             "SVKL" => {
470                 handle!(SVKL, tables);
471             }
472             "TCPA" => {
473                 handle!(TCPA, tables);
474             }
475             "TPM2" => {
476                 handle!(TPM2, tables);
477             }
478             "UEFI" => {
479                 handle!(UEFI, tables);
480             }
481             "WAET" => {
482                 handle!(WAET, tables);
483             }
484             "WDAT" => {
485                 handle!(WDAT, tables);
486             }
487             "WDRT" => {
488                 handle!(WDRT, tables);
489             }
490             "WPBT" => {
491                 handle!(WPBT, tables);
492             }
493             "WSMT" => {
494                 handle!(WSMT, tables);
495             }
496             "XENV" => {
497                 handle!(XENV, tables);
498             }
499 
500             _ => {
501                 kerror!("AttrAcpiTable::read(): unknown table. name: {}", self.name);
502                 return Err(SystemError::ENODEV);
503             }
504         };
505     }
506 
507     fn size(&self) -> usize {
508         return self.size;
509     }
510 }
511