aarch64: add dtb scheme
This commit is contained in:
@@ -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();
|
||||
|
||||
|
||||
@@ -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!");
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user