1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
pub mod fat;
use alloc::boxed::Box;
use alloc::vec::Vec;
use spin::Mutex;
use crate::LibUserResult;
use crate::interface::driver::FileSystemDriver;
use crate::interface::filesystem::FileSystemOperations;
use storage_device::block::Block;
use storage_device::block_device::*;
use storage_device::storage_device::StorageBlockDevice;
use storage_device::cached_block_device::CachedBlockDevice;
use sunrise_libuser::fs::{DiskId, FileSystemType, PartitionId};
use sunrise_libuser::ahci::*;
use sunrise_libuser::ahci::Block as AhciBlock;
use sunrise_libuser::error::{Error, FileSystemError};
use lazy_static::lazy_static;
use alloc::sync::{Arc, Weak};
use crate::interface::storage::{PartitionStorage, IStorage};
use hashbrown::HashMap;
type PartitionHashMap<T> = HashMap<DiskId, HashMap<PartitionId, Weak<Mutex<T>>>>;
type BoxedIStorage = Box<dyn IStorage<Error = Error>>;
pub struct DriverManager {
registry: Vec<Box<dyn FileSystemDriver>>,
drives: HashMap<DiskId, Arc<Mutex<BoxedIStorage>>>,
partitions: PartitionHashMap<Box<dyn FileSystemOperations>>,
ahci_interface: AhciInterfaceProxy
}
impl Default for DriverManager {
fn default() -> Self {
DriverManager {
registry: Vec::new(),
ahci_interface: AhciInterfaceProxy::raw_new().expect("Cannot create AHCI interface"),
drives: HashMap::new(),
partitions: HashMap::new()
}
}
}
impl DriverManager {
pub fn register_driver(&mut self, driver: Box<dyn FileSystemDriver>) {
self.registry.push(driver);
}
pub fn add_opened_drive(&mut self, disk_id: DiskId, drive: Arc<Mutex<BoxedIStorage>>) {
self.drives.insert(disk_id, drive);
self.partitions.insert(disk_id, HashMap::new());
}
pub fn init_drives(&mut self) -> LibUserResult<()> {
let disk_count = self.ahci_interface.discovered_disks_count()?;
if disk_count == 0 {
warn!("No drive have been found!");
}
for disk_id in 0..disk_count {
let ahci_disk = self.ahci_interface.get_disk(disk_id)?;
let device = Arc::new(Mutex::new(Box::new(StorageBlockDevice::new(CachedBlockDevice::new(AhciDiskStorage::new(ahci_disk), 0x100))) as BoxedIStorage));
self.add_opened_drive(disk_id, device);
}
Ok(())
}
pub fn open_disk_storage(&mut self, disk_id: DiskId) -> LibUserResult<Arc<Mutex<BoxedIStorage>>> {
self.drives.get(&disk_id).ok_or_else(|| FileSystemError::DiskNotFound.into()).map(|arc| arc.clone())
}
pub fn get_disks_count(&mut self) -> u32 {
self.drives.len() as u32
}
pub fn construct_filesystem_from_disk_partition(&mut self, disk_id: DiskId, partition_id: PartitionId, mut storage: PartitionStorage) -> LibUserResult<Arc<Mutex<Box<dyn FileSystemOperations>>>> {
let disk_hashmap_opt = self.partitions.get_mut(&disk_id);
if disk_hashmap_opt.is_none() {
return Err(FileSystemError::DiskNotFound.into())
}
let disk_hashmap = disk_hashmap_opt.unwrap();
let cached_res: LibUserResult<_> = disk_hashmap.get(&partition_id).ok_or_else(|| FileSystemError::InvalidPartition.into()).map(|arc| arc.upgrade());
if let Ok(Some(res)) = cached_res {
return Ok(res);
}
for driver in &self.registry {
if driver.probe(&mut storage).is_some() {
let res = Arc::new(Mutex::new(driver.construct(Box::new(storage))?));
disk_hashmap.insert(partition_id, Arc::downgrade(&res));
return Ok(res)
}
}
Err(FileSystemError::InvalidPartition.into())
}
pub fn format_disk_partition(&self, storage: PartitionStorage, filesytem_type: FileSystemType) -> LibUserResult<()> {
for driver in &self.registry {
if driver.is_supported(filesytem_type) {
return driver.format(Box::new(storage), filesytem_type)
}
}
Err(FileSystemError::InvalidPartition.into())
}
}
lazy_static! {
pub static ref DRIVER_MANAGER: Mutex<DriverManager> = Mutex::default();
}
#[derive(Debug)]
pub struct AhciDiskStorage {
inner: IDiskProxy
}
impl AhciDiskStorage {
pub fn new(device: IDiskProxy) -> Self {
AhciDiskStorage {
inner: device
}
}
}
impl BlockDevice for AhciDiskStorage {
type Block = Block;
type Error = Error;
fn read(&mut self, blocks: &mut [Self::Block], index: BlockIndex) -> Result<(), Error> {
self.inner.read_dma(index.0, unsafe {
core::slice::from_raw_parts_mut(blocks.as_mut_ptr() as *mut AhciBlock, blocks.len())
})
}
fn write(&mut self, blocks: &[Self::Block], index: BlockIndex) -> Result<(), Error> {
self.inner.write_dma(index.0, unsafe {
core::slice::from_raw_parts(blocks.as_ptr() as *const AhciBlock, blocks.len())
})
}
fn count(&mut self) -> Result<BlockCount, Error> {
self.inner.sector_count().map(|result| BlockCount(result))
}
}