Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 27 additions & 26 deletions crates/filesystem/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,14 @@ struct DirectoryEntryData {

const _: () = assert!(size_of::<DirectoryEntryData>() == 8);

#[derive(Debug)]
pub struct DirectoryEntryRef<'a> {
inode_num: u32,
rec_len: u16,
name_len: u8,
file_type: u8,
name: &'a [u8],
dir_offset: usize,
pub inode_num: u32,
pub rec_len: u16,
pub name_len: u8,
pub file_type: u8,
pub name: &'a [u8],
pub dir_offset: usize,
}

impl DirectoryEntryData {
Expand Down Expand Up @@ -258,24 +259,24 @@ const _: () = assert!(size_of::<BGD>() == 32);
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct INode {
i_mode: u16,
i_uid: u16,
i_size: u32,
i_atime: u32,
i_ctime: u32,
i_mtime: u32,
i_dtime: u32,
i_gid: u16,
i_links_count: u16,
i_blocks: u32,
i_flags: u32,
i_osd1: u32,
i_block: [u32; 15], // 12 direct, single, double, triple
i_generation: u32,
i_file_acl: u32,
i_dir_acl: u32,
i_faddr: u32,
i_osd2: [u8; 12],
pub i_mode: u16,
pub i_uid: u16,
pub i_size: u32,
pub i_atime: u32,
pub i_ctime: u32,
pub i_mtime: u32,
pub i_dtime: u32,
pub i_gid: u16,
pub i_links_count: u16,
pub i_blocks: u32,
pub i_flags: u32,
pub i_osd1: u32,
pub i_block: [u32; 15], // 12 direct, single, double, triple
pub i_generation: u32,
pub i_file_acl: u32,
pub i_dir_acl: u32,
pub i_faddr: u32,
pub i_osd2: [u8; 12],
}

const _: () = assert!(size_of::<INode>() == 128);
Expand Down Expand Up @@ -351,8 +352,8 @@ const UNALLOCATED_BLOCK_SLOT: u32 = 0;

#[derive(Debug)]
pub struct INodeWrapper {
inode: INode,
_inode_num: u32,
pub inode: INode,
pub _inode_num: u32,
}

unsafe impl bytemuck::Zeroable for DirectoryEntryData {}
Expand Down
57 changes: 57 additions & 0 deletions crates/kernel/examples/ext2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#![no_std]
#![no_main]

extern crate alloc;
extern crate kernel;

use device::{discover_compatible, find_device_addr, sdcard};
use filesystem::BlockDevice;
use fs::ext2::Ext2File;
use kernel::{device::sdcard::SD, sync::SpinLock, *};

#[no_mangle]
extern "Rust" fn kernel_main(tree: device_tree::DeviceTree) {
println!("| starting kernel_main");

// Should use this on hardware
// let sdcard = discover_compatible(&tree, b"brcm,bcm2711-emmc2")
// .unwrap()
// .next()
// .unwrap();
// The bcm2835-sdhci requires additional gpio pin initialization which could possibly conflict with other drivers that need those pinss
let sdcard = discover_compatible(&tree, b"brcm,bcm2835-sdhci")
.unwrap()
.next()
.unwrap();
let (sdcard_addr, _) = find_device_addr(sdcard).unwrap().unwrap();
let sdcard_base = unsafe { memory::map_device(sdcard_addr) }.as_ptr();
println!("| SD Card controller addr: {:#010x}", sdcard_addr as usize);
println!("| SD Card controller base: {:#010x}", sdcard_base as usize);
let sdcard = unsafe { sdcard::bcm2711_emmc2_driver::init(sdcard_base) };
unsafe { SD.init(SpinLock::new(sdcard)) };
println!("| initialized SD Card");

let block_device = SD.get();
println!("Initializing ext2 filesystem");
let mut fs = filesystem::Ext2::new(block_device).unwrap();

println!("Reading root dir");
let root = fs.get_root_inode_wrapper();
root.borrow_mut().get_dir_entries(&mut fs, |entry| {
let filename = core::str::from_utf8(entry.name).unwrap();
println!("- {:?}: {:?}", filename, entry);
core::ops::ControlFlow::<()>::Continue(())
}, None).unwrap();

println!("Creating 'example-file.txt'");
fs.create_file(&mut *root.borrow_mut(), b"example-file.txt").unwrap();

println!("Re-reading root dir");
root.borrow_mut().get_dir_entries(&mut fs, |entry| {
let filename = core::str::from_utf8(entry.name).unwrap();
println!("- {:?}: {:?}", filename, entry);
core::ops::ControlFlow::<()>::Continue(())
}, None).unwrap();

println!("Done with test");
}
10 changes: 10 additions & 0 deletions crates/kernel/examples/sd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ extern crate kernel;

use device::{discover_compatible, find_device_addr, sdcard};
use filesystem::BlockDevice;
use fs::ext2::Ext2File;
use kernel::{device::sdcard::SD, sync::SpinLock, *};

#[no_mangle]
Expand Down Expand Up @@ -72,4 +73,13 @@ extern "Rust" fn kernel_main(tree: device_tree::DeviceTree) {
println!("{:?}", buf1024);
assert_eq!(buf1024[0..512], buf0);
assert_eq!(buf1024[512..1024], buf0);

let block_device = SD.get();
let mut fs = filesystem::Ext2::new(block_device).unwrap();

let root = fs.get_root_inode_wrapper();
root.borrow_mut().get_dir_entries(&mut fs, |entry| {
println!("entry: {:?}", entry);
core::ops::ControlFlow::<()>::Continue(())
}, None).unwrap();
}
3 changes: 2 additions & 1 deletion crates/kernel/scripts/run-usb.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#!/usr/bin/env bash

set -ex
QEMU_DISPLAY="default" QEMU_DEVICES="-usb -device usb-kbd -device usb-mouse -device usb-net,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2222-:22 -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh"
QEMU_DISPLAY="default" QEMU_DEVICES="-usb -device usb-kbd -device usb-mouse" "$(dirname "$0")/run.sh"
#QEMU_DISPLAY="default" QEMU_DEVICES="-usb -device usb-kbd -device usb-mouse -device usb-net,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2222-:22 -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh"
# QEMU_DISPLAY="default" QEMU_DEVICES="-usb -device usb-kbd -device usb-mouse -device usb-net,netdev=net0 -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh"

# QEMU_DISPLAY="default" QEMU_DEVICES="-usb -device usb-kbd -device usb-mouse -device usb-net,netdev=net0 -netdev bridge,id=net0,br=br0 -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh"
4 changes: 3 additions & 1 deletion crates/kernel/scripts/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ set -e
# Check if sdcard.img exists, create it if not
if [ ! -f sdcard.img ]; then
echo "Creating SD card image"
qemu-img create -f raw sdcard.img 32M
mkfs.ext2 -q -b 4096 -i 4096 -I 128 -r 0 -t ext2 -d ../init/fs sdcard.img 32m
echo "SD card image created"
fi

Expand Down Expand Up @@ -58,3 +58,5 @@ qemu-system-aarch64 \
# -netdev user,id=net0,hostfwd=tcp::2222-:22 \
# -object filter-dump,id=f1,netdev=net0,file=net0.pcap \
# -trace enable=net* \

rm -f sdcard.img
82 changes: 60 additions & 22 deletions crates/kernel/src/device/sdcard.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
#![allow(dead_code, nonstandard_style)]

pub static SD: UnsafeInit<SpinLock<bcm2711_emmc2_driver>> = unsafe { UnsafeInit::uninit() };

// SDHCI driver for raspberry pi 4b
// TODO:
// Rest of PR fixes
// Better error handling
// Assert test in sd.rs in /examples
// spin_sleep() timing validation
// cleanup error handling
// cleanup comments

// https://github.com/jncronin/rpi-boot/blob/master/emmc.c
// https://github.com/rsta2/circle/blob/master/addon/SDCard/emmc.cpp
Expand All @@ -21,6 +19,8 @@ use filesystem::BlockDevice;
// use super::{gpio, GPIO};
use super::{mailbox, MAILBOX};

pub static SD: UnsafeInit<SpinLock<bcm2711_emmc2_driver>> = unsafe { UnsafeInit::uninit() };

#[derive(Debug, Copy, Clone)]
pub struct SdScr {
pub scr: [u32; 2],
Expand Down Expand Up @@ -521,6 +521,8 @@ impl bcm2711_emmc2_driver {
panic!("Cannot init SD card");
}

println!("| SD capacity is {:?} Bytes", driver.get_capacity());

driver
}

Expand Down Expand Up @@ -1310,7 +1312,6 @@ impl bcm2711_emmc2_driver {
}

self.emmc.capacity = (nSize << nShift) as u64 * SD_BLOCK_SIZE as u64;
println!("SD capacity is {:?} Bytes", self.emmc.capacity);

if let Err(e) = self.issue_command(SELECT_CARD, self.emmc.card_rca << 16, 500000) {
println!("Error sending CMD7");
Expand Down Expand Up @@ -1395,7 +1396,7 @@ impl bcm2711_emmc2_driver {
let old_irpt_mask = self.reg(IRPT_MASK).read();
let new_irpt_mask = old_irpt_mask & !(1 << 8);
self.reg(IRPT_MASK).write(new_irpt_mask);

self.issue_command(STOP_TRANSMISSION, 0, 500000);
if self.issue_command(SET_BUS_WIDTH, 2, 500000).is_err() {
println!("Switch to 4-bit data mode failed");
} else {
Expand All @@ -1407,7 +1408,7 @@ impl bcm2711_emmc2_driver {
}

println!(
"Found a valid {:#?} SD Card",
"| Found a valid {:#?} SD Card",
SD_VERSIONS[(*self.emmc.scr).sd_version as usize]
);

Expand All @@ -1430,7 +1431,7 @@ impl bcm2711_emmc2_driver {
let vendor = ver >> 24;
let slot_status = ver & 0xff;
println!(
"SD version: {:#?}, vendor: {:#010x}, slot status: {:#010x}",
"| SD version: {:#?}, vendor: {:#010x}, slot status: {:#010x}",
SD_VERSIONS[sdversion as usize], vendor, slot_status
);

Expand All @@ -1453,12 +1454,16 @@ impl bcm2711_emmc2_driver {

fn ensure_data_mode(&mut self) -> Result<(), SdCardError> {
if self.emmc.card_rca == CARD_RCA_INVALID {
println!("Card rca invalid, resetting");
let ret = self.card_reset();
if ret.is_err() {
println!("Card reset failed");
return ret;
}
}



if let Err(e) = self.issue_command(SEND_STATUS, self.emmc.card_rca << 16, 500000) {
self.emmc.card_rca = CARD_RCA_INVALID;
println!("ensure_data_mode() error sending CMD13");
Expand All @@ -1482,12 +1487,14 @@ impl bcm2711_emmc2_driver {
}
let _ = self.reset_dat();
} else if cur_state != 4 {
println!("Card not in data mode resetting, cur_state: {:#010x}", cur_state);
let ret = self.card_reset();
if ret.is_err() {
return ret;
}
}
if cur_state != 4 {
println!("Card still not in data mode, cur_state: {:#010x}", cur_state);
if let Err(e) = self.issue_command(SEND_STATUS, self.emmc.card_rca << 16, 500000) {
self.emmc.card_rca = CARD_RCA_INVALID;
println!("ensure_data_mode() error sending CMD13");
Expand All @@ -1497,7 +1504,7 @@ impl bcm2711_emmc2_driver {
cur_state = (status >> 9) & 0xf;
if cur_state != 4 {
self.emmc.card_rca = CARD_RCA_INVALID;
sderror!("Unable to initialize SD card to date mode")
sderror!("Unable to initialize SD card to data mode")
}
}
Ok(())
Expand Down Expand Up @@ -1562,6 +1569,7 @@ impl bcm2711_emmc2_driver {
self.emmc.card_rca = CARD_RCA_INVALID;
return Err(SdCardError::Error);
}
self.issue_command(STOP_TRANSMISSION, 0, 500000)?;
Ok(())
}

Expand All @@ -1574,9 +1582,7 @@ impl bcm2711_emmc2_driver {
}

fn do_write(&mut self, buf: &[u8], block_no: u32) -> Result<u32, SdCardError> {
if self.ensure_data_mode().is_err() {
return Err(SdCardError::Error);
}
self.ensure_data_mode()?;
let ptr = buf.as_ptr() as *mut u8;
let tmp: &mut [u8] = unsafe { core::slice::from_raw_parts_mut(ptr, buf.len()) };
self.do_data_command(true, tmp, block_no)?;
Expand Down Expand Up @@ -1631,6 +1637,28 @@ impl bcm2711_emmc2_driver {
&self.emmc.id
}

pub fn read_sector(
&mut self,
index: u64,
buffer: &mut [u8; filesystem::SECTOR_SIZE],
) -> Result<(), filesystem::BlockDeviceError> {
self.seek(index * filesystem::SECTOR_SIZE as u64);
self.read(buffer)
.map_err(|_| filesystem::BlockDeviceError::Unknown)?;
Ok(())
}

pub fn write_sector(
&mut self,
index: u64,
buffer: &[u8; filesystem::SECTOR_SIZE],
) -> Result<(), filesystem::BlockDeviceError> {
self.seek(index * filesystem::SECTOR_SIZE as u64);
self.write(buffer)
.map_err(|_| filesystem::BlockDeviceError::Unknown)?;
Ok(())
}

pub fn read_sectors(
&mut self,
index: u64,
Expand All @@ -1653,27 +1681,37 @@ impl bcm2711_emmc2_driver {
}
}

impl BlockDevice for bcm2711_emmc2_driver {
impl BlockDevice for &SpinLock<bcm2711_emmc2_driver> {
fn read_sector(
&mut self,
index: u64,
buffer: &mut [u8; filesystem::SECTOR_SIZE],
) -> Result<(), filesystem::BlockDeviceError> {
self.seek(index * filesystem::SECTOR_SIZE as u64);
self.read(buffer)
.map_err(|_| filesystem::BlockDeviceError::Unknown)?;
Ok(())
self.lock().read_sector(index, buffer)
}

fn write_sector(
&mut self,
index: u64,
buffer: &[u8; filesystem::SECTOR_SIZE],
) -> Result<(), filesystem::BlockDeviceError> {
self.seek(index * filesystem::SECTOR_SIZE as u64);
self.write(buffer)
.map_err(|_| filesystem::BlockDeviceError::Unknown)?;
Ok(())
self.lock().write_sector(index, buffer)
}

fn read_sectors(
&mut self,
start_index: u64,
buffer: &mut [u8],
) -> Result<(), filesystem::BlockDeviceError> {
self.lock().read_sectors(start_index, buffer)
}

fn write_sectors(
&mut self,
start_index: u64,
buffer: &[u8],
) -> Result<(), filesystem::BlockDeviceError> {
self.lock().write_sectors(start_index, buffer)
}
}

Expand Down
Loading