TwlIPL/build/libraries_sysmenu/hotsw/ARM7/src/hotsw.c
(no author) 3035b1ffb3 (更新:Akabane Jumpei)
・Secure1,2モードのデータリードシーケンスを共通化
・ソースちょっと整理

git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlIPL/trunk@1110 b08762b0-b915-fc4b-9d8c-17b2551a87ff
2008-04-11 10:04:30 +00:00

2009 lines
69 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*---------------------------------------------------------------------------*
Project: TwlIPL
File: hotsw.c
Copyright 2007-2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
*---------------------------------------------------------------------------*/
#include <twl.h>
#include <twl/os/common/format_rom.h>
#include <twl/mcu.h>
#include <nitro/card/types.h>
#include <firm/os/common/system.h>
#include <sysmenu.h>
#include <hotswTypes.h>
#include <blowfish.h>
#include <dsCardCommon.h>
#include <romEmulation.h>
#include <customNDma.h>
#include <../build/libraries/mb/common/include/mb_fileinfo.h>
#define DEBUG_MODE
// カード電源ONからROMヘッダロードまでの期間にスリープに入る時のワンセグ対策しない場合
//#define HOWSW_ENABLE_DEEP_SLEEP_WHILE_INSERT_CARD
// define -------------------------------------------------------------------
#define CHATTERING_COUNTER 0x1988 // 100ms分 (0x1988 * 15.3us = 100000us)
#define COUNTER_A 0x51C // 20ms分 ( 0x51C * 15.3us = 20012us)
#define CARD_EXIST_CHECK_INTERVAL 200
#define UNDEF_CODE 0xe7ffdeff // 未定義コード
#define ENCRYPT_DEF_SIZE 0x800 // 2KB ※ ARM9常駐モジュール先頭2KB
#define DIGEST_HASH_BLOCK_SIZE_SHA1 (512/8)
#define SLOT_B_LOCK_BUF HW_CTRDG_LOCK_BUF
#define HOTSW_DSTV_GAME_CODE 'JSNU'
#ifdef SDK_ARM9
#define reg_HOTSW_EXMEMCNT reg_MI_EXMEMCNT
#define HOTSW_EXMEMCNT_SELB_MASK REG_MI_EXMEMCNT_MPB_MASK
#define HOTSW_EXMEMCNT_SELB_SHIFT REG_MI_EXMEMCNT_MPB_SHIFT
#else // SDK_ARM7
#define reg_HOTSW_EXMEMCNT reg_MI_EXMEMCNT_L
#define HOTSW_EXMEMCNT_SELB_MASK 0x0400
#define HOTSW_EXMEMCNT_SELB_SHIFT 10
#endif
// Function prototype -------------------------------------------------------
static BOOL IsSwap(void);
static u32 GetMcSlotShift(void);
static u32 GetMcSlotMask(void);
static u32 GetMcSlotMode(void);
static void SetMcSlotMode(u32 mode);
static BOOL CmpMcSlotMode(u32 mode);
static void SetInterruptCallback( OSIrqMask intr_bit, OSIrqFunction func );
static void SetInterruptCallbackEx( OSIrqMask intr_bit, void *func );
static void SetInterrupt(void);
static void InterruptCallbackCard(void);
static void InterruptCallbackCardDet(void);
static void InterruptCallbackNDma(void);
static void InterruptCallbackPxi(PXIFifoTag tag, u32 data, BOOL err);
static void LockHotSwRsc(OSLockWord* word);
static void UnlockHotSwRsc(OSLockWord* word);
static void HotSwThread(void *arg);
static void MonitorThread(void *arg);
static void McPowerOn(void);
static void McPowerOff(void);
static void SetMCSCR(void);
static BOOL isTwlModeLoad(void);
static HotSwState ReadSecureModeCardData(void);
static void GenVA_VB_VD(void);
static HotSwState DecryptObjectFile(void);
static HotSwState LoadBannerData(void);
static HotSwState LoadStaticModule(void);
static HotSwState LoadCardData(void);
static HotSwState CheckCardAuthCode(void);
static HotSwState CheckStaticModuleHash(void);
static s32 LockExCard(u16 lockID);
static s32 UnlockExCard(u16 lockID);
static BOOL CheckArm7HashValue(void);
static BOOL CheckArm9HashValue(void);
static BOOL CheckExtArm7HashValue(void);
static BOOL CheckExtArm9HashValue(void);
static void ShowRegisterData(void);
static void ShowRomHeaderData(void);
static void DebugPrintErrorMessage(HotSwState state);
HotSwState HOTSWi_RefreshBadBlock(u32 romMode);
// Static Values ------------------------------------------------------------
#include <twl/ltdwram_begin.h>
static char encrypt_object_key[] ATTRIBUTE_ALIGN(4) = "encryObj";
static u16 s_RscLockID;
static u16 s_CardLockID;
static u16 s_bondingOp;
static u32 s_BootSegBufSize, s_SecureSegBufSize, s_Secure2SegBufSize;
static BootSegmentData *s_pBootSegBuffer;
static u32 *s_pSecureSegBuffer;
static u32 *s_pSecure2SegBuffer;
static CardBootData s_cbData;
static SYSMRomEmuInfo s_romEmuInfo;
static BOOL debuggerFlg;
static BOOL s_IsPulledOut = TRUE;
static BOOL s_isHotSwBusy = FALSE;
// HMACSHA1の鍵
static u8 s_digestDefaultKey[ DIGEST_HASH_BLOCK_SIZE_SHA1 ] = {
0x21, 0x06, 0xc0, 0xde,
0xba, 0x98, 0xce, 0x3f,
0xa6, 0x92, 0xe3, 0x9d,
0x46, 0xf2, 0xed, 0x01,
0x76, 0xe3, 0xcc, 0x08,
0x56, 0x23, 0x63, 0xfa,
0xca, 0xd4, 0xec, 0xdf,
0x9a, 0x62, 0x78, 0x34,
0x8f, 0x6d, 0x63, 0x3c,
0xfe, 0x22, 0xca, 0x92,
0x20, 0x88, 0x97, 0x23,
0xd2, 0xcf, 0xae, 0xc2,
0x32, 0x67, 0x8d, 0xfe,
0xca, 0x83, 0x64, 0x98,
0xac, 0xfd, 0x3e, 0x37,
0x87, 0x46, 0x58, 0x24
};
static CardSecureModeFunction s_funcTable[] = {
// DS Card Type 1
{ ReadIDSecure, ReadSegSecure, SwitchONPNGSecure, ChangeModeSecure},
// DS Card Type 2
{ ReadIDSecure, ReadSegSecure, SwitchONPNGSecure, ChangeModeSecure},
// TWL Card Type 1
{ ReadIDSecure, ReadSegSecure, SwitchONPNGSecure, ChangeModeSecure},
// RomEmulation
{ReadIDSecure_ROMEMU, ReadSegSecure_ROMEMU, SwitchONPNGSecure_ROMEMU, ChangeModeSecure_ROMEMU}
};
// Global Values ------------------------------------------------------------
BLOWFISH_CTX HotSwBlowfishInitTableBufDS;
CardThreadData HotSwThreadData;
#include <twl/ltdwram_end.h>
// ===========================================================================
// Function Describe
// ===========================================================================
/*---------------------------------------------------------------------------*
Name: HOTSW_Init
Description:
*---------------------------------------------------------------------------*/
void HOTSW_Init(u32 threadPrio)
{
OS_InitTick();
OS_InitThread();
#ifndef USE_LOCAL_KEYTABLE
// 初期化後に他の用途でWRAM_0を使用できるようにローカルバッファへコピーしておく
MI_CpuCopyFast((void *)HW_WRAM_0_LTD, &HotSwBlowfishInitTableBufDS, sizeof(BLOWFISH_CTX));
#endif
// PXI初期化
PXI_Init();
PXI_SetFifoRecvCallback(PXI_FIFO_TAG_HOTSW, InterruptCallbackPxi);
// 割り込みマスクの設定
SetInterrupt();
// 割り込みの有効化
(void)OS_EnableIrq();
(void)OS_EnableInterrupts();
// チャッタリングカウンタの値を設定
reg_MI_MC1 = (u32)((reg_MI_MC1 & ~REG_MI_MC1_CC_MASK) |
(CHATTERING_COUNTER << REG_MI_MC1_CC_SHIFT));
// Counter-Aの値を設定
reg_MI_MC2 = COUNTER_A;
// Bonding Optionの取得
s_bondingOp = SCFG_REG_GetBondingOption();
// 構造体の初期化
MI_CpuClear8(&s_cbData, sizeof(CardBootData));
// カードスレッド用構造体の初期化
MI_CpuClear8(&HotSwThreadData, sizeof(CardThreadData));
// HotSwリソースの排他制御用Lock IDの取得(開放しないで持ち続ける)
{
s32 tempLockID;
// ARM9と排他制御用のロックIDの取得
while((tempLockID = OS_GetLockID()) == OS_LOCK_ID_ERROR){
OS_PutString("Error - Can't Get Lock ID\n");
}
s_RscLockID = (u16)tempLockID;
// カードアクセス用のロックIDの取得
while((tempLockID = OS_GetLockID()) == OS_LOCK_ID_ERROR){
OS_PutString("Error - Can't Get Lock ID\n");
}
s_CardLockID = (u16)tempLockID;
}
// カードデータロード用スレッドの生成
OS_CreateThread(&HotSwThreadData.hotswThread,
HotSwThread,
NULL,
HotSwThreadData.hotswStack + HOTSW_THREAD_STACK_SIZE / sizeof(u64),
HOTSW_THREAD_STACK_SIZE,
threadPrio
);
// カードの状態監視用スレッドの生成 ( DSテレビ対策 )
// [TODO] 優先度の設定
OS_CreateThread(&HotSwThreadData.monitorThread,
MonitorThread,
NULL,
HotSwThreadData.monitorStack + HOTSW_THREAD_STACK_SIZE / sizeof(u64),
HOTSW_THREAD_STACK_SIZE,
threadPrio
);
// メッセージキューの初期化
OS_InitMessageQueue( &HotSwThreadData.hotswQueue, &HotSwThreadData.hotswMsgBuffer[0], HOTSW_MSG_BUFFER_NUM );
// メッセージキューの初期化
OS_InitMessageQueue( &HotSwThreadData.hotswDmaQueue, &HotSwThreadData.hotswDmaMsgBuffer[0], HOTSW_DMA_MSG_NUM );
// スレッド起動
OS_WakeupThreadDirect(&HotSwThreadData.hotswThread);
OS_WakeupThreadDirect(&HotSwThreadData.monitorThread);
// Boot Segment バッファの設定
HOTSW_SetBootSegmentBuffer((void *)SYSM_CARD_ROM_HEADER_BAK, SYSM_CARD_ROM_HEADER_SIZE );
// Secure1 Segment バッファの設定
HOTSW_SetSecureSegmentBuffer(HOTSW_MODE1, (void *)SYSM_CARD_NTR_SECURE_BUF, SECURE_AREA_SIZE );
// Secure2 Segment バッファの設定
HOTSW_SetSecureSegmentBuffer(HOTSW_MODE2, (void *)SYSM_CARD_TWL_SECURE_BUF, SECURE_AREA_SIZE );
// カードが挿さってあったらスレッドを起動する
if(HOTSW_IsCardExist()){
// メッセージ送信
OS_SendMessage(&HotSwThreadData.hotswQueue, (OSMessage)&HotSwThreadData.hotswInsertMsg[HotSwThreadData.idx_insert], OS_MESSAGE_NOBLOCK);
// メッセージインデックスをインクリメント
HotSwThreadData.idx_insert = (HotSwThreadData.idx_insert+1) % HOTSW_INSERT_MSG_NUM;
}
else{
SYSMi_GetWork()->flags.hotsw.is1stCardChecked = TRUE;
}
}
/*---------------------------------------------------------------------------*
Name: LoadCardData
Description: カードからデータをロードする
※BootSegmentBuffer SecureSegmentBufferの設定を行ってから
この関数を呼んでください。
*---------------------------------------------------------------------------*/
static HotSwState LoadCardData(void)
{
OSTick start;
HotSwState retval = HOTSW_SUCCESS;
HotSwState state = HOTSW_SUCCESS;
u32 romMode = HOTSW_ROM_MODE_NULL;
start = OS_GetTick();
s_isHotSwBusy = TRUE;
// カードのロック
#ifndef DEBUG_USED_CARD_SLOT_B_
CARD_LockRom(s_CardLockID);
#else
LockExCard(s_CardLockID);
#endif
// カード電源リセット
McPowerOff();
#ifndef HOWSW_ENABLE_DEEP_SLEEP_WHILE_INSERT_CARD
MCU_EnableDeepSleepToPowerLine( MCU_PWR_LINE_33, FALSE );
#endif
McPowerOn();
// バッファを設定
s_cbData.pBootSegBuf = s_pBootSegBuffer;
s_cbData.pSecureSegBuf = s_pSecureSegBuffer;
s_cbData.pSecure2SegBuf= s_pSecure2SegBuffer;
// ロード処理開始
if(HOTSW_IsCardAccessible()){
s_cbData.modeType = HOTSW_MODE1;
// カード側でKey Tableをロードする
state = LoadTable();
retval = (retval == HOTSW_SUCCESS) ? state : retval;
// ---------------------- Normal Mode ----------------------
romMode = HOTSW_ROM_MODE_NORMAL;
// カードID読み込み
state = ReadIDNormal(&s_cbData);
retval = (retval == HOTSW_SUCCESS) ? state : retval;
// カードタイプを判別をして、使う関数を切替える IDの最上位ビットが1なら3DM
s_cbData.cardType = (s_cbData.id_nml & HOTSW_ROMID_1TROM_MASK) ? DS_CARD_TYPE_2 : DS_CARD_TYPE_1;
{
SYSMRomEmuInfo *romEmuInfo = (void *)&s_romEmuInfo;
BOOL enableDeepSleep = TRUE;
// バナーリードが完了して、フラグ処理が終わるまでARM9と排他制御する
LockHotSwRsc(&SYSMi_GetWork()->lockCardRsc);
// Boot Segment読み込み
state = ReadBootSegNormal(&s_cbData);
retval = (retval == HOTSW_SUCCESS) ? state : retval;
// ワンセグ差込み時はカードバス電源をディープスリープPFMに入れない
// (スリープ時シャットダウン対策。カードロード中にスリープしても良いように早目に設定)
if ( *(u32*)(s_cbData.pBootSegBuf->rh.s.game_code) == HOTSW_DSTV_GAME_CODE )
{
enableDeepSleep = FALSE;
}
MCU_EnableDeepSleepToPowerLine( MCU_PWR_LINE_33, enableDeepSleep );
// ARM9/7で不整合が発生しないようにRomエミュレーション情報ロードは初回のみ
if ( ! SYSMi_GetWork()->flags.hotsw.is1stCardChecked )
{
// Romエミュレーション情報を取得
state = ReadRomEmulationInfo(&s_romEmuInfo);
retval = (retval == HOTSW_SUCCESS) ? state : retval;
// 取得したRomエミュレーション情報を比較
debuggerFlg = TRUE;
if ( romEmuInfo->magic_code != SYSM_ROMEMU_INFO_MAGIC_CODE ){
debuggerFlg = FALSE;
}
}
// 初回のRomエミュレーション情報を使用
if(HOTSWi_IsRomEmulation()){
OS_PutString("Read Emulation ROM\n");
s_cbData.cardType = ROM_EMULATION;
s_cbData.gameCommondParam = s_cbData.pBootSegBuf->rh.s.game_cmd_param & ~SCRAMBLE_MASK;
OS_TPrintf("SYSMi_GetWork()->gameCommondParam : 0x%08x\n", s_cbData.gameCommondParam);
}
else{
s_cbData.gameCommondParam = s_cbData.pBootSegBuf->rh.s.game_cmd_param;
}
SYSMi_GetWork()->gameCommondParam = s_cbData.gameCommondParam;
// ROMヘッダCRCを算出してチェック。NintendoロゴCRCも確認。
SYSMi_GetWork()->cardHeaderCrc16_bak = SVC_GetCRC16( 65535, s_cbData.pBootSegBuf, 0x015e );
OS_TPrintf( "RomHeaderCRC16 : calc = %04x romh = %04x\n",
SYSMi_GetWork()->cardHeaderCrc16_bak, s_cbData.pBootSegBuf->rh.s.header_crc16 );
if( ( SYSMi_GetWork()->cardHeaderCrc16_bak != s_cbData.pBootSegBuf->rh.s.header_crc16 ) ||
( 0xcf56 != s_cbData.pBootSegBuf->rh.s.nintendo_logo_crc16 ) ){
retval = (retval == HOTSW_SUCCESS) ? HOTSW_CRC_CHECK_ERROR : retval;
}
}
if( retval == HOTSW_SUCCESS ) {
// NTRカードかTWLカードか
#ifdef DEBUG_MODE
if(s_cbData.pBootSegBuf->rh.s.main_ltd_rom_offset && s_cbData.pBootSegBuf->rh.s.sub_ltd_rom_offset)
#else
if(s_cbData.pBootSegBuf->rh.s.platform_code & 0x02)
#endif
{
OS_TPrintf("TWL Card.\n");
s_cbData.twlFlg = TRUE;
}
else{
// NTRカードの場合はRomHeaderバッファの1ページ目以降をクリアしておく。
MI_CpuClearFast((void *)(SYSM_CARD_ROM_HEADER_BAK + PAGE_SIZE), SYSM_CARD_ROM_HEADER_SIZE - PAGE_SIZE);
}
// SecureコマンドのPNG_ONコマンドetc用のレイテンシを求める(Latency1とLatency2を足す)
s_cbData.secureLatency = AddLatency2ToLatency1(s_cbData.pBootSegBuf->rh.s.secure_cmd_param);
// Key Table初期化
MakeBlowfishTableDS(&s_cbData, 8);
// コマンド認証値・コマンドカウンタ初期値・PNジェネレータ初期値の生成
GenVA_VB_VD();
// セキュアモードに移行
state = ChangeModeNormal(&s_cbData);
retval = (retval == HOTSW_SUCCESS) ? state : retval;
// ---------------------- Secure Mode ----------------------
romMode = HOTSW_ROM_MODE_SECURE;
// SecureモードのIDとSecureSegmentを読み込む
state = ReadSecureModeCardData();
retval = (retval == HOTSW_SUCCESS) ? state : retval;
// ★TWLカード対応 一旦リセット後Secure2モードに移行
// SCFG
if((s_cbData.isLoadTypeTwl = isTwlModeLoad()) == TRUE){
OS_PutString("Read Mode : TwlCard\n");
// Mode2に移行する準備
s_cbData.modeType = HOTSW_MODE2;
// ---------------------- Reset ----------------------
McPowerOff();
McPowerOn();
// ---------------------- Normal Mode ----------------------
state = ReadIDNormal(&s_cbData);
retval = (retval == HOTSW_SUCCESS) ? state : retval;
// 先頭1Page分だけでOK。データは読み捨てバッファに
state = ReadBootSegNormal(&s_cbData);
retval = (retval == HOTSW_SUCCESS) ? state : retval;
// Key Table初期化
MakeBlowfishTableDS(&s_cbData, 8);
// コマンド認証値・コマンドカウンタ初期値・PNジェネレータ初期値の生成
GenVA_VB_VD();
// セキュア2モードに移行
state = ChangeModeNormal2(&s_cbData);
retval = (retval == HOTSW_SUCCESS) ? state : retval;
// ---------------------- Secure2 Mode ----------------------
// Secure2モードのIDとSecureSegmentを読み込む
state = ReadSecureModeCardData();
retval = (retval == HOTSW_SUCCESS) ? state : retval;
}
// ゲームモードに移行
state = s_funcTable[s_cbData.cardType].ChangeMode_S(&s_cbData);
retval = (retval == HOTSW_SUCCESS) ? state : retval;
// ---------------------- Game Mode ----------------------
romMode = HOTSW_ROM_MODE_GAME;
// ID読み込み
state = ReadIDGame(&s_cbData);
retval = (retval == HOTSW_SUCCESS) ? state : retval;
// バナーファイルの読み込み
state = LoadBannerData();
retval = (retval == HOTSW_SUCCESS) ? state : retval;
// 排他制御ここまで(※CRCチェックまでにミスがなかったら、排他制御ここまで)
UnlockHotSwRsc(&SYSMi_GetWork()->lockCardRsc);
// カードIDの比較をして、一致しなければFALSEを返す
if(s_cbData.id_scr != s_cbData.id_gam){
retval = (retval == HOTSW_SUCCESS) ? HOTSW_ID_CHECK_ERROR : retval;
goto end;
}
// 常駐モジュール残りを指定先に転送
state = LoadStaticModule();
retval = (retval == HOTSW_SUCCESS) ? state : retval;
// ARM9常駐モジュールの先頭2KBの暗号化領域を複合化
(void)DecryptObjectFile();
// 認証コード読み込み&ワーク領域にコピー
state = CheckCardAuthCode();
retval = (retval == HOTSW_SUCCESS) ? state : retval;
}
else{
// 排他制御ここまで(※CRCチェックまでにミスがあったら、ここで開放する)
UnlockHotSwRsc(&SYSMi_GetWork()->lockCardRsc);
OS_TPrintf("ng... Card Data Load Skip ( state : %d )\n", retval);
}
}
else{
state = HOTSW_PULLED_OUT_ERROR;
retval = (retval == HOTSW_SUCCESS) ? state : retval;
}
end:
if( retval == HOTSW_SUCCESS )
{
// バッドブロックを置換
state = HOTSWi_RefreshBadBlock(romMode);
retval = (retval == HOTSW_SUCCESS) ? state : retval;
}
// カードDMA終了確認
HOTSW_WaitDmaCtrl(HOTSW_NDMA_NO);
// カードアクセス終了確認
HOTSW_WaitCardCtrl();
// カードのロック開放(※ロックIDは開放せずに持ち続ける)
#ifndef DEBUG_USED_CARD_SLOT_B_
CARD_UnlockRom(s_CardLockID);
#else
UnlockExCard(s_CardLockID);
#endif
s_isHotSwBusy = FALSE;
// OS_TPrintf( "Load Card Time : %dms\n\n", OS_TicksToMilliSeconds( OS_GetTick() - start ) );
return retval;
}
/*---------------------------------------------------------------------------*
Name: isTwlModeLoad
Description: カードのロードをTWLモードで行うかDSモードで行うかを決める
■ Bonding Op = 0 (製品版)
ソフトウェア |     DSカード | TWLカード
------------------------------------------------------------------------
DS用 | DSカード読みシーケンス | DSカード読みシーケンス(※1)
TWL用 | 不正カードフラグ立て | TWLカード読みシーケンス
ハイブリット | 不正カードフラグ立て | TWLカード読みシーケンス
■ Bonding Op = 0以外 (開発用)
ソフトウェア |     DSカード | TWLカード
------------------------------------------------------------------------
DS用 | DSカード読みシーケンス | DSカード読みシーケンス(※1)
TWL用 | DSカード読みシーケンス | TWLカード読みシーケンス
ハイブリット | DSカード読みシーケンス | TWLカード読みシーケンス
※1 [TODO] 動作に関してはカードGと相談して決める
*---------------------------------------------------------------------------*/
static BOOL isTwlModeLoad(void)
{
// TWLカード
if(s_cbData.id_nml & HOTSW_ROMID_TWLROM_MASK){
// PlatformCodeがTwl or Hybridの場合
if(s_cbData.pBootSegBuf->rh.s.platform_code & 0x02){
OS_PutString("TWL Card : TWL Application : Read Sequence -> TWL\n");
return TRUE;
}
else{
// [TODO] 仕様確認
OS_PutString("TWL Card : NTR Application : Read Sequence -> NTR\n");
return FALSE;
}
}
// DSカード
else{
// 製品版の場合
if(s_bondingOp == SCFG_OP_PRODUCT){
// PlatformCodeがTwl or Hybridの場合
if(s_cbData.pBootSegBuf->rh.s.platform_code & 0x02){
OS_PutString("NTR Card : TWL Application : Illegal Card\n");
s_cbData.illegalCardFlg = TRUE;
return FALSE;
}
else{
OS_PutString("NTR Card : NTR Application : Read Sequence -> NTR\n");
return FALSE;
}
}
// 開発用の場合
else{
OS_PutString("Bonding Option Development : NTR Card : Read Sequence -> NTR\n");
return FALSE;
}
}
}
/*---------------------------------------------------------------------------*
Name: ReadSecureModeCardData
Description: セキュアモードの各種読み込みを行う関数
※ s_cbData.modeTypeの設定はこの関数の外で行う
*---------------------------------------------------------------------------*/
static HotSwState ReadSecureModeCardData(void)
{
HotSwState retval = HOTSW_SUCCESS;
HotSwState state = HOTSW_SUCCESS;
// PNG設定
state = s_funcTable[s_cbData.cardType].SetPNG_S(&s_cbData);
retval = (retval == HOTSW_SUCCESS) ? state : retval;
// DS側符号生成回路初期値設定 (レジスタ設定)
SetMCSCR();
// ID読み込み
state = s_funcTable[s_cbData.cardType].ReadID_S(&s_cbData);
retval = (retval == HOTSW_SUCCESS) ? state : retval;
// カードIDの比較をして、一致しなければFALSEを返す
if(s_cbData.id_nml != s_cbData.id_scr){
retval = (retval == HOTSW_SUCCESS) ? HOTSW_ID_CHECK_ERROR : retval;
}
if(retval == HOTSW_SUCCESS){
// Secure領域のSegment読み込み
state = s_funcTable[s_cbData.cardType].ReadSegment_S(&s_cbData);
retval = (retval == HOTSW_SUCCESS) ? state : retval;
}
return retval;
}
/*---------------------------------------------------------------------------*
Name: HOTSWi_RefreshBadBlock
Description: ノーマルモードまたはゲームモードでバッドブロックを置換
*---------------------------------------------------------------------------*/
HotSwState HOTSWi_RefreshBadBlock(u32 romMode)
{
HotSwState retval = HOTSW_SUCCESS;
HotSwState state = HOTSW_SUCCESS;
HotSwState (*pReadStatus)(CardBootData *cbd);
HotSwState (*pRefreshBadBlock)(CardBootData *cbd);
if ( ! ( romMode == HOTSW_ROM_MODE_NORMAL || romMode == HOTSW_ROM_MODE_GAME ) )
{
return HOTSW_SUCCESS;
}
if ( romMode == HOTSW_ROM_MODE_NORMAL )
{
pReadStatus = ReadStatusNormal;
pRefreshBadBlock = RefreshBadBlockNormal;
}
else
if ( romMode == HOTSW_ROM_MODE_GAME )
{
pReadStatus = ReadStatusGame;
pRefreshBadBlock = RefreshBadBlockGame;
}
// ステータス対応ROMのみステータス読み込み
if ( s_cbData.id_nml & HOTSW_ROMID_RFSSUP_MASK )
{
state = pReadStatus(&s_cbData);
retval = (retval == HOTSW_SUCCESS) ? state : retval;
// 要求レベルに関わらずバッドブロックを置換(製品カードでは滅多に発生しない)
if ( s_cbData.romStatus & (HOTSW_ROMST_RFS_WARN_L1_MASK | HOTSW_ROMST_RFS_WARN_L2_MASK) )
{
state = pRefreshBadBlock(&s_cbData);
retval = (retval == HOTSW_SUCCESS) ? state : retval;
}
}
return retval;
}
/*---------------------------------------------------------------------------*
Name: HOTSWi_IsRunOnDebugger
Description: ISデバッガ上で動作しているか
*---------------------------------------------------------------------------*/
BOOL HOTSWi_IsRunOnDebugger(void)
{
return debuggerFlg;
}
/*---------------------------------------------------------------------------*
Name: HOTSWi_IsRomEmulation
Description: ROMをエミュレーションしているか
*---------------------------------------------------------------------------*/
BOOL HOTSWi_IsRomEmulation(void)
{
return debuggerFlg &&
#ifndef DEBUG_USED_CARD_SLOT_B_
s_romEmuInfo.isEnableSlot1;
#else
s_romEmuInfo.isEnableSlot2;
#endif
}
/*---------------------------------------------------------------------------*
Name: LoadBannerData
Description: バナーデータを読み込む
注:ゲームモードになってから呼び出してください
*---------------------------------------------------------------------------*/
static HotSwState LoadBannerData(void)
{
BOOL state;
HotSwState retval = HOTSW_SUCCESS;
// バナーリード
if( s_cbData.pBootSegBuf->rh.s.banner_offset ) {
retval = ReadPageGame(&s_cbData, s_cbData.pBootSegBuf->rh.s.banner_offset,
(u32 *)SYSM_CARD_BANNER_BUF,
sizeof(TWLBannerFile) );
// バナーリードが成功していたら各種フラグTRUE その他の場合はFALSE (この関数の外で排他制御されているからここでは排他制御しないでOK)
state = (retval == HOTSW_SUCCESS) ? TRUE : FALSE;
SYSMi_GetWork()->flags.hotsw.isValidCardBanner = state;
SYSMi_GetWork()->flags.hotsw.isExistCard = state;
}
else{
// バナーデータが登録されていない場合 (この関数の外で排他制御されているからここでは排他制御しないでOK)
SYSMi_GetWork()->flags.hotsw.isValidCardBanner = FALSE;
SYSMi_GetWork()->flags.hotsw.isExistCard = TRUE;
}
if ( SYSMi_GetWork()->flags.hotsw.isExistCard )
{
SYSMi_GetWork()->flags.hotsw.isInspectCard = s_cbData.pBootSegBuf->rh.s.inspect_card;
}
else
{
SYSMi_GetWork()->flags.hotsw.isInspectCard = FALSE;
}
// デバッガ情報
if ( ! SYSMi_GetWork()->flags.hotsw.is1stCardChecked && debuggerFlg )
{
MI_CpuCopy8( &s_romEmuInfo, &(SYSMi_GetWork()->romEmuInfo), ROM_EMULATION_DATA_SIZE );
SYSMi_GetWork()->flags.hotsw.isOnDebugger = debuggerFlg;
}
SYSMi_GetWork()->flags.hotsw.isCardStateChanged = TRUE;
SYSMi_GetWork()->flags.hotsw.is1stCardChecked = TRUE;
return retval;
}
/*---------------------------------------------------------------------------*
Name: LoadStaticModule
Description: ARM7,9の常駐モジュールを展開する関数
注:ゲームモードになってから呼び出してください
*---------------------------------------------------------------------------*/
static HotSwState LoadStaticModule(void)
{
HotSwState retval = HOTSW_SUCCESS;
HotSwState state = HOTSW_SUCCESS;
u32 arm9StcEnd = s_cbData.pBootSegBuf->rh.s.main_rom_offset + s_cbData.pBootSegBuf->rh.s.main_size;
u32 arm9LtdStcEnd = s_cbData.pBootSegBuf->rh.s.main_ltd_rom_offset + s_cbData.pBootSegBuf->rh.s.main_ltd_size;
u32 secure2SegEnd = (u32)(s_cbData.pBootSegBuf->rh.s.twl_card_keytable_area_rom_offset * TWLCARD_BORDER_OFFSET + SECURE_SEGMENT_SIZE);
// 配置先と再配置情報を取得 & Arm9の常駐モジュール残りを指定先に転送
s_cbData.arm9Stc = (u32)s_cbData.pBootSegBuf->rh.s.main_ram_address;
if(SYSM_CheckLoadRegionAndSetRelocateInfo( ARM9_STATIC, &s_cbData.arm9Stc, s_cbData.pBootSegBuf->rh.s.main_size, &SYSMi_GetWork()->romRelocateInfo[ARM9_STATIC] , s_cbData.twlFlg)){
if(arm9StcEnd > SECURE_SEGMENT_END){
state = ReadPageGame(&s_cbData, s_cbData.pBootSegBuf->rh.s.main_rom_offset + SECURE_SEGMENT_SIZE, (u32 *)(s_cbData.arm9Stc + SECURE_SEGMENT_SIZE), MATH_ROUNDUP( arm9StcEnd, SYSM_ALIGNMENT_LOAD_MODULE ) - SECURE_SEGMENT_END);
retval = (retval == HOTSW_SUCCESS) ? state : retval;
}
}
else{
retval = (retval == HOTSW_SUCCESS) ? HOTSW_BUFFER_OVERRUN_ERROR : retval;
}
if(retval != HOTSW_SUCCESS){
return retval;
}
// 配置先と再配置情報を取得 & Arm7の常駐モジュールを指定先に転送
s_cbData.arm7Stc = (u32)s_cbData.pBootSegBuf->rh.s.sub_ram_address;
if(SYSM_CheckLoadRegionAndSetRelocateInfo( ARM7_STATIC, &s_cbData.arm7Stc, s_cbData.pBootSegBuf->rh.s.sub_size, &SYSMi_GetWork()->romRelocateInfo[ARM7_STATIC], s_cbData.twlFlg)){
state = ReadPageGame(&s_cbData, s_cbData.pBootSegBuf->rh.s.sub_rom_offset, (u32 *)s_cbData.arm7Stc, MATH_ROUNDUP( s_cbData.pBootSegBuf->rh.s.sub_size, SYSM_ALIGNMENT_LOAD_MODULE ) );
retval = (retval == HOTSW_SUCCESS) ? state : retval;
}
else{
retval = (retval == HOTSW_SUCCESS) ? HOTSW_BUFFER_OVERRUN_ERROR : retval;
}
if(retval != HOTSW_SUCCESS){
return retval;
}
// 拡張常駐モジュールの読み込み
if( s_cbData.twlFlg ) {
u32 size = ( s_cbData.pBootSegBuf->rh.s.main_ltd_size < SECURE_SEGMENT_SIZE ) ? s_cbData.pBootSegBuf->rh.s.main_ltd_size : SECURE_SEGMENT_SIZE;
s_cbData.arm9Ltd = (u32)s_cbData.pBootSegBuf->rh.s.main_ltd_ram_address;
// 配置先と再配置情報を取得 & Arm9の常駐モジュールを指定先に転送
if(SYSM_CheckLoadRegionAndSetRelocateInfo( ARM9_LTD_STATIC, &s_cbData.arm9Ltd, s_cbData.pBootSegBuf->rh.s.main_ltd_size, &SYSMi_GetWork()->romRelocateInfo[ARM9_LTD_STATIC] , TRUE)){
if(!s_cbData.isLoadTypeTwl){
// Secure2領域読み
state = ReadPageGame(&s_cbData, s_cbData.pBootSegBuf->rh.s.main_ltd_rom_offset, (u32 *)SYSM_CARD_TWL_SECURE_BUF, MATH_ROUNDUP( size, SYSM_ALIGNMENT_LOAD_MODULE ));
retval = (retval == HOTSW_SUCCESS) ? state : retval;
}
// (Arm9Ltd領域 - Secure2領域)分の読み込み
if( s_cbData.pBootSegBuf->rh.s.main_ltd_size > SECURE_SEGMENT_SIZE ) {
state = ReadPageGame(&s_cbData, s_cbData.pBootSegBuf->rh.s.main_ltd_rom_offset + SECURE_SEGMENT_SIZE,
(u32 *)(s_cbData.arm9Ltd + SECURE_SEGMENT_SIZE),
MATH_ROUNDUP( s_cbData.pBootSegBuf->rh.s.main_ltd_size, SYSM_ALIGNMENT_LOAD_MODULE ) - size);
retval = (retval == HOTSW_SUCCESS) ? state : retval;
}
}
else{
retval = (retval == HOTSW_SUCCESS) ? HOTSW_BUFFER_OVERRUN_ERROR : retval;
}
if(retval != HOTSW_SUCCESS){
return retval;
}
// 配置先と再配置情報を取得 & Arm7の常駐モジュールを指定先に転送
s_cbData.arm7Ltd = (u32)s_cbData.pBootSegBuf->rh.s.sub_ltd_ram_address;
if(SYSM_CheckLoadRegionAndSetRelocateInfo( ARM7_LTD_STATIC, &s_cbData.arm7Ltd, s_cbData.pBootSegBuf->rh.s.sub_ltd_size, &SYSMi_GetWork()->romRelocateInfo[ARM7_LTD_STATIC], TRUE)){
state = ReadPageGame(&s_cbData, s_cbData.pBootSegBuf->rh.s.sub_ltd_rom_offset, (u32 *)s_cbData.arm7Ltd, MATH_ROUNDUP( s_cbData.pBootSegBuf->rh.s.sub_ltd_size, SYSM_ALIGNMENT_LOAD_MODULE ) );
retval = (retval == HOTSW_SUCCESS) ? state : retval;
}
else{
retval = (retval == HOTSW_SUCCESS) ? HOTSW_BUFFER_OVERRUN_ERROR : retval;
}
if(retval != HOTSW_SUCCESS){
return retval;
}
// セキュア領域先頭2K分のハッシュ値を求めて、Work領域にコピー
{
SVCHMACSHA1Context hash;
// ハッシュ初期化
SVC_HMACSHA1Init( &hash, s_digestDefaultKey, sizeof(s_digestDefaultKey) );
// セキュア領域先頭2kb分UpDate
SVC_HMACSHA1Update( &hash, s_cbData.pSecureSegBuf, ENCRYPT_DEF_SIZE );
// Arm9と排他制御する
LockHotSwRsc(&SYSMi_GetWork()->lockHotSW);
// ハッシュコンテキストをWork領域にコピー
MI_CpuCopy8( &hash, &SYSMi_GetWork2()->hmac_sha1_context, sizeof(SVCHMACSHA1Context) );
// Arm9との排他制御、ここまで
UnlockHotSwRsc(&SYSMi_GetWork()->lockHotSW);
}
#define MY_DEBUG
#ifdef MY_DEBUG
(void)CheckStaticModuleHash();
#endif
}
return retval;
}
/*---------------------------------------------------------------------------*
Name: CheckCardAuthCode
Description: Rom Headerの認証コードアドレスを読んで、クローンブート対応か判定する
*---------------------------------------------------------------------------*/
static HotSwState CheckCardAuthCode(void)
{
u32 authBuf[PAGE_SIZE/sizeof(u32)];
u32 auth_offset = s_cbData.pBootSegBuf->rh.s.rom_valid_size ? s_cbData.pBootSegBuf->rh.s.rom_valid_size : 0x01000000;
u32 page_offset = auth_offset & 0xFFFFFE00;
HotSwState retval = HOTSW_SUCCESS;
u8 *p = (u8 *)authBuf;
if(!HOTSW_IsCardAccessible()){
return HOTSW_PULLED_OUT_ERROR;
}
retval = ReadPageGame( &s_cbData, page_offset, authBuf, MB_AUTHCODE_SIZE );
p += auth_offset & 0x000001FF;
if( *p++ == 'a' && *p == 'c' ) {
OS_PutString(" ☆ Clone Boot Mode\n");
SYSMi_GetWork()->cloneBootMode = SYSM_CLONE_BOOT_MODE;
}else {
OS_PutString(" □ Other Boot Mode\n");
SYSMi_GetWork()->cloneBootMode = SYSM_OTHER_BOOT_MODE;
}
return retval;
}
/*---------------------------------------------------------------------------*
Name: HOTSW_SetBootSegmentBuffer
Description: Boot Segment バッファの指定
注:カードデータロード中は呼び出さないようにする
*---------------------------------------------------------------------------*/
void HOTSW_SetBootSegmentBuffer(void* buf, u32 size)
{
SDK_ASSERT(size > BOOT_SEGMENT_SIZE);
s_pBootSegBuffer = (BootSegmentData *)buf;
s_BootSegBufSize = size;
s_cbData.pBootSegBuf = s_pBootSegBuffer;
// バッファの初期化
MI_CpuClear8(s_pBootSegBuffer, size);
}
/*---------------------------------------------------------------------------*
Name: HOTSW_SetSecureSegmentBuffer
Description: Secure Segment バッファの指定
注:カードデータロード中は呼び出さないようにする
*---------------------------------------------------------------------------*/
void HOTSW_SetSecureSegmentBuffer(ModeType type ,void* buf, u32 size)
{
SDK_ASSERT(size > SECURE_SEGMENT_SIZE);
if(type == HOTSW_MODE1){
s_pSecureSegBuffer = (u32 *)buf;
s_SecureSegBufSize = size;
s_cbData.pSecureSegBuf = s_pSecureSegBuffer;
// バッファの初期化
MI_CpuClear8(s_pSecureSegBuffer, size);
}
else{
s_pSecure2SegBuffer = (u32 *)buf;
s_Secure2SegBufSize = size;
s_cbData.pSecure2SegBuf = s_pSecure2SegBuffer;
// バッファの初期化
MI_CpuClear8(s_pSecure2SegBuffer, size);
}
}
/*---------------------------------------------------------------------------*
Name: GenVA_VB_VD
Description: コマンド認証値・コマンドカウンタ・PNジェネレータ初期値の生成
*---------------------------------------------------------------------------*/
static void GenVA_VB_VD(void)
{
u32 dummy = 0;
MATHRandContext32 rnd;
// 乱数を初期化 VBlankカウンタ値を種とする。
// [TODO] プログラムがV周期に同期しているためVカウンタでは固定値になりやすい
// (特にダイレクトブート)。
// 起動する度に変化するパラメータと組み合わせるべき。
MATH_InitRand32(&rnd, (u64)OS_GetVBlankCount());
s_cbData.vae = MATH_Rand32(&rnd, 0);
s_cbData.vbi = MATH_Rand32(&rnd, 0);
s_cbData.vd = MATH_Rand32(&rnd, 0);
dummy = MATH_Rand32(&rnd, 0);
EncryptByBlowfish(&s_cbData.keyTable, &s_cbData.vae, &s_cbData.vbi);
EncryptByBlowfish(&s_cbData.keyTable, &s_cbData.vd , &dummy);
s_cbData.vae &= 0xffffff;
s_cbData.vbi &= 0xfffff;
s_cbData.vd &= 0xffffff;
}
/*---------------------------------------------------------------------------*
Name: DecryptObjectFile
Description: セキュア領域先頭2KBの暗号化領域を復号化
注:セキュア領域を読み込んでからこの関数を呼び出してください
*---------------------------------------------------------------------------*/
static u32 encDestBuf[ENCRYPT_DEF_SIZE/sizeof(u32)];
static HotSwState DecryptObjectFile(void)
{
u8 i;
s32 restSize;
s32 size = (s32)s_cbData.pBootSegBuf->rh.s.main_size;
u32 *pEncBuf = encDestBuf;
u32 *pEncDes = s_cbData.pSecureSegBuf;
BLOWFISH_CTX *tableBufp = &s_cbData.keyTable;
BOOL exist = TRUE;
HotSwState retval = HOTSW_SUCCESS;
if (size > ENCRYPT_DEF_SIZE) {
size = ENCRYPT_DEF_SIZE;
}
restSize = size;
// 読み込んだセキュア領域をバッファから一時バッファにコピー
MI_CpuCopy32(s_cbData.pSecureSegBuf, pEncBuf, (u32)size);
// セキュア領域先頭8バイトをBlowfishで複合化
DecryptByBlowfish(&s_cbData.keyTable, &(pEncBuf)[1], &(pEncBuf)[0]);
// Key Tableを変換
s_cbData.keyBuf[1] = (s_cbData.keyBuf[1] << 1);
s_cbData.keyBuf[2] = (s_cbData.keyBuf[2] >> 1);
InitBlowfishKeyAndTableDS(&s_cbData.keyTable, s_cbData.keyBuf, 8);
// もう一度セキュア領域先頭8バイトをBlowfishで複合化
DecryptByBlowfish(&s_cbData.keyTable, &(pEncBuf)[1], &(pEncBuf)[0]);
for ( i=0; i<8; i++ ){
// 先頭8バイトが複合化の結果 "encryObj" となっていたら複合化成功
if ( encrypt_object_key[i] != ((char*)pEncBuf)[i] ){
exist = FALSE;
break;
}
}
// 暗号化オブジェクト有効時
if ( exist ){
u32 *bufp = pEncBuf;
bufp[0] = UNDEF_CODE;
bufp[1] = UNDEF_CODE;
while ((restSize -= 8) > 0) {
bufp += 2; // 復号処理
DecryptByBlowfish(tableBufp, &(bufp)[1], &(bufp)[0]);
}
}
else{
retval = HOTSW_DATA_DECRYPT_ERROR;
MI_NDmaFill( HOTSW_NDMA_NO, pEncBuf, UNDEF_CODE, (u32)size ); // 未定義コードでクリア
}
MI_CpuCopy32(pEncBuf, pEncDes, (u32)size);
return retval;
}
/*---------------------------------------------------------------------------*
Name: LockHotSwRsc
Description: 共有ワークのリソースの排他制御用 lockを行う
*---------------------------------------------------------------------------*/
static void LockHotSwRsc(OSLockWord* word)
{
while(OS_TryLockByWord( s_RscLockID, word, NULL ) != OS_LOCK_SUCCESS){
OS_Sleep(1);
}
}
/*---------------------------------------------------------------------------*
Name: UnlockHotSwRsc
Description: 共有ワークのリソースの排他制御用 Unlockを行う
*---------------------------------------------------------------------------*/
static void UnlockHotSwRsc(OSLockWord* word)
{
OS_UnlockByWord( s_RscLockID, word, NULL );
}
/*---------------------------------------------------------------------------*
Name: HOTSW_IsCardExist
Description: SCFG_MC1のCDETフラグを見て、カードの存在判定を行う
*---------------------------------------------------------------------------*/
BOOL HOTSW_IsCardExist(void)
{
#ifndef DEBUG_USED_CARD_SLOT_B_
u32 mask = (u32)(REG_MI_MC_SL1_CDET_MASK << GetMcSlotShift());
#else
u32 mask = (u32)(REG_MI_MC_SL2_CDET_MASK >> GetMcSlotShift());
#endif
if( !(reg_MI_MC1 & mask) ){
return TRUE;
}
else{
return FALSE;
}
}
/*---------------------------------------------------------------------------*
Name: HOTSW_IsCardAccessible
Description: SCFG_MC1のCDETフラグとM(モード)を見て、カードスロットにアクセスできる状態か判定する
*---------------------------------------------------------------------------*/
BOOL HOTSW_IsCardAccessible(void)
{
if( HOTSW_IsCardExist() && CmpMcSlotMode(SLOT_STATUS_MODE_10) == TRUE){
return TRUE;
}
else{
return FALSE;
}
}
/*---------------------------------------------------------------------------*
Name: IsSwap
Description: SCFG_MC1のSWPフラグを見て、スロットがスワップされているか判定する
*---------------------------------------------------------------------------*/
static BOOL IsSwap(void)
{
if( reg_MI_MC1 & REG_MI_MC1_SWP_MASK ){
return TRUE;
}
else{
return FALSE;
}
}
/*---------------------------------------------------------------------------*
Name: GetMcSlotShift
Description: カードスロットのシフトビット数の取得
*---------------------------------------------------------------------------*/
static u32 GetMcSlotShift(void)
{
return (u32)(IsSwap() * REG_MI_MC_SL2_CDET_SHIFT);
}
/*---------------------------------------------------------------------------*
Name: GetMcSlotMask
Description: カードスロットのシフトビット数の取得
*---------------------------------------------------------------------------*/
static u32 GetMcSlotMask(void)
{
#ifndef DEBUG_USED_CARD_SLOT_B_
return (u32)(REG_MI_MC_SL1_MODE_MASK << GetMcSlotShift());
#else
return (u32)(REG_MI_MC_SL2_MODE_MASK >> GetMcSlotShift());
#endif
}
/*---------------------------------------------------------------------------*
Name: GetMcSlotMode
Description: スロットの現在のモードを返す
*---------------------------------------------------------------------------*/
static u32 GetMcSlotMode(void)
{
#ifndef DEBUG_USED_CARD_SLOT_B_
return (reg_MI_MC1 & GetMcSlotMask()) >> GetMcSlotShift();
#else
return (reg_MI_MC1 & GetMcSlotMask()) << GetMcSlotShift();
#endif
}
/*---------------------------------------------------------------------------*
Name: SetMcSlotMode
Description: カードスロットのモード設定
*---------------------------------------------------------------------------*/
static void SetMcSlotMode(u32 mode)
{
#ifndef DEBUG_USED_CARD_SLOT_B_
reg_MI_MC1 = (u32)((reg_MI_MC1 & ~GetMcSlotMask()) | (mode << GetMcSlotShift()));
#else
reg_MI_MC1 = (u32)((reg_MI_MC1 & ~GetMcSlotMask()) | (mode >> GetMcSlotShift()));
#endif
}
/*---------------------------------------------------------------------------*
Name: CmpMcSlotMode
Description: 引数で与えられてモードと現在のカードスロットのモードを比較
*---------------------------------------------------------------------------*/
static BOOL CmpMcSlotMode(u32 mode)
{
#ifndef DEBUG_USED_CARD_SLOT_B_
if((reg_MI_MC1 & GetMcSlotMask()) == (mode << GetMcSlotShift())){
#else
if((reg_MI_MC1 & GetMcSlotMask()) == (mode >> GetMcSlotShift())){
#endif
return TRUE;
}
else{
return FALSE;
}
}
/*---------------------------------------------------------------------------*
Name: McPowerOn
Description: スロット電源ON
*---------------------------------------------------------------------------*/
static void McPowerOn(void)
{
// Counter-Aカウンタ設定値到達まで待つ
while(CmpMcSlotMode(SLOT_STATUS_MODE_11) == TRUE){
OS_Sleep(1);
}
if(CmpMcSlotMode(SLOT_STATUS_MODE_00) == TRUE){
// [TODO:]待ち時間は暫定値。金子さんに数値を測定してもらう。
// VDDの安定期間待ち
OS_Sleep(100);
// SCFG_MC1 の Slot Status の M1,M0 を 01 にする
SetMcSlotMode(SLOT_STATUS_MODE_01);
// 10ms待ち
OS_Sleep(10);
// SCFG_MC1 の Slot Status の M1,M0 を 10 にする
SetMcSlotMode(SLOT_STATUS_MODE_10);
// [TODO:]待ち時間は暫定値。金子さんに数値を測定してもらう。
// RESBを上げるまでの待ち時間
OS_Sleep(1);
// リセットをhighに (RESB = 1にする)
reg_HOTSW_MCCNT1 = RESB_MASK;
// [TODO:]待ち時間は暫定値。金子さんに数値を測定してもらう。
// カードへ最初のコマンドを送るまでの待ち時間
OS_Sleep(120);
}
}
/*---------------------------------------------------------------------------*
Name: McPowerOff
Description: スロット電源OFF
*---------------------------------------------------------------------------*/
static void McPowerOff(void)
{
// Counter-Aカウンタ設定値到達まで待つ
while(CmpMcSlotMode(SLOT_STATUS_MODE_11) == TRUE){
OS_Sleep(1);
}
if(CmpMcSlotMode(SLOT_STATUS_MODE_10) == TRUE){
// SCFG_MC1 の Slot Status の M1,M0 を 11 にする
SetMcSlotMode(SLOT_STATUS_MODE_11);
// SCFG_MC1 の Slot Status の M1,M0 が 00 になるまでポーリング
while(CmpMcSlotMode(SLOT_STATUS_MODE_00) == FALSE){
OS_Sleep(1);
}
}
}
/*---------------------------------------------------------------------------*
Name: HOTSWi_TurnCardPowerOn
Description: デバッガ通信用にカードスロットの電源をONにする。
Arguments: None.
Returns: None.
*---------------------------------------------------------------------------*/
void HOTSWi_TurnCardPowerOn(u32 slot)
{
u32 shift;
u32 mask = slot >= 2 ? (u32)REG_MI_MC_SL2_CDET_MASK : (u32)REG_MI_MC_SL1_CDET_MASK;
// カードが差さっていなければONしない
if ( reg_MI_MC & mask )
{
return;
}
shift = slot >= 2 ? (u32)REG_MI_MC_SL2_MODE_SHIFT : (u32)REG_MI_MC_SL1_MODE_SHIFT;
mask = slot >= 2 ? (u32)REG_MI_MC_SL2_MODE_MASK : (u32)REG_MI_MC_SL1_MODE_MASK;
// 電源が落ちている最中なら待つ
if ( (reg_MI_MC & mask) == (0x3 << shift) )
{
OS_SpinWait( OS_MSEC_TO_CPUCYC(1) );
}
if ( (reg_MI_MC & mask) == (0x0 << shift) )
{
reg_MI_MC = (u16)((reg_MI_MC & ~mask) | (0x1 << shift));
// VDDの安定期間
OS_SpinWait( OS_MSEC_TO_CPUCYC(100) );
reg_MI_MC = (u16)((reg_MI_MC & ~mask) | (0x2 << shift));
// RESBのLow期間
OS_SpinWait( OS_MSEC_TO_CPUCYC(1) );
reg_MI_MCCNT1_B = REG_MI_MCCNT1_RESB_MASK;
// RESBのHigh期間
OS_SpinWait( OS_MSEC_TO_CPUCYC(100) );
}
}
/*---------------------------------------------------------------------------*
Name: SetMCSCR
Description: 符号生成回路初期値設定レジスタを設定する
※注この関数はセキュアモードで、sPNG_ONコマンドを実行してから呼び出してください。
*---------------------------------------------------------------------------*/
static void SetMCSCR(void)
{
static u32 pnbL = 0x879b9b05;
static u8 pnbH = 0x5c;
static u8 pnaL1 = 0x60;
static u8 pnaL0Table[8] = { 0xe8, 0x4d, 0x5a, 0xb1, 0x17, 0x8f, 0x99, 0xd5 };
u32 pnaL = s_cbData.vd << 15 | pnaL1 << 8 | pnaL0Table[(s_cbData.pBootSegBuf->rh.s.rom_type & 0x7)];
u8 pnaH = (u8)((s_cbData.vd >> 17) & 0x7f);
// SCR A
reg_HOTSW_MCSCR0 = pnaL;
// SCR B
reg_HOTSW_MCSCR1 = pnbL;
// [d0 -d6 ] -> SCR A
// [d16-d22] -> SCR B
reg_HOTSW_MCSCR2 = (u32)(pnaH | pnbH << 16);
// MCCNT1 レジスタ設定 (SCR = 1に)
reg_HOTSW_MCCNT1 = SCR_MASK;
}
/*---------------------------------------------------------------------------*
Name: HotSwThread
Description: カード抜け・挿し処理スレッド
[TODO:]挿抜のフロー・フラグケアetcの確認(今の所、抜き挿ししてもタイトルが更新されない)
*---------------------------------------------------------------------------*/
static void HotSwThread(void *arg)
{
#pragma unused( arg )
// BOOL isPulledOut = TRUE;
HotSwState retval;
HotSwMessage *msg;
while(1){
OS_ReceiveMessage(&HotSwThreadData.hotswQueue, (OSMessage *)&msg, OS_MESSAGE_BLOCK);
if( msg->ctrl == TRUE ) {
// [TODO]とりあえず、ここでHOTSWを抑制した時点でisExistCardがFALSEなら、HOTSWのFinalizeをするようにする。
SYSMi_GetWork()->flags.hotsw.isEnableHotSW = msg->value;
// [TODO]カードがあるときとないときで場合分けしてFinalize処理を実装
// PXIメッセージを「抑制」と「Finalize」で分けて処理
// → 1.全てのレジスタをクリアする (カードがささっていない時)
// 一度電源を落としてNomalモードにする (NANDアプリ等を起動する場合)
// 3.必要なレジスタを残して、後はクリア (ささっているカードを起動する場合)
//
// NANDアプリ起動時の終了処理が確認できたら、、BOOTAPIでKillThreadでスレッドを殺せるようにしておく。
// スレッドを殺す前に、IREQとDET割り込みを無効にしておく。
// HOTSW_Finalize();
}
while(1){
// 活線挿抜抑制フラグが立っていたら処理しない
if( !SYSMi_GetWork()->flags.hotsw.isEnableHotSW ) {
SYSMi_GetWork()->flags.hotsw.is1stCardChecked = TRUE;
OS_PutString("### HotSw is restrained...\n");
break;
}
// カードが挿さってたら
if(HOTSW_IsCardExist()){
// 前の状態が挿し
if(!s_IsPulledOut){
// 抜きがなかったか判定
if(CmpMcSlotMode(SLOT_STATUS_MODE_10) == TRUE){
// フラグケア
LockHotSwRsc(&SYSMi_GetWork()->lockCardRsc);
SYSMi_GetWork()->flags.hotsw.isExistCard = TRUE;
SYSMi_GetWork()->flags.hotsw.isCardStateChanged = TRUE;
// 新しいカードのIDを入れる
SYSMi_GetWork()->nCardID = s_cbData.id_gam;
// カードデータロード完了フラグ
SYSMi_GetWork()->flags.hotsw.isCardLoadCompleted = TRUE;
UnlockHotSwRsc(&SYSMi_GetWork()->lockCardRsc);
OS_PutString("ok!\n");
break;
}
}
// カード読み込み開始
// [TODO] エラー発生時に電源ON/OFFを繰り返さないため、
// 挿入時に一度しかロードしないように必要がある
retval = LoadCardData();
// Debug表示
DebugPrintErrorMessage(retval);
// カード読みが失敗していたらカードがないことにする
if(retval != HOTSW_SUCCESS){
LockHotSwRsc(&SYSMi_GetWork()->lockHotSW);
SYSMi_GetWork()->flags.hotsw.isExistCard = FALSE;
SYSMi_GetWork()->flags.hotsw.isValidCardBanner = FALSE;
SYSMi_GetWork()->flags.hotsw.isCardStateChanged = TRUE;
UnlockHotSwRsc(&SYSMi_GetWork()->lockHotSW);
// カードブート用構造体の初期化
MI_CpuClear32(&s_cbData, sizeof(CardBootData));
// バッファのクリア
MI_CpuClearFast(s_pBootSegBuffer, s_BootSegBufSize);
MI_CpuClearFast(s_pSecureSegBuffer, s_SecureSegBufSize);
MI_CpuClearFast((u32 *)SYSM_CARD_BANNER_BUF, sizeof(TWLBannerFile));
break;
}
// 状態フラグを更新
s_IsPulledOut = FALSE;
}
// カードが抜けてたら
else{
// フラグ処理
LockHotSwRsc(&SYSMi_GetWork()->lockHotSW);
SYSMi_GetWork()->flags.hotsw.isExistCard = FALSE;
SYSMi_GetWork()->flags.hotsw.isValidCardBanner = FALSE;
SYSMi_GetWork()->flags.hotsw.isCardStateChanged = TRUE;
SYSMi_GetWork()->flags.hotsw.isCardLoadCompleted = FALSE;
UnlockHotSwRsc(&SYSMi_GetWork()->lockHotSW);
// カードブート用構造体の初期化
MI_CpuClear32(&s_cbData, sizeof(CardBootData));
// バッファのクリア
MI_CpuClearFast(s_pBootSegBuffer, s_BootSegBufSize);
MI_CpuClearFast(s_pSecureSegBuffer, s_SecureSegBufSize);
MI_CpuClearFast((u32 *)SYSM_CARD_BANNER_BUF, sizeof(TWLBannerFile));
s_IsPulledOut = TRUE;
// ワンセグのスリープ時シャットダウン対策を戻す
MCU_EnableDeepSleepToPowerLine( MCU_PWR_LINE_33, TRUE );
break;
}
}
SYSMi_GetWork()->flags.hotsw.is1stCardChecked = TRUE;
} // while loop
}
/*---------------------------------------------------------------------------*
Name: MonitorThread
Description: 実際のカード状態とHotSwThreadで状態を比べて、違いがあった場合は
メッセージを送る
s_IsPulledOut : True -> カードなし HOTSW_IsCardExist : True -> カードあり
False -> カードあり False -> カードなし
*---------------------------------------------------------------------------*/
static void MonitorThread(void *arg)
{
#pragma unused( arg )
BOOL isPullOutNow;
while(1){
// カードデータロード中は待機
do{
OS_Sleep(CARD_EXIST_CHECK_INTERVAL);
}
while(s_isHotSwBusy);
// 現在カードが抜けているか
isPullOutNow = !HOTSW_IsCardExist();
// 状態の比較
if(s_IsPulledOut != isPullOutNow){
OSIntrMode enabled = OS_DisableInterrupts();
// 本当は抜けてた場合
if(isPullOutNow){
HotSwThreadData.hotswPulledOutMsg[HotSwThreadData.idx_pulledOut].ctrl = FALSE;
HotSwThreadData.hotswPulledOutMsg[HotSwThreadData.idx_pulledOut].value = 0;
HotSwThreadData.hotswPulledOutMsg[HotSwThreadData.idx_pulledOut].type = HOTSW_PULLOUT;
// メッセージをキューの先頭に入れる
OS_JamMessage(&HotSwThreadData.hotswQueue, (OSMessage *)&HotSwThreadData.hotswPulledOutMsg[HotSwThreadData.idx_pulledOut], OS_MESSAGE_NOBLOCK);
// メッセージインデックスをインクリメント
HotSwThreadData.idx_pulledOut = (HotSwThreadData.idx_pulledOut+1) % HOTSW_PULLED_MSG_NUM;
}
// 本当は挿さっていた場合
else{
HotSwThreadData.hotswInsertMsg[HotSwThreadData.idx_insert].ctrl = FALSE;
HotSwThreadData.hotswInsertMsg[HotSwThreadData.idx_insert].value = 0;
HotSwThreadData.hotswInsertMsg[HotSwThreadData.idx_insert].type = HOTSW_INSERT;
// メッセージをキューの先頭に入れる
OS_JamMessage(&HotSwThreadData.hotswQueue, (OSMessage *)&HotSwThreadData.hotswInsertMsg[HotSwThreadData.idx_insert], OS_MESSAGE_NOBLOCK);
// メッセージインデックスをインクリメント
HotSwThreadData.idx_insert = (HotSwThreadData.idx_insert+1) % HOTSW_INSERT_MSG_NUM;
}
(void)OS_RestoreInterrupts( enabled );
OS_PutString(">>> Card State Error\n");
}
}
}
/*---------------------------------------------------------------------------*
Name: InterruptCallbackCard
Description: カードB抜け割り込みハンドラ
*---------------------------------------------------------------------------*/
static void InterruptCallbackCard(void)
{
HotSwThreadData.hotswPulledOutMsg[HotSwThreadData.idx_pulledOut].ctrl = FALSE;
HotSwThreadData.hotswPulledOutMsg[HotSwThreadData.idx_pulledOut].value = 0;
HotSwThreadData.hotswPulledOutMsg[HotSwThreadData.idx_pulledOut].type = HOTSW_PULLOUT;
// メッセージ送信
OS_SendMessage(&HotSwThreadData.hotswQueue, (OSMessage *)&HotSwThreadData.hotswPulledOutMsg[HotSwThreadData.idx_pulledOut], OS_MESSAGE_NOBLOCK);
// メッセージインデックスをインクリメント
HotSwThreadData.idx_pulledOut = (HotSwThreadData.idx_pulledOut+1) % HOTSW_PULLED_MSG_NUM;
/* // スロットのモードを
if(GetMcSlotMode() == SLOT_STATUS_MODE_01 || GetMcSlotMode() == SLOT_STATUS_MODE_10){
SetMcSlotMode(SLOT_STATUS_MODE_11);
}*/
OS_PutString("\n");
}
/*---------------------------------------------------------------------------*
Name: InterruptCallbackCardDet
Description: カードB挿し割り込みハンドラ
*---------------------------------------------------------------------------*/
static void InterruptCallbackCardDet(void)
{
HotSwThreadData.hotswInsertMsg[HotSwThreadData.idx_insert].ctrl = FALSE;
HotSwThreadData.hotswInsertMsg[HotSwThreadData.idx_insert].value = 0;
HotSwThreadData.hotswInsertMsg[HotSwThreadData.idx_insert].type = HOTSW_INSERT;
// メッセージ送信
OS_SendMessage(&HotSwThreadData.hotswQueue, (OSMessage *)&HotSwThreadData.hotswInsertMsg[HotSwThreadData.idx_insert], OS_MESSAGE_NOBLOCK);
// メッセージインデックスをインクリメント
HotSwThreadData.idx_insert = (HotSwThreadData.idx_insert+1) % HOTSW_INSERT_MSG_NUM;
OS_PutString("\n");
}
/*---------------------------------------------------------------------------*
Name: InterruptCallbackPxi
Description: PXI割り込みハンドラ
*---------------------------------------------------------------------------*/
static void InterruptCallbackPxi(PXIFifoTag tag, u32 data, BOOL err)
{
#pragma unused(tag)
#pragma unused(err)
HotSwPxiMessage d;
d.data = data;
HotSwThreadData.hotswPxiMsg[HotSwThreadData.idx_ctrl].ctrl = (d.msg.ctrl) ? TRUE : FALSE;
HotSwThreadData.hotswPxiMsg[HotSwThreadData.idx_ctrl].value = d.msg.value;
HotSwThreadData.hotswPxiMsg[HotSwThreadData.idx_ctrl].type = HOTSW_CONTROL;
// メッセージ送信
OS_SendMessage(&HotSwThreadData.hotswQueue, (OSMessage *)&HotSwThreadData.hotswPxiMsg[HotSwThreadData.idx_ctrl], OS_MESSAGE_NOBLOCK);
// メッセージインデックスをインクリメント
HotSwThreadData.idx_ctrl = (HotSwThreadData.idx_ctrl+1) % HOTSW_CTRL_MSG_NUM;
}
/*---------------------------------------------------------------------------*
Name: AllocateExCardBus
Description: アクセス権を設定する
*---------------------------------------------------------------------------*/
#ifdef SDK_ARM9
static inline void SetExCardProcessor(MIProcessor proc)
{
reg_HOTSW_EXMEMCNT =
(u16)((reg_HOTSW_EXMEMCNT & ~HOTSW_EXMEMCNT_SELB_MASK) | (proc << HOTSW_EXMEMCNT_SELB_SHIFT));
}
#endif
/*---------------------------------------------------------------------------*
Name: AllocateExCardBus
Description: スロットBへのアクセス権を設定する
*---------------------------------------------------------------------------*/
static void AllocateExCardBus(void)
{
#ifdef SDK_ARM9
// preset reset flag with status of disable interrupts in OSi_DoTryLockByWord
if ( ! ( reg_MI_MC & REG_MI_MC_SL2_CDET_MASK ) )
{
reg_MI_MCCNT1 |= REG_MI_MCCNT2_RESB_MASK;
}
SetExCardProcessor(MI_PROCESSOR_ARM9); // Arm9側で動作している場合
#endif
}
/*---------------------------------------------------------------------------*
Name: FreeExCardBus
Description: スロットBへのアクセス権を設定する
*---------------------------------------------------------------------------*/
static void FreeExCardBus(void)
{
#ifdef SDK_ARM9
SetExCardProcessor(MI_PROCESSOR_ARM7); // Card for SUB
#endif
}
/*---------------------------------------------------------------------------*
Name: LockSlotB
Description: スロットBをロックする
*---------------------------------------------------------------------------*/
static s32 LockExCard(u16 lockID)
{
return OS_LockByWord(lockID, (OSLockWord *)SLOT_B_LOCK_BUF, AllocateExCardBus);
}
/*---------------------------------------------------------------------------*
Name: UnlockSlotB
Description: スロットBをロックする
*---------------------------------------------------------------------------*/
static s32 UnlockExCard(u16 lockID)
{
return OS_UnlockByWord(lockID, (OSLockWord *)SLOT_B_LOCK_BUF, FreeExCardBus);
}
/*---------------------------------------------------------------------------*
Name: SetInterruptCallback
SetInterruptCallbackEx
Description: 割り込みコールバック関数と割り込み許可の設定を行う
*---------------------------------------------------------------------------*/
static void SetInterruptCallback( OSIrqMask intr_bit, OSIrqFunction func )
{
(void)OS_SetIrqFunction(intr_bit, func);
(void)OS_EnableIrqMask(intr_bit);
}
static void SetInterruptCallbackEx( OSIrqMask intr_bit, void *func )
{
(void)OS_SetIrqFunctionEx(intr_bit, func);
(void)OS_EnableIrqMaskEx(intr_bit);
}
/*---------------------------------------------------------------------------*
Name: SetInterrupt
Description: 割り込みコールバック関数を一度に設定する関数
*---------------------------------------------------------------------------*/
static void SetInterrupt(void)
{
#ifndef DEBUG_USED_CARD_SLOT_B_
SetInterruptCallback( OS_IE_CARD_A_IREQ , InterruptCallbackCard );
SetInterruptCallback( OS_IE_CARD_A_DET , InterruptCallbackCardDet );
(void)OS_EnableIrqMask(OS_IE_NDMA2);
#else
SetInterruptCallback( OS_IE_CARD_B_IREQ , InterruptCallbackCard );
SetInterruptCallback( OS_IE_CARD_B_DET , InterruptCallbackCardDet );
(void)OS_EnableIrqMask(OS_IE_NDMA2);
#endif
}
#include <twl/os/common/systemCall.h>
/*---------------------------------------------------------------------------*
Name: CheckStaticModuleHash
Description: 常駐モジュールのハッシュチェックを行う
*---------------------------------------------------------------------------*/
static HotSwState CheckStaticModuleHash(void)
{
BOOL flg = TRUE;
// Arm9常駐モジュール Hash値のチェック
if(!CheckArm9HashValue()){
flg = FALSE;
OS_PutString("×Arm9 Static Module Hash Check Error...\n");
}
// Arm7常駐モジュール Hash値のチェック
if(!CheckArm7HashValue()){
flg = FALSE;
OS_PutString("×Arm7 Static Module Hash Check Error...\n");
}
// Arm9拡張常駐モジュール Hash値のチェック
if(!CheckExtArm9HashValue()){
flg = FALSE;
OS_PutString("×Arm9 Ltd Static Module Hash Check Error...\n");
}
// Arm7拡張常駐モジュール Hash値のチェック
if(!CheckExtArm7HashValue()){
flg = FALSE;
OS_PutString("×Arm7 Ltd Static Module Hash Check Error...\n");
}
if(flg){
OS_PutString("*** Static Module Load was Completed!!\n");
}
return flg ? HOTSW_SUCCESS : HOTSW_HASH_CHECK_ERROR;
}
/*---------------------------------------------------------------------------*
Name: CheckArm7HashValue
Description: Arm7常駐モジュールのハッシュチェック
*---------------------------------------------------------------------------*/
static BOOL CheckArm7HashValue(void)
{
u8 sha1data[DIGEST_SIZE_SHA1];
BOOL retval = TRUE;
// クリア
MI_CpuClear8(sha1data, sizeof(sha1data));
// ARM7常駐モジュールのHash値照合
SVC_CalcHMACSHA1( sha1data,
(u32 *)(s_cbData.arm7Stc),
s_cbData.pBootSegBuf->rh.s.sub_size,
s_digestDefaultKey,
sizeof(s_digestDefaultKey) );
return SVC_CompareSHA1( sha1data, s_cbData.pBootSegBuf->rh.s.sub_static_digest );
}
/*---------------------------------------------------------------------------*
Name: CheckArm9HashValue
Description: Arm9常駐モジュールのハッシュチェック
※ 先頭2Kの復号化が行われる前のデータのハッシュを比べる
*---------------------------------------------------------------------------*/
static BOOL CheckArm9HashValue(void)
{
u8 sha1data[DIGEST_SIZE_SHA1];
BOOL retval = TRUE;
SVCHMACSHA1Context hash;
// クリア
MI_CpuClear8(sha1data, sizeof(sha1data));
// ハッシュ初期化
SVC_HMACSHA1Init( &hash, s_digestDefaultKey, sizeof(s_digestDefaultKey) );
// セキュア領域分UpDate
SVC_HMACSHA1Update( &hash, s_cbData.pSecureSegBuf, SECURE_SEGMENT_SIZE );
// ゲーム領域分UpDate
SVC_HMACSHA1Update( &hash, (u32 *)(s_cbData.arm9Stc + SECURE_SEGMENT_SIZE), s_cbData.pBootSegBuf->rh.s.main_size - SECURE_SEGMENT_SIZE );
// Hash値取得
SVC_HMACSHA1GetHash( &hash, sha1data );
return SVC_CompareSHA1( sha1data, s_cbData.pBootSegBuf->rh.s.main_static_digest );
}
/*---------------------------------------------------------------------------*
Name: CheckExtArm7HashValue
Description: Arm7拡張常駐モジュールのハッシュチェック
*---------------------------------------------------------------------------*/
static BOOL CheckExtArm7HashValue(void)
{
u8 sha1data[DIGEST_SIZE_SHA1];
BOOL retval = TRUE;
// クリア
MI_CpuClear8(sha1data, sizeof(sha1data));
// ARM7常駐モジュールのHash値照合
SVC_CalcHMACSHA1( sha1data,
(u32 *)s_cbData.arm7Ltd,
s_cbData.pBootSegBuf->rh.s.sub_ltd_size,
s_digestDefaultKey,
sizeof(s_digestDefaultKey) );
return SVC_CompareSHA1( sha1data, s_cbData.pBootSegBuf->rh.s.sub_ltd_static_digest );
}
/*---------------------------------------------------------------------------*
Name: CheckExtArm9HashValue
Description: Arm9拡張常駐モジュールのハッシュチェック
*---------------------------------------------------------------------------*/
static BOOL CheckExtArm9HashValue(void)
{
u8 sha1data[DIGEST_SIZE_SHA1];
u32 size;
BOOL retval = TRUE;
SVCHMACSHA1Context hash;
// Arm9拡張常駐モジュールのセキュア領域分のサイズを取得
size = ( s_cbData.pBootSegBuf->rh.s.main_ltd_size < SECURE_SEGMENT_SIZE ) ?
s_cbData.pBootSegBuf->rh.s.main_ltd_size : SECURE_SEGMENT_SIZE;
// クリア
MI_CpuClear8(sha1data, sizeof(sha1data));
// ハッシュ初期化
SVC_HMACSHA1Init( &hash, s_digestDefaultKey, sizeof(s_digestDefaultKey) );
// セキュア領域分UpDate
SVC_HMACSHA1Update( &hash, (u32 *)SYSM_CARD_TWL_SECURE_BUF, size );
// ゲーム領域分UpDate (Arm9拡張常駐モジュールがSecure領域で収まってたらここは飛ばす)
if( s_cbData.pBootSegBuf->rh.s.main_ltd_size > SECURE_SEGMENT_SIZE ){
SVC_HMACSHA1Update( &hash, (u32 *)(s_cbData.arm9Ltd + SECURE_SEGMENT_SIZE), s_cbData.pBootSegBuf->rh.s.main_ltd_size - size );
}
// Hash値取得
SVC_HMACSHA1GetHash( &hash, sha1data );
return SVC_CompareSHA1( sha1data, s_cbData.pBootSegBuf->rh.s.main_ltd_static_digest );
}
// **************************************************************************
//
// Debug用表示関数
//
// **************************************************************************
/*---------------------------------------------------------------------------*
Name: ShowRomHeaderData
Description:
*---------------------------------------------------------------------------*/
static void ShowRomHeaderData(void)
{
OS_TPrintf("\nDebug Data -------------------------------\n");
OS_TPrintf("1. Normal Mode ID : 0x%08x\n" , s_cbData.id_nml);
OS_TPrintf("2. Secure Mode ID : 0x%08x\n" , s_cbData.id_scr);
OS_TPrintf("3. Game Mode ID : 0x%08x\n" , s_cbData.id_gam);
OS_TPrintf("title Name : %s\n", s_pBootSegBuffer->rh.s.title_name);
OS_TPrintf("initial Code : %x\n\n", *(u32 *)s_pBootSegBuffer->rh.s.game_code);
OS_TPrintf("platform Code : 0x%02x\n\n", s_cbData.pBootSegBuf->rh.s.platform_code);
OS_TPrintf("main rom offset : 0x%08x\n" , s_cbData.pBootSegBuf->rh.s.main_rom_offset);
OS_TPrintf("main entry addr : 0x%08x\n" , s_cbData.pBootSegBuf->rh.s.main_entry_address);
OS_TPrintf("main ram addr : 0x%08x\n" , s_cbData.pBootSegBuf->rh.s.main_ram_address);
OS_TPrintf("main size : 0x%08x\n\n", s_cbData.pBootSegBuf->rh.s.main_size);
OS_TPrintf("sub rom offset : 0x%08x\n", s_cbData.pBootSegBuf->rh.s.sub_rom_offset);
OS_TPrintf("sub entry addr : 0x%08x\n", s_cbData.pBootSegBuf->rh.s.sub_entry_address);
OS_TPrintf("sub ram addr : 0x%08x\n", s_cbData.pBootSegBuf->rh.s.sub_ram_address);
OS_TPrintf("sub size : 0x%08x\n", s_cbData.pBootSegBuf->rh.s.sub_size);
if(s_cbData.twlFlg){
OS_TPrintf("\nLtd main rom offset: 0x%08x\n" , s_cbData.pBootSegBuf->rh.s.main_ltd_rom_offset);
OS_TPrintf("Ltd main ram addr: 0x%08x\n" , s_cbData.pBootSegBuf->rh.s.main_ltd_ram_address);
OS_TPrintf("Ltd main size : 0x%08x\n\n", s_cbData.pBootSegBuf->rh.s.main_ltd_size);
OS_TPrintf("Ltd Sub rom offset : 0x%08x\n" , s_cbData.pBootSegBuf->rh.s.sub_ltd_rom_offset);
OS_TPrintf("Ltd Sub ram addr : 0x%08x\n" , s_cbData.pBootSegBuf->rh.s.sub_ltd_ram_address);
OS_TPrintf("Ltd Sub size : 0x%08x\n", s_cbData.pBootSegBuf->rh.s.sub_ltd_size);
}
OS_TPrintf("------------------------------------------\n\n");
}
/*---------------------------------------------------------------------------*
Name: ShowRegisterData
Description:
*---------------------------------------------------------------------------*/
static void ShowRegisterData(void)
{
OS_TPrintf("----------------------------------------------------------\n");
OS_TPrintf("拡張機能制御レジスタ (MC_B(d24)) : %08x\n", reg_SCFG_EXT);
OS_TPrintf("MC I/F制御レジスタ (slot status) : %08x\n", reg_MI_MC1);
OS_TPrintf("MC I/F制御レジスタ (Counter-A) : %04x\n", reg_MI_MC2);
OS_TPrintf("MC コントロールレジスタ0 (SEL etc) : %04x\n", reg_HOTSW_MCCNT0);
OS_TPrintf("MC コントロールレジスタ1 (START etc) : %08x\n", reg_HOTSW_MCCNT1);
OS_TPrintf("----------------------------------------------------------\n");
}
/*---------------------------------------------------------------------------*
Name: DebugPrintErrorMessage
Description:
*---------------------------------------------------------------------------*/
static void DebugPrintErrorMessage(HotSwState state)
{
switch(state){
case HOTSW_SUCCESS:
OS_PutString(" - Success\n");
break;
case HOTSW_TIME_OUT:
OS_PutString(" - Error 1 : TimeOut\n");
break;
case HOTSW_CARD_LOCK_ERROR:
OS_PutString(" - Error 2 : Slot Lock\n");
break;
case HOTSW_CRC_CHECK_ERROR:
OS_PutString(" - Error 3 : CRC Check\n");
break;
case HOTSW_HASH_CHECK_ERROR:
OS_PutString(" - Error 4 : Hash Check\n");
break;
case HOTSW_ID_CHECK_ERROR:
OS_PutString(" - Error 5 : ID Check\n");
break;
case HOTSW_PULLED_OUT_ERROR:
OS_PutString(" - Error 6 : Pulled Out\n");
break;
case HOTSW_DATA_DECRYPT_ERROR:
OS_PutString(" - Error 7 : Data Decrypt\n");
break;
case HOTSW_BUFFER_OVERRUN_ERROR:
OS_PutString(" - Error 8 : Buffer OverRun\n");
break;
case HOTSW_UNEXPECTED_ERROR:
OS_PutString(" - Error 9 : Unexpected\n");
break;
default :
OS_PutString(" - illigal Error\n");
break;
}
}