Skip to content

Commit 5bc8086

Browse files
retragerbradford
authored andcommitted
block: Introduce SectorBuf to reduce hard-coded sector size
The current implementation assumes the block device sector size is always 512 bytes. This can be a blocking issue when supporting block devices with other sector sizes. To mitigate this, this commit introduces `SectorBuf` that represents a single sector buffer instead of `[u8; 512]`. Signed-off-by: Akira Moroo <retrage01@gmail.com>
1 parent 6ece796 commit 5bc8086

File tree

8 files changed

+155
-86
lines changed

8 files changed

+155
-86
lines changed

src/block.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,30 @@ struct BlockRequestFooter {
9696
status: u8,
9797
}
9898

99+
const SECTOR_SIZE: usize = 512;
100+
101+
#[repr(C)]
102+
pub struct SectorBuf([u8; SECTOR_SIZE]);
103+
104+
impl SectorBuf {
105+
pub const fn new() -> Self {
106+
Self([0_u8; SECTOR_SIZE])
107+
}
108+
109+
#[inline]
110+
pub const fn len() -> usize {
111+
SECTOR_SIZE
112+
}
113+
114+
pub fn as_bytes(&self) -> &[u8] {
115+
&self.0
116+
}
117+
118+
pub fn as_mut_bytes(&mut self) -> &mut [u8] {
119+
&mut self.0
120+
}
121+
}
122+
99123
pub trait SectorRead {
100124
/// Read a single sector (512 bytes) from the block device. `data` must be
101125
/// exactly 512 bytes long.
@@ -213,7 +237,7 @@ impl<'a> VirtioBlockDevice<'a> {
213237
request: RequestType,
214238
) -> Result<(), Error> {
215239
if request != RequestType::Flush {
216-
assert_eq!(512, data.as_ref().unwrap().len());
240+
assert_eq!(SectorBuf::len(), data.as_ref().unwrap().len());
217241
}
218242

219243
const VIRTQ_DESC_F_NEXT: u16 = 1;
@@ -245,7 +269,7 @@ impl<'a> VirtioBlockDevice<'a> {
245269
let next_desc = (next_desc + 1) % QUEUE_SIZE;
246270
if request != RequestType::Flush {
247271
d.addr = data.unwrap().as_ptr() as u64;
248-
d.length = core::mem::size_of::<[u8; 512]>() as u32;
272+
d.length = SectorBuf::len() as u32;
249273
}
250274

251275
d.flags = VIRTQ_DESC_F_NEXT

src/bzimage.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use atomic_refcell::AtomicRefCell;
1515

1616
use crate::{
17+
block::SectorBuf,
1718
boot::{E820Entry, Header, Info, Params},
1819
fat::{self, Read},
1920
mem::MemoryRegion,
@@ -62,7 +63,7 @@ impl Kernel {
6263
0 => 4,
6364
n => n as u32,
6465
};
65-
let setup_bytes = (setup_sects + 1) * 512;
66+
let setup_bytes = (setup_sects + 1) * SectorBuf::len() as u32;
6667
let remaining_bytes = f.get_size() - setup_bytes;
6768

6869
let mut region = MemoryRegion::new(KERNEL_LOCATION, remaining_bytes as u64);

src/efi/block.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ use r_efi::{
2020
protocols::device_path::Protocol as DevicePathProtocol,
2121
};
2222

23+
use crate::block::SectorBuf;
24+
2325
pub const PROTOCOL_GUID: Guid = Guid::from_fields(
2426
0x964e_5b21,
2527
0x6459,
@@ -118,12 +120,13 @@ pub extern "win64" fn read_blocks(
118120
let wrapper = container_of!(proto, BlockWrapper, proto);
119121
let wrapper = unsafe { &*wrapper };
120122

121-
let blocks = (size / 512) as usize;
123+
let block_size = wrapper.media.block_size as usize;
124+
let blocks = size / block_size;
122125
let mut region = crate::mem::MemoryRegion::new(buffer as u64, size as u64);
123126

124127
for i in 0..blocks {
125128
use crate::block::SectorRead;
126-
let data = region.as_mut_slice(i as u64 * 512, 512);
129+
let data = region.as_mut_slice((i * block_size) as u64, block_size as u64);
127130
let block = unsafe { &*wrapper.block };
128131
match block.read(wrapper.start_lba + start + i as u64, data) {
129132
Ok(()) => continue,
@@ -146,12 +149,13 @@ pub extern "win64" fn write_blocks(
146149
let wrapper = container_of!(proto, BlockWrapper, proto);
147150
let wrapper = unsafe { &*wrapper };
148151

149-
let blocks = (size / 512) as usize;
152+
let block_size = wrapper.media.block_size as usize;
153+
let blocks = (size / block_size) as usize;
150154
let mut region = crate::mem::MemoryRegion::new(buffer as u64, size as u64);
151155

152156
for i in 0..blocks {
153157
use crate::block::SectorWrite;
154-
let data = region.as_mut_slice(i as u64 * 512, 512);
158+
let data = region.as_mut_slice((i * block_size) as u64, block_size as u64);
155159
let block = unsafe { &*wrapper.block };
156160
match block.write(wrapper.start_lba + start + i as u64, data) {
157161
Ok(()) => continue,
@@ -208,7 +212,7 @@ impl<'a> BlockWrapper<'a> {
208212
logical_partition: false,
209213
read_only: true,
210214
write_caching: false,
211-
block_size: 512,
215+
block_size: SectorBuf::len() as u32,
212216
io_align: 0,
213217
last_block,
214218
},

src/efi/file.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ use r_efi::{
2222
},
2323
};
2424

25+
use crate::block::SectorBuf;
26+
2527
#[repr(C)]
2628
pub struct FileDevicePathProtocol {
2729
pub device_path: DevicePathProtocol,
@@ -154,12 +156,12 @@ pub extern "win64" fn read(file: *mut FileProtocol, size: *mut usize, buf: *mut
154156
loop {
155157
let buf = unsafe { core::slice::from_raw_parts_mut(buf as *mut u8, *size) };
156158

157-
let mut data: [u8; 512] = [0; 512];
159+
let mut data = SectorBuf::new();
158160
unsafe {
159-
match (*wrapper).node.read(&mut data) {
161+
match (*wrapper).node.read(data.as_mut_bytes()) {
160162
Ok(bytes_read) => {
161163
buf[current_offset..current_offset + bytes_read as usize]
162-
.copy_from_slice(&data[0..bytes_read as usize]);
164+
.copy_from_slice(&data.as_bytes()[0..bytes_read as usize]);
163165
current_offset += bytes_read as usize;
164166

165167
if bytes_remaining <= bytes_read as usize {

0 commit comments

Comments
 (0)