aarch64: add dtb scheme

This commit is contained in:
Ivan Tan
2023-09-15 12:00:30 +08:00
committed by Jeremy Soller
parent a76cbc9f31
commit eb0d48ac81
5 changed files with 217 additions and 1 deletions
+3 -1
View File
@@ -9,7 +9,7 @@ use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use crate::memory::{Frame};
use crate::paging::{Page, PAGE_SIZE, PhysicalAddress, VirtualAddress};
use crate::allocator;
use crate::{allocator, dtb};
use crate::device;
#[cfg(feature = "graphical_debug")]
use crate::devices::graphical_debug;
@@ -154,6 +154,8 @@ pub unsafe extern "C" fn kstart(args_ptr: *const KernelArgs) -> ! {
// Initialize devices
device::init();
dtb::init(Some((crate::PHYS_OFFSET + args.dtb_base, args.dtb_size)));
// Initialize all of the non-core devices not otherwise needed to complete initialization
device::init_noncore();
+23
View File
@@ -0,0 +1,23 @@
use core::slice;
use alloc::vec::Vec;
use spin::once::Once;
pub static DTB_BINARY: Once<Vec<u8>> = Once::new();
pub unsafe fn init(dtb: Option<(usize, usize)>) {
let mut initialized = false;
DTB_BINARY.call_once(|| {
initialized = true;
let mut binary = Vec::new();
if let Some((dtb_base, dtb_size)) = dtb {
let data = unsafe { slice::from_raw_parts(dtb_base as *const u8, dtb_size) };
binary.extend(data);
};
binary
});
if !initialized {
println!("DTB_BINARY INIT TWICE!");
}
}
+3
View File
@@ -89,6 +89,9 @@ pub mod allocator;
#[cfg(all(feature = "acpi", any(target_arch = "x86", target_arch = "x86_64")))]
mod acpi;
#[cfg(all(any(target_arch = "aarch64")))]
mod dtb;
/// Context management
pub mod context;
+181
View File
@@ -0,0 +1,181 @@
use core::sync::atomic::{self, AtomicUsize};
use alloc::boxed::Box;
use alloc::collections::BTreeMap;
use spin::{Once, RwLock};
use crate::dtb::DTB_BINARY;
use crate::scheme::SchemeId;
use crate::syscall::flag::{
MODE_FILE,
O_STAT,
SEEK_CUR, SEEK_END, SEEK_SET,
};
use crate::syscall::data::Stat;
use crate::syscall::scheme::Scheme;
use crate::syscall::error::*;
use crate::syscall::usercopy::{UserSliceRo, UserSliceWo};
use super::KernelScheme;
pub struct DtbScheme;
#[derive(Eq, PartialEq)]
enum HandleKind {
RawData,
}
struct Handle {
offset: usize,
kind: HandleKind,
stat: bool,
}
static HANDLES: RwLock<BTreeMap<usize, Handle>> = RwLock::new(BTreeMap::new());
static NEXT_FD: AtomicUsize = AtomicUsize::new(0);
static DATA: Once<Box<[u8]>> = Once::new();
static SCHEME_ID: Once<SchemeId> = Once::new();
impl DtbScheme {
pub fn new(id: SchemeId) -> Self {
let mut id_init = false;
let mut data_init = false;
DATA.call_once(|| {
data_init = true;
let dtb = match DTB_BINARY.get() {
Some(dtb) => dtb.as_slice(),
None => &[]
};
Box::from(dtb)
});
SCHEME_ID.call_once(|| {
id_init = true;
id
});
if !data_init || !id_init {
log::error!("DtbScheme::new called multiple times");
}
Self
}
}
impl Scheme for DtbScheme {
fn open(&self, path: &str, _flags: usize, uid: u32, _gid: u32) -> Result<usize> {
if uid != 0 {
return Err(Error::new(EACCES));
}
let path = path.trim_matches('/');
if path.is_empty() {
let id = NEXT_FD.fetch_add(1, atomic::Ordering::Relaxed);
let mut handles_guard = HANDLES.write();
let _ = handles_guard.insert(id, Handle {
offset: 0,
kind: HandleKind::RawData,
stat: _flags & O_STAT == O_STAT,
});
return Ok(id)
}
Err(Error::new(ENOENT))
}
fn seek(&self, id: usize, pos: isize, whence: usize) -> Result<isize> {
let mut handles = HANDLES.write();
let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;
if handle.stat {
return Err(Error::new(EBADF));
}
let file_len = match handle.kind {
HandleKind::RawData => DATA.get().ok_or(Error::new(EBADFD))?.len(),
};
let new_offset = match whence {
SEEK_SET => pos as usize,
SEEK_CUR => if pos < 0 {
handle.offset.checked_sub((-pos) as usize).ok_or(Error::new(EINVAL))?
} else {
handle.offset.saturating_add(pos as usize)
}
SEEK_END => if pos < 0 {
file_len.checked_sub((-pos) as usize).ok_or(Error::new(EINVAL))?
} else {
file_len
}
_ => return Err(Error::new(EINVAL)),
};
handle.offset = new_offset;
Ok(new_offset as isize)
}
fn close(&self, id: usize) -> Result<usize> {
if HANDLES.write().remove(&id).is_none() {
return Err(Error::new(EBADF));
}
Ok(0)
}
}
impl KernelScheme for DtbScheme {
fn kwrite(&self, _id: usize, _buf: UserSliceRo) -> Result<usize> {
Err(Error::new(EBADF))
}
fn kread(&self, id: usize, dst_buf: UserSliceWo) -> Result<usize> {
let mut handles = HANDLES.write();
let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;
if handle.stat {
return Err(Error::new(EBADF));
}
let data = match handle.kind {
HandleKind::RawData => DATA.get().ok_or(Error::new(EBADFD))?,
};
let src_offset = core::cmp::min(handle.offset, data.len());
let src_buf = data
.get(src_offset..)
.expect("expected data to be at least data.len() bytes long");
let bytes_copied = dst_buf.copy_common_bytes_from_slice(src_buf)?;
handle.offset += bytes_copied;
Ok(bytes_copied)
}
fn kfstat(&self, id: usize, buf: UserSliceWo) -> Result<usize> {
let handles = HANDLES.read();
let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
buf.copy_exactly(&match handle.kind {
HandleKind::RawData => {
let data = DATA.get().ok_or(Error::new(EBADFD))?;
Stat {
st_mode: MODE_FILE,
st_uid: 0,
st_gid: 0,
st_size: data.len().try_into().unwrap_or(u64::max_value()),
..Default::default()
}
}
})?;
Ok(0)
}
}
+7
View File
@@ -25,6 +25,8 @@ use crate::syscall::usercopy::{UserSliceRo, UserSliceWo};
#[cfg(all(feature = "acpi", any(target_arch = "x86", target_arch = "x86_64")))]
use self::acpi::AcpiScheme;
#[cfg(all(any(target_arch = "aarch64")))]
use self::dtb::DtbScheme;
use self::debug::DebugScheme;
use self::event::EventScheme;
@@ -42,6 +44,8 @@ use self::user::UserInner;
/// When compiled with the "acpi" feature - `acpi:` - allows drivers to read a limited set of ACPI tables.
#[cfg(all(feature = "acpi", any(target_arch = "x86", target_arch = "x86_64")))]
pub mod acpi;
#[cfg(all(any(target_arch = "aarch64")))]
pub mod dtb;
/// `debug:` - provides access to serial console
pub mod debug;
@@ -164,6 +168,9 @@ impl SchemeList {
#[cfg(all(feature = "acpi", any(target_arch = "x86", target_arch = "x86_64")))] {
self.insert(ns, "kernel/acpi", |scheme_id| Arc::new(AcpiScheme::new(scheme_id))).unwrap();
}
#[cfg(all(any(target_arch = "aarch64")))] {
self.insert(ns, "kernel/dtb", |scheme_id| Arc::new(DtbScheme::new(scheme_id))).unwrap();
}
self.insert(ns, "debug", |scheme_id| Arc::new(DebugScheme::new(scheme_id))).unwrap();
self.insert(ns, "irq", |scheme_id| Arc::new(IrqScheme::new(scheme_id))).unwrap();
self.insert(ns, "proc", |scheme_id| Arc::new(ProcScheme::new(scheme_id))).unwrap();