|
@@ -23,6 +23,41 @@ use system_error::SystemError;
|
|
|
|
|
|
use super::{acpi_kset, AcpiManager};
|
|
|
|
|
|
+// 定义所有ACPI表结构体
|
|
|
+macro_rules! define_acpi_tables {
|
|
|
+ ($($name:ident),*) => {
|
|
|
+ $(
|
|
|
+ #[repr(transparent)]
|
|
|
+ #[allow(non_snake_case)]
|
|
|
+ #[allow(non_camel_case_types)]
|
|
|
+ struct $name {
|
|
|
+ header: SdtHeader,
|
|
|
+ }
|
|
|
+
|
|
|
+ unsafe impl acpi::AcpiTable for $name {
|
|
|
+ const SIGNATURE: acpi::sdt::Signature = acpi::sdt::Signature::$name;
|
|
|
+ fn header(&self) -> &acpi::sdt::SdtHeader {
|
|
|
+ return &self.header;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ )*
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+define_acpi_tables!(
|
|
|
+ RSDT, XSDT, FADT, HPET, MADT, MCFG, SSDT, BERT, BGRT, CPEP, DSDT, ECDT, EINJ, ERST, FACS, FPDT,
|
|
|
+ GTDT, HEST, MSCT, MPST, NFIT, PCCT, PHAT, PMTT, PSDT, RASF, SBST, SDEV, SLIT, SRAT, AEST, BDAT,
|
|
|
+ CDIT, CEDT, CRAT, CSRT, DBGP, DBG2, DMAR, DRTM, ETDT, IBFT, IORT, IVRS, LPIT, MCHI, MPAM, MSDM,
|
|
|
+ PRMT, RGRT, SDEI, SLIC, SPCR, SPMI, STAO, SVKL, TCPA, TPM2, UEFI, WAET, WDAT, WDRT, WPBT, WSMT,
|
|
|
+ XENV
|
|
|
+);
|
|
|
+
|
|
|
+macro_rules! handle_read_table {
|
|
|
+ ($name: ident, $name_str: expr, $tables: expr, $buf: expr, $offset: expr) => {{
|
|
|
+ AttrAcpiTable::do_binattr_read_table::<$name>($tables, $name_str, $buf, $offset)
|
|
|
+ }};
|
|
|
+}
|
|
|
+
|
|
|
static mut __HOTPLUG_KSET_INSTANCE: Option<Arc<KSet>> = None;
|
|
|
static mut __ACPI_TABLES_KSET_INSTANCE: Option<Arc<KSet>> = None;
|
|
|
static mut __ACPI_TABLES_DATA_KSET_INSTANCE: Option<Arc<KSet>> = None;
|
|
@@ -202,308 +237,319 @@ impl AttrAcpiTable {
|
|
|
)?;
|
|
|
return Ok(result);
|
|
|
}
|
|
|
-}
|
|
|
-
|
|
|
-impl Attribute for AttrAcpiTable {
|
|
|
- fn show(&self, _kobj: Arc<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> {
|
|
|
- return Err(SystemError::ENOSYS);
|
|
|
- }
|
|
|
-
|
|
|
- fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
|
|
|
- return Err(SystemError::ENOSYS);
|
|
|
- }
|
|
|
|
|
|
- fn name(&self) -> &str {
|
|
|
- return &self.filename;
|
|
|
- }
|
|
|
-
|
|
|
- fn mode(&self) -> ModeType {
|
|
|
- return ModeType::from_bits_truncate(0o400);
|
|
|
- }
|
|
|
-
|
|
|
- fn support(&self) -> SysFSOpsSupport {
|
|
|
- return SysFSOpsSupport::empty();
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl BinAttribute for AttrAcpiTable {
|
|
|
- fn support_battr(&self) -> SysFSOpsSupport {
|
|
|
- return SysFSOpsSupport::BATTR_READ;
|
|
|
- }
|
|
|
- fn write(
|
|
|
- &self,
|
|
|
- _kobj: Arc<dyn KObject>,
|
|
|
- _buf: &[u8],
|
|
|
- _offset: usize,
|
|
|
+ #[inline(never)]
|
|
|
+ fn do_binattr_read_table<T: acpi::AcpiTable>(
|
|
|
+ tables: &'static acpi::AcpiTables<crate::driver::acpi::AcpiHandlerImpl>,
|
|
|
+ name: &str,
|
|
|
+ buf: &mut [u8],
|
|
|
+ offset: usize,
|
|
|
) -> Result<usize, SystemError> {
|
|
|
- return Err(SystemError::ENOSYS);
|
|
|
+ let table = tables.find_entire_table::<T>().map_err(|e| {
|
|
|
+ warn!(
|
|
|
+ "AttrAcpiTable::read(): failed to find table. name: {}, error: {:?}",
|
|
|
+ name, e
|
|
|
+ );
|
|
|
+ SystemError::ENODEV
|
|
|
+ })?;
|
|
|
+
|
|
|
+ let from = unsafe {
|
|
|
+ core::slice::from_raw_parts(
|
|
|
+ table.virtual_start().as_ptr() as *const u8,
|
|
|
+ table.region_length(),
|
|
|
+ )
|
|
|
+ };
|
|
|
+ if offset >= from.len() {
|
|
|
+ return Ok(0);
|
|
|
+ }
|
|
|
+ let mut count = buf.len();
|
|
|
+ if count > from.len() - offset {
|
|
|
+ count = from.len() - offset;
|
|
|
+ }
|
|
|
+ buf[0..count].copy_from_slice(&from[offset..offset + count]);
|
|
|
+ return Ok(count);
|
|
|
}
|
|
|
|
|
|
- /// 展示 ACPI 表的内容
|
|
|
- ///
|
|
|
- /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/acpi/sysfs.c?fi=acpi_sysfs_init#320
|
|
|
- fn read(
|
|
|
+ #[inline(never)]
|
|
|
+ fn do_binattr_read_1(
|
|
|
&self,
|
|
|
- _kobj: Arc<dyn KObject>,
|
|
|
+ tables: &'static acpi::AcpiTables<crate::driver::acpi::AcpiHandlerImpl>,
|
|
|
+ name_str: &str,
|
|
|
buf: &mut [u8],
|
|
|
offset: usize,
|
|
|
) -> Result<usize, SystemError> {
|
|
|
- macro_rules! copy_data {
|
|
|
- ($table:expr) => {
|
|
|
- let from = unsafe {
|
|
|
- core::slice::from_raw_parts(
|
|
|
- $table.virtual_start().as_ptr() as *const u8,
|
|
|
- $table.region_length(),
|
|
|
- )
|
|
|
- };
|
|
|
- if offset >= from.len() {
|
|
|
- return Ok(0);
|
|
|
- }
|
|
|
- let mut count = buf.len();
|
|
|
- if count > from.len() - offset {
|
|
|
- count = from.len() - offset;
|
|
|
- }
|
|
|
- buf[0..count].copy_from_slice(&from[offset..offset + count]);
|
|
|
- return Ok(count);
|
|
|
- };
|
|
|
- }
|
|
|
-
|
|
|
- macro_rules! define_struct {
|
|
|
- ($name:ident) => {
|
|
|
- #[repr(transparent)]
|
|
|
- #[allow(non_snake_case)]
|
|
|
- #[allow(non_camel_case_types)]
|
|
|
- struct $name {
|
|
|
- header: SdtHeader,
|
|
|
- }
|
|
|
-
|
|
|
- unsafe impl acpi::AcpiTable for $name {
|
|
|
- const SIGNATURE: acpi::sdt::Signature = acpi::sdt::Signature::$name;
|
|
|
- fn header(&self) -> &acpi::sdt::SdtHeader {
|
|
|
- return &self.header;
|
|
|
- }
|
|
|
- }
|
|
|
- };
|
|
|
- }
|
|
|
-
|
|
|
- macro_rules! handle {
|
|
|
- ($name: ident, $tables: expr) => {
|
|
|
- define_struct!($name);
|
|
|
- let table = $tables.find_entire_table::<$name>().map_err(|e| {
|
|
|
- warn!(
|
|
|
- "AttrAcpiTable::read(): failed to find table. name: {}, error: {:?}",
|
|
|
- self.name, e
|
|
|
- );
|
|
|
- SystemError::ENODEV
|
|
|
- })?;
|
|
|
-
|
|
|
- copy_data!(table);
|
|
|
- };
|
|
|
- }
|
|
|
-
|
|
|
- let tables = acpi_manager().tables().unwrap();
|
|
|
- match self.name.as_str() {
|
|
|
+ match name_str {
|
|
|
"RSDT" => {
|
|
|
- handle!(RSDT, tables);
|
|
|
+ handle_read_table!(RSDT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"XSDT" => {
|
|
|
- handle!(XSDT, tables);
|
|
|
+ handle_read_table!(XSDT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"FACP" => {
|
|
|
- handle!(FADT, tables);
|
|
|
+ handle_read_table!(FADT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"HPET" => {
|
|
|
- handle!(HPET, tables);
|
|
|
+ handle_read_table!(HPET, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"APIC" => {
|
|
|
- handle!(MADT, tables);
|
|
|
+ handle_read_table!(MADT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"MCFG" => {
|
|
|
- handle!(MCFG, tables);
|
|
|
+ handle_read_table!(MCFG, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"SSDT" => {
|
|
|
- handle!(SSDT, tables);
|
|
|
+ handle_read_table!(SSDT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"BERT" => {
|
|
|
- handle!(BERT, tables);
|
|
|
+ handle_read_table!(BERT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"BGRT" => {
|
|
|
- handle!(BGRT, tables);
|
|
|
+ handle_read_table!(BGRT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"CPEP" => {
|
|
|
- handle!(CPEP, tables);
|
|
|
+ handle_read_table!(CPEP, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"DSDT" => {
|
|
|
- handle!(DSDT, tables);
|
|
|
+ handle_read_table!(DSDT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"ECDT" => {
|
|
|
- handle!(ECDT, tables);
|
|
|
+ handle_read_table!(ECDT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"EINJ" => {
|
|
|
- handle!(EINJ, tables);
|
|
|
+ handle_read_table!(EINJ, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"ERST" => {
|
|
|
- handle!(ERST, tables);
|
|
|
+ handle_read_table!(ERST, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"FACS" => {
|
|
|
- handle!(FACS, tables);
|
|
|
+ handle_read_table!(FACS, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"FPDT" => {
|
|
|
- handle!(FPDT, tables);
|
|
|
+ handle_read_table!(FPDT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"GTDT" => {
|
|
|
- handle!(GTDT, tables);
|
|
|
+ handle_read_table!(GTDT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"HEST" => {
|
|
|
- handle!(HEST, tables);
|
|
|
+ handle_read_table!(HEST, name_str, tables, buf, offset)
|
|
|
}
|
|
|
+
|
|
|
+ _ => Err(SystemError::ENODEV),
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[inline(never)]
|
|
|
+ fn do_binattr_read_2(
|
|
|
+ &self,
|
|
|
+ tables: &'static acpi::AcpiTables<crate::driver::acpi::AcpiHandlerImpl>,
|
|
|
+ name_str: &str,
|
|
|
+ buf: &mut [u8],
|
|
|
+ offset: usize,
|
|
|
+ ) -> Result<usize, SystemError> {
|
|
|
+ match name_str {
|
|
|
"MSCT" => {
|
|
|
- handle!(MSCT, tables);
|
|
|
+ handle_read_table!(MSCT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"MPST" => {
|
|
|
- handle!(MPST, tables);
|
|
|
+ handle_read_table!(MPST, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"NFIT" => {
|
|
|
- handle!(NFIT, tables);
|
|
|
+ handle_read_table!(NFIT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"PCCT" => {
|
|
|
- handle!(PCCT, tables);
|
|
|
+ handle_read_table!(PCCT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"PHAT" => {
|
|
|
- handle!(PHAT, tables);
|
|
|
+ handle_read_table!(PHAT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"PMTT" => {
|
|
|
- handle!(PMTT, tables);
|
|
|
+ handle_read_table!(PMTT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"PSDT" => {
|
|
|
- handle!(PSDT, tables);
|
|
|
+ handle_read_table!(PSDT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"RASF" => {
|
|
|
- handle!(RASF, tables);
|
|
|
+ handle_read_table!(RASF, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"SBST" => {
|
|
|
- handle!(SBST, tables);
|
|
|
+ handle_read_table!(SBST, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"SDEV" => {
|
|
|
- handle!(SDEV, tables);
|
|
|
+ handle_read_table!(SDEV, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"SLIT" => {
|
|
|
- handle!(SLIT, tables);
|
|
|
+ handle_read_table!(SLIT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"SRAT" => {
|
|
|
- handle!(SRAT, tables);
|
|
|
+ handle_read_table!(SRAT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"AEST" => {
|
|
|
- handle!(AEST, tables);
|
|
|
+ handle_read_table!(AEST, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"BDAT" => {
|
|
|
- handle!(BDAT, tables);
|
|
|
+ handle_read_table!(BDAT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"CDIT" => {
|
|
|
- handle!(CDIT, tables);
|
|
|
+ handle_read_table!(CDIT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"CEDT" => {
|
|
|
- handle!(CEDT, tables);
|
|
|
+ handle_read_table!(CEDT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"CRAT" => {
|
|
|
- handle!(CRAT, tables);
|
|
|
+ handle_read_table!(CRAT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"CSRT" => {
|
|
|
- handle!(CSRT, tables);
|
|
|
+ handle_read_table!(CSRT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"DBGP" => {
|
|
|
- handle!(DBGP, tables);
|
|
|
+ handle_read_table!(DBGP, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"DBG2" => {
|
|
|
- handle!(DBG2, tables);
|
|
|
+ handle_read_table!(DBG2, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"DMAR" => {
|
|
|
- handle!(DMAR, tables);
|
|
|
+ handle_read_table!(DMAR, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"DRTM" => {
|
|
|
- handle!(DRTM, tables);
|
|
|
+ handle_read_table!(DRTM, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"ETDT" => {
|
|
|
- handle!(ETDT, tables);
|
|
|
+ handle_read_table!(ETDT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"IBFT" => {
|
|
|
- handle!(IBFT, tables);
|
|
|
+ handle_read_table!(IBFT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"IORT" => {
|
|
|
- handle!(IORT, tables);
|
|
|
+ handle_read_table!(IORT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"IVRS" => {
|
|
|
- handle!(IVRS, tables);
|
|
|
+ handle_read_table!(IVRS, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"LPIT" => {
|
|
|
- handle!(LPIT, tables);
|
|
|
+ handle_read_table!(LPIT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"MCHI" => {
|
|
|
- handle!(MCHI, tables);
|
|
|
+ handle_read_table!(MCHI, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"MPAM" => {
|
|
|
- handle!(MPAM, tables);
|
|
|
+ handle_read_table!(MPAM, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"MSDM" => {
|
|
|
- handle!(MSDM, tables);
|
|
|
+ handle_read_table!(MSDM, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"PRMT" => {
|
|
|
- handle!(PRMT, tables);
|
|
|
+ handle_read_table!(PRMT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"RGRT" => {
|
|
|
- handle!(RGRT, tables);
|
|
|
+ handle_read_table!(RGRT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"SDEI" => {
|
|
|
- handle!(SDEI, tables);
|
|
|
+ handle_read_table!(SDEI, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"SLIC" => {
|
|
|
- handle!(SLIC, tables);
|
|
|
+ handle_read_table!(SLIC, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"SPCR" => {
|
|
|
- handle!(SPCR, tables);
|
|
|
+ handle_read_table!(SPCR, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"SPMI" => {
|
|
|
- handle!(SPMI, tables);
|
|
|
+ handle_read_table!(SPMI, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"STAO" => {
|
|
|
- handle!(STAO, tables);
|
|
|
+ handle_read_table!(STAO, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"SVKL" => {
|
|
|
- handle!(SVKL, tables);
|
|
|
+ handle_read_table!(SVKL, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"TCPA" => {
|
|
|
- handle!(TCPA, tables);
|
|
|
+ handle_read_table!(TCPA, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"TPM2" => {
|
|
|
- handle!(TPM2, tables);
|
|
|
+ handle_read_table!(TPM2, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"UEFI" => {
|
|
|
- handle!(UEFI, tables);
|
|
|
+ handle_read_table!(UEFI, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"WAET" => {
|
|
|
- handle!(WAET, tables);
|
|
|
+ handle_read_table!(WAET, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"WDAT" => {
|
|
|
- handle!(WDAT, tables);
|
|
|
+ handle_read_table!(WDAT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"WDRT" => {
|
|
|
- handle!(WDRT, tables);
|
|
|
+ handle_read_table!(WDRT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"WPBT" => {
|
|
|
- handle!(WPBT, tables);
|
|
|
+ handle_read_table!(WPBT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"WSMT" => {
|
|
|
- handle!(WSMT, tables);
|
|
|
+ handle_read_table!(WSMT, name_str, tables, buf, offset)
|
|
|
}
|
|
|
"XENV" => {
|
|
|
- handle!(XENV, tables);
|
|
|
+ handle_read_table!(XENV, name_str, tables, buf, offset)
|
|
|
}
|
|
|
+ _ => Err(SystemError::ENODEV),
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
- _ => {
|
|
|
- error!("AttrAcpiTable::read(): unknown table. name: {}", self.name);
|
|
|
- return Err(SystemError::ENODEV);
|
|
|
- }
|
|
|
- };
|
|
|
+impl Attribute for AttrAcpiTable {
|
|
|
+ fn show(&self, _kobj: Arc<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> {
|
|
|
+ return Err(SystemError::ENOSYS);
|
|
|
+ }
|
|
|
+
|
|
|
+ fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
|
|
|
+ return Err(SystemError::ENOSYS);
|
|
|
+ }
|
|
|
+
|
|
|
+ fn name(&self) -> &str {
|
|
|
+ return &self.filename;
|
|
|
+ }
|
|
|
+
|
|
|
+ fn mode(&self) -> ModeType {
|
|
|
+ return ModeType::from_bits_truncate(0o400);
|
|
|
+ }
|
|
|
+
|
|
|
+ fn support(&self) -> SysFSOpsSupport {
|
|
|
+ return SysFSOpsSupport::empty();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl BinAttribute for AttrAcpiTable {
|
|
|
+ fn support_battr(&self) -> SysFSOpsSupport {
|
|
|
+ return SysFSOpsSupport::BATTR_READ;
|
|
|
+ }
|
|
|
+ fn write(
|
|
|
+ &self,
|
|
|
+ _kobj: Arc<dyn KObject>,
|
|
|
+ _buf: &[u8],
|
|
|
+ _offset: usize,
|
|
|
+ ) -> Result<usize, SystemError> {
|
|
|
+ return Err(SystemError::ENOSYS);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 展示 ACPI 表的内容
|
|
|
+ ///
|
|
|
+ /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/acpi/sysfs.c?fi=acpi_sysfs_init#320
|
|
|
+ fn read(
|
|
|
+ &self,
|
|
|
+ _kobj: Arc<dyn KObject>,
|
|
|
+ buf: &mut [u8],
|
|
|
+ offset: usize,
|
|
|
+ ) -> Result<usize, SystemError> {
|
|
|
+ let tables = acpi_manager().tables().unwrap();
|
|
|
+ let name_str = self.name.as_str();
|
|
|
+ // 这里分多个函数进行处理,是为了减小栈内存的使用。
|
|
|
+ if let Ok(x) = self.do_binattr_read_1(tables, name_str, buf, offset) {
|
|
|
+ return Ok(x);
|
|
|
+ }
|
|
|
+
|
|
|
+ if let Ok(x) = self.do_binattr_read_2(tables, name_str, buf, offset) {
|
|
|
+ return Ok(x);
|
|
|
+ }
|
|
|
+
|
|
|
+ error!("AttrAcpiTable::read(): unknown table. name: {}", self.name);
|
|
|
+ return Err(SystemError::ENODEV);
|
|
|
}
|
|
|
|
|
|
fn size(&self) -> usize {
|