Initializes kernel process

This commit is contained in:
Putta Khunchalee 2022-10-08 04:56:17 +07:00
parent d1fc330d8c
commit ca26853d27
15 changed files with 353 additions and 34 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
/.kernel-debug
/build/
/src/target/

10
.vscode/launch.json vendored
View File

@ -1,12 +1,20 @@
{
"configurations": [
{
"name": "Launch",
"name": "Main",
"type": "lldb",
"request": "launch",
"program": "${workspaceFolder}/build/src/obliteration",
"args": [],
"cwd": "${workspaceFolder}"
},
{
"name": "Kernel",
"type": "lldb",
"request": "launch",
"program": "${workspaceFolder}/src/target/debug/obliteration-kernel",
"args": ["--debug"],
"cwd": "${workspaceFolder}"
}
],
"version": "2.0.0"

View File

@ -153,6 +153,10 @@ The application consist of 2 binaries:
1. Main application. This is what user will see when they launch Obliteration. Its entry point is inside `src/main.cpp`.
2. Emulator kernel. This is where PS4 emulation take place. Its entry point is inside `src/kernel/src/main.rs`.
### Debugging kernel
Create `.kernel-debug` in the root of repository. The content of this file is YAML and the kernel will deserialize it to `Args` struct in `src/kernel/src/main.rs` when passing `--debug` flag to the kernel. We already provided a launch configuration for VS Code so all you need to do is just choose `Kernel` as a configuration and start debugging.
### Action icons
We use icons from https://materialdesignicons.com for action icon (e.g. on menu and toolbar).

View File

@ -141,8 +141,8 @@ struct SelfHeader
uint8_t ident[12];
uint16_t size1;
uint16_t size2;
uint64_t file_size;
uint16_t segments_num;
uint64_t file_size; // 0x10
uint16_t segments_num; // 0x18
uint16_t unknown;
uint32_t pad;
};

69
src/Cargo.lock generated
View File

@ -255,6 +255,12 @@ dependencies = [
"wasi",
]
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "heck"
version = "0.4.0"
@ -279,6 +285,16 @@ dependencies = [
"digest",
]
[[package]]
name = "indexmap"
version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]]
name = "inout"
version = "0.1.3"
@ -289,6 +305,12 @@ dependencies = [
"generic-array",
]
[[package]]
name = "itoa"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
[[package]]
name = "kernel"
version = "0.1.0"
@ -296,6 +318,8 @@ dependencies = [
"clap",
"memmap2",
"pfs",
"serde",
"serde_yaml",
"util",
]
@ -554,6 +578,45 @@ dependencies = [
"zeroize",
]
[[package]]
name = "ryu"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
[[package]]
name = "serde"
version = "1.0.145"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.145"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_yaml"
version = "0.9.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8613d593412a0deb7bbd8de9d908efff5a0cb9ccd8f62c641e7b2ed2f57291d1"
dependencies = [
"indexmap",
"itoa",
"ryu",
"serde",
"unsafe-libyaml",
]
[[package]]
name = "sha2"
version = "0.10.6"
@ -631,6 +694,12 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
[[package]]
name = "unsafe-libyaml"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1e5fa573d8ac5f1a856f8d7be41d390ee973daf97c806b2c1a465e4e1406e68"
[[package]]
name = "util"
version = "0.1.0"

View File

@ -11,4 +11,6 @@ path = "src/main.rs"
clap = { version = "4.0", features = ["derive"] }
memmap2 = "0.5"
pfs = { path = "../pfs" }
serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.9"
util = { path = "../util" }

View File

@ -1,4 +1,5 @@
use std::error::Error;
use std::fmt::Display;
pub trait Driver {
fn open_root(&self, path: &str) -> Result<Box<dyn Directory + '_>, OpenError>;
@ -24,7 +25,26 @@ pub trait File<'driver> {
pub trait FileToken {}
#[derive(Debug)]
pub enum OpenError {
NotFound,
DriverFailed(Box<dyn Error>),
}
impl Error for OpenError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::DriverFailed(e) => Some(e.as_ref()),
_ => None,
}
}
}
impl Display for OpenError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::NotFound => f.write_str("not found"),
Self::DriverFailed(_) => f.write_str("driver failed"),
}
}
}

22
src/kernel/src/fs/file.rs Normal file
View File

@ -0,0 +1,22 @@
use super::driver::{Driver, FileToken};
use std::sync::Arc;
pub struct File {
driver: Arc<dyn Driver>,
token: Box<dyn FileToken>,
path: String,
}
impl File {
pub(super) fn new(driver: Arc<dyn Driver>, token: Box<dyn FileToken>, path: String) -> Self {
Self {
driver,
token,
path,
}
}
pub fn path(&self) -> &str {
self.path.as_ref()
}
}

View File

