mirror of
https://github.com/obhq/obliteration.git
synced 2024-11-23 11:19:56 +00:00
Initializes kernel process
This commit is contained in:
parent
d1fc330d8c
commit
ca26853d27
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
/.kernel-debug
|
||||
/build/
|
||||
/src/target/
|
||||
|
10
.vscode/launch.json
vendored
10
.vscode/launch.json
vendored
@ -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"
|
||||
|
@ -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).
|
||||
|
@ -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
69
src/Cargo.lock
generated
@ -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"
|
||||
|
@ -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" }
|
||||
|
@ -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
22
src/kernel/src/fs/file.rs
Normal 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()
|
||||
}
|
||||
}
|
@ -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,
|
||||
|
@ -26,5 +26,9 @@ macro_rules! error {
|
||||
|
||||
// End with full stop and new line.
|
||||
eprintln!(".");
|
||||
}}
|
||||
}};
|
||||
($pid:expr, $($arg:tt)*) => {
|
||||
eprint!("{}: ", $pid);
|
||||
eprintln!($($arg)*);
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
24
src/kernel/src/process/mod.rs
Normal file
24
src/kernel/src/process/mod.rs
Normal 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(())
|
||||
}
|
||||
}
|
@ -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 {}
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user