Skip to content

Commit 6e8f9fa

Browse files
committed
Ensure proper alignment of DAP target buffer
1 parent f1f5457 commit 6e8f9fa

File tree

2 files changed

+54
-34
lines changed

2 files changed

+54
-34
lines changed

bios/second_stage/src/disk.rs

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,21 @@ pub struct DiskAccess {
99
}
1010

1111
impl Read for DiskAccess {
12-
fn read_exact(&mut self, input_buf: &mut [u8]) {
13-
static mut TMP_BUF: [u8; 512] = [0; 512];
14-
let tmp_buf = unsafe { &mut TMP_BUF[..] };
15-
let (buf, copy_needed) = if input_buf.len() >= tmp_buf.len() {
16-
(&mut input_buf[..], false)
17-
} else {
18-
(&mut tmp_buf[..], true)
12+
fn read_exact(&mut self, len: usize) -> &[u8] {
13+
static mut TMP_BUF: AlignedBuffer<512> = AlignedBuffer {
14+
buffer: [0; 512],
15+
limit: 512,
1916
};
17+
let buf = unsafe { &mut TMP_BUF };
18+
assert!(len <= buf.buffer.len());
19+
20+
self.read_exact_into(buf);
21+
22+
&buf.buffer[..len]
23+
}
24+
25+
fn read_exact_into(&mut self, buf: &mut dyn AlignedSlice) {
26+
let buf = buf.slice_mut();
2027
assert_eq!(buf.len() % 512, 0);
2128

2229
let end_addr = self.base_offset + self.current_offset + u64::try_from(buf.len()).unwrap();
@@ -48,13 +55,6 @@ impl Read for DiskAccess {
4855
}
4956

5057
self.current_offset = end_addr;
51-
52-
if copy_needed {
53-
let len = input_buf.len();
54-
for i in 0..len {
55-
input_buf[i] = tmp_buf[i];
56-
}
57-
}
5858
}
5959
}
6060

@@ -76,7 +76,8 @@ impl Seek for DiskAccess {
7676
}
7777

7878
pub trait Read {
79-
fn read_exact(&mut self, buf: &mut [u8]);
79+
fn read_exact(&mut self, len: usize) -> &[u8];
80+
fn read_exact_into(&mut self, buf: &mut dyn AlignedSlice);
8081
}
8182

8283
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -88,3 +89,23 @@ pub enum SeekFrom {
8889
pub trait Seek {
8990
fn seek(&mut self, pos: SeekFrom) -> u64;
9091
}
92+
93+
#[repr(align(2))]
94+
pub struct AlignedBuffer<const LEN: usize> {
95+
pub buffer: [u8; LEN],
96+
pub limit: usize,
97+
}
98+
99+
pub trait AlignedSlice {
100+
fn slice(&self) -> &[u8];
101+
fn slice_mut(&mut self) -> &mut [u8];
102+
}
103+
104+
impl<const LEN: usize> AlignedSlice for AlignedBuffer<LEN> {
105+
fn slice(&self) -> &[u8] {
106+
&self.buffer[..self.limit]
107+
}
108+
fn slice_mut(&mut self) -> &mut [u8] {
109+
&mut self.buffer[..self.limit]
110+
}
111+
}

bios/second_stage/src/fat.rs

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// based on https://crates.io/crates/mini_fat by https://github.com/gridbugs
22

33
use crate::{
4-
disk::{Read, Seek, SeekFrom},
4+
disk::{AlignedBuffer, AlignedSlice, Read, Seek, SeekFrom},
55
screen,
66
};
77
use core::{char::DecodeUtf16Error, fmt::Write as _};
@@ -36,12 +36,7 @@ struct Bpb {
3636

3737
impl Bpb {
3838
fn parse<D: Read + Seek>(disk: &mut D) -> Self {
39-
static mut BPB_BUFFER: [u8; 512] = [0; 512];
40-
let mut raw = {
41-
let buffer = unsafe { &mut BPB_BUFFER[..] };
42-
&mut buffer[..512]
43-
};
44-
disk.read_exact(&mut raw);
39+
let raw = disk.read_exact(512);
4540

4641
let bytes_per_sector = u16::from_le_bytes(raw[11..13].try_into().unwrap());
4742
let sectors_per_cluster = raw[13];
@@ -217,16 +212,20 @@ impl<D: Read + Seek> FileSystem<D> {
217212
}
218213
FatType::Fat12 | FatType::Fat16 => {
219214
let root_directory_size = self.bpb.root_directory_size();
220-
static mut ROOT_DIR_BUFFER: [u8; 0x4000] = [0; 0x4000];
221-
let buffer = unsafe { &mut ROOT_DIR_BUFFER[..] };
222-
assert!(root_directory_size <= buffer.len());
223-
let raw = &mut buffer[..root_directory_size];
215+
static mut ROOT_DIR_BUFFER: AlignedBuffer<0x4000> = AlignedBuffer {
216+
buffer: [0; 0x4000],
217+
limit: 0x4000,
218+
};
219+
let buffer = unsafe { &mut ROOT_DIR_BUFFER };
220+
buffer.limit = root_directory_size;
224221

225222
self.disk
226223
.seek(SeekFrom::Start(self.bpb.root_directory_offset()));
227-
self.disk.read_exact(raw);
224+
self.disk.read_exact_into(buffer);
228225

229-
raw.chunks(DIRECTORY_ENTRY_BYTES)
226+
buffer
227+
.slice()
228+
.chunks(DIRECTORY_ENTRY_BYTES)
230229
.take_while(|raw_entry| raw_entry[0] != END_OF_DIRECTORY_PREFIX)
231230
.filter(|raw_entry| raw_entry[0] != UNUSED_ENTRY_PREFIX)
232231
.map(RawDirectoryEntry::parse)
@@ -535,22 +534,22 @@ where
535534
FatType::Fat32 => {
536535
let base = n as u64 * 4;
537536
disk.seek(SeekFrom::Start(fat_start + base));
538-
let mut buf = [0; 4];
539-
disk.read_exact(&mut buf);
537+
let buf = disk.read_exact(4);
538+
let buf: [u8; 4] = buf.try_into().unwrap();
540539
u32::from_le_bytes(buf) & 0x0FFFFFFF
541540
}
542541
FatType::Fat16 => {
543542
let base = n as u64 * 2;
544543
disk.seek(SeekFrom::Start(fat_start + base));
545-
let mut buf = [0; 2];
546-
disk.read_exact(&mut buf);
544+
let buf = disk.read_exact(2);
545+
let buf: [u8; 2] = buf.try_into().unwrap();
547546
u16::from_le_bytes(buf) as u32
548547
}
549548
FatType::Fat12 => {
550549
let base = n as u64 + (n as u64 / 2);
551550
disk.seek(SeekFrom::Start(fat_start + base));
552-
let mut buf = [0; 2];
553-
disk.read_exact(&mut buf);
551+
let buf = disk.read_exact(2);
552+
let buf: [u8; 2] = buf.try_into().unwrap();
554553
let entry16 = u16::from_le_bytes(buf);
555554
if n & 1 == 0 {
556555
(entry16 & 0xFFF) as u32

0 commit comments

Comments
 (0)