@ -1,10 +1,12 @@
use self::driver::Driver;
use self::file::File;
use std::collections::HashMap;
use std::error::Error;
use std::fmt::{Debug, Display, Formatter};
use std::sync::{Arc, RwLock};
pub mod driver;
pub mod file;
pub mod path;
pub struct Fs {
@ -52,22 +54,22 @@ impl Fs {
Ok(v) => v,
Err(e) => return Err(GetError::DriverFailed(current, e)),
};
} else {
// Open directory.
let entry = match directory.open(component) {
Ok(v) => v,
Err(e) => return Err(GetError::DriverFailed(current, e)),
};
continue;
}
// Open directory.
let entry = match directory.open(component) {
Ok(v) => v,
Err(e) => return Err(GetError::DriverFailed(current, e)),
};
match entry {
driver::Entry::Directory(v) => directory = v,
driver::Entry::File(v) => {
return Ok(Item::File(File(driver.clone(), v.to_token())));
match entry {
driver::Entry::Directory(v) => directory = v,
driver::Entry::File(v) => {
return Ok(Item::File(File::new(driver.clone(), v.to_token(), current)));
}
}
}
current.push('/');
}
// If we reached here that mean the the last component is a directory.
@ -102,14 +104,32 @@ pub enum Item {
pub struct Directory(Arc<dyn Driver>, Box<dyn driver::DirectoryToken>);
pub struct File(Arc<dyn Driver>, Box<dyn driver::FileToken>);
#[derive(Debug)]
pub enum GetError {
InvalidPath,
NoRootFs,
DriverFailed(String, driver::OpenError),
}
impl Error for GetError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::DriverFailed(_, e) => Some(e),
_ => None,
}
}
}
impl Display for GetError {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
match self {
Self::InvalidPath => f.write_str("invalid path"),
Self::NoRootFs => f.write_str("no rootfs mounted"),
Self::DriverFailed(p, _) => write!(f, "driver failed on {}", p),
}
}
}
#[derive(Debug)]
pub enum MountError {
AlreadyMounted,

View File

@ -26,5 +26,9 @@ macro_rules! error {
// End with full stop and new line.
eprintln!(".");
}}
}};
($pid:expr, $($arg:tt)*) => {
eprint!("{}: ", $pid);
eprintln!($($arg)*);
}
}

View File

