use Error;
use serde::de;
use std::{fmt, u32};
use std::marker::PhantomData;
#[derive(Debug, Deserialize)]
pub struct Header {
pub magic: u32,
pub signature: Signature,
pub base_addr: u32,
pub header_size: u32,
pub image_size: u32,
pub image_header_size: u32,
pub time_date: u32,
pub cert_addr: u32,
pub num_sections: u32,
pub section_headers_addr: u32,
pub init_flags: u32,
pub entry_point: u32,
pub tls_addr: u32,
pub pe_stack_commit: u32,
pub pe_heap_reserve: u32,
pub pe_heap_commit: u32,
pub pe_base_addr: u32,
pub pe_size: u32,
pub pe_checksum: u32,
pub pe_time_date: u32,
pub debug_pathname_addr: u32,
pub debug_filename_addr: u32,
pub debug_unicode_filename_addr: u32,
pub kernel_thunk_addr: u32,
pub non_kernel_import_dir_addr: u32,
pub num_library_versions: u32,
pub library_versions_addr: u32,
pub kernel_library_version_addr: u32,
pub xapi_library_version_addr: u32,
pub logo_bitmap_addr: u32,
pub logo_bitmap_size: u32,
}
impl Header {
pub fn parse(data: &mut &[u8]) -> Result<Self, Error> {
::bincode::deserialize_from(data).map_err(|e| Error::Malformed(format!("{:?}", e)))
}
pub fn rel_addr(&self, addr: u32) -> u32 {
addr.checked_sub(self.base_addr)
.unwrap_or(u32::MAX)
}
}
struct SliceAdapter<F, S: 'static, R>
where F: FnOnce(&[S]) -> R {
map: F,
expected: &'static str,
num_elements: usize,
_phantom: PhantomData<&'static S>,
}
impl<F, S: 'static, R> SliceAdapter<F, S, R>
where F: FnOnce(&[S]) -> R {
fn new(map: F, expected: &'static str, num_bytes: usize) -> Self {
Self {
map, expected,
num_elements: num_bytes,
_phantom: PhantomData,
}
}
}
impl<'de, F, S: 'static, R> de::Visitor<'de> for SliceAdapter<F, S, R>
where
F: FnOnce(&[S]) -> R,
S: de::Deserialize<'de>
{
type Value = R;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "{}", self.expected)
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error> where
A: de::SeqAccess<'de>, {
let mut buf = Vec::with_capacity(self.num_elements);
while let Some(byte) = seq.next_element::<S>()? {
buf.push(byte);
}
Ok((self.map)(&buf))
}
}
#[derive(Copy, Clone)]
pub struct Signature(pub [u8; 256]);
impl fmt::Debug for Signature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let slice: &[u8] = &self.0;
write!(f, "0x")?;
for b in slice {
write!(f, "{:02X}", b)?;
}
Ok(())
}
}
impl<'de> de::Deserialize<'de> for Signature {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where
D: de::Deserializer<'de> {
deserializer.deserialize_tuple(256, SliceAdapter::new(
|slice| {
let mut buf = [0; 256];
buf.copy_from_slice(slice);
Signature(buf)
},
"signature blob (256 Bytes)",
256,
))
}
}
#[derive(Debug, Deserialize)]
pub struct Certificate {
pub size: u32,
pub time_date: u32,
pub title_id: u32,
pub title_name: TitleName, pub alt_title_ids: [u32; 16],
pub allowed_media: u32,
pub game_region: u32,
pub game_ratings: u32,
pub disk_number: u32,
pub version: u32,
pub lan_key: [u8; 16],
pub signature_key: [u8; 16],
pub alt_signature_keys: [[u8; 16]; 16],
}
impl Certificate {
pub fn parse(data: &mut &[u8]) -> Result<Self, Error> {
::bincode::deserialize_from(data)
.map_err(|e| Error::Malformed(format!("{:?}", e)))
}
}
pub struct TitleName(pub [u16; 40]);
impl fmt::Debug for TitleName {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let slice: &[u16] = &self.0;
slice.fmt(f)
}
}
impl<'de> de::Deserialize<'de> for TitleName {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where
D: de::Deserializer<'de> {
deserializer.deserialize_tuple(40, SliceAdapter::new(
|slice| {
let mut buf = [0u16; 40];
buf.copy_from_slice(slice);
TitleName(buf)
},
"title name (80 Bytes)",
40,
))
}
}
#[derive(Debug, Deserialize)]
pub struct SectionHeader {
pub section_flags: u32,
pub virt_addr: u32,
pub virt_size: u32, pub raw_addr: u32,
pub raw_size: u32,
pub section_name_addr: u32,
pub section_name_refcount: u32,
pub head_shared_page_refcount_addr: u32,
pub tail_shared_page_refcount_addr: u32,
pub section_digest: [u8; 20],
}
impl SectionHeader {
pub fn parse(data: &mut &[u8]) -> Result<Self, Error> {
::bincode::deserialize_from(data)
.map_err(|e| Error::Malformed(format!("{:?}", e)))
}
}
#[derive(Debug, Deserialize)]
pub struct LibraryVersion {
pub library_name: [u8; 8],
pub major_version: u16,
pub minor_version: u16,
pub build_version: u16,
pub library_flags: u16,
}
impl LibraryVersion {
pub fn parse(data: &mut &[u8]) -> Result<Self, Error> {
::bincode::deserialize_from(data)
.map_err(|e| Error::Malformed(format!("{:?}", e)))
}
}
#[derive(Debug, Deserialize)]
pub struct Tls {
pub data_start_addr: u32,
pub data_end_addr: u32,
pub tls_index_addr: u32,
pub tls_callback_addr: u32,
pub zero_fill_size: u32,
pub characteristics: u32,
}
impl Tls {
pub fn parse(data: &mut &[u8]) -> Result<Self, Error> {
::bincode::deserialize_from(data)
.map_err(|e| Error::Malformed(format!("{:?}", e)))
}
}