From f4638369d1593ca4df7bd9fae702ce05fe4c1ad3 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Fri, 4 Oct 2024 19:53:07 -0600 Subject: [PATCH] Extract Wii region.bin --- Cargo.lock | 12 ++++++------ Cargo.toml | 2 +- nod/src/disc/gcn.rs | 1 + nod/src/disc/mod.rs | 4 +++- nod/src/disc/wii.rs | 19 ++++++++++++++++++- nodtool/src/cmd/extract.rs | 27 +++++++++++++++------------ 6 files changed, 44 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 20dd100..d49221e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -441,7 +441,7 @@ dependencies = [ [[package]] name = "nod" -version = "1.4.1" +version = "1.4.2" dependencies = [ "adler", "aes", @@ -464,7 +464,7 @@ dependencies = [ [[package]] name = "nodtool" -version = "1.4.1" +version = "1.4.2" dependencies = [ "argp", "base16ct", @@ -1033,18 +1033,18 @@ checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984" [[package]] name = "zerocopy" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df7885ffcb82507a0f213c593e77c5f13d12cb96588d4e835ad7e9423ba034db" +checksum = "dd2e5ce961dea177d282ec084dca2aa411b7411199a68d79eb1beacb305a6cd9" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "930ad75608219e8ffdb8962a5433cb2b30064c7ccb564d3b76c2963390b1e435" +checksum = "b06304eeddb6081af98ac59db08c868ac197e586086b996d15a86ed70e09a754" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 8061d7d..c1b25fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ strip = "debuginfo" codegen-units = 1 [workspace.package] -version = "1.4.1" +version = "1.4.2" edition = "2021" rust-version = "1.74" authors = ["Luke Street "] diff --git a/nod/src/disc/gcn.rs b/nod/src/disc/gcn.rs index 3d39b6c..7d5e9af 100644 --- a/nod/src/disc/gcn.rs +++ b/nod/src/disc/gcn.rs @@ -214,6 +214,7 @@ pub(crate) fn read_part_meta( raw_apploader: raw_apploader.into_boxed_slice(), raw_fst, raw_dol: raw_dol.into_boxed_slice(), + raw_region: None, raw_ticket: None, raw_tmd: None, raw_cert_chain: None, diff --git a/nod/src/disc/mod.rs b/nod/src/disc/mod.rs index e48e9da..72c51af 100644 --- a/nod/src/disc/mod.rs +++ b/nod/src/disc/mod.rs @@ -24,7 +24,7 @@ pub(crate) mod wii; pub use fst::{Fst, Node, NodeKind}; pub use streams::{FileStream, OwnedFileStream, WindowedStream}; -pub use wii::{SignedHeader, Ticket, TicketLimit, TmdHeader}; +pub use wii::{SignedHeader, Ticket, TicketLimit, TmdHeader, REGION_SIZE}; /// Size in bytes of a disc sector. pub const SECTOR_SIZE: usize = 0x8000; @@ -365,6 +365,8 @@ pub struct PartitionMeta { pub raw_fst: Box<[u8]>, /// Main binary (main.dol) pub raw_dol: Box<[u8]>, + /// Disc region info (region.bin, Wii only) + pub raw_region: Option>, /// Ticket (ticket.bin, Wii only) pub raw_ticket: Option>, /// TMD (tmd.bin, Wii only) diff --git a/nod/src/disc/wii.rs b/nod/src/disc/wii.rs index 609c283..60c1f09 100644 --- a/nod/src/disc/wii.rs +++ b/nod/src/disc/wii.rs @@ -21,7 +21,10 @@ use crate::{ KeyBytes, }, static_assert, - util::{div_rem, read::read_box_slice}, + util::{ + div_rem, + read::{read_box, read_box_slice}, + }, Error, OpenOptions, Result, ResultContext, }; @@ -31,6 +34,12 @@ pub(crate) const HASHES_SIZE: usize = 0x400; /// Size in bytes of the data block in a Wii disc sector (excluding hashes) pub(crate) const SECTOR_DATA_SIZE: usize = SECTOR_SIZE - HASHES_SIZE; // 0x7C00 +/// Size of the disc region info (region.bin) +pub const REGION_SIZE: usize = 0x20; + +/// Offset of the disc region info +pub const REGION_OFFSET: u64 = 0x4E000; + // ppki (Retail) const RVL_CERT_ISSUER_PPKI_TICKET: &str = "Root-CA00000001-XS00000003"; #[rustfmt::skip] @@ -270,6 +279,7 @@ pub struct PartitionWii { sector: u32, pos: u64, verify: bool, + raw_region: Box<[u8; REGION_SIZE]>, raw_tmd: Box<[u8]>, raw_cert_chain: Box<[u8]>, raw_h3_table: Box<[u8]>, @@ -287,6 +297,7 @@ impl Clone for PartitionWii { sector: u32::MAX, pos: 0, verify: self.verify, + raw_region: self.raw_region.clone(), raw_tmd: self.raw_tmd.clone(), raw_cert_chain: self.raw_cert_chain.clone(), raw_h3_table: self.raw_h3_table.clone(), @@ -304,6 +315,10 @@ impl PartitionWii { let block_size = inner.block_size(); let mut reader = PartitionGC::new(inner, disc_header)?; + // Read region + reader.seek(SeekFrom::Start(REGION_OFFSET)).context("Seeking to region offset")?; + let raw_region: Box<[u8; REGION_SIZE]> = read_box(&mut reader).context("Reading region")?; + // Read TMD, cert chain, and H3 table let offset = partition.start_sector as u64 * SECTOR_SIZE as u64; reader @@ -333,6 +348,7 @@ impl PartitionWii { sector: u32::MAX, pos: 0, verify: options.validate_hashes, + raw_region, raw_tmd, raw_cert_chain, raw_h3_table, @@ -482,6 +498,7 @@ impl PartitionBase for PartitionWii { fn meta(&mut self) -> Result> { self.seek(SeekFrom::Start(0)).context("Seeking to partition header")?; let mut meta = read_part_meta(self, true)?; + meta.raw_region = Some(self.raw_region.clone()); meta.raw_ticket = Some(Box::from(self.partition.header.ticket.as_bytes())); meta.raw_tmd = Some(self.raw_tmd.clone()); meta.raw_cert_chain = Some(self.raw_cert_chain.clone()); diff --git a/nodtool/src/cmd/extract.rs b/nodtool/src/cmd/extract.rs index 3869d36..bd1fb18 100644 --- a/nodtool/src/cmd/extract.rs +++ b/nodtool/src/cmd/extract.rs @@ -152,18 +152,21 @@ fn extract_sys_files( fs::create_dir_all(&disc_dir) .with_context(|| format!("Creating directory {}", display(&disc_dir)))?; extract_file(&header.as_bytes()[..0x100], &disc_dir.join("header.bin"), quiet)?; - } - if let Some(ticket) = data.raw_ticket.as_deref() { - extract_file(ticket, &out_dir.join("ticket.bin"), quiet)?; - } - if let Some(tmd) = data.raw_tmd.as_deref() { - extract_file(tmd, &out_dir.join("tmd.bin"), quiet)?; - } - if let Some(cert_chain) = data.raw_cert_chain.as_deref() { - extract_file(cert_chain, &out_dir.join("cert.bin"), quiet)?; - } - if let Some(h3_table) = data.raw_h3_table.as_deref() { - extract_file(h3_table, &out_dir.join("h3.bin"), quiet)?; + if let Some(region) = data.raw_region.as_deref() { + extract_file(region, &disc_dir.join("region.bin"), quiet)?; + } + if let Some(ticket) = data.raw_ticket.as_deref() { + extract_file(ticket, &out_dir.join("ticket.bin"), quiet)?; + } + if let Some(tmd) = data.raw_tmd.as_deref() { + extract_file(tmd, &out_dir.join("tmd.bin"), quiet)?; + } + if let Some(cert_chain) = data.raw_cert_chain.as_deref() { + extract_file(cert_chain, &out_dir.join("cert.bin"), quiet)?; + } + if let Some(h3_table) = data.raw_h3_table.as_deref() { + extract_file(h3_table, &out_dir.join("h3.bin"), quiet)?; + } } Ok(()) }