TwlIPL/build/libraries_sysmenu/hotsw/ARM7/src/hotsw.c
(no author) 5c9b369dd8 (更新:Akabane Jumpei)
・活線挿抜処理を修正(まだ調整中)
・カードからデータのロードが完了したことを通知するフラグを追加

git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlIPL/trunk@624 b08762b0-b915-fc4b-9d8c-17b2551a87ff
2008-02-08 07:43:54 +00:00

1350 lines
48 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

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: TwlSDK
File: hotsw.c
Copyright 2007 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 <nitro/card/types.h>
#include <sysmenu.h>
#include <hotswTypes.h>
#include <blowfish.h>
#include <dsCardType1.h>
#include <dsCardType2.h>
#include <romEmulation.h>
#include <customNDma.h>
// define -------------------------------------------------------------------
#define UNDEF_CODE 0xe7ffdeff // 未定義コード
#define ENCRYPT_DEF_SIZE 0x800 // 2KB ※ ARM9常駐モジュール先頭2KB
#define DIGEST_HASH_BLOCK_SIZE_SHA1 (512/8)
#define ROM_EMULATION_START_OFS 0x160
#define ROM_EMULATION_END_OFS 0x180
#define HOTSW_THREAD_STACK_SIZE 1024 // スタックサイズ
#define HOTSW_THREAD_PRIO 11 // カード電源ON → ゲームモードのスレッド優先度
#define HOTSW_MSG_BUFFER_NUM 32 // 受信バッファの数
#define HOTSW_INSERT_MSG_NUM 16 // 挿し割り込み送信メッセージの数
#define HOTSW_PULLED_MSG_NUM 16 // 抜け割り込み送信メッセージの数
#define SLOT_B_LOCK_BUF HW_CTRDG_LOCK_BUF
#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
// enum ---------------------------------------------------------------------
typedef enum IntrType{
HOTSW_INSERT = 0,
HOTSW_PULLEDOUT = 1
}
IntrType;
// struct -------------------------------------------------------------------
typedef struct HotSwMessage{
IntrType type;
u32 hotswCount;
}
HotSwMessage;
// スレッド・メッセージ関係をまとめた構造体
typedef struct CardThreadData{
u64 stack[HOTSW_THREAD_STACK_SIZE / sizeof(u64)];
OSThread thread;
u32 idx_insert;
u32 idx_pulledOut;
HotSwMessage hotswInsertMsg[HOTSW_INSERT_MSG_NUM];
HotSwMessage hotswPulledOutMsg[HOTSW_PULLED_MSG_NUM];
OSMessageQueue hotswQueue;
OSMessage hotswMsgBuffer[HOTSW_MSG_BUFFER_NUM];
}
CardThreadData;
// Function prototype -------------------------------------------------------
static BOOL IsCardExist(void);
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 InterruptCallbackCardData(void);
static void McThread(void *arg);
static void McPowerOn(void);
static void McPowerOff(void);
static void SetMCSCR(void);
static void GenVA_VB_VD(void);
static void LoadTable(void);
static void ReadRomEmulationData(void);
static void ReadIDNormal(void);
static void DecryptObjectFile(void);
static void SetHotSwState(BOOL busy);
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 Values ------------------------------------------------------------
static char *encrypt_object_key ATTRIBUTE_ALIGN(4) = "encryObj";
static char *rom_emu_info ATTRIBUTE_ALIGN(4) = "TWLD";
static u32 s_SecureSegBufSize, s_BootSegBufSize;
static u32 *s_pSecureSegBuffer; // カード抜けてもバッファの場所覚えとく
static BootSegmentData *s_pBootSegBuffer; // カード抜けてもバッファの場所覚えとく
static CardBootData s_cbData;
static CardThreadData s_ctData;
// 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 CardBootFunction s_funcTable[] = {
// DS Card Type 1
{ ReadBootSegNormal_DSType1, ChangeModeNormal_DSType1, // Normalモード関数
ReadIDSecure_DSType1, ReadSegSecure_DSType1, SwitchONPNGSecure_DSType1, ChangeModeSecure_DSType1, // Secureモード関数
ReadIDGame_DSType1, ReadPageGame_DSType1}, // Game モード関数
// DS Card Type 2
{ ReadBootSegNormal_DSType2, ChangeModeNormal_DSType2, // Normalモード関数
ReadIDSecure_DSType2, ReadSegSecure_DSType2, SwitchONPNGSecure_DSType2, ChangeModeSecure_DSType2, // Secureモード関数
ReadIDGame_DSType2, ReadPageGame_DSType2}, // Game モード関数
// TWL Card Type 1
{ ReadBootSegNormal_DSType2, ChangeModeNormal_DSType2, // Normalモード関数
ReadIDSecure_DSType2, ReadSegSecure_DSType2, SwitchONPNGSecure_DSType2, ChangeModeSecure_DSType2, // Secureモード関数
ReadIDGame_DSType2, ReadPageGame_DSType2}, // Game モード関数
// RomEmulation
{ ReadBootSegNormal_ROMEMU, ChangeModeNormal_ROMEMU, // Normalモード関数
ReadIDSecure_ROMEMU, ReadSegSecure_ROMEMU, SwitchONPNGSecure_ROMEMU, ChangeModeSecure_ROMEMU, // Secureモード関数
ReadIDGame_ROMEMU, ReadPageGame_ROMEMU} // Game モード関数
};
// ===========================================================================
// Function Describe
// ===========================================================================
/*---------------------------------------------------------------------------*
Name: HOTSW_Init
Arguments: None.
Returns: None.
*---------------------------------------------------------------------------*/
void HOTSW_Init(void)
{
OS_InitTick();
OS_InitThread();
// 割り込みマスクの設定
SetInterrupt();
// 割り込みの有効化
(void)OS_EnableIrq();
(void)OS_EnableInterrupts();
#ifdef SDK_ARM7
// チャッタリングカウンタの値を設定
reg_MI_MC1 = (u32)((reg_MI_MC1 & 0xfff) | 0x1000000);
// Counter-Aの値を設定
reg_MI_MC2 = 0x100;
#else
// PXI経由でARM7にチャッタリングカウンタ・カウンタAの値を設定してもらう。設定されるまで待つ。
#endif
// カードブート用構造体の初期化
MI_CpuClear8(&s_cbData, sizeof(CardBootData));
// カードスレッド用構造体の初期化
MI_CpuClear8(&s_ctData, sizeof(CardThreadData));
// カードブート用スレッドの生成
OS_CreateThread(&s_ctData.thread,
McThread,
NULL,
s_ctData.stack + HOTSW_THREAD_STACK_SIZE / sizeof(u64),
HOTSW_THREAD_STACK_SIZE,
HOTSW_THREAD_PRIO
);
// メッセージキューの初期化
OS_InitMessageQueue( &s_ctData.hotswQueue, &s_ctData.hotswMsgBuffer[0], HOTSW_MSG_BUFFER_NUM );
// スレッド起動
OS_WakeupThreadDirect(&s_ctData.thread);
// Boot Segment バッファの設定
HOTSW_SetBootSegmentBuffer((void *)SYSM_CARD_ROM_HEADER_BAK, SYSM_CARD_ROM_HEADER_SIZE );
// Secure Segment バッファの設定
HOTSW_SetSecureSegmentBuffer((void *)SYSM_CARD_NTR_SECURE_BUF, SECURE_AREA_SIZE );
// カードが挿さってあったらスレッドを起動する
if(IsCardExist()){
// OS_PutString("Card Boot Start\n");
// 送信メッセージを作成 (活線挿抜回数を取得・カード挿し)
s_ctData.hotswInsertMsg[s_ctData.idx_insert].hotswCount = CARDi_GetSlotResetCount();
s_ctData.hotswInsertMsg[s_ctData.idx_insert].type = HOTSW_INSERT;
// メッセージ送信
OS_SendMessage(&s_ctData.hotswQueue, (OSMessage)&s_ctData.hotswInsertMsg[s_ctData.idx_insert], OS_MESSAGE_NOBLOCK);
// メッセージインデックスをインクリメント
s_ctData.idx_insert = (s_ctData.idx_insert+1) % HOTSW_INSERT_MSG_NUM;
}
else{
// OS_PutString("No Card...\n");
#ifdef DEBUG_USED_CARD_SLOT_B_
SYSMi_GetWork()->flags.common.is1stCardChecked = TRUE;
#endif
}
}
/* -----------------------------------------------------------------
* HOTSW_LoadCardData関数
*
* カードからデータをロードする
*
* ※BootSegmentBuffer SecureSegmentBufferの設定を行ってから
* この関数を呼んでください。
* ----------------------------------------------------------------- */
BOOL HOTSW_LoadCardData(void)
{
OSTick start;
s32 tempLockID;
BOOL retval = TRUE;
start = OS_GetTick();
// スロットがスワップされてたら元に戻す。
if(reg_MI_MC1 & 0x8000){
reg_MI_MC1 = reg_MI_MC1 & 0xff;
}
// OS_TPrintf("---------------- Card Boot Start ---------------\n");
#ifdef SDK_ARM7
// カード電源リセット
McPowerOff();
McPowerOn();
#else // SDK_ARM9
// ARM7にPXI経由でカード電源ONをお願い。ONになるまで待つ。
#endif
// バッファを設定
s_cbData.pBootSegBuf = s_pBootSegBuffer;
s_cbData.pSecureSegBuf = s_pSecureSegBuffer;
// バッファのクリア
MI_CpuClearFast(s_pBootSegBuffer, s_BootSegBufSize);
MI_CpuClearFast(s_pSecureSegBuffer, s_SecureSegBufSize);
// カードのロックIDを取得
tempLockID = OS_GetLockID();
if(tempLockID == OS_LOCK_ID_ERROR){
retval = FALSE;
}
else{
s_cbData.lockID = (u16)tempLockID;
}
// ブート処理開始
if(IsCardExist() && retval){
// カードのロック
#ifdef DEBUG_USED_CARD_SLOT_B_
LockExCard(s_cbData.lockID);
#else
OS_LockCard(s_cbData.lockID);
#endif
// カード側でKey Tableをロードする
LoadTable();
// ---------------------- Normal Mode ----------------------
// カードID読み込み
ReadIDNormal();
s_funcTable[0].ReadID_G(&s_cbData);
// カードタイプを判別をして、使う関数を切替える IDの最上位ビットが1なら3DM
if(s_cbData.id_nml & 0x80000000){
s_cbData.cardType = DS_CARD_TYPE_2;
// OS_TPrintf("Card Type2\n");
}
else{
s_cbData.cardType = DS_CARD_TYPE_1;
// OS_TPrintf("Card Type1\n");
}
{
u8 i;
u8 *romEmuInf = (u8 *)s_cbData.romEmuBuf;
// ※最低限ARM9と排他制御しないといけない範囲はこれだけ
u16 id = (u16)OS_GetLockID();
(void)OS_LockByWord( id, &SYSMi_GetWork()->lockCardRsc, NULL ); // ARM9と排他制御する
// Boot Segment読み込み
s_funcTable[s_cbData.cardType].ReadBootSegment_N(&s_cbData);
// Romエミュレーション情報を取得
ReadRomEmulationData();
// 取得したRomエミュレーション情報を比較
s_cbData.debuggerFlg = TRUE;
for(i=0; i<4; i++){
if ( rom_emu_info[i] != romEmuInf[i] ){
s_cbData.debuggerFlg = FALSE;
break;
}
}
if(s_cbData.debuggerFlg){
OS_PutString("Read Debugger\n");
s_cbData.cardType = ROM_EMULATION;
SYSMi_GetWork()->gameCommondParam = s_cbData.pBootSegBuf->rh.s.game_cmd_param & ~SCRAMBLE_MASK;
OS_TPrintf("SYSMi_GetWork()->gameCommondParam : 0x%08x\n",SYSMi_GetWork()->gameCommondParam);
}
else{
SYSMi_GetWork()->gameCommondParam = s_cbData.pBootSegBuf->rh.s.game_cmd_param;
}
// 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 = FALSE;
}
(void)OS_UnlockByWord( id, &SYSMi_GetWork()->lockCardRsc, NULL ); // ARM9と排他制御する
OS_ReleaseLockID( id );
}
if( retval ) {
// NTRカードかTWLカードか
if(s_cbData.pBootSegBuf->rh.s.platform_code & 0x02){
// 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初期化
GCDm_MakeBlowfishTableDS(&s_cbData.keyTable, &s_pBootSegBuffer->rh.s, s_cbData.keyBuf, 8);
// コマンド認証値・コマンドカウンタ初期値・PNジェネレータ初期値の生成
GenVA_VB_VD();
// セキュアモードに移行
s_funcTable[s_cbData.cardType].ChangeMode_N(&s_cbData);
// ---------------------- Secure Mode ----------------------
// PNG設定
s_funcTable[s_cbData.cardType].SetPNG_S(&s_cbData);
// DS側符号生成回路初期値設定 (レジスタ設定)
SetMCSCR();
// ID読み込み
s_funcTable[s_cbData.cardType].ReadID_S(&s_cbData);
// カードIDの比較をして、一致しなければFALSEを返す
if(s_cbData.id_nml != s_cbData.id_scr){
return FALSE;
}
// Secure領域のSegment読み込み
s_funcTable[s_cbData.cardType].ReadSegment_S(&s_cbData);
// ゲームモードに移行
s_funcTable[s_cbData.cardType].ChangeMode_S(&s_cbData);
// ---------------------- Game Mode ----------------------
// ID読み込み
s_funcTable[s_cbData.cardType].ReadID_G(&s_cbData);
// カードIDの比較をして、一致しなければFALSEを返す
if(s_cbData.id_scr != s_cbData.id_gam){
return FALSE;
}
// 常駐モジュール残りを指定先に転送
HOTSW_LoadStaticModule();
// ARM9常駐モジュールの先頭2KBの暗号化領域を複合化
DecryptObjectFile();
}
// カードのロック開放
#ifdef DEBUG_USED_CARD_SLOT_B_
UnlockExCard(s_cbData.lockID);
#else
OS_UnlockCard(s_cbData.lockID);
#endif
// OS_TPrintf("-----------------------------------------------\n");
}
else{
// OS_TPrintf("Card Not Found\n");
retval = FALSE;
}
// カードロックIDの開放
OS_ReleaseLockID( s_cbData.lockID );
// OS_TPrintf( "Load Card Time : %dms\n\n", OS_TicksToMilliSeconds( OS_GetTick() - start ) );
return retval;
}
/* -----------------------------------------------------------------
* HOTSW_GetRomEmulationBuffer関数
*
* Romエミュレーション情報を格納しているバッファへのポインタを返す
* ----------------------------------------------------------------- */
void* HOTSW_GetRomEmulationBuffer(void)
{
return s_cbData.romEmuBuf;
}
/* -----------------------------------------------------------------
* HOTSW_LoadStaticModule関数
*
* ARM7,9の常駐モジュールを展開する関数
*
* 注:一度カードブートしてゲームモードになってから呼び出してください
* ----------------------------------------------------------------- */
void HOTSW_LoadStaticModule(void)
{
#ifdef DEBUG_USED_CARD_SLOT_B_
// バナーリード
if( s_cbData.pBootSegBuf->rh.s.banner_offset ) {
// OS_TPrintf(" - Banner Loading...\n");
s_funcTable[s_cbData.cardType].ReadPage_G(&s_cbData,
s_cbData.pBootSegBuf->rh.s.banner_offset,
(u32 *)SYSM_CARD_BANNER_BUF,
sizeof(TWLBannerFile) );
}
if(IsCardExist())
{
SYSMi_GetWork()->flags.common.isValidCardBanner = TRUE;
SYSMi_GetWork()->flags.common.isCardStateChanged = TRUE;
SYSMi_GetWork()->flags.common.isExistCard = TRUE;
}
#endif
s_cbData.arm9Stc = (u32)s_cbData.pBootSegBuf->rh.s.main_ram_address;
// 配置先と再配置情報を取得 & Arm9の常駐モジュール残りを指定先に転送
SYSM_CheckLoadRegionAndSetRelocateInfo( ARM9_STATIC, &s_cbData.arm9Stc, s_cbData.pBootSegBuf->rh.s.main_size, &SYSMi_GetWork()->romRelocateInfo[ARM9_STATIC] , s_cbData.twlFlg);
s_funcTable[s_cbData.cardType].ReadPage_G(&s_cbData,
s_cbData.pBootSegBuf->rh.s.main_rom_offset + SECURE_SEGMENT_SIZE,
(u32 *)(s_cbData.arm9Stc + SECURE_SEGMENT_SIZE),
s_cbData.pBootSegBuf->rh.s.main_size - SECURE_SEGMENT_SIZE);
s_cbData.arm7Stc = (u32)s_cbData.pBootSegBuf->rh.s.sub_ram_address;
// 配置先と再配置情報を取得 & Arm7の常駐モジュールを指定先に転送
SYSM_CheckLoadRegionAndSetRelocateInfo( ARM7_STATIC, &s_cbData.arm7Stc, s_cbData.pBootSegBuf->rh.s.sub_size, &SYSMi_GetWork()->romRelocateInfo[ARM7_STATIC] , s_cbData.twlFlg);
s_funcTable[s_cbData.cardType].ReadPage_G(&s_cbData,
s_cbData.pBootSegBuf->rh.s.sub_rom_offset,
(u32 *)s_cbData.arm7Stc,
s_cbData.pBootSegBuf->rh.s.sub_size);
// TWLでのみロード
if( s_cbData.pBootSegBuf->rh.s.platform_code & PLATFORM_CODE_FLAG_TWL ) {
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の常駐モジュールを指定先に転送※TWLカード対応していないので、注意
SYSM_CheckLoadRegionAndSetRelocateInfo( ARM9_LTD_STATIC, &s_cbData.arm9Ltd, s_cbData.pBootSegBuf->rh.s.main_ltd_size, &SYSMi_GetWork()->romRelocateInfo[ARM9_LTD_STATIC] , TRUE);
s_funcTable[s_cbData.cardType].ReadPage_G(&s_cbData,
s_cbData.pBootSegBuf->rh.s.main_ltd_rom_offset,
(u32 *)SYSM_CARD_TWL_SECURE_BUF,
size);
if( s_cbData.pBootSegBuf->rh.s.main_ltd_size > SECURE_SEGMENT_SIZE ) {
s_funcTable[s_cbData.cardType].ReadPage_G(&s_cbData,
s_cbData.pBootSegBuf->rh.s.main_ltd_rom_offset + SECURE_SEGMENT_SIZE,
(u32 *)(s_cbData.arm9Ltd + SECURE_SEGMENT_SIZE),
s_cbData.pBootSegBuf->rh.s.main_ltd_size - size);
}
s_cbData.arm7Ltd = (u32)s_cbData.pBootSegBuf->rh.s.sub_ltd_ram_address;
// 配置先と再配置情報を取得 & Arm7の常駐モジュールを指定先に転送
SYSM_CheckLoadRegionAndSetRelocateInfo( ARM7_LTD_STATIC, &s_cbData.arm7Ltd, s_cbData.pBootSegBuf->rh.s.sub_ltd_size, &SYSMi_GetWork()->romRelocateInfo[ARM7_LTD_STATIC], TRUE);
s_funcTable[s_cbData.cardType].ReadPage_G(&s_cbData,
s_cbData.pBootSegBuf->rh.s.sub_ltd_rom_offset,
(u32 *)s_cbData.arm7Ltd,
s_cbData.pBootSegBuf->rh.s.sub_ltd_size);
// Arm9常駐モジュール Hash値のチェック
if(!CheckArm9HashValue()){
OS_PutString("×Arm9 Static Module Hash Check Error...\n");
}
// Arm7常駐モジュール Hash値のチェック
if(!CheckArm7HashValue()){
OS_PutString("×Arm7 Static Module Hash Check Error...\n");
}
// Arm9拡張常駐モジュール Hash値のチェック
if(!CheckExtArm9HashValue()){
OS_PutString("×Arm9 Ltd Static Module Hash Check Error...\n");
}
// Arm7拡張常駐モジュール Hash値のチェック
if(!CheckExtArm7HashValue()){
OS_PutString("×Arm7 Ltd Static Module Hash Check Error...\n");
}
}
}
/* -----------------------------------------------------------------
* HOTSW_SetBootSegmentBuffer関数
*
* 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);
OS_TPrintf("*** Boot Segm Address : 0x%08x\n", s_pBootSegBuffer);
}
/* -----------------------------------------------------------------
* HOTSW_SetSecureSegmentBuffer関数
*
* Secure Segment バッファの指定
*
* 注:カードブート処理中は呼び出さないようにする
* ----------------------------------------------------------------- */
void HOTSW_SetSecureSegmentBuffer(void* buf, u32 size)
{
SDK_ASSERT(size > SECURE_SEGMENT_SIZE);
s_pSecureSegBuffer = (u32 *)buf;
s_SecureSegBufSize = size;
s_cbData.pSecureSegBuf = s_pSecureSegBuffer;
// バッファの初期化
MI_CpuClear8(s_pSecureSegBuffer, size);
OS_TPrintf("*** Scr Seg Buf Address : 0x%08x\n", s_pSecureSegBuffer);
}
/* -----------------------------------------------------------------
* GenVA_VB_VD関数
*
* コマンド認証値・コマンドカウンタ・PNジェネレータ初期値の生成
* ----------------------------------------------------------------- */
static void GenVA_VB_VD(void)
{
u32 dummy = 0;
MATHRandContext32 rnd;
// 乱数を初期化 VBlankカウンタ値を種とする。
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;
}
/* -----------------------------------------------------------------
* LoadTable関数
*
* カード側の Key Table をロードする関数。
*
* ※この関数は開発カード用に発行しないといけない。
* 製品版カードの場合、このコマンドは無視される設計
* ----------------------------------------------------------------- */
static void LoadTable(void)
{
u32 temp;
// MCCMD レジスタ設定
reg_HOTSW_MCCMD0 = 0x0000009f;
reg_HOTSW_MCCMD1 = 0x00000000;
// MCCNT0 レジスタ設定 (E = 1 I = 1 SEL = 0に)
reg_HOTSW_MCCNT0 = (u16)((reg_HOTSW_MCCNT0 & 0x0fff) | 0xc000);
// MCCNT1 レジスタ設定 (START = 1 W/R = 0 PC = 101(16ページ) latency1 = 0(必要ないけど) に)
reg_HOTSW_MCCNT1 = START_MASK | PC_MASK & (0x5 << PC_SHIFT);
// MCCNTレジスタのRDYフラグをポーリングして、フラグが立ったらデータをMCD1レジスタに再度セット。スタートフラグが0になるまでループ。
while(reg_HOTSW_MCCNT1 & START_FLG_MASK){
while(!(reg_HOTSW_MCCNT1 & READY_FLG_MASK)){}
temp = reg_HOTSW_MCD1;
}
}
/*---------------------------------------------------------------------------*
Name: ReadRomEmulationData
Description: Romエミュレーションデータの読み込み
*---------------------------------------------------------------------------*/
static void ReadRomEmulationData(void)
{
u32 count=0;
u32 temp;
u32 *dst = s_cbData.romEmuBuf;
// 量産用CPUでは平文アクセス防止のためリードしない
if ( ! (*(u8*)(OS_CHIPTYPE_DEBUGGER_ADDR) & OS_CHIPTYPE_DEBUGGER_MASK) )
{
return;
}
// MCCMD レジスタ設定
reg_HOTSW_MCCMD0 = 0x3e000000;
reg_HOTSW_MCCMD1 = 0x0;
// MCCNT1 レジスタ設定 (START = 1 PC = 001(1ページリード)に latency1 = 0x5fe)
reg_HOTSW_MCCNT1 = START_MASK | PC_MASK & (0x1 << PC_SHIFT) | (0x5fe & LATENCY1_MASK);
// MCCNTレジスタのRDYフラグをポーリングして、フラグが立ったらデータをMCD1レジスタに再度セット。スタートフラグが0になるまでループ。
while(reg_HOTSW_MCCNT1 & START_FLG_MASK){
while(!(reg_HOTSW_MCCNT1 & READY_FLG_MASK)){}
if(count >= ROM_EMULATION_START_OFS && count < ROM_EMULATION_END_OFS){
*dst++ = reg_HOTSW_MCD1;
}
else{
temp = reg_HOTSW_MCD1;
}
count+=4;
}
MI_CpuCopyFast(s_cbData.romEmuBuf, (void*)HW_ISD_RESERVED, 32);
}
/* -----------------------------------------------------------------
* ReadIDNormal関数
*
* ーマルモード時のカードIDを読み込む関数
* ----------------------------------------------------------------- */
void ReadIDNormal(void)
{
// カード割り込みによるDMAコピー
HOTSW_NDmaCopy_Card( HOTSW_DMA_NO, (u32 *)HOTSW_MCD1, &s_cbData.id_nml, sizeof(s_cbData.id_nml) );
// MCCMD レジスタ設定
reg_HOTSW_MCCMD0 = 0x00000090;
reg_HOTSW_MCCMD1 = 0x00000000;
// MCCNT0 レジスタ設定 (E = 1 I = 1 SEL = 0に)
reg_HOTSW_MCCNT0 = (u16)((reg_HOTSW_MCCNT0 & 0x0fff) | 0xc000);
// MCCNT1 レジスタ設定 (START = 1 PC = 111(ステータスリード) latency1 = 1 に)
reg_HOTSW_MCCNT1 = START_MASK | PC_MASK & (0x7 << PC_SHIFT) | (0x1 & LATENCY1_MASK);
// カードデータ転送終了割り込みが起こるまで寝る(割り込みハンドラの中で起こされる)
OS_SleepThread(NULL);
}
/* -----------------------------------------------------------------
* DecryptObjectFile関数
*
* セキュア領域先頭2KBの暗号化領域を復号化
*
* 注:セキュアモード中、またはセキュアモード前にこの関数を呼ぶと、
*   正常にコマンドの暗号化が行えなくなります。
* ----------------------------------------------------------------- */
static u32 encDestBuf[ENCRYPT_DEF_SIZE/sizeof(u32)];
static void 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;
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{
OS_PutString("▼ DecryptObjectFile : Error...\n");
MI_NDmaFill( HOTSW_DMA_NO, pEncBuf, UNDEF_CODE, (u32)size ); // 未定義コードでクリア
}
MI_CpuCopy32(pEncBuf, pEncDes, (u32)size);
}
/* -----------------------------------------------------------------
* IsCardExist関数
*
* カードの存在判定
*
* ※SCFG_MC1のCDETフラグを見ている
* ----------------------------------------------------------------- */
static BOOL IsCardExist(void)
{
if(!(reg_MI_MC1 & SLOT_STATUS_CDET_MSK)){
return TRUE;
}
else{
return FALSE;
}
}
/*---------------------------------------------------------------------------*
Name: McPowerOn
Description: スロットB 電源ON関数
*---------------------------------------------------------------------------*/
static void McPowerOn(void)
{
if((reg_MI_MC1 & SLOT_STATUS_MODE_SELECT_MSK) == SLOT_STATUS_MODE_00){
// SCFG_MC1 の Slot Status の M1,M0 を 01 にする
reg_MI_MC1 = (u32)((reg_MI_MC1 & (~SLOT_STATUS_MODE_SELECT_MSK)) | SLOT_STATUS_MODE_01);
// 1ms待ち
OS_Sleep(1);
// SCFG_MC1 の Slot Status の M1,M0 を 10 にする
reg_MI_MC1 = (u32)((reg_MI_MC1 & (~SLOT_STATUS_MODE_SELECT_MSK)) | SLOT_STATUS_MODE_10);
// 1ms待ち
OS_Sleep(1);
// リセットをhighに (RESB = 1にする)
reg_HOTSW_MCCNT1 = RESB_MASK;
// 27ms待ち
OS_Sleep(27);
}
}
/*---------------------------------------------------------------------------*
Name: McPowerOff
Description: スロットB 電源OFF関数
*---------------------------------------------------------------------------*/
static void McPowerOff(void)
{
if((reg_MI_MC1 & SLOT_STATUS_MODE_SELECT_MSK) == SLOT_STATUS_MODE_10){
// SCFG_MC1 の Slot Status の M1,M0 を 11 にする
reg_MI_MC1 = (u32)((reg_MI_MC1 & (~SLOT_STATUS_MODE_SELECT_MSK)) | SLOT_STATUS_MODE_11);
// SCFG_MC1 の Slot Status の M1,M0 が 00 になるまでポーリング
while((reg_MI_MC1 & SLOT_STATUS_MODE_SELECT_MSK) != SLOT_STATUS_MODE_00){}
// 100ms待ち [TODO:]待ち時間は暫定値。金子さんに数値を測定してもらう。
OS_Sleep(100);
}
}
/*---------------------------------------------------------------------------*
Name: SetMCSCR
Description: 符号生成回路初期値設定レジスタを設定する
※注:この関数はセキュアモードで、
sPNG_ONコマンドを実行してから呼び出してください。
*---------------------------------------------------------------------------*/
static void SetMCSCR(void)
{
u32 pna_l = (u32)(PNA_BASE_VALUE | (s_cbData.vd << 15));
u32 pna_h = (u32)(s_cbData.vd >> 17);
// SCR A
reg_HOTSW_MCSCR0 = pna_l;
// SCR B
reg_HOTSW_MCSCR1 = PNB_L_VALUE;
// [d0 -d6 ] -> SCR A
// [d16-d22] -> SCR B
reg_HOTSW_MCSCR2 = (u32)(pna_h | PNB_H_VALUE << 16);
// MCCNT1 レジスタ設定 (SCR = 1に)
reg_HOTSW_MCCNT1 = SCR_MASK;
}
/*---------------------------------------------------------------------------*
Name: McThread
Description: カード抜け・挿し処理スレッド
*---------------------------------------------------------------------------*/
static void McThread(void *arg)
{
#pragma unused( arg )
BOOL retval;
HotSwMessage *msg;
while(1){
OS_ReceiveMessage(&s_ctData.hotswQueue, (OSMessage *)&msg, OS_MESSAGE_BLOCK);
// カードデータロード完了フラグを下ろす
SYSMi_GetWork()->flags.common.isCardLoadCompleted = FALSE;
// カード挿し割り込みによるスレッド起動
if(msg->type == HOTSW_INSERT){
OS_PutString("-> Insert\n");
// 活線挿抜抑制フラグが立っていたら処理しない
if( !SYSMi_GetWork()->flags.common.isEnableHotSW ) {
#ifdef DEBUG_USED_CARD_SLOT_B_
SYSMi_GetWork()->flags.common.is1stCardChecked = TRUE;
#endif
continue;
}
// カードが挿してある
if(IsCardExist()){
// HotSwをbusy状態にする
SetHotSwState(TRUE);
// カード読み込み開始
retval = HOTSW_LoadCardData();
// HotSwをfree状態にする
SetHotSwState(FALSE);
// カード読み込みに失敗してた場合 or 挿抜回数不一致 or カード抜かれてた
if(!retval || !CARDi_IsPulledOutEx(msg->hotswCount) || !IsCardExist()){
OS_TPrintf("Load Card Data Retval : %x HotSwCount : %d(msg : %d) IsCardExist : %d\n",
retval, CARDi_GetSlotResetCount(),msg->hotswCount,IsCardExist());
// フラグ処理
SYSMi_GetWork()->flags.common.isValidCardBanner = FALSE;
SYSMi_GetWork()->flags.common.isCardStateChanged = FALSE;
SYSMi_GetWork()->flags.common.isExistCard = FALSE;
// カードロックの開放
#ifdef DEBUG_USED_CARD_SLOT_B_
UnlockExCard(s_cbData.lockID);
#else
OS_UnlockCard(s_cbData.lockID);
#endif
// カードロックIDの開放
OS_ReleaseLockID( s_cbData.lockID );
OS_PutString("### Card Read Error\n");
}
// カード読み込み・状態に問題がない場合
else{
u16 id = (u16)OS_GetLockID();
(void)OS_LockByWord( id, &SYSMi_GetWork()->lockHotSW, NULL );
if( SYSMi_GetWork()->flags.arm9.reqChangeHotSW ) {
SYSMi_GetWork()->flags.common.isEnableHotSW = SYSMi_GetWork()->flags.arm9.nextHotSWStatus;
SYSMi_GetWork()->flags.arm9.reqChangeHotSW = 0;
SYSMi_GetWork()->flags.arm9.nextHotSWStatus = 0;
}
(void)OS_UnlockByWord( id, &SYSMi_GetWork()->lockHotSW, NULL );
OS_ReleaseLockID( id );
// 新しいカードのIDを入れる
SYSMi_GetWork()->nCardID = s_cbData.id_gam;
// デバッガ情報
MI_CpuCopy8( HOTSW_GetRomEmulationBuffer(), &SYSMi_GetWork()->romEmuInfo, ROM_EMULATION_DATA_SIZE );
SYSMi_GetWork()->flags.common.isOnDebugger = s_cbData.debuggerFlg;
// カードデータロード完了フラグ
SYSMi_GetWork()->flags.common.isCardLoadCompleted = TRUE;
}
} // end [if(IsCardExist())]
#ifdef DEBUG_USED_CARD_SLOT_B_
SYSMi_GetWork()->flags.common.is1stCardChecked = TRUE;
#endif
}
// カード抜き割り込みによるスレッド起動
else if(msg->type == HOTSW_PULLEDOUT){
OS_PutString("-> Init\n\n");
// HOTSW抑制フラグが立ってたら、処理しない
if( !SYSMi_GetWork()->flags.common.isEnableHotSW ) {
continue;
}
// カードが抜かれている
if(!IsCardExist()){
// フラグケア
{
u16 id = (u16)OS_GetLockID();
(void)OS_LockByWord( id, &SYSMi_GetWork()->lockHotSW, NULL );
SYSMi_GetWork()->flags.common.isExistCard = FALSE;
SYSMi_GetWork()->flags.common.isValidCardBanner = FALSE;
SYSMi_GetWork()->flags.common.isCardStateChanged = TRUE;
(void)OS_UnlockByWord( id, &SYSMi_GetWork()->lockHotSW, NULL );
OS_ReleaseLockID( id );
}
// カードブート用構造体の初期化
MI_CpuClear32(&s_cbData, sizeof(CardBootData));
}
}
} // while loop
}
/*---------------------------------------------------------------------------*
Name: InterruptCallbackCard
Description: カードB抜け割り込みハンドラ
*---------------------------------------------------------------------------*/
static void InterruptCallbackCard(void)
{
OS_TPrintf("*** Pulled Out Interrupt\n");
// 送信メッセージを作成 (活線挿抜回数を取得・カード挿し)
s_ctData.hotswPulledOutMsg[s_ctData.idx_pulledOut].hotswCount = CARDi_GetSlotResetCount();
s_ctData.hotswPulledOutMsg[s_ctData.idx_pulledOut].type = HOTSW_PULLEDOUT;
// メッセージ送信
OS_SendMessage(&s_ctData.hotswQueue, (OSMessage *)&s_ctData.hotswPulledOutMsg[s_ctData.idx_pulledOut], OS_MESSAGE_NOBLOCK);
// メッセージインデックスをインクリメント
s_ctData.idx_pulledOut = (s_ctData.idx_pulledOut+1) % HOTSW_PULLED_MSG_NUM;
// OS_TPrintf(" - idx_pulledOut : %d\n", s_ctData.idx_pulledOut);
#ifdef USE_SLOT_A
OS_SetIrqCheckFlagEx(OS_IE_CARD_A_IREQ);
#else
OS_SetIrqCheckFlagEx(OS_IE_CARD_B_IREQ);
#endif
}
/*---------------------------------------------------------------------------*
Name: InterruptCallbackCardDet
Description: カードB挿し割り込みハンドラ
*---------------------------------------------------------------------------*/
static void InterruptCallbackCardDet(void)
{
OS_TPrintf("*** Insert Interrupt\n");
// SDKのカード状態をリセットする
CARDi_ResetSlotStatus();
// 送信メッセージを作成 (活線挿抜回数を取得・カード挿し)
s_ctData.hotswInsertMsg[s_ctData.idx_insert].hotswCount = CARDi_GetSlotResetCount();
s_ctData.hotswInsertMsg[s_ctData.idx_insert].type = HOTSW_INSERT;
// メッセージ送信
OS_SendMessage(&s_ctData.hotswQueue, (OSMessage *)&s_ctData.hotswInsertMsg[s_ctData.idx_insert], OS_MESSAGE_NOBLOCK);
// メッセージインデックスをインクリメント
s_ctData.idx_insert = (s_ctData.idx_insert+1) % HOTSW_INSERT_MSG_NUM;
// OS_TPrintf(" - idx_insert : %d\n", s_ctData.idx_insert);
#ifdef USE_SLOT_A
OS_SetIrqCheckFlagEx(OS_IE_CARD_A_DET);
#else
OS_SetIrqCheckFlagEx(OS_IE_CARD_B_DET);
#endif
}
/*---------------------------------------------------------------------------*
Name: InterruptCallbackCardData
Description: カードB データ転送終了割り込みハンドラ
*---------------------------------------------------------------------------*/
static void InterruptCallbackCardData(void)
{
// データ転送終了待ちまで寝ていたのを起こす
OS_WakeupThreadDirect(&s_ctData.thread);
#ifdef USE_SLOT_A
OS_SetIrqCheckFlagEx(OS_IE_CARD_A_DATA);
#else
OS_SetIrqCheckFlagEx(OS_IE_CARD_B_DATA);
#endif
}
/*---------------------------------------------------------------------------*
Name: SetHotSwState
Description: HotSwの状態を設定する
*---------------------------------------------------------------------------*/
static void SetHotSwState(BOOL busy)
{
u16 id = (u16)OS_GetLockID();
(void)OS_LockByWord( id, &SYSMi_GetWork()->lockHotSW, NULL );
SYSMi_GetWork()->flags.common.isBusyHotSW = busy ? 1 : 0;
(void)OS_UnlockByWord( id, &SYSMi_GetWork()->lockHotSW, NULL );
OS_ReleaseLockID( id );
}
/*---------------------------------------------------------------------------*
Name: AllocateExCardBus
Description: アクセス権を設定する
*---------------------------------------------------------------------------*/
static inline void SetExCardProcessor(MIProcessor proc)
{
reg_HOTSW_EXMEMCNT =
(u16)((reg_HOTSW_EXMEMCNT & ~HOTSW_EXMEMCNT_SELB_MASK) | (proc << HOTSW_EXMEMCNT_SELB_SHIFT));
}
/*---------------------------------------------------------------------------*
Name: AllocateExCardBus
Description: スロットBへのアクセス権を設定する
*---------------------------------------------------------------------------*/
static void AllocateExCardBus(void)
{
#ifdef SDK_ARM9
SetExCardProcessor(MI_PROCESSOR_ARM9); // Arm9側で動作している場合
#else
SetExCardProcessor(MI_PROCESSOR_ARM7); // Arm7側で動作している場合
#endif
}
/*---------------------------------------------------------------------------*
Name: FreeExCardBus
Description: スロットBへのアクセス権を設定する
*---------------------------------------------------------------------------*/
static void FreeExCardBus(void)
{
SetExCardProcessor(MI_PROCESSOR_ARM7); // Card for SUB
}
/*---------------------------------------------------------------------------*
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)
{
#ifdef USE_SLOT_A
SetInterruptCallback( OS_IE_CARD_A_IREQ , InterruptCallbackCard );
SetInterruptCallback( OS_IE_CARD_A_DET , InterruptCallbackCardDet );
SetInterruptCallback( OS_IE_CARD_A_DATA , InterruptCallbackCardData );
#else
SetInterruptCallback( OS_IE_CARD_B_IREQ , InterruptCallbackCard );
SetInterruptCallback( OS_IE_CARD_B_DET , InterruptCallbackCardDet );
SetInterruptCallback( OS_IE_CARD_B_DATA , InterruptCallbackCardData );
#endif
}
/* -----------------------------------------------------------------
* CheckHashValue関数
*
* 常駐モジュール・拡張常駐モジュールのハッシュを計算して、
* カード内のハッシュ値と比べる。
* ----------------------------------------------------------------- */
#include <twl/os/common/systemCall.h>
// ----------------------------------------------------------------------
// 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 );
}
// ----------------------------------------------------------------------
// 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 );
}
// ----------------------------------------------------------------------
// 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 );
}
// ----------------------------------------------------------------------
// 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");
}