Register with devfs to provide device files

This commit is contained in:
pjht 2024-08-25 11:13:11 -05:00
parent 1a888d63d5
commit b83ab5306e
Signed by: pjht
GPG Key ID: 7B5F6AFBEC7EE78E
5 changed files with 157 additions and 145 deletions

87
Cargo.lock generated
View File

@ -7,17 +7,16 @@ name = "ahci"
version = "0.1.0"
dependencies = [
"binread",
"bitfield",
"bitflags",
"derive_builder",
"dev_driver_rpc",
"devfs_rpc",
"file_rpc",
"humansize",
"itertools",
"libm",
"parking_lot",
"pci_rpc",
"register",
"rhexdump",
"syslog_rpc",
"uuid",
"volatile 0.6.1",
"x86_64",
]
@ -65,12 +64,6 @@ version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
[[package]]
name = "bitfield"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5acf59e2452f0c4b968b15ce4b9468f57b45f7733b919d68b19fcc39264bfb8"
[[package]]
name = "bitflags"
version = "2.6.0"
@ -95,6 +88,26 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15"
[[package]]
name = "const_format"
version = "0.2.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673"
dependencies = [
"const_format_proc_macros",
]
[[package]]
name = "const_format_proc_macros"
version = "0.2.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "critical-section"
version = "1.1.2"
@ -167,6 +180,24 @@ dependencies = [
"syn 2.0.72",
]
[[package]]
name = "dev_driver_rpc"
version = "0.1.0"
dependencies = [
"parking_lot",
"postcard",
"serde",
]
[[package]]
name = "devfs_rpc"
version = "0.1.0"
dependencies = [
"parking_lot",
"postcard",
"serde",
]
[[package]]
name = "either"
version = "1.13.0"
@ -179,6 +210,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced"
[[package]]
name = "file_rpc"
version = "0.1.0"
dependencies = [
"parking_lot",
"postcard",
"serde",
]
[[package]]
name = "fnv"
version = "1.0.7"
@ -292,11 +332,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8"
dependencies = [
"cobs",
"const_format",
"embedded-io",
"heapless",
"postcard-derive",
"serde",
]
[[package]]
name = "postcard-derive"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc4b01218787dd4420daf63875163a787a78294ad48a24e9f6fa8c6507759a79"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "proc-macro2"
version = "1.0.86"
@ -333,12 +386,6 @@ dependencies = [
"tock-registers",
]
[[package]]
name = "rhexdump"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a92cbe1a3dd221e3777fef339115d3b85e17a538668e03a0f3ae9c6a98351c7"
[[package]]
name = "rustc_version"
version = "0.4.0"
@ -462,10 +509,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "uuid"
version = "1.10.0"
name = "unicode-xid"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "volatile"

View File

@ -5,17 +5,16 @@ edition = "2021"
[dependencies]
binread = "2.2.0"
bitfield = "0.16.1"
bitflags = "2.6.0"
derive_builder = "0.20.0"
dev_driver_rpc = { version = "0.1.0", path = "../dev_driver_rpc" }
devfs_rpc = { version = "0.1.0", path = "../devfs/devfs_rpc" }
file_rpc = { version = "0.1.0", path = "../file_rpc" }
humansize = "2.1.3"
itertools = "0.13.0"
libm = "0.2.8"
parking_lot = "0.12.3"
pci_rpc = { version = "0.1.0", path = "../pci/pci_rpc" }
register = "1.0.2"
rhexdump = "0.2.0"
syslog_rpc = { version = "0.1.0", path = "../syslog/syslog_rpc" }
uuid = "1.10.0"
volatile = { version = "0.6.1", features = ["unstable"] }
x86_64 = "0.15.1"

View File

