Skip to content

Commit

Permalink
Implement fat16 read
Browse files Browse the repository at this point in the history
  • Loading branch information
gcarvellas committed Oct 22, 2024
1 parent 8cde597 commit b9512ae
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 45 deletions.
Binary file modified fat16.img
Binary file not shown.
52 changes: 32 additions & 20 deletions src/fs/fat/fat16.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ struct FatDirectoryItem {
filesize: u32,
}

impl FatDirectoryItem {
fn first_cluster(&self) -> u16 {
self.high_16_bits_first_cluster | self.low_16_bits_first_cluster
}
}

// Internal Structures

struct FatDirectory {
Expand Down Expand Up @@ -152,13 +158,8 @@ enum FatItem {
Directory(FatDirectory),
}

union FatItemData {
item: *const FatDirectoryItem,
directory: *const FatDirectory,
}

struct FatFileDescriptor {
item: FatItem,
item: Arc<FatItem>,
pos: u32,
}

Expand Down Expand Up @@ -284,12 +285,12 @@ impl Fat16 {
Ok(cluster_to_use)
}

fn read_internal_recursively(
fn read_internal_recursively<T : Sized>(
&mut self,
cluster: u16,
offset: usize,
mut total: usize,
out: &mut [FatDirectoryItem],
out: &mut [T],
mut idx: usize,
) -> Result<(), ErrorCode> {
let size_of_cluster_bytes =
Expand All @@ -309,7 +310,8 @@ impl Fat16 {

self.private.cluster_read_stream.seek(starting_pos);

let mut buf = [0; size_of::<FatDirectoryItem>()];
let size = size_of::<T>();
let mut buf = Vec::with_capacity(size);
*out.get_mut(idx).ok_or(ErrorCode::OutOfBounds)? =
self.private.cluster_read_stream.read_into(&mut buf)?;
idx += 1;
Expand All @@ -321,12 +323,12 @@ impl Fat16 {
}
}

fn read_internal(
fn read_internal<T: Sized>(
&mut self,
cluster: u16,
offset: usize,
total: usize,
out: &mut [FatDirectoryItem],
out: &mut [T],
) -> Result<(), ErrorCode> {
self.read_internal_recursively(cluster, offset, total, out, 0)
}
Expand All @@ -336,7 +338,7 @@ impl Fat16 {
return Err(ErrorCode::InvArg);
}

let cluster = get_first_cluster(item);
let cluster = item.first_cluster();
let cluster_sector = self.cluster_to_sector(cluster);
let total_items: usize = get_total_items_for_directory(
self.sector_size,
Expand Down Expand Up @@ -423,6 +425,7 @@ fn to_proper_fat16_bytes(
let mut current_byte = *bytes.get(i).ok_or(ErrorCode::OutOfBounds)?;
while current_byte != 0x00 && current_byte != 0x20 {
*out.get_mut(i + offset).ok_or(ErrorCode::OutOfBounds)? = current_byte;

if i >= size - 1 {
break; // We exceeded input buffer size. Cannot process anymore
}
Expand All @@ -436,10 +439,10 @@ fn to_proper_fat16_bytes(
fn get_full_relative_filename(item: &FatDirectoryItem) -> Result<String, ErrorCode> {
let mut out = [0; MAX_PATH];
let mut offset = 0;

offset += to_proper_fat16_bytes(&item.filename, &mut out, item.filename.len(), 0)?;

if item.ext[0] != 0x00 && item.ext[0] != 0x20 {
// This should never fail, since filename will always be far less than MAX_PATH
*out.get_mut(offset).unwrap() = b'.';

offset += 1;
Expand All @@ -448,10 +451,6 @@ fn get_full_relative_filename(item: &FatDirectoryItem) -> Result<String, ErrorCo
char_array_to_ascii_string(&out)
}

fn get_first_cluster(item: &FatDirectoryItem) -> u16 {
item.high_16_bits_first_cluster | item.low_16_bits_first_cluster
}

impl FileSystem for Fat16 {
fn name(&self) -> &str {
"FAT16"
Expand Down Expand Up @@ -480,7 +479,7 @@ impl FileSystem for Fat16 {

self.fds.push(FatFileDescriptor {
pos: 0,
item: root_item,
item: Arc::new(root_item),
});
Ok(())
}
Expand All @@ -489,8 +488,21 @@ impl FileSystem for Fat16 {
unimplemented!()
}

fn fread(&self, size: u32, nmemb: u32, fd: usize) -> Result<&[u16], ErrorCode> {
unimplemented!()
fn fread(&mut self, out: &mut [u16], size: u32, nmemb: u32, fd: usize) -> Result<u32, ErrorCode> {

let fat_desc = self.fds.get(fd).ok_or(ErrorCode::InvArg)?;
let item_binding = Arc::clone(&fat_desc.item);
let item = match &*item_binding {
FatItem::File(file) => file,
FatItem::Directory(_) => panic!("Fat16 fd {} is a directory", fd),
};

let offset = fat_desc.pos;

for _ in 0..nmemb {
self.read_internal(item.first_cluster(), offset.try_into()?, size.try_into()?, out)?;
}
Ok(nmemb)
}

fn fstat(&self, fd: usize, stat: FileStat) -> Result<(), ErrorCode> {
Expand Down
54 changes: 32 additions & 22 deletions src/fs/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use crate::disk::Disk;
use crate::status::ErrorCode;

use super::pparser::parse_path;
use super::FileSystem;

static FILE_DESCRIPTORS: RwLock<[Option<Arc<FileDescriptor>>; MAX_FILE_DESCRIPTORS]> =
RwLock::new([const { None }; MAX_FILE_DESCRIPTORS]);
Expand Down Expand Up @@ -48,33 +47,27 @@ pub struct FileDescriptor {
impl FileDescriptor {
pub fn new(disk: Arc<Mutex<Disk>>) -> Result<Arc<Self>, ErrorCode> {
let mut descriptors = FILE_DESCRIPTORS.write();

for (i, descriptor) in descriptors.iter_mut().enumerate() {
if descriptor.is_none() {
let fd = Arc::new(Self {
index: i + 1,
disk: Arc::clone(&disk),
});

*descriptor = Some(Arc::clone(&fd));

return Ok(fd);
}

if let Some((i, slot)) = descriptors.iter_mut().enumerate().find(|(_, d)| d.is_none()) {
let fd = Arc::new(Self {
index: i + 1,
disk: Arc::clone(&disk),
});

*slot = Some(Arc::clone(&fd));
return Ok(fd);
}
Err(ErrorCode::NoFdAvailable)
}

pub fn get(fd: FileDescriptorIndex) -> Result<Option<Arc<Self>>, ErrorCode> {
// Descriptors start at 1
let index = fd - 1;

let descriptors = FILE_DESCRIPTORS.read();

Ok(descriptors
.get(index)
pub fn get(fd: FileDescriptorIndex) -> Result<Arc<Self>, ErrorCode> {
FILE_DESCRIPTORS
.read()
.get(fd - 1) // descriptors start at 1
.ok_or(ErrorCode::InvArg)?
.as_ref()
.map(Arc::clone))
.map(Arc::clone)
.ok_or(ErrorCode::InvArg)
}
}

Expand All @@ -87,6 +80,23 @@ fn file_get_mode_by_string(mode_str: &str) -> FileMode {
}
}

pub fn fread(out: &mut [u16], size: u32, nmemb: u32, fd: FileDescriptorIndex) -> Result<(), ErrorCode> {
if size == 0 || nmemb == 0 || fd < 1 {
return Err(ErrorCode::InvArg);
}

let desc = FileDescriptor::get(fd)?;

{
let mut disk = desc.disk.lock();
match &mut disk.fs {
None => return Err(ErrorCode::NoFs),
Some(fs) => fs.fread(out, size, nmemb, fd)?
};
}
Ok(())
}

pub fn fopen(filename: &str, mode_str: &str) -> Result<FileDescriptorIndex, ErrorCode> {
let root_path = parse_path(filename)?;

Expand Down
2 changes: 1 addition & 1 deletion src/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub trait FileSystem: Send + Sync {
mode: FileMode,
) -> Result<(), ErrorCode>;
fn fseek(&self, fd: usize, offset: usize, whence: FileSeekMode) -> Result<(), ErrorCode>;
fn fread(&self, size: u32, nmemb: u32, fd: usize) -> Result<&[u16], ErrorCode>;
fn fread(&mut self, out: &mut [u16], size: u32, nmemb: u32, fd: usize) -> Result<u32, ErrorCode>;
fn fstat(&self, fd: usize, stat: FileStat) -> Result<(), ErrorCode>;
fn fclose(&self, fd: usize) -> Result<(), ErrorCode>;
fn fs_resolve(disk: &Disk) -> Result<Self, ErrorCode>
Expand Down
10 changes: 8 additions & 2 deletions src/kernel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ use crate::memory::paging::PageAddress;
use crate::memory::paging::PageDirectoryEntry;
use crate::memory::paging::Paging256TBChunk;
use alloc::boxed::Box;
use fs::file::fread;
use core::panic::PanicInfo;
use fs::file::fopen;
use idt::IDT;
Expand Down Expand Up @@ -157,10 +158,15 @@ pub extern "C" fn kernel_main() -> ! {

test_paging();

println!("Attempting to open 0:/hello.txt");
let fd = fopen("1:/HELLO.TXT", "r").expect("Failed to open hello.txt");
println!("Attempting to open 1:/HELLO.TXT");
let fd = fopen("1:/HELLO.TXT", "r").expect("Failed to open HELLO.TXT");
println!("We opened 1:/HELLO.TXT at fd {}", fd);

let mut buf = [0; 8];
fread(&mut buf, 8, 1, fd).expect("Failed to read HELLO.TXT");
println!("We read 1:/HELLO.TXT: \"{:?}\"", buf);


println!("Testing a kernel panic using Rust's unimplemented! macro.");

unimplemented!();
Expand Down

0 comments on commit b9512ae

Please sign in to comment.