Skip to content

Commit

Permalink
Revises dump reader
Browse files Browse the repository at this point in the history
  • Loading branch information
ultimaweapon committed Dec 1, 2024
1 parent ebae8d0 commit 1f6f06d
Show file tree
Hide file tree
Showing 9 changed files with 312 additions and 207 deletions.
4 changes: 2 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"[rust]": {
"editor.defaultFormatter": "rust-lang.rust-analyzer",
"editor.formatOnSave": true
},
"files.insertFinalNewline": true,
Expand All @@ -9,8 +10,7 @@
"rust-analyzer.cargo.extraEnv": {
"RUSTFLAGS": "--cfg fw=\"1100\""
},
"rust-analyzer.cargo.features": ["read", "write"],
"rust-analyzer.cargo.target": "x86_64-unknown-none",
"rust-analyzer.cargo.features": "all",
"rust-analyzer.imports.granularity.enforce": true,
"rust-analyzer.imports.granularity.group": "module",
"rust-analyzer.imports.group.enable": false
Expand Down
23 changes: 22 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 6 additions & 9 deletions dumper/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use core::mem::{zeroed, MaybeUninit};
use core::panic::PanicInfo;
use core::ptr::null_mut;
use obfw::ps4::PartItem;
use obfw::FirmwareDump;
use obfw::{DumpItem, MAGIC};
use okf::fd::{openat, write_all, OpenFlags, AT_FDCWD};
use okf::lock::MtxLock;
use okf::mount::{Filesystem, FsOps, FsStats, Mount};
Expand Down Expand Up @@ -92,7 +92,7 @@ fn run<K: Kernel>(k: K) {
};