@ -11,6 +11,9 @@ pub struct Hba {
syslog_client: syslog_rpc::Client,
}
unsafe impl Sync for Hba {}
unsafe impl Send for Hba {}
#[derive(Clone, Copy, Debug)]
pub enum HBAInitError {
No64BitDma,

View File

@ -27,15 +27,62 @@ mod hba;
mod identify;
mod port;
use std::os::mikros::{address_space::ACTIVE_SPACE, syscalls};
use std::{
collections::HashMap,
os::mikros::{address_space::ACTIVE_SPACE, ipc, syscalls},
path::{Path, PathBuf},
sync::Arc,
};
use hba::Hba;
use itertools::Itertools;
use parking_lot::Mutex;
use port::DeviceEnum;
use uuid::Uuid;
use x86_64::structures::paging::PageTableFlags;
use std::fmt::Debug;
#[derive(Clone)]
struct AhciState {
hba: Arc<Mutex<Hba>>,
dev_port_map: Arc<HashMap<PathBuf, usize>>,
}
impl dev_driver_rpc::Server for AhciState {
fn open(&self, path: &Path) -> Result<u64, ()> {
Ok(*self.dev_port_map.get(path).ok_or(())? as u64)
}
}
impl file_rpc::Server for AhciState {
#[allow(clippy::significant_drop_tightening)]
fn read(&self, fd: u64, pos: u64, len: usize) -> Result<std::borrow::Cow<'_, [u8]>, ()> {
let hba = self.hba.lock();
let port = hba.ports().get(fd as usize).ok_or(())?;
let device = port.get_device().map_err(|_| ())?.ok_or(())?;
let DeviceEnum::Ata(device) = device else {
return Err(());
};
let mut buf = vec![0; len];
device.read(pos as usize, &mut buf).map_err(|_| ())?;
Ok(buf.into())
}
fn write(&self, _fd: u64, _pos: u64, _data: &[u8]) -> Result<(), ()> {
todo!()
}
fn close(&self, _fd: u64) {}
#[allow(clippy::significant_drop_tightening)]
fn size(&self, fd: u64) -> Option<u64> {
let hba = self.hba.lock();
let port = hba.ports().get(fd as usize)?;
let device = port.get_device().ok()??;
let DeviceEnum::Ata(device) = device else {
return None;
};
Some(device.capacity() as u64)
}
}
fn main() {
let syslog_pid = loop {
@ -44,10 +91,10 @@ fn main() {
}
};
let syslog_client = syslog_rpc::Client::new(syslog_pid);
let (bus_str, dev_str, func_str, pci_pid_str) = std::env::args()
let (bus_str, dev_str, func_str, pci_pid_str, dev_id_str) = std::env::args()
.skip(1)
.collect_tuple::<(_, _, _, _)>()
.expect("Usage: ahci <bus> <dev> <func> <PCI driver PID>");
.collect_tuple::<(_, _, _, _, _)>()
.expect("Usage: ahci <bus> <dev> <func> <PCI driver PID> <Device ID>");
let bus = bus_str
.parse::<u8>()
.unwrap_or_else(|_| panic!("{bus_str:?} is not a valid bus number"));
@ -60,6 +107,9 @@ fn main() {
let pci_pid = pci_pid_str
.parse::<u64>()
.unwrap_or_else(|_| panic!("{pci_pid_str:?} is not a valid PID"));
let dev_id = dev_id_str
.parse::<u64>()
.unwrap_or_else(|_| panic!("{dev_id_str:?} is not a valid device ID"));
syslog_client.send_text_message("ahci", format!("Started on PCI device with address: Bus # {bus}, device # {dev}, and function # {func}")).unwrap();
syslog_client
@ -83,7 +133,9 @@ fn main() {
let hba = unsafe { Hba::new(reg_base, syslog_client) }.unwrap();
for port in hba.ports() {
let mut dev_port_map = HashMap::new();
for (i, port) in hba.ports().iter().enumerate() {
let Ok(device) = port.get_device() else {
syslog_client
.send_text_message(
@ -116,6 +168,10 @@ fn main() {
),
)
.unwrap();
dev_port_map.insert(
Path::new(&format!("ahci{}d{}", dev_id, device.phys_no())).to_owned(),
i,
);
}
port::DeviceEnum::Atapi(device) => {
syslog_client
@ -139,123 +195,27 @@ fn main() {
}
}
let mut mbr = [0; 512];
let DeviceEnum::Ata(ata_dev) = hba.ports()[0].get_device().unwrap().unwrap() else {
panic!();
let state = AhciState {
hba: Arc::new(Mutex::new(hba)),
dev_port_map: Arc::new(dev_port_map.clone()),
};
ata_dev.read(0, &mut mbr).unwrap();
dev_driver_rpc::register_server(Box::new(state.clone()));
file_rpc::register_server(Box::new(state));
let mbr_entries = (0..4)
.map(|i| {
let entry_offset = 0x1BE + 0x10 * i;
let active = mbr[entry_offset] & 0x80 == 0x80;
let typ = mbr[entry_offset + 0x4];
let start = u32::from_le_bytes(
mbr[entry_offset + 0x8..entry_offset + 0xC]
.try_into()
.unwrap(),
);
let size = u32::from_le_bytes(
mbr[entry_offset + 0xC..entry_offset + 0x10]
.try_into()
.unwrap(),
);
let act_str = if active { ", active" } else { "" };
println!(
"MBR partition {i}: start {}, size {}, type {:#x}{}",
humansize::format_size(start * 512, humansize::BINARY),
humansize::format_size(size * 512, humansize::BINARY),
typ,
act_str
);
MbrEntry {
active,
typ,
start,
size,
}
})
.collect_vec();
if mbr_entries[0].typ == 0xEE {
println!("Disk has GPT, parsing");
let mut gpt_header = [0; 512];
ata_dev.read(512, &mut gpt_header).unwrap();
if &gpt_header[0..8] != b"EFI PART" {
println!("Invalid GPT signature!");
return;
}
let alt_header_lba = u64::from_le_bytes(gpt_header[32..40].try_into().unwrap()) as usize;
let first_lba = u64::from_le_bytes(gpt_header[40..48].try_into().unwrap()) as usize;
let last_lba = u64::from_le_bytes(gpt_header[48..56].try_into().unwrap()) as usize;
let disk_guid = Uuid::from_bytes_le(gpt_header[56..72].try_into().unwrap());
let part_table_start_lba =
u64::from_le_bytes(gpt_header[72..80].try_into().unwrap()) as usize;
let num_parts = u32::from_le_bytes(gpt_header[80..84].try_into().unwrap()) as usize;
let entry_len = u32::from_le_bytes(gpt_header[84..88].try_into().unwrap()) as usize;
println!("Disk identifier: {disk_guid}");
println!("First usable LBA: {first_lba}");
println!("Last usable LBA: {last_lba}");
println!("Alternative LBA: {alt_header_lba}");
println!("Partition entries starting LBA: {part_table_start_lba}");
println!("Allocated partition entries: {num_parts}");
let part_table_len = num_parts * entry_len;
let part_table_num_lbas = part_table_len.div_ceil(512);
let part_table_end_lba = part_table_start_lba + part_table_num_lbas - 1;
println!("Partition entries ending LBA: {part_table_end_lba}");
let mut gpt_part_table = vec![0; part_table_len.next_multiple_of(512)];
ata_dev
.read(part_table_start_lba * 512, &mut gpt_part_table)
.unwrap();
for i in 0..num_parts {
let entry_offset = i * entry_len;
let entry_data = &gpt_part_table[entry_offset..(entry_offset + entry_len)];
if entry_data[0..16] == [0; 16] {
continue;
}
let type_guid = Uuid::from_bytes_le(entry_data[0..16].try_into().unwrap());
let entry_guid = Uuid::from_bytes_le(entry_data[16..32].try_into().unwrap());
let start = u64::from_le_bytes(entry_data[32..40].try_into().unwrap());
let end = u64::from_le_bytes(entry_data[40..48].try_into().unwrap());
let len = end - start;
let name_u16s = &entry_data[56..]
.iter()
.tuples::<(_, _)>()
.map(|(&x, &y)| u16::from_le_bytes([x, y]))
.collect_vec();
let name = String::from_utf16(name_u16s).unwrap();
println!(
"{:X}: type {:X}, start {}, size {}, name {}",
entry_guid,
type_guid,
humansize::format_size(start * 512, humansize::BINARY),
humansize::format_size(len * 512, humansize::BINARY),
name
);
let devfs_pid;
loop {
if let Some(pid) = syscalls::try_get_registered(1) {
devfs_pid = pid;
break;
}
}
}
#[derive(Clone, Copy, Debug, Default)]
#[allow(unused)]
struct MbrEntry {
active: bool,
typ: u8,
start: u32,
size: u32,
for dev in dev_port_map.keys() {
devfs_rpc::Client::new(devfs_pid).register_dev(dev.to_str().unwrap()).unwrap();
}
loop {
ipc::process_messages();
}
}

View File

@ -24,6 +24,9 @@ pub struct AhciPort {
has_device: bool,
}
unsafe impl Sync for AhciPort {}
unsafe impl Send for AhciPort {}
#[derive(Copy, Clone, Debug)]
pub enum CommandIssueError {
PrdtTooBig,