diff --git a/src/drivers/acpi.rs b/src/drivers/acpi.rs index 482e8d7..e99bbab 100644 --- a/src/drivers/acpi.rs +++ b/src/drivers/acpi.rs @@ -1,4 +1,8 @@ -use crate::{log_error, log_info, log_ok}; +use crate::{ + libs::{lazy::Lazy, mutex::Mutex}, + log_error, log_info, log_ok, +}; +use alloc::{sync::Arc, vec::Vec}; use limine::RsdpRequest; static RSDP_REQUEST: RsdpRequest = RsdpRequest::new(0); @@ -10,14 +14,52 @@ struct Rsdp { oem_id: [u8; 6], revision: u8, rsdt_address: u32, +} - // Only on Revision > 0 +#[repr(C, packed)] +struct Xsdp { length: u32, xsdt_address: u64, extended_checksum: u8, reserved: [u8; 3], } +pub struct Acpi { + tables: Arc<[*const u8]>, + entries: usize, + v2: bool, +} + +impl Acpi { + fn has_signature(&self, table_index: usize, signature: &str) -> bool { + unsafe { + let sdt_header: &SdtHeader = &*(self.tables[table_index] as *const SdtHeader); + let st = core::str::from_utf8_unchecked(&sdt_header.signature); + st == signature + } + } + + pub fn list_tables(&self) { + unsafe { + for i in 0..self.entries { + let sdt_header: &SdtHeader = &*(self.tables[i] as *const SdtHeader); + let st = sdt_header.signature; + log_info!("entry {:02}: {:?}", i + 1, sdt_header); + } + } + } + + pub fn get_table(&self, signature: &str) -> Option<*const u8> { + for i in 0..self.entries { + if self.has_signature(i, signature) { + return Some(self.tables[i]); + } + } + + None + } +} + const RSDP_V1_LENGTH: usize = 20; const RSDP_V2_EXT_LENGTH: usize = core::mem::size_of::() - RSDP_V1_LENGTH; const RSDP_SIG: [u8; 8] = *b"RSD PTR "; @@ -28,21 +70,10 @@ impl Rsdp { return false; } - if core::str::from_utf8(&self.oem_id).is_err() { - return false; - } - - let length = if self.revision > 0 { - self.length as usize - } else { - RSDP_V1_LENGTH - }; - - let bytes = - unsafe { core::slice::from_raw_parts(self as *const Rsdp as *const u8, length) }; + let bytes = unsafe { core::slice::from_raw_parts(self as *const Rsdp as *const u8, 20) }; let sum = bytes.iter().fold(0u8, |sum, &byte| sum.wrapping_add(byte)); - if sum != 0 { + if sum & 0xFF != 0 { return false; } @@ -50,37 +81,130 @@ impl Rsdp { } } -pub fn init_acpi() { - let rsdp_response = RSDP_REQUEST.get_response().get(); +impl Xsdp { + pub fn is_valid(&self) -> bool { + let bytes = unsafe { core::slice::from_raw_parts(self as *const Xsdp as *const u8, 20) }; + let sum = bytes.iter().fold(0u8, |sum, &byte| sum.wrapping_add(byte)); - if rsdp_response.is_none() { - log_error!("Failed to initialize ACPI: RSDP not found!"); - return; + if sum & 0xFF != 0 { + return false; + } + + return true; } - - let rsdp_address = &rsdp_response.unwrap().address; - - let rsdp_table: &Rsdp = unsafe { &*(rsdp_address.as_ptr().unwrap() as *const Rsdp) }; - - if !rsdp_table.is_valid() { - log_error!("Failed to initialize ACPI: RSDP was not valid!"); - return; - } - - log_info!("{}", rsdp_table.revision); - let mut facp: Option<&AcpiSdtHeader> = None; - - let rsdt_address = rsdp_table.rsdt_address; - facp = find_facp(rsdt_address as *const u32, rsdp_table.revision); - - if facp.is_some() { - log_ok!("Successfully found FADT"); - } - log_ok!("Successfully initialized ACPI"); } +static ACPI: Lazy> = Lazy::new(|| { + let acpi = resolve_acpi(); + + if acpi.is_err() { + panic!("Failed to resolve ACPI!"); + } + + Mutex::new(acpi.unwrap()) +}); + +pub fn init_acpi() { + let acpi_lock = ACPI.lock(); + let acpi = acpi_lock.read(); + + log_ok!("Successfully initialized ACPI with {} tables", acpi.entries); + + acpi.list_tables() +} + +#[derive(Debug)] +enum AcpiRootTable { + Rsdp(u32), + Xsdp(u64), +} + +impl AcpiRootTable { + pub fn get_from_bootloader() -> Result { + let rsdp_response = RSDP_REQUEST.get_response().get(); + + if rsdp_response.is_none() { + log_error!("Failed to initialize ACPI: RSDP not found!"); + return Err(()); + } + + let rsdp_address = &rsdp_response.unwrap().address; + + let rsdp_table: &Rsdp = unsafe { &*(rsdp_address.as_ptr().unwrap() as *const Rsdp) }; + + if !rsdp_table.is_valid() { + log_error!("Failed to initialize ACPI: RSDP was not valid!"); + return Err(()); + } + + if rsdp_table.revision == 2 { + let xsdp_table: &Xsdp = unsafe { &*(rsdp_address.as_ptr().unwrap() as *const Xsdp) }; + + if !xsdp_table.is_valid() { + log_error!("Failed to initalize ACPI: XSDP was not valid!"); + return Err(()); + } + + return Ok(AcpiRootTable::Xsdp(xsdp_table.xsdt_address)); + } + + return Ok(AcpiRootTable::Rsdp(rsdp_table.rsdt_address)); + } +} + +fn resolve_acpi() -> Result { + let root_table = AcpiRootTable::get_from_bootloader()?; + + crate::println!("{:?}", root_table); + + let (header_addr, ptr_size, ext_table) = match root_table { + AcpiRootTable::Rsdp(addr) => (addr as u64, core::mem::size_of::(), false), + AcpiRootTable::Xsdp(addr) => (addr, core::mem::size_of::(), true), + }; + + let root_header: &SdtHeader = unsafe { &*(header_addr as *const SdtHeader) }; + + unsafe { + if !ext_table { + if core::str::from_utf8_unchecked(&root_header.signature) != "RSDT" { + log_error!("Invalid root table header, expected RSDT."); + return Err(()); + } + } else { + if core::str::from_utf8_unchecked(&root_header.signature) != "XSDT" { + log_error!("Invalid root table header, expected XSDT."); + return Err(()); + } + } + } + + let mut entries = (root_header.length as usize - core::mem::size_of::()) / ptr_size; + if entries > 48 { + log_error!("Expected at most 48 ACPI tables, got {entries}!"); + entries = 48; + } + + let mut acpi_tables: Vec<*const u8> = Vec::with_capacity(entries); + + for i in 0..entries { + let address = + (header_addr + (core::mem::size_of::() + i * ptr_size) as u64) as *const u8; + + acpi_tables.push(address); + } + + crate::println!("{:?} {}", acpi_tables, entries); + + return Ok(Acpi { + tables: Arc::from(acpi_tables), + entries, + v2: ext_table, + }); +} + +#[derive(Clone, Copy, Debug)] #[repr(C)] -struct AcpiSdtHeader { +struct SdtHeader { signature: [u8; 4], length: u32, revision: u8, @@ -92,7 +216,7 @@ struct AcpiSdtHeader { creator_revision: u32, } -fn check_rsdt_checksum(table_header: *const AcpiSdtHeader) -> bool { +fn check_rsdt_checksum(table_header: *const SdtHeader) -> bool { let mut sum: u8 = 0; for i in 0..unsafe { (*table_header).length } { @@ -102,34 +226,35 @@ fn check_rsdt_checksum(table_header: *const AcpiSdtHeader) -> bool { return sum == 0; } -#[repr(C)] -struct Rsdt { - h: AcpiSdtHeader, - pointer_to_other_sdt: *const u32, +#[repr(C, packed)] +struct RSDT { + h: SdtHeader, + pointer_to_other_sdt: *const u8, } -fn find_facp(root_sdt: *const u32, revision: u8) -> Option<&'static AcpiSdtHeader> { - let rsdt: &mut Rsdt = unsafe { &mut *(root_sdt as *mut Rsdt) }; - rsdt.pointer_to_other_sdt = - [(rsdt.h.length - core::mem::size_of::() as u32) / 4].as_ptr(); +fn find_fadt(root_sdt: *const RSDT) -> Option { + // unsafe { + // let rsdt = root_sdt.as_ref()?; + // let entries = (rsdt.h.length - core::mem::size_of::() as u32) / 4; - let entry_bytes = if revision > 0 { 8 } else { 4 }; + // let pointer_to_other_sdt = - let entries = (rsdt.h.length - core::mem::size_of::() as u32) / entry_bytes; + // for i in 0..entries { + // crate::println!("{i}"); - for i in 0..entries { - crate::println!("{i}"); - let h = unsafe { rsdt.pointer_to_other_sdt.add(i as usize) as *const AcpiSdtHeader }; - let signature_bytes = unsafe { (*h).signature }; - let signature_str = core::str::from_utf8(&signature_bytes).unwrap_or(""); + // let h_ptr = rsdt.pointer_to_other_sdt[i as usize] as *const AcpiSdtHeader; + // let h = h_ptr.as_ref()?; + // let slice = core::slice::from_raw_parts(h.signature.as_ptr(), 4); - crate::println!("{signature_str} {signature_bytes:?} {:?}", b"FACP"); + // let signature = core::str::from_utf8(slice).ok()?; - // if signature_str == "FACP" { - // let facp_header = unsafe { &*(h as *const _) }; - // return None; - // } - } + // if signature == "FACP" { + // return Some(*h_ptr); + // } + // } - return None; + // // No FACP found + // return None; + // } + None } diff --git a/src/drivers/fs/initramfs/mod.rs b/src/drivers/fs/initramfs/mod.rs index 36183da..f205622 100755 --- a/src/drivers/fs/initramfs/mod.rs +++ b/src/drivers/fs/initramfs/mod.rs @@ -2,10 +2,13 @@ pub mod compressors; use core::fmt::{self, Debug}; -use alloc::{boxed::Box, sync::Arc, vec::Vec}; +use alloc::{boxed::Box, fmt::format, format, sync::Arc, vec::Vec}; use limine::ModuleRequest; -use crate::libs::{lazy::Lazy, math::ceil}; +use crate::{ + drivers::serial::write_serial, + libs::{lazy::Lazy, math::ceil}, +}; use super::vfs::{VfsDirectory, VfsFile, VfsFileSystem}; @@ -233,10 +236,9 @@ impl Squashfs<'_> { // } let mut buffer: Vec = Vec::new(); + let bytes = if metadata_block.0 { &table[2..] } else { table }; if table_is_compressed { - let bytes = if metadata_block.0 { &table[2..] } else { table }; - match self.superblock.compressor { SquashfsCompressionType::Gzip => { buffer.extend_from_slice(&compressors::gzip::uncompress_data(bytes).unwrap()); @@ -246,15 +248,7 @@ impl Squashfs<'_> { } } } else { - unsafe { - core::ptr::copy_nonoverlapping( - table.as_ptr().add(2), - buffer.as_mut_ptr(), - table_size as usize, - ); - - buffer.set_len(table_size as usize); - } + buffer.extend(bytes); } return buffer; @@ -500,15 +494,9 @@ impl<'a> VfsFile for BasicFileInode<'a> { ), ); - unsafe { - core::ptr::copy_nonoverlapping( - data_table.as_ptr().add(self.block_offset as usize), - block_data.as_mut_ptr(), - self.file_size as usize, - ); - - block_data.set_len(self.file_size as usize); - } + block_data.extend( + &data_table[self.block_offset as usize..(self.block_offset + self.file_size) as usize], + ); return Ok(Arc::from(block_data)); } diff --git a/src/main.rs b/src/main.rs index 7227fc6..bc46c62 100755 --- a/src/main.rs +++ b/src/main.rs @@ -17,7 +17,10 @@ use drivers::serial; use libs::util::hcf; use limine::KernelFileRequest; -use crate::mem::LabelBytes; +use crate::{ + drivers::fs::{initramfs::INITRAMFS, vfs::VfsFileSystem}, + mem::LabelBytes, +}; pub static KERNEL_REQUEST: KernelFileRequest = KernelFileRequest::new(0); @@ -37,6 +40,8 @@ pub extern "C" fn _start() -> ! { drivers::fs::vfs::init(); + // crate::println!("{:?}", INITRAMFS.open("/font.psf").unwrap().read()); + if let Some(kernel) = KERNEL_REQUEST.get_response().get() { crate::println!("{:X?}", kernel.kernel_file.get().unwrap().gpt_disk_uuid); }