[SC64][SW] Added option to set custom CIC seed in deployer

This commit is contained in:
Mateusz Faderewski 2023-12-14 20:28:21 +01:00
parent ff27e35ae8
commit 3f3f1e3b86
5 changed files with 55 additions and 37 deletions

View File

@ -148,7 +148,7 @@ type: *word* | default: `0xFFFF`
Use this setting to force specific CIC seed. Use this setting to force specific CIC seed.
By setting value `0xFFFF` bootloader will try to guess needed values from loaded ROM IPL3. 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).
--- ---

View File

@ -1,4 +1,5 @@
#include "boot.h" #include "boot.h"
#include "cic.h"
#include "error.h" #include "error.h"
#include "init.h" #include "init.h"
#include "io.h" #include "io.h"
@ -26,7 +27,7 @@ void main (void) {
menu_load(); menu_load();
boot_params.device_type = BOOT_DEVICE_TYPE_ROM; boot_params.device_type = BOOT_DEVICE_TYPE_ROM;
boot_params.reset_type = BOOT_RESET_TYPE_NMI; 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; boot_params.detect_cic_seed = false;
break; break;

View File

@ -5,7 +5,7 @@ mod sc64;
use chrono::Local; use chrono::Local;
use clap::{Args, Parser, Subcommand, ValueEnum}; use clap::{Args, Parser, Subcommand, ValueEnum};
use clap_num::maybe_hex_range; use clap_num::{maybe_hex, maybe_hex_range};
use colored::Colorize; use colored::Colorize;
use panic_message::panic_message; use panic_message::panic_message;
use std::{ use std::{
@ -100,6 +100,10 @@ struct UploadArgs {
/// Force TV type /// Force TV type
#[arg(long, conflicts_with = "direct")] #[arg(long, conflicts_with = "direct")]
tv: Option<TvType>, tv: Option<TvType>,
/// Force CIC seed
#[arg(long, value_parser = |s: &str| maybe_hex::<u8>(s))]
cic_seed: Option<u8>,
} }
#[derive(Subcommand)] #[derive(Subcommand)]
@ -141,6 +145,10 @@ struct _64DDArgs {
/// Force TV type /// Force TV type
#[arg(long, conflicts_with = "direct")] #[arg(long, conflicts_with = "direct")]
tv: Option<TvType>, tv: Option<TvType>,
/// Force CIC seed
#[arg(long, value_parser = |s: &str| maybe_hex::<u8>(s))]
cic_seed: Option<u8>,
} }
#[derive(Args)] #[derive(Args)]
@ -376,7 +384,7 @@ fn handle_upload_command(connection: Connection, args: &UploadArgs) -> Result<()
sc64.set_tv_type(tv_type)?; sc64.set_tv_type(tv_type)?;
} }
sc64.calculate_cic_parameters()?; sc64.calculate_cic_parameters(args.cic_seed)?;
Ok(()) Ok(())
} }
@ -477,7 +485,7 @@ fn handle_64dd_command(connection: Connection, args: &_64DDArgs) -> Result<(), s
sc64.set_tv_type(tv_type)?; sc64.set_tv_type(tv_type)?;
} }
sc64.calculate_cic_parameters()?; sc64.calculate_cic_parameters(args.cic_seed)?;
if args.disk.len() == 0 { if args.disk.len() == 0 {
let dd_mode = sc64::DdMode::DdIpl; let dd_mode = sc64::DdMode::DdIpl;

View File

@ -110,31 +110,35 @@ fn calculate_ipl3_checksum(ipl3: &[u8], seed: u8) -> Result<u64, Error> {
Ok(checksum) Ok(checksum)
} }
pub fn sign_ipl3(ipl3: &[u8]) -> Result<(u8, u64), Error> { pub fn sign_ipl3(ipl3: &[u8], custom_seed: Option<u8>) -> Result<(u8, u64), Error> {
let known_seed_checksum_pairs = [ if let Some(seed) = custom_seed {
(0xDD, 0x083C6C77E0B1u64), // 5167 Ok((seed, calculate_ipl3_checksum(ipl3, seed)?))
(0x3F, 0x45CC73EE317Au64), // 6101 } else {
(0x3F, 0x44160EC5D9AFu64), // 7102 let known_seed_checksum_pairs = [
(0x3F, 0xA536C0F1D859u64), // 6102/7102 (0xDD, 0x083C6C77E0B1u64), // 5167
(0x78, 0x586FD4709867u64), // 6103/7103 (0x3F, 0x45CC73EE317Au64), // 6101
(0x91, 0x8618A45BC2D3u64), // 6105/7105 (0x3F, 0x44160EC5D9AFu64), // 7102
(0x85, 0x2BBAD4E6EB74u64), // 6106/7106 (0x3F, 0xA536C0F1D859u64), // 6102/7102
(0xDD, 0x6EE8D9E84970u64), // NDXJ0 (0x78, 0x586FD4709867u64), // 6103/7103
(0xDD, 0x6C216495C8B9u64), // NDDJ0 (0x91, 0x8618A45BC2D3u64), // 6105/7105
(0xDD, 0xE27F43BA93ACu64), // NDDJ1 (0x85, 0x2BBAD4E6EB74u64), // 6106/7106
(0xDD, 0x32B294E2AB90u64), // NDDJ2 (0xDD, 0x6EE8D9E84970u64), // NDXJ0
(0xDE, 0x05BA2EF0A5F1u64), // NDDE0 (0xDD, 0x6C216495C8B9u64), // NDDJ0
]; (0xDD, 0xE27F43BA93ACu64), // NDDJ1
(0xDD, 0x32B294E2AB90u64), // NDDJ2
(0xDE, 0x05BA2EF0A5F1u64), // NDDE0
];
for (seed, checksum) in known_seed_checksum_pairs { for (seed, checksum) in known_seed_checksum_pairs {
if calculate_ipl3_checksum(ipl3, seed)? == checksum { if calculate_ipl3_checksum(ipl3, seed)? == checksum {
return Ok((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))
} }

View File

@ -497,16 +497,21 @@ impl SC64 {
self.memory_read_chunked(writer, address, length) self.memory_read_chunked(writer, address, length)
} }
pub fn calculate_cic_parameters(&mut self) -> Result<(), Error> { pub fn calculate_cic_parameters(&mut self, custom_seed: Option<u8>) -> Result<(), Error> {
let boot_mode = get_config!(self, BootMode)?; let (address, cic_seed, boot_seed) = match get_config!(self, BootMode)? {
let address = match boot_mode { BootMode::Menu => (BOOTLOADER_ADDRESS, None, None),
BootMode::DirectRom => SDRAM_ADDRESS, BootMode::Rom => (BOOTLOADER_ADDRESS, None, custom_seed),
BootMode::DirectDdIpl => DDIPL_ADDRESS, BootMode::DdIpl => (BOOTLOADER_ADDRESS, None, custom_seed),
_ => BOOTLOADER_ADDRESS, 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 ipl3 = self.command_memory_read(address + IPL3_OFFSET, IPL3_LENGTH)?;
let (seed, checksum) = sign_ipl3(&ipl3)?; let (seed, checksum) = sign_ipl3(&ipl3, cic_seed)?;
self.command_cic_params_set(false, seed, checksum) 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> { pub fn set_boot_mode(&mut self, boot_mode: BootMode) -> Result<(), Error> {