@ -1,6 +1,8 @@
use self::fs::Fs;
use self::process::Process;
use self::rootfs::RootFs;
use clap::Parser;
use serde::Deserialize;
use std::fs::File;
use std::path::{Path, PathBuf};
use std::sync::Arc;
@ -8,11 +10,12 @@ use std::sync::Arc;
mod fs;
mod log;
mod pfs;
mod process;
mod rootfs;
#[derive(Parser)]
#[derive(Parser, Deserialize)]
struct Args {
#[arg(short, long)]
#[arg(long)]
game: PathBuf,
}
@ -22,8 +25,27 @@ fn main() {
fn run() -> bool {
// Load arguments.
let args = Args::parse();
let args = if std::env::args().any(|a| a == "--debug") {
let file = match File::open(".kernel-debug") {
Ok(v) => v,
Err(e) => {
error!(0, e, "Failed to open .kernel-debug");
return false;
}
};
match serde_yaml::from_reader(file) {
Ok(v) => v,
Err(e) => {
error!(0, e, "Failed to read .kernel-debug");
return false;
}
}
} else {
Args::parse()
};
// Show basic infomation.
info!(0, "Starting Obliteration kernel.");
info!(0, "Game directory is {}.", args.game.display());
@ -41,6 +63,34 @@ fn run() -> bool {
return false;
}
// Get eboot.bin.
info!(0, "Getting /mnt/app0/eboot.bin.");
let app = match fs.get("/mnt/app0/eboot.bin") {
Ok(v) => match v {
fs::Item::Directory(_) => {
error!(0, "Path to eboot.bin is a directory.");
return false;
}
fs::Item::File(v) => v,
},
Err(e) => {
error!(0, e, "Getting failed");
return false;
}
};
// Load eboot.bin.
info!(0, "Loading {}.", app.path());
let app = match Process::load(app) {
Ok(v) => v,
Err(e) => {
error!(0, e, "Load failed");
return false;
}
};
loop {}
}
@ -72,7 +122,14 @@ fn mount_pfs<G: AsRef<Path>>(fs: &Fs, game: G) -> bool {
}
};
// Load PFS image.
info!(
0,
"PFS is mapped to {:p} - {:p}.",
&raw[..],
&raw[raw.len()..]
);
// Create reader.
info!(0, "Initializing PFS reader.");
let image = match ::pfs::open(raw, None) {
@ -83,6 +140,16 @@ fn mount_pfs<G: AsRef<Path>>(fs: &Fs, game: G) -> bool {
}
};
let hdr = image.header();
info!(0, "Mode : {}", hdr.mode());
info!(0, "Block size : {}", hdr.block_size());
info!(0, "Inodes : {}", hdr.inode_count());
info!(0, "Inode blocks: {}", hdr.inode_block_count());
info!(0, "Super-root : {}", hdr.super_root_inode());
info!(0, "Key seed : {:02x?}", hdr.key_seed());
// Load PFS.
info!(0, "Loading PFS.");
let pfs = match ::pfs::mount(image) {

View File

@ -13,12 +13,30 @@ impl<'image> Pfs<'image> {
impl<'image> driver::Driver for Pfs<'image> {
fn open_root(&self, _: &str) -> Result<Box<dyn driver::Directory + '_>, OpenError> {
match self.pfs.open_super_root() {
Ok(v) => Ok(Box::new(Directory {
pfs: v,
// Open super-root.
let super_root = match self.pfs.open_super_root() {
Ok(v) => v,
Err(e) => return Err(OpenError::DriverFailed(e.into())),
};
// Open "uroot", which is a real root.
let entries = match super_root.open() {
Ok(v) => v,
Err(e) => return Err(OpenError::DriverFailed(e.into())),
};
let uroot = match entries.get(b"uroot") {
Some(v) => v,
None => return Err(OpenError::NotFound),
};
// Check if uroot is a directory.
match uroot {
pfs::directory::Item::Directory(v) => Ok(Box::new(Directory {
pfs: v.clone(),
phantom: PhantomData,
})),
Err(e) => Err(OpenError::DriverFailed(e.into())),
pfs::directory::Item::File(_) => Err(OpenError::NotFound),
}
}
}

View File

@ -0,0 +1,24 @@
use crate::fs::file::File;
use std::error::Error;
use std::fmt::{Display, Formatter};
pub struct Process {
bin: File,
}
impl Process {
pub(super) fn load(bin: File) -> Result<Self, LoadError> {
Ok(Self { bin })
}
}
#[derive(Debug)]
pub enum LoadError {}
impl Error for LoadError {}
impl Display for LoadError {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
Ok(())
}
}

View File

@ -1,4 +1,4 @@
use crate::fs::driver::{Driver, Entry, OpenError};
use crate::fs::driver::{self, Driver, Entry, OpenError};
use std::marker::PhantomData;
/// Represents a virtual root file system. The directory structure the kernel will see will be the
@ -12,27 +12,45 @@ impl RootFs {
}
impl Driver for RootFs {
fn open_root(&self, _: &str) -> Result<Box<dyn crate::fs::driver::Directory + '_>, OpenError> {
fn open_root(&self, path: &str) -> Result<Box<dyn driver::Directory + '_>, OpenError> {
Ok(Box::new(Directory {
path: path.into(),
phantom: PhantomData,
}))
}
}
struct Directory<'driver> {
path: String,
phantom: PhantomData<&'driver RootFs>,
}
impl<'driver> crate::fs::driver::Directory<'driver> for Directory<'driver> {
fn open(&self, _: &str) -> Result<Entry<'driver>, OpenError> {
Err(OpenError::NotFound)
impl<'driver> driver::Directory<'driver> for Directory<'driver> {
fn open(&self, name: &str) -> Result<Entry<'driver>, OpenError> {
// Build full path.
let path = if self.path == "/" {
format!("/{}", name)
} else {
format!("{}/{}", self.path, name)
};
// Map entry.
let entry = match path.as_str() {
"/mnt" | "/mnt/app0" => Entry::Directory(Box::new(Directory {
path,
phantom: PhantomData,
})),
_ => return Err(OpenError::NotFound),
};
Ok(entry)
}
fn to_token(&self) -> Box<dyn crate::fs::driver::DirectoryToken> {
fn to_token(&self) -> Box<dyn driver::DirectoryToken> {
Box::new(DirectoryToken {})
}
}
struct DirectoryToken;
impl crate::fs::driver::DirectoryToken for DirectoryToken {}
impl driver::DirectoryToken for DirectoryToken {}

View File

@ -103,6 +103,48 @@ impl Mode {
}
}
impl Display for Mode {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
write!(f, "{:x}", self.0)?;
let mut op = false;
let mut first = true;
let mut flag = |name: &str| -> std::fmt::Result {
if !op {
f.write_str(" (")?;
op = true;
}
if !first {
f.write_str(", ")?;
}
f.write_str(name)?;
first = false;
Ok(())
};
if self.is_signed() {
flag("signed")?;
}
if self.is_64bits() {
flag("64-bits")?;
}
if self.is_encrypted() {
flag("encrypted")?;
}
if op {
f.write_str(")")?;
}
Ok(())
}
}
#[derive(Debug)]
pub enum ReadError {
TooSmall,