feat(vfs): CoW for memfs, init start
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
use crate::debug::Level;
|
||||
use crate::util;
|
||||
use error::Errno;
|
||||
use fdt_rs::prelude::*;
|
||||
use fdt_rs::{
|
||||
base::DevTree,
|
||||
index::{DevTreeIndex, DevTreeIndexNode, DevTreeIndexProp},
|
||||
};
|
||||
use libcommon::path_component_left;
|
||||
|
||||
#[repr(align(16))]
|
||||
struct Wrap {
|
||||
@@ -74,7 +74,7 @@ fn dump_node(level: Level, node: &INode, depth: usize) {
|
||||
}
|
||||
|
||||
fn find_node<'a>(at: INode<'a>, path: &str) -> Option<INode<'a>> {
|
||||
let (item, path) = util::path_component_left(path);
|
||||
let (item, path) = path_component_left(path);
|
||||
if item == "" {
|
||||
assert_eq!(path, "");
|
||||
Some(at)
|
||||
|
||||
+29
-11
@@ -5,7 +5,9 @@ use crate::mem::{
|
||||
phys::{self, PageUsage},
|
||||
virt::{MapAttributes, Space},
|
||||
};
|
||||
use core::mem::{size_of, MaybeUninit};
|
||||
use error::Errno;
|
||||
use libcommon::{Read, Seek, SeekDir};
|
||||
|
||||
trait Elf {
|
||||
type Addr;
|
||||
@@ -86,12 +88,12 @@ fn map_flags(elf_flags: usize) -> MapAttributes {
|
||||
unsafe fn load_bytes<F>(
|
||||
space: &mut Space,
|
||||
dst_virt: usize,
|
||||
read: F,
|
||||
mut read: F,
|
||||
size: usize,
|
||||
flags: usize,
|
||||
) -> Result<(), Errno>
|
||||
where
|
||||
F: Fn(usize, &mut [u8]) -> Result<(), Errno>,
|
||||
F: FnMut(usize, &mut [u8]) -> Result<(), Errno>,
|
||||
{
|
||||
let dst_page_off = dst_virt & 0xFFF;
|
||||
let dst_page = dst_virt & !0xFFF;
|
||||
@@ -125,17 +127,32 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
unsafe fn read_struct<T, F: Seek + Read>(src: &mut F, pos: usize) -> Result<T, Errno> {
|
||||
let mut storage: MaybeUninit<T> = MaybeUninit::uninit();
|
||||
let size = size_of::<T>();
|
||||
src.seek(pos as isize, SeekDir::Set)?;
|
||||
let res = src.read(core::slice::from_raw_parts_mut(
|
||||
storage.as_mut_ptr() as *mut u8,
|
||||
size,
|
||||
))?;
|
||||
if res != size {
|
||||
Err(Errno::InvalidArgument)
|
||||
} else {
|
||||
Ok(storage.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
pub fn load_elf(space: &mut Space, elf_base: *const u8) -> Result<usize, Errno> {
|
||||
let ehdr: &Ehdr<Elf64> = unsafe { &*(elf_base as *const _) };
|
||||
pub fn load_elf<F: Seek + Read>(space: &mut Space, source: &mut F) -> Result<usize, Errno> {
|
||||
let ehdr: Ehdr<Elf64> = unsafe { read_struct(source, 0).unwrap() };
|
||||
|
||||
if &ehdr.ident[0..4] != b"\x7FELF" {
|
||||
return Err(Errno::InvalidArgument);
|
||||
}
|
||||
|
||||
for i in 0..(ehdr.phnum as usize) {
|
||||
let phdr: &Phdr<Elf64> = unsafe {
|
||||
&*(elf_base.add(ehdr.phoff as usize + ehdr.phentsize as usize * i) as *const _)
|
||||
let phdr: Phdr<Elf64> = unsafe {
|
||||
read_struct(source, ehdr.phoff as usize + ehdr.phentsize as usize * i).unwrap()
|
||||
};
|
||||
|
||||
if phdr.typ == 1
|
||||
@@ -154,11 +171,12 @@ pub fn load_elf(space: &mut Space, elf_base: *const u8) -> Result<usize, Errno>
|
||||
space,
|
||||
phdr.vaddr as usize,
|
||||
|off, dst| {
|
||||
let src = elf_base.add(phdr.offset as usize + off);
|
||||
assert!(off + dst.len() <= phdr.filesz as usize);
|
||||
let src_slice = core::slice::from_raw_parts(src, dst.len());
|
||||
dst.copy_from_slice(src_slice);
|
||||
Ok(())
|
||||
source.seek(phdr.offset as isize + off as isize, SeekDir::Set)?;
|
||||
if source.read(dst)? == dst.len() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Errno::InvalidArgument)
|
||||
}
|
||||
},
|
||||
phdr.filesz as usize,
|
||||
phdr.flags as usize,
|
||||
|
||||
@@ -66,21 +66,17 @@ pub unsafe fn enter(initrd: Option<(usize, usize)>) -> ! {
|
||||
let (start, end) = unsafe { *(initrd_ptr as *const (usize, usize)) };
|
||||
let size = end - start;
|
||||
|
||||
infoln!("Constructing initrd filesystem in memory, this may take a while...");
|
||||
let fs = Ramfs::open(start as *mut u8, size, MemfsBlockAlloc {}).unwrap();
|
||||
infoln!("Done constructing ramfs");
|
||||
let root = fs.root().unwrap();
|
||||
let ioctx = Ioctx::new(root);
|
||||
|
||||
// Open a test file
|
||||
let node = ioctx.find(None, "/test.txt").unwrap();
|
||||
let node = ioctx.find(None, "/init").unwrap();
|
||||
let mut file = node.open().unwrap();
|
||||
let mut buf = [0u8; 16];
|
||||
|
||||
while let Ok(count) = file.read(&mut buf) {
|
||||
if count == 0 {
|
||||
break;
|
||||
}
|
||||
debugln!("Read {} bytes: {:?}", count, &buf[0..count]);
|
||||
}
|
||||
Process::execve(|space| elf::load_elf(space, &mut file), 0).unwrap();
|
||||
}, initrd as usize);
|
||||
}
|
||||
SCHED.enter();
|
||||
|
||||
@@ -51,12 +51,3 @@ impl<T> InitOnce<T> {
|
||||
}
|
||||
|
||||
unsafe impl<T> Sync for InitOnce<T> {}
|
||||
|
||||
///
|
||||
pub fn path_component_left(path: &str) -> (&str, &str) {
|
||||
if let Some((left, right)) = path.split_once('/') {
|
||||
(left, right.trim_start_matches('/'))
|
||||
} else {
|
||||
(path, "")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user