axdriver_block/
ramdisk.rs1extern crate alloc;
4
5use alloc::alloc::{alloc_zeroed, dealloc};
6use core::{
7 alloc::Layout,
8 ops::{Deref, DerefMut},
9 ptr::NonNull,
10};
11
12use axdriver_base::{BaseDriverOps, DevError, DevResult, DeviceType};
13
14use crate::BlockDriverOps;
15
16const BLOCK_SIZE: usize = 512;
17
18pub enum RamDisk {
20 Heap(NonNull<[u8]>),
22 Static(&'static mut [u8]),
24}
25
26unsafe impl Send for RamDisk {}
27unsafe impl Sync for RamDisk {}
28
29impl Default for RamDisk {
30 fn default() -> Self {
32 Self::Heap(NonNull::<[u8; 0]>::dangling())
33 }
34}
35
36impl RamDisk {
37 pub fn new(size_hint: usize) -> Self {
42 let size = align_up(size_hint);
43 if size == 0 {
44 return Self::default();
45 }
46 let ptr = unsafe {
48 NonNull::new(alloc_zeroed(
49 Layout::from_size_align(size, BLOCK_SIZE).unwrap(),
50 ))
51 .unwrap()
52 };
53 Self::Heap(NonNull::slice_from_raw_parts(ptr, size))
54 }
55
56 pub fn from_static(buf: &'static mut [u8]) -> Self {
63 assert_eq!(buf.as_ptr().addr() & (BLOCK_SIZE - 1), 0);
64 assert!(buf.len().is_multiple_of(BLOCK_SIZE));
65 Self::Static(buf)
66 }
67
68 pub fn copy_from_slice(data: &[u8]) -> Self {
70 let mut this = RamDisk::new(data.len());
71 this[..data.len()].copy_from_slice(data);
72 this
73 }
74}
75
76impl Drop for RamDisk {
77 fn drop(&mut self) {
78 if let RamDisk::Heap(ptr) = self
79 && !ptr.is_empty()
80 {
81 unsafe {
82 dealloc(
83 ptr.cast::<u8>().as_ptr(),
84 Layout::from_size_align(ptr.len(), BLOCK_SIZE).unwrap(),
85 )
86 }
87 }
88 }
89}
90
91impl Deref for RamDisk {
92 type Target = [u8];
93
94 fn deref(&self) -> &Self::Target {
95 match self {
96 RamDisk::Heap(ptr) => unsafe { ptr.as_ref() },
97 RamDisk::Static(slice) => slice,
98 }
99 }
100}
101
102impl DerefMut for RamDisk {
103 fn deref_mut(&mut self) -> &mut Self::Target {
104 match self {
105 RamDisk::Heap(ptr) => unsafe { ptr.as_mut() },
106 RamDisk::Static(slice) => slice,
107 }
108 }
109}
110
111impl From<&'static mut [u8]> for RamDisk {
112 fn from(data: &'static mut [u8]) -> Self {
114 RamDisk::from_static(data)
115 }
116}
117
118impl BaseDriverOps for RamDisk {
119 fn device_name(&self) -> &str {
120 "ramdisk"
121 }
122
123 fn device_type(&self) -> DeviceType {
124 DeviceType::Block
125 }
126}
127
128impl BlockDriverOps for RamDisk {
129 #[inline]
130 fn num_blocks(&self) -> u64 {
131 (self.len() / BLOCK_SIZE) as u64
132 }
133
134 #[inline]
135 fn block_size(&self) -> usize {
136 BLOCK_SIZE
137 }
138
139 fn read_block(&mut self, block_id: u64, buf: &mut [u8]) -> DevResult {
140 if !buf.len().is_multiple_of(BLOCK_SIZE) {
141 return Err(DevError::InvalidParam);
142 }
143 let block_id: usize = block_id.try_into().map_err(|_| DevError::InvalidParam)?;
144 let offset = block_id
145 .checked_mul(BLOCK_SIZE)
146 .ok_or(DevError::InvalidParam)?;
147 if offset.saturating_add(buf.len()) > self.len() {
148 return Err(DevError::InvalidParam);
149 }
150 buf.copy_from_slice(&self[offset..offset + buf.len()]);
151 Ok(())
152 }
153
154 fn write_block(&mut self, block_id: u64, buf: &[u8]) -> DevResult {
155 if !buf.len().is_multiple_of(BLOCK_SIZE) {
156 return Err(DevError::InvalidParam);
157 }
158 let block_id: usize = block_id.try_into().map_err(|_| DevError::InvalidParam)?;
159 let offset = block_id
160 .checked_mul(BLOCK_SIZE)
161 .ok_or(DevError::InvalidParam)?;
162 if offset.saturating_add(buf.len()) > self.len() {
163 return Err(DevError::InvalidParam);
164 }
165 self[offset..offset + buf.len()].copy_from_slice(buf);
166 Ok(())
167 }
168
169 fn flush(&mut self) -> DevResult {
170 Ok(())
171 }
172}
173
174const fn align_up(val: usize) -> usize {
175 (val + BLOCK_SIZE - 1) & !(BLOCK_SIZE - 1)
176}