Skip to content

Commit

Permalink
Bootloader: Fix fatfs lookup issue with the fat table
Browse files Browse the repository at this point in the history
  • Loading branch information
corigan01 committed Jan 6, 2025
1 parent 3c103f8 commit f34643b
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 23 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,6 @@ overflow-checks = true
[profile.kernel]
inherits = "release"
panic = "abort"
strip = true
strip = false
debug = 1
overflow-checks = true
8 changes: 8 additions & 0 deletions bootloader/stage-64bit/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,14 @@ fn build_memory_map(s2s: &Stage32toStage64, kernel_exe_len: usize) -> paging::Pa
})
.expect("Unable to add stage32 to memory map");

let (elf_start, elf_len) = s2s.kernel_ptr;
mm.add_region(PhysMemoryEntry {
kind: PhysMemoryKind::Bootloader,
start: elf_start,
end: elf_start + elf_len,
})
.expect("Unable to add elf to memory map");

let (s64_start, s64_len) = s2s.stage64_ptr;
mm.add_region(PhysMemoryEntry {
kind: PhysMemoryKind::Bootloader,
Expand Down
59 changes: 42 additions & 17 deletions crates/fs/src/fatfs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use crate::{
fatfs::inode::{DirectoryEntry, Inode},
io::{Read, Seek},
};
use core::{fmt::Debug, mem::size_of};
use core::{cell::SyncUnsafeCell, fmt::Debug, mem::size_of};

mod bpb;
mod inode;
Expand Down Expand Up @@ -101,6 +101,7 @@ impl FatEntry {
pub struct FatFile<'a, Part: ReadSeek> {
filesize: usize,
start_cluster: ClusterId,
last_cluster: Option<(ClusterId, u64)>,
fatfs: &'a mut Fat<Part>,
seek: u64,
}
Expand Down Expand Up @@ -139,9 +140,15 @@ where
let mut bytes_read = 0;

loop {
let cluster_info = self
.fatfs
.cluster_of_offset(self.start_cluster, self.seek)?;
let (cluster_id, offset) = match self.last_cluster {
Some((last_cluster, last_seek)) if last_seek <= self.seek => {
(last_cluster, self.seek - last_seek)
}
_ => (self.start_cluster, self.seek),
};

let cluster_info = self.fatfs.cluster_of_offset(cluster_id, offset)?;
self.last_cluster = Some((cluster_info.0, self.seek));

let disk_loc = self.fatfs.bpb.cluster_physical_loc(cluster_info.0) + cluster_info.1;

Expand All @@ -158,7 +165,9 @@ where

assert!(
bytes_read <= buf.len(),
"It should not be possible to read more bytes ({}) than the buffer has capacity for ({})!", bytes_read, buf.len()
"Attemped to more bytes ({}) than buffer's capacity ({})!",
bytes_read,
buf.len()
);

if bytes_read == buf.len() {
Expand All @@ -168,6 +177,8 @@ where
}
}

static FAT_BLOCK_RESERVE: SyncUnsafeCell<(u64, [u8; 512])> = SyncUnsafeCell::new((0, [0; 512]));

impl<Part: ReadSeek> Fat<Part> {
pub fn new(mut disk: Part) -> Result<Self> {
let bpb = Bpb::new(&mut disk)?;
Expand All @@ -186,19 +197,32 @@ impl<Part: ReadSeek> Fat<Part> {
return Err(FsError::InvalidInput);
}

let mut sector_array = [0u8; 512];
self.disk.seek(SeekFrom::Start(
entry_sector * self.bpb.sector_size() as u64,
))?;
self.disk.read(&mut sector_array)?;
if entry_sector != unsafe { (&*FAT_BLOCK_RESERVE.get()).0 } {
self.disk.seek(SeekFrom::Start(
entry_sector * self.bpb.sector_size() as u64,
))?;
unsafe {
self.disk
.read(&mut (&mut *FAT_BLOCK_RESERVE.get()).1.as_mut())?;
(&mut *FAT_BLOCK_RESERVE.get()).0 = entry_sector;
}
}

Ok(match self.bpb.kind() {
FatKind::Fat16 => FatEntry::from_fat16(unsafe {
core::ptr::read_unaligned(sector_array.as_ptr().add(entry_offset * 2))
} as ClusterId),
FatKind::Fat32 => FatEntry::from_fat32(unsafe {
core::ptr::read_unaligned(sector_array.as_ptr().add(entry_offset * 4))
} as ClusterId),
FatKind::Fat16 => unsafe {
let arr = core::slice::from_raw_parts(
(&*FAT_BLOCK_RESERVE.get()).1.as_ptr() as *const u16,
256,
);
FatEntry::from_fat16(arr[entry_offset] as u32)
},
FatKind::Fat32 => unsafe {
let arr = core::slice::from_raw_parts(
(&*FAT_BLOCK_RESERVE.get()).1.as_ptr() as *const u32,
128,
);
FatEntry::from_fat32(arr[entry_offset])
},
FatKind::Fat12 => todo!("Support reading FAT12"),
})
}
Expand All @@ -210,7 +234,7 @@ impl<Part: ReadSeek> Fat<Part> {
) -> Result<(ClusterId, u64)> {
let mut search_cluster = cluster_start;
let mut total_offset = 0;
let cluster_size_bytes = (self.bpb.cluster_sectors() * self.bpb.sector_size()) as u64;
let cluster_size_bytes = self.bpb.cluster_sectors() as u64 * self.bpb.sector_size() as u64;

loop {
if offset - total_offset < cluster_size_bytes {
Expand Down Expand Up @@ -240,6 +264,7 @@ impl<Part: ReadSeek> Fat<Part> {
start_cluster: entry_info.cluster_id(),
fatfs: self,
seek: 0,
last_cluster: None,
})
}

Expand Down
1 change: 1 addition & 0 deletions crates/fs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
*/

#![no_std]
#![feature(sync_unsafe_cell)]

#[cfg(feature = "fatfs")]
pub mod fatfs;
Expand Down
2 changes: 2 additions & 0 deletions kernel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ documentation.workspace = true
bootloader = { workspace = true }
lldebug = { workspace = true }
serial = { workspace = true }
util = {workspace = true}
mem = {workspace = true}
14 changes: 9 additions & 5 deletions kernel/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,24 @@ mod panic;
use bootloader::KernelBootHeader;
use lldebug::{debug_ready, logln, make_debug};
use serial::{Serial, baud::SerialBaud};
use util::bytes::HumanBytes;

make_debug! {
"Serial": Option<Serial> = Serial::probe_first(SerialBaud::Baud115200);
}

#[unsafe(no_mangle)]
#[unsafe(link_section = ".start")]
extern "C" fn _start(stage_to_stage: u64) -> ! {
main(unsafe { &*(stage_to_stage as *const KernelBootHeader) });
extern "C" fn _start(kbh: u64) -> ! {
main(unsafe { &*(kbh as *const KernelBootHeader) });
panic!("Main should not return");
}

#[debug_ready]
fn main(stage_to_stage: &KernelBootHeader) {
logln!("{:#?}", stage_to_stage);
loop {}
fn main(kbh: &KernelBootHeader) {
logln!("Welcome to the Quantum Kernel!");
logln!(
"Free Memory : {}",
HumanBytes::from(kbh.phys_mem_map.bytes_of(mem::phys::PhysMemoryKind::Free))
);
}

0 comments on commit f34643b

Please sign in to comment.