diff --git a/docs/04_config_options.md b/docs/04_config_options.md index c84efd4..5254f24 100644 --- a/docs/04_config_options.md +++ b/docs/04_config_options.md @@ -148,7 +148,7 @@ type: *word* | default: `0xFFFF` Use this setting to force specific CIC seed. By setting value `0xFFFF` bootloader will try to guess needed values from loaded ROM IPL3. -This setting is not used when **BOOT_MODE** is set to `3` or `4` (direct boot). +This setting is not used when **BOOT_MODE** is set to `0` (menu), `3` or `4` (direct boot). --- diff --git a/sw/bootloader/src/main.c b/sw/bootloader/src/main.c index d437bdf..f162fb0 100644 --- a/sw/bootloader/src/main.c +++ b/sw/bootloader/src/main.c @@ -1,4 +1,5 @@ #include "boot.h" +#include "cic.h" #include "error.h" #include "init.h" #include "io.h" @@ -26,7 +27,7 @@ void main (void) { menu_load(); boot_params.device_type = BOOT_DEVICE_TYPE_ROM; boot_params.reset_type = BOOT_RESET_TYPE_NMI; - boot_params.cic_seed = 0x3F; + boot_params.cic_seed = cic_get_seed(CIC_6102_7101); boot_params.detect_cic_seed = false; break; diff --git a/sw/deployer/src/main.rs b/sw/deployer/src/main.rs index f02fba5..cf63b1e 100644 --- a/sw/deployer/src/main.rs +++ b/sw/deployer/src/main.rs @@ -5,7 +5,7 @@ mod sc64; use chrono::Local; use clap::{Args, Parser, Subcommand, ValueEnum}; -use clap_num::maybe_hex_range; +use clap_num::{maybe_hex, maybe_hex_range}; use colored::Colorize; use panic_message::panic_message; use std::{ @@ -100,6 +100,10 @@ struct UploadArgs { /// Force TV type #[arg(long, conflicts_with = "direct")] tv: Option, + + /// Force CIC seed + #[arg(long, value_parser = |s: &str| maybe_hex::(s))] + cic_seed: Option, } #[derive(Subcommand)] @@ -141,6 +145,10 @@ struct _64DDArgs { /// Force TV type #[arg(long, conflicts_with = "direct")] tv: Option, + + /// Force CIC seed + #[arg(long, value_parser = |s: &str| maybe_hex::(s))] + cic_seed: Option, } #[derive(Args)] @@ -376,7 +384,7 @@ fn handle_upload_command(connection: Connection, args: &UploadArgs) -> Result<() sc64.set_tv_type(tv_type)?; } - sc64.calculate_cic_parameters()?; + sc64.calculate_cic_parameters(args.cic_seed)?; Ok(()) } @@ -477,7 +485,7 @@ fn handle_64dd_command(connection: Connection, args: &_64DDArgs) -> Result<(), s sc64.set_tv_type(tv_type)?; } - sc64.calculate_cic_parameters()?; + sc64.calculate_cic_parameters(args.cic_seed)?; if args.disk.len() == 0 { let dd_mode = sc64::DdMode::DdIpl; diff --git a/sw/deployer/src/sc64/cic.rs b/sw/deployer/src/sc64/cic.rs index cb6d93e..cdcb6b2 100644 --- a/sw/deployer/src/sc64/cic.rs +++ b/sw/deployer/src/sc64/cic.rs @@ -110,31 +110,35 @@ fn calculate_ipl3_checksum(ipl3: &[u8], seed: u8) -> Result { Ok(checksum) } -pub fn sign_ipl3(ipl3: &[u8]) -> Result<(u8, u64), Error> { - let known_seed_checksum_pairs = [ - (0xDD, 0x083C6C77E0B1u64), // 5167 - (0x3F, 0x45CC73EE317Au64), // 6101 - (0x3F, 0x44160EC5D9AFu64), // 7102 - (0x3F, 0xA536C0F1D859u64), // 6102/7102 - (0x78, 0x586FD4709867u64), // 6103/7103 - (0x91, 0x8618A45BC2D3u64), // 6105/7105 - (0x85, 0x2BBAD4E6EB74u64), // 6106/7106 - (0xDD, 0x6EE8D9E84970u64), // NDXJ0 - (0xDD, 0x6C216495C8B9u64), // NDDJ0 - (0xDD, 0xE27F43BA93ACu64), // NDDJ1 - (0xDD, 0x32B294E2AB90u64), // NDDJ2 - (0xDE, 0x05BA2EF0A5F1u64), // NDDE0 - ]; +pub fn sign_ipl3(ipl3: &[u8], custom_seed: Option) -> Result<(u8, u64), Error> { + if let Some(seed) = custom_seed { + Ok((seed, calculate_ipl3_checksum(ipl3, seed)?)) + } else { + let known_seed_checksum_pairs = [ + (0xDD, 0x083C6C77E0B1u64), // 5167 + (0x3F, 0x45CC73EE317Au64), // 6101 + (0x3F, 0x44160EC5D9AFu64), // 7102 + (0x3F, 0xA536C0F1D859u64), // 6102/7102 + (0x78, 0x586FD4709867u64), // 6103/7103 + (0x91, 0x8618A45BC2D3u64), // 6105/7105 + (0x85, 0x2BBAD4E6EB74u64), // 6106/7106 + (0xDD, 0x6EE8D9E84970u64), // NDXJ0 + (0xDD, 0x6C216495C8B9u64), // NDDJ0 + (0xDD, 0xE27F43BA93ACu64), // NDDJ1 + (0xDD, 0x32B294E2AB90u64), // NDDJ2 + (0xDE, 0x05BA2EF0A5F1u64), // NDDE0 + ]; - for (seed, checksum) in known_seed_checksum_pairs { - if calculate_ipl3_checksum(ipl3, seed)? == checksum { - return Ok((seed, checksum)); + for (seed, checksum) in known_seed_checksum_pairs { + if calculate_ipl3_checksum(ipl3, seed)? == checksum { + return Ok((seed, checksum)); + } } + + // Unknown IPL3 detected, sign it with arbitrary seed (CIC6102/7101 value is used here) + const DEFAULT_SEED: u8 = 0x3F; + let checksum = calculate_ipl3_checksum(ipl3, DEFAULT_SEED)?; + + Ok((DEFAULT_SEED, checksum)) } - - // Unknown IPL3 detected, sign it with arbitrary seed (CIC6102/7101 value is used here) - const DEFAULT_SEED: u8 = 0x3F; - let checksum = calculate_ipl3_checksum(ipl3, DEFAULT_SEED)?; - - Ok((DEFAULT_SEED, checksum)) } diff --git a/sw/deployer/src/sc64/mod.rs b/sw/deployer/src/sc64/mod.rs index f033a77..92e31af 100644 --- a/sw/deployer/src/sc64/mod.rs +++ b/sw/deployer/src/sc64/mod.rs @@ -497,16 +497,21 @@ impl SC64 { self.memory_read_chunked(writer, address, length) } - pub fn calculate_cic_parameters(&mut self) -> Result<(), Error> { - let boot_mode = get_config!(self, BootMode)?; - let address = match boot_mode { - BootMode::DirectRom => SDRAM_ADDRESS, - BootMode::DirectDdIpl => DDIPL_ADDRESS, - _ => BOOTLOADER_ADDRESS, + pub fn calculate_cic_parameters(&mut self, custom_seed: Option) -> Result<(), Error> { + let (address, cic_seed, boot_seed) = match get_config!(self, BootMode)? { + BootMode::Menu => (BOOTLOADER_ADDRESS, None, None), + BootMode::Rom => (BOOTLOADER_ADDRESS, None, custom_seed), + BootMode::DdIpl => (BOOTLOADER_ADDRESS, None, custom_seed), + BootMode::DirectRom => (SDRAM_ADDRESS, custom_seed, None), + BootMode::DirectDdIpl => (DDIPL_ADDRESS, custom_seed, None), }; let ipl3 = self.command_memory_read(address + IPL3_OFFSET, IPL3_LENGTH)?; - let (seed, checksum) = sign_ipl3(&ipl3)?; - self.command_cic_params_set(false, seed, checksum) + let (seed, checksum) = sign_ipl3(&ipl3, cic_seed)?; + self.command_cic_params_set(false, seed, checksum)?; + if let Some(seed) = boot_seed { + self.command_config_set(Config::CicSeed(CicSeed::Seed(seed)))?; + } + Ok(()) } pub fn set_boot_mode(&mut self, boot_mode: BootMode) -> Result<(), Error> {