refactor: change add_char_device

This commit is contained in:
2021-11-03 13:24:57 +02:00
parent abfa6d28eb
commit ad17789d94
14 changed files with 277 additions and 83 deletions
+9 -4
View File
@@ -9,7 +9,12 @@ extern crate libusr;
fn main() -> i32 {
let mut buf = [0; 128];
print!("\x1B[2J\x1B[1;1H");
println!("Hello!");
loop {
print!("> ");
let count = unsafe {
libusr::sys::sys_read(0, buf.as_mut_ptr(), buf.len())
};
@@ -21,13 +26,13 @@ fn main() -> i32 {
if let Ok(s) = core::str::from_utf8(&buf[..count]) {
println!("Got string {:?}", s);
if s == "quit" {
break;
}
} else {
println!("Got string (non-utf8) {:?}", &buf[..count]);
}
unsafe {
libusr::sys::sys_ex_nanosleep(1_000_000_000, core::ptr::null_mut());
}
}
-1
}
+40 -18
View File
@@ -5,7 +5,9 @@ use crate::arch::{
machine,
};
use crate::fs::devfs;
use crate::dev::{fdt::DeviceTree, irq::IntSource, Device};
use crate::dev::{fdt::{DeviceTree, find_prop}, irq::IntSource, Device};
use error::Errno;
use crate::config::{CONFIG, ConfigKey};
//use crate::debug::Level;
use crate::mem::{
self, heap,
@@ -17,6 +19,39 @@ use cortex_a::asm::barrier::{self, dsb, isb};
use cortex_a::registers::{SCTLR_EL1, VBAR_EL1};
use tock_registers::interfaces::{ReadWriteable, Writeable};
fn init_device_tree(fdt_base_phys: usize) -> Result<(), Errno> {
use fdt_rs::prelude::*;
let fdt = if fdt_base_phys != 0 {
DeviceTree::from_phys(fdt_base_phys + 0xFFFFFF8000000000)?
} else {
warnln!("No FDT present");
return Ok(());
};
use crate::debug::Level;
fdt.dump(Level::Debug);
let mut cfg = CONFIG.lock();
if let Some(chosen) = fdt.node_by_path("/chosen") {
if let Some(initrd_start) = find_prop(chosen.clone(), "linux,initrd-start") {
let initrd_end = find_prop(chosen.clone(), "linux,initrd-end").unwrap();
let initrd_start = initrd_start.u32(0).unwrap() as usize;
let initrd_end = initrd_end.u32(0).unwrap() as usize;
cfg.set_usize(ConfigKey::InitrdBase, initrd_start);
cfg.set_usize(ConfigKey::InitrdSize, initrd_end - initrd_start);
}
if let Some(cmdline) = find_prop(chosen, "bootargs") {
cfg.set_cmdline(cmdline.str().unwrap());
}
}
Ok(())
}
#[no_mangle]
extern "C" fn __aa64_bsp_main(fdt_base: usize) -> ! {
// Disable FP instruction trapping
@@ -49,6 +84,8 @@ extern "C" fn __aa64_bsp_main(fdt_base: usize) -> ! {
// physical memory
machine::init_board_early().unwrap();
init_device_tree(fdt_base).expect("Device tree init failed");
// Setup a heap
unsafe {
let heap_base_phys = phys::alloc_contiguous_pages(PageUsage::KernelHeap, 4096)
@@ -61,29 +98,14 @@ extern "C" fn __aa64_bsp_main(fdt_base: usize) -> ! {
machine::init_board().unwrap();
let initrd;
if fdt_base != 0 {
let fdt = DeviceTree::from_phys(fdt_base + 0xFFFFFF8000000000);
if let Ok(fdt) = fdt {
use crate::debug::Level;
fdt.dump(Level::Debug);
initrd = fdt.initrd();
} else {
initrd = None;
errorln!("Failed to init FDT");
}
} else {
initrd = None;
warnln!("No FDT present");
}
debugln!("Config: {:#x?}", CONFIG.lock());
infoln!("Machine init finished");
unsafe {
machine::local_timer().enable().unwrap();
machine::local_timer().init_irqs().unwrap();
proc::enter(initrd);
proc::enter();
}
}
@@ -11,6 +11,7 @@ use crate::dev::{
timer::TimestampSource,
Device,
};
use crate::fs::devfs::{self, CharDeviceType};
use crate::mem::phys;
use error::Errno;
@@ -43,6 +44,7 @@ pub fn init_board() -> Result<(), Errno> {
GPIO.enable()?;
UART0.init_irqs()?;
devfs::add_char_device(&UART0, CharDeviceType::TtySerial)?;
R_WDOG.enable()?;
@@ -71,7 +71,6 @@ impl RtcDevice for Rtc {}
impl IntSource for Rtc {
fn handle_irq(&self) -> Result<(), Errno> {
self.regs.get().lock().arm_alarm0_irq(1);
debugln!("Tick!");
Ok(())
}
+22 -3
View File
@@ -2,8 +2,9 @@ use crate::arch::machine::{self, IrqNumber};
use crate::dev::{
irq::{IntController, IntSource},
serial::SerialDevice,
Device,
tty::CharRing, Device,
};
use vfs::CharDevice;
use crate::mem::virt::DeviceMemoryIo;
use crate::sync::IrqSafeSpinLock;
use crate::util::InitOnce;
@@ -78,6 +79,7 @@ struct UartInner {
pub(super) struct Uart {
inner: InitOnce<IrqSafeSpinLock<UartInner>>,
ring: CharRing<16>,
base: usize,
irq: IrqNumber,
}
@@ -120,6 +122,23 @@ impl SerialDevice for Uart {
}
}
impl CharDevice for Uart {
fn read(&self, blocking: bool, data: &mut [u8]) -> Result<usize, Errno> {
assert!(blocking);
self.ring.line_read(data, self)
}
fn write(&self, blocking: bool, data: &[u8]) -> Result<usize, Errno> {
assert!(blocking);
for &byte in data {
unsafe {
self.send(byte)?;
}
}
Ok(data.len())
}
}
impl IntSource for Uart {
fn handle_irq(&self) -> Result<(), Errno> {
let byte = self.inner.get().lock().regs.DR_DLL.get();
@@ -132,8 +151,7 @@ impl IntSource for Uart {
}
}
use crate::dev::gpio::GpioDevice;
machine::GPIO.toggle_pin(machine::PinAddress::new(3, 26));
self.ring.putc(byte as u8, false).ok();
Ok(())
}
@@ -150,6 +168,7 @@ impl Uart {
pub const unsafe fn new(base: usize, irq: IrqNumber) -> Self {
Self {
inner: InitOnce::new(),
ring: CharRing::new(),
base,
irq,
}
+2 -2
View File
@@ -11,7 +11,7 @@ use crate::dev::{
serial::{pl011::Pl011, SerialDevice},
Device,
};
use crate::fs::devfs;
use crate::fs::devfs::{self, CharDeviceType};
use crate::mem::phys;
use error::Errno;
@@ -47,7 +47,7 @@ pub fn init_board() -> Result<(), Errno> {
GIC.enable()?;
UART0.init_irqs()?;
devfs::add_char_device("uart0", &UART0)?;
devfs::add_char_device(&UART0, CharDeviceType::TtySerial)?;
RTC.enable()?;
RTC.init_irqs()?;
+105
View File
@@ -0,0 +1,105 @@
#![allow(missing_docs)]
use crate::sync::IrqSafeSpinLock;
use core::fmt;
#[derive(Debug)]
pub struct Config {
cmdline: ConfigString<256>,
console: ConfigString<16>,
mem_limit: usize,
initrd_base: usize,
initrd_size: usize,
}
#[derive(Clone, Copy, Debug)]
pub enum ConfigKey {
Cmdline,
Console,
MemLimit,
InitrdBase,
InitrdSize
}
struct ConfigString<const N: usize> {
buf: [u8; N],
len: usize,
}
pub static CONFIG: IrqSafeSpinLock<Config> = IrqSafeSpinLock::new(Config::default());
impl const Default for Config {
fn default() -> Self {
Self {
cmdline: ConfigString::empty(),
console: ConfigString::empty(),
mem_limit: usize::MAX,
initrd_base: 0,
initrd_size: 0
}
}
}
impl Config {
pub fn set_usize(&mut self, key: ConfigKey, value: usize) {
match key {
ConfigKey::InitrdBase => { self.initrd_base = value }
ConfigKey::InitrdSize => { self.initrd_size = value }
ConfigKey::MemLimit => { self.mem_limit = value }
_ => panic!("Invalid usize key: {:?}", key)
}
}
pub fn set_str(&mut self, key: ConfigKey, value: &str) {
match key {
ConfigKey::Cmdline => { self.cmdline.set_from_str(value) }
_ => panic!("Invalid str key: {:?}", key)
}
}
pub fn get_usize(&self, key: ConfigKey) -> usize {
match key {
ConfigKey::InitrdBase => self.initrd_base,
ConfigKey::InitrdSize => self.initrd_size,
ConfigKey::MemLimit => self.mem_limit,
_ => panic!("Invalid usize key: {:?}", key)
}
}
pub fn get_str(&self, key: ConfigKey) -> &str {
match key {
ConfigKey::Cmdline => self.cmdline.as_str(),
ConfigKey::Console => self.console.as_str(),
_ => panic!("Invalid str key: {:?}", key)
}
}
pub fn set_cmdline(&self, cmdline: &str) {
// TODO
}
}
impl<const N: usize> ConfigString<N> {
pub const fn empty() -> Self {
Self {
buf: [0; N],
len: 0,
}
}
pub fn as_str(&self) -> &str {
core::str::from_utf8(&self.buf[..self.len]).unwrap()
}
pub fn set_from_str(&mut self, data: &str) {
let bytes = data.as_bytes();
self.buf[..bytes.len()].copy_from_slice(&bytes);
self.len = bytes.len();
}
}
impl<const N: usize> fmt::Debug for ConfigString<N> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.as_str())
}
}
+1 -1
View File
@@ -88,7 +88,7 @@ fn find_node<'a>(at: INode<'a>, path: &str) -> Option<INode<'a>> {
}
}
fn find_prop<'a>(at: INode<'a>, name: &str) -> Option<IProp<'a>> {
pub fn find_prop<'a>(at: INode<'a>, name: &str) -> Option<IProp<'a>> {
at.props().find(|p| p.name().unwrap() == name)
}
+31 -4
View File
@@ -1,7 +1,13 @@
use vfs::{Vnode, VnodeKind, CharDevice, VnodeRef, CharDeviceWrapper};
use alloc::boxed::Box;
use crate::util::InitOnce;
use alloc::boxed::Box;
use core::sync::atomic::{AtomicUsize, Ordering};
use error::Errno;
use vfs::{CharDevice, CharDeviceWrapper, Vnode, VnodeKind, VnodeRef};
#[derive(Debug)]
pub enum CharDeviceType {
TtySerial,
}
static DEVFS_ROOT: InitOnce<VnodeRef> = InitOnce::new();
@@ -13,8 +19,9 @@ pub fn root() -> &'static VnodeRef {
DEVFS_ROOT.get()
}
pub fn add_char_device(name: &str, dev: &'static dyn CharDevice) -> Result<(), Errno> {
debugln!("Add device: {}", name);
fn _add_char_device(dev: &'static dyn CharDevice, name: &str) -> Result<(), Errno> {
infoln!("Add char device: {}", name);
let node = Vnode::new(name, VnodeKind::Char, 0);
node.set_data(Box::new(CharDeviceWrapper::new(dev)));
@@ -22,3 +29,23 @@ pub fn add_char_device(name: &str, dev: &'static dyn CharDevice) -> Result<(), E
Ok(())
}
pub fn add_char_device(dev: &'static dyn CharDevice, kind: CharDeviceType) -> Result<(), Errno> {
static TTYS_COUNT: AtomicUsize = AtomicUsize::new(0);
let mut buf = [0u8; 32];
let (count, prefix) = match kind {
CharDeviceType::TtySerial => (&TTYS_COUNT, b"ttyS"),
};
let value = count.fetch_add(1, Ordering::Relaxed);
if value > 9 {
panic!("Too many character devices of type {:?}", kind);
}
buf[..prefix.len()].copy_from_slice(prefix);
buf[prefix.len()] = (value as u8) + b'0';
let name = core::str::from_utf8(&buf[..=prefix.len()]).map_err(|_| Errno::InvalidArgument)?;
_add_char_device(dev, name)
}
+53
View File
@@ -0,0 +1,53 @@
use crate::config::{ConfigKey, CONFIG};
use crate::fs::{devfs, MemfsBlockAlloc};
use crate::mem;
use crate::proc::{elf, Process};
use memfs::Ramfs;
use vfs::{FileMode, Filesystem, Ioctx};
#[inline(never)]
pub extern "C" fn init_fn(_arg: usize) -> ! {
let proc = Process::current();
debugln!("Running kernel init process");
let cfg = CONFIG.lock();
let initrd_start = cfg.get_usize(ConfigKey::InitrdBase);
let initrd_size = cfg.get_usize(ConfigKey::InitrdSize);
let console = cfg.get_str(ConfigKey::Console);
if initrd_start == 0 {
panic!("No initrd specified");
}
let initrd_start = mem::virtualize(initrd_start);
let fs =
unsafe { Ramfs::open(initrd_start as *mut u8, initrd_size, MemfsBlockAlloc {}).unwrap() };
let root = fs.root().unwrap();
let ioctx = Ioctx::new(root);
let node = ioctx.find(None, "/init", true).unwrap();
let mut file = node.open().unwrap();
proc.set_ioctx(ioctx);
// Open stdout
{
let devfs_root = devfs::root();
let tty_node = if console.is_empty() {
devfs_root.lookup("ttyS0")
} else {
devfs_root.lookup(console)
}.expect("Failed to open stdout for init process");
let mut io = proc.io.lock();
// TODO fd cloning?
io.place_file(tty_node.open().unwrap()).unwrap();
}
drop(cfg);
Process::execve(|space| elf::load_elf(space, &mut file), 0).unwrap();
panic!("Unreachable");
}
+4
View File
@@ -7,6 +7,7 @@
const_raw_ptr_deref,
const_fn_fn_ptr_basics,
const_fn_trait_bound,
const_trait_impl,
const_panic,
panic_info_message,
alloc_error_handler,
@@ -27,6 +28,7 @@ extern crate alloc;
pub mod debug;
pub mod arch;
pub mod config;
pub mod dev;
pub mod fs;
pub mod mem;
@@ -35,6 +37,8 @@ pub mod sync;
#[allow(missing_docs)]
pub mod syscall;
pub mod util;
#[allow(missing_docs)]
pub mod init;
#[panic_handler]
fn panic_handler(pi: &core::panic::PanicInfo) -> ! {
+3 -1
View File
@@ -1,5 +1,6 @@
//! Physical memory management facilities
use crate::config::{ConfigKey, CONFIG};
use crate::mem::PAGE_SIZE;
use core::mem::size_of;
use error::Errno;
@@ -133,12 +134,13 @@ pub unsafe fn init_from_iter<T: Iterator<Item = MemoryRegion> + Clone>(iter: T)
// Step 3. Initialize the memory manager with available pages
let mut manager = ManagerImpl::initialize(mem_base, pages_base, total_pages);
let mut usable_pages = 0usize;
let cfg = CONFIG.lock();
'l0: for region in iter {
for addr in (region.start..region.end).step_by(PAGE_SIZE) {
if !reserved::is_reserved(addr) {
manager.add_page(addr);
usable_pages += 1;
if usable_pages == MAX_PAGES {
if usable_pages >= cfg.get_usize(ConfigKey::MemLimit) {
break 'l0;
}
}
+3 -47
View File
@@ -1,6 +1,7 @@
//! Process and thread manipulation facilities
use crate::mem;
use crate::init;
use crate::sync::IrqSafeSpinLock;
use alloc::{boxed::Box, collections::BTreeMap};
@@ -57,53 +58,8 @@ pub(self) static PROCESSES: IrqSafeSpinLock<BTreeMap<Pid, ProcessRef>> =
/// # Safety
///
/// Unsafe: May only be called once.
pub unsafe fn enter(initrd: Option<(usize, usize)>) -> ! {
pub unsafe fn enter() -> ! {
SCHED.init();
let initrd = Box::into_raw(Box::new(initrd));
spawn!(fn (initrd_ptr: usize) {
use memfs::Ramfs;
use vfs::{Filesystem, Ioctx, FileMode};
use crate::fs::{MemfsBlockAlloc, devfs};
debugln!("Running kernel init process");
let initrd = unsafe { *(initrd_ptr as *const Option<(usize, usize)>) };
if let Some((start, end)) = initrd {
let proc = Process::current();
let size = end - start;
let start = mem::virtualize(start);
infoln!("Constructing initrd filesystem in memory, this may take a while...");
let fs = unsafe {
Ramfs::open(start as *mut u8, size, MemfsBlockAlloc {}).unwrap()
};
infoln!("Done constructing ramfs");
let root = fs.root().unwrap();
let devfs_root = devfs::root();
let dir = root.mkdir("dev", FileMode::default_dir()).unwrap();
dir.mount(devfs_root.clone()).unwrap();
let ioctx = Ioctx::new(root);
// Open a test file
let node = ioctx.find(None, "/init", true).unwrap();
let mut file = node.open().unwrap();
proc.set_ioctx(ioctx);
// Open stdout
{
let mut io = proc.io.lock();
let node = io.ioctx().find(None, "/dev/uart0", true).unwrap();
// TODO fd cloning?
io.place_file(node.open().unwrap()).unwrap();
}
Process::execve(|space| elf::load_elf(space, &mut file), 0).unwrap();
} else {
infoln!("No initrd, exiting!");
}
}, initrd as usize);
SCHED.enqueue(Process::new_kernel(init::init_fn, 0).unwrap().id());
SCHED.enter();
}
+2 -2
View File
@@ -71,9 +71,9 @@ impl<T> DerefMut for IrqSafeSpinLockGuard<'_, T> {
}
}
impl<T> fmt::Debug for IrqSafeSpinLockGuard<'_, T> {
impl<T: fmt::Debug> fmt::Debug for IrqSafeSpinLockGuard<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", &*self)
fmt::Debug::fmt(unsafe { &*self.lock.value.get() }, f)
}
}