// Write magic.
if !write_dump(k, fd.as_raw_fd(), FirmwareDump::<()>::MAGIC) {
if !write_dump(k, fd.as_raw_fd(), MAGIC) {
return;
}

Expand Down Expand Up @@ -141,11 +141,7 @@ fn run<K: Kernel>(k: K) {
}

// Write end entry.
if !write_dump(
k,
fd.as_raw_fd(),
core::slice::from_ref(&FirmwareDump::<()>::ITEM_END),
) {
if !write_dump(k, fd.as_raw_fd(), &[DumpItem::End.into()]) {
return;
}

Expand Down Expand Up @@ -174,7 +170,7 @@ unsafe fn dump_mount<K: Kernel>(k: K, fd: c_int, mp: *mut K::Mount, lock: MtxLoc
}

// Write entry type.
if !write_dump(k, fd, &[FirmwareDump::<()>::ITEM_PARTITION]) {
if !write_dump(k, fd, &[DumpItem::Ps4Part.into()]) {
return false;
}

Expand Down Expand Up @@ -443,7 +439,8 @@ fn notify<K: Kernel>(k: K, msg: &str) {
unsafe { write_all(k, fd.as_raw_fd(), data, td).ok() };
}

#[panic_handler]
#[allow(dead_code)]
#[cfg_attr(target_os = "none", panic_handler)]
fn panic(_: &PanicInfo) -> ! {
// Nothing to do here since we enabled panic_immediate_abort.
unsafe { unreachable_unchecked() };
Expand Down
2 changes: 1 addition & 1 deletion obfw/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ edition = "2021"

[features]
read = []
std = []
write = []

[dependencies]
num_enum = { version = "0.7.3", default-features = false }
thiserror = { version = "2.0.3", default-features = false }
40 changes: 0 additions & 40 deletions obfw/src/io.rs

This file was deleted.

174 changes: 20 additions & 154 deletions obfw/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,170 +1,36 @@
#![no_std]

pub use self::io::*;

mod io;
pub mod ps4;

#[cfg(feature = "read")]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;

/// Encapsulates a firmware dump.
pub struct FirmwareDump<F> {
file: F,
}

impl<F> FirmwareDump<F> {
pub const MAGIC: &'static [u8; 4] = b"\x7FOBF";
pub const ITEM_END: u8 = 0;
pub const ITEM_PARTITION: u8 = 1;

pub fn new(file: F) -> Self {
Self { file }
}
}

#[cfg(feature = "read")]
impl<F: DumpRead> FirmwareDump<F> {
pub fn read(&mut self) -> Result<FirmwareItems<F>, ItemError<F::Err>> {
Ok(FirmwareItems {
file: &mut self.file,
})
}
}

/// Iterator to numerate items in a firmware dump.
///
/// This type does not implement [`Iterator`] due to its [`Iterator::Item`] has incompatible
/// lifetime.
#[cfg(feature = "read")]
pub struct FirmwareItems<'a, F> {
file: &'a mut F,
}

#[cfg(feature = "read")]
impl<'a, F: DumpRead> FirmwareItems<'a, F> {
#[allow(clippy::should_implement_trait)] // We want to be able to drop-in implement Iterator.
pub fn next(&mut self) -> Option<Result<FirmwareItem<F>, ItemError<F::Err>>> {
// Read item type.
let mut ty = 0;

if let Err(e) = self.file.read(core::slice::from_mut(&mut ty)) {
return Some(Err(ItemError::ReadFailed(e)));
}

if ty == FirmwareDump::<F>::ITEM_END {
return None;
}

// Read item version.
let mut ver = 0;

if let Err(e) = self.file.read(core::slice::from_mut(&mut ver)) {
return Some(Err(ItemError::ReadFailed(e)));
}

// Read item data.
Some(match (ty, ver) {
(FirmwareDump::<F>::ITEM_PARTITION, 0) => self
.read_partition_v0()
.map(|v| FirmwareItem::Partition(v.0, v.1)),
(FirmwareDump::<F>::ITEM_PARTITION, _) => Err(ItemError::UnknownVersion(ty, ver)),
_ => Err(ItemError::UnknownItem(ty)),
})
}
pub use self::reader::*;

fn read_partition_v0(
&mut self,
) -> Result<(alloc::string::String, ItemReader<F>), ItemError<F::Err>> {
// Read name length.
let mut len = 0;
use core::fmt::{Display, Formatter};
use num_enum::{IntoPrimitive, TryFromPrimitive};

self.file
.read(core::slice::from_mut(&mut len))
.map_err(ItemError::ReadFailed)?;

// Read name.
let mut name = alloc::vec![0; len.into()];

self.file.read(&mut name).map_err(ItemError::ReadFailed)?;

// Check if name valid.
let name = alloc::string::String::from_utf8(name).map_err(|_| ItemError::FileCorrupted)?;

// Read data length.
let mut len = [0; 8];
let len = match self.file.read(&mut len) {
Ok(_) => u64::from_le_bytes(len),
Err(e) => return Err(ItemError::ReadFailed(e)),
};

Ok((name, ItemReader::new(self.file, len)))
}
}

/// Encapsulates an item in a firmware dump.
#[cfg(feature = "read")]
pub enum FirmwareItem<'a, F: DumpRead> {
Partition(alloc::string::String, ItemReader<'a, F>),
}
pub mod ps4;

/// Struct to read a raw item in a firmware dump.
///
/// [`Drop`] implementation on this struct may panic if there are some unread data.
#[cfg(feature = "read")]
pub struct ItemReader<'a, F: DumpRead> {
file: &'a mut F,
pos: u64,
len: u64,
}
mod reader;

#[cfg(feature = "read")]
impl<'a, F: DumpRead> ItemReader<'a, F> {
fn new(file: &'a mut F, len: u64) -> Self {
Self { file, pos: 0, len }
}
}
extern crate std;

#[cfg(feature = "read")]
impl<'a, F: DumpRead> Drop for ItemReader<'a, F> {
fn drop(&mut self) {
if self.pos != self.len {
self.file.seek(self.pos).unwrap();
}
}
}
pub const MAGIC: &'static [u8; 4] = b"\x7FOBF";

/// Represents an error when [`FirmwareDump::read()`] or [`FirmwareItems`] fails to enumerate a next
/// item.
#[cfg(feature = "read")]
#[derive(Debug)]
pub enum ItemError<F> {
FileCorrupted,
ReadFailed(F),
UnknownItem(u8),
UnknownVersion(u8, u8),
/// Type of top-level item in the dump file.
#[repr(u8)]
#[derive(Debug, Clone, Copy, IntoPrimitive, TryFromPrimitive)]
pub enum DumpItem {
End = 0,
Ps4Part = 1,
}

#[cfg(all(feature = "read", feature = "std"))]
impl<F: std::error::Error + 'static> std::error::Error for ItemError<F> {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::ReadFailed(e) => Some(e),
_ => None,
}
}
}
impl Display for DumpItem {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
let v = match self {
Self::End => "",
Self::Ps4Part => "PlayStation 4 partition",
};

#[cfg(feature = "read")]
impl<F> core::fmt::Display for ItemError<F> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::FileCorrupted => f.write_str("file corrupted"),
Self::ReadFailed(_) => f.write_str("couldn't read the file"),
Self::UnknownItem(ty) => write!(f, "unknown item type {ty}"),
Self::UnknownVersion(ty, ver) => write!(f, "unknown version {ver} on item type {ty}"),
}
f.write_str(v)
}
}
6 changes: 6 additions & 0 deletions obfw/src/ps4.rs → obfw/src/ps4/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
#[cfg(feature = "read")]
pub use self::part::*;

use num_enum::{IntoPrimitive, TryFromPrimitive};

#[cfg(feature = "read")]
mod part;

/// Type of item in the partition dump.
#[repr(u8)]
#[derive(Clone, Copy, PartialEq, Eq, IntoPrimitive, TryFromPrimitive)]
Expand Down
Loading

0 comments on commit 1f6f06d

Please sign in to comment.