ntr_bootrom/trunk/IrisSubp/IrisSubpMon/IrisSubpMonSub.c

724 lines
18 KiB
C
Raw Permalink 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.

//*******************************************************************
// IRIS-SUBPモニタプログラム サブルーチン
//*******************************************************************
#include "IrisSubpMon.h"
//--------------------- グローバル 変数 -------------------------------
SharedWork *sharedWorkp; // 共有ワークポインタ
SecureWork *secureWorkp; // セキュア情報ワークポインタ
IntrFuncp intrTable[4]; // 割り込みテーブル
u32 CharTmpBuf[0x200/4];
u16 NinLogoBak[256/2];
//----------------------------------------------------------------------
// レジスタ初期化
//----------------------------------------------------------------------
void InitReg(void)
{
*(vu32 *)REG_IME = 0; // IME クリア
*(vu32 *)REG_IE = 0; // IE クリア
*(vu32 *)REG_IF = -1; // IF クリア
#ifdef BOOT_FROM_CARTRIDGE
*(vu16 *)REG_POWCNT = POW_SOUND_ON; // サウンドON
ChangeSoundBias16(1, 8) ; // サウンドバイアス セット
#endif // BOOT_FROM_CARTRIDGE
}
//----------------------------------------------------------------------
// メモリ初期化
//----------------------------------------------------------------------
void PreInitRam(void)
{
CpuClearFast32(0, CPU_WRAM_END - 0x4000, 0x4000 - 512); // ARM7用ワーク領域 後半16KBクリア
}
void PostInitRam(void)
{
CpuClearFast32(0, CPU_WRAM, 0x4000); // ARM7用ワーク領域 前半16KBクリア
}
//----------------------------------------------------------------------
// メインメモリSECURE領域先頭64KB クリア
//----------------------------------------------------------------------
void ClearMmemSecureArea(void)
{
CpuClearFast32(0, MAIN_MEM, MROM_SECURE_SIZE * 4);
}
//----------------------------------------------------------------------
// CRC16bit 算出
//----------------------------------------------------------------------
const u16 crc16_table[16] = {
0x0000, 0xCC01, 0xD801, 0x1400,
0xF001, 0x3C00, 0x2800, 0xE401,
0xA001, 0x6C00, 0x7800, 0xB401,
0x5000, 0x9C01, 0x8801, 0x4400
};
u16 GetCRC16(u32 start, u16 *datap, u32 size)
{
u16 *dataEndp = datap + size/2;
u16 data16;
u32 shift = 0;
u16 r1, total = start;
while(datap < dataEndp) {
if (!shift) data16 = *datap;
// 4bit単位
r1 = crc16_table[total & 0xf];
total = (total >>4);
total = total ^ r1 ^ crc16_table[(data16 >>shift) & 0xf];
shift += 4;
if (shift >= 0x10) {
shift = 0;
datap++;
}
}
return total;
}
//----------------------------------------------------------------------
// メインメモリ 拡張チェック
//----------------------------------------------------------------------
const u16 mmemSizeCheckTable[] = {0x56a9, 0x695a, 0xa695, 0x96a5};
s32 IsMmem8MB(void)
{
u32 mmemExFlag = 0;
int i;
#ifdef ENABLE_DEBUGGER_ON_4MB
return 1;
#endif // ENABLE_DEBUGGER_ON_4MB
for (i=0; i<4; i++) {
*(vu16 *)MMEM_CHK_SIZE_WRITE_BUF = mmemSizeCheckTable[i];
if (*(vu16 *)MMEM_CHK_SIZE_READ_BUF != mmemSizeCheckTable[i]) mmemExFlag++;
}
*(vu16 *)MMEM_CHK_SIZE_WRITE_BUF = 0;
return (mmemExFlag >= 3);
}
//----------------------------------------------------------------------
// デバッガ上か?
//----------------------------------------------------------------------
extern u16 sio_handshake_data[];
extern u16 sio_send_code;
extern u16 sio_recv_code;
extern u16 sio_add_code;
#define SIO_SEND_CODE 0x4e54
#define SIO_RECV_CODE 0x4944
#define SIO_ADD_CODE 0x524f
#define SYSROM_VERSION 0x0100
void SendSioData(u32 data) // SIOデータ送信
{
*(vu32 *)REG_SIODATA32 = data;
StartSio();
WaitSio();
WaitByLoop(0x8000/4); // 0.97ms待ち
while (!IsSioSendEnable()) ;
}
s32 CheckSioData(u32 data, u32 checkMask) // SIO戻り値チェック
{
#ifndef DISABLE_SECURE_CODE
if ((*(vu32 *)REG_SIODATA32 & checkMask)
!= ((((data + sio_add_code) & 0xffff) | (~data & 0xffff0000)) & checkMask))
return 0;
#endif // DISABLE_SECURE_CODE
return 1;
}
void CheckDebugger(void)
{
SharedWork *shwp = GetSharedWorkAddr();
u32 sioData[2];
int i;
shwp->isOnDebugger = 0;
if (!IsMmem8MB()) return; // メインメモリが 4MB ならデバッガではない
#ifndef DISABLE_SECURE_CODE
sioData[0] = shwp->recvRtc[0] | 0x80000000;
sioData[1] = shwp->recvRtc[1] | 0x80000000;
*(vu16 *)REG_RCNT = R_SIO_MASTER_MODE; // SIOハンドシェイク
*(vu16 *)REG_SIOCNT = SIO_32BIT_MODE | SIO_IN_SCK_256K;
if (!IsSioSendEnable()) {
return; // 初めに SI が Low で無ければデバッガではない
} else {
*(vu16 *)REG_SIOCNT |= SIO_SCK_IN; // 応答が正しくなければデバッガではない
SendSioData((sio_send_code <<16) | SYSROM_VERSION);
if (!CheckSioData((~sio_recv_code <<16), 0xffff0000)) return;
SendSioData(sioData[1]);
SendSioData(sioData[0]);
if (!CheckSioData(sioData[1], -1)) return;
SendSioData(sioData[1]);
if (!CheckSioData(sioData[0], -1)) return;
}
*(vu32 *)REG_SIODATA32 = 0;
*(vu32 *)REG_SIOCNT = 0;
shwp->isOnDebugger = 1;
#endif // DISABLE_SECURE_CODE
}
//----------------------------------------------------------------------
// Blowfishテーブル生成
//----------------------------------------------------------------------
void InitBlowfishKeyAnaTableFook(BLOWFISH_CTX *tableBufp, u32 *keyBufp, u32 keyLen);
u32 ChangeEncryptKey1(u32 key);
u32 ChangeEncryptKey2(u32 key);
u32 ChangeEncryptKey3(u32 key);
u32 ChangeEncryptKey4(u32 key);
void MakeBlowfishTable(BLOWFISH_CTX *tableBufp, const u32 *keyp, u32 *keyBufp, u32 keyLen)
{
#ifndef DISABLE_SECURE_CODE
#ifndef ENABLE_TEST_BLOWFISH
const BLOWFISH_CTX *blowfishInitTablep = &blowfishInitTable;
#else
const BLOWFISH_CTX *blowfishInitTablep = &blowfishTestTable;
#endif // ENABLE_TEST_BLOWFISH
u32 keyBuf[3];
#ifndef NDEBUG
*(u32 *)REG_TM2CNT = TMR_PRESCALER_256CK | TMR_ENABLE; // タイマー スタート
#endif // NDEBUG
CopyBiosAreaFook(blowfishInitTablep, tableBufp, sizeof(BLOWFISH_CTX));
keyBufp[0] = *keyp;
keyBufp[1] = ChangeEncryptKey1(*keyp);
keyBufp[2] = ChangeEncryptKey2(*keyp);
InitBlowfishKeyAnaTableFook(tableBufp, keyBufp, keyLen);
{ SecureWork *scwp = GetSecureWorkAddr();
RomHeader *rmhp = GetRomHeaderAddr();
FlashHeader *fhp = GetFlashHeaderAddr();
u32 *blowfishedKeyp;
if (keyLen == 8) {
*(u64 *)scwp->cardNormalModeKey = *(u64 *)rmhp->romNormalModeKey;
blowfishedKeyp = scwp->cardNormalModeKey;
} else {
*(u64 *)scwp->unScrambleKey = *(u64 *)fhp->unScrambleKey;
blowfishedKeyp = scwp->unScrambleKey;
}
DecryptByBlowfishFook(tableBufp, blowfishedKeyp);
if (keyLen > 8)
scwp->isGenUnScrambleKey = 1;
}
#ifndef NDEBUG
*(u16 *)REG_TM2CNT_H = 0;
#endif // NDEBUG
InitBlowfishKeyAnaTableFook(tableBufp, keyBufp, keyLen);
#endif // DISABLE_SECURE_CODE
}
//----------------------------------------------------------------------
// Blowfishキーテーブル単位初期化
//----------------------------------------------------------------------
void InitBlowfishKeyAnaTable(BLOWFISH_CTX *tableBufp, u32 *keyBufp, u32 keyLen)
{
#ifndef DISABLE_SECURE_CODE
EncryptByBlowfishFook2(tableBufp, keyBufp); // EncryptByBlowfish(tableBufp, &keyBufp[2], &keyBufp[1]);
EncryptByBlowfishFook1(tableBufp, keyBufp); // EncryptByBlowfish(tableBufp, &keyBufp[1], &keyBufp[0]);
InitBlowfishFook(tableBufp, (u8 *)keyBufp, keyLen);
#endif // DISABLE_SECURE_CODE
}
//----------------------------------------------------------------------
// 暗号化オブジェクトの復号
//----------------------------------------------------------------------
#ifndef DISABLE_SECURE_CODE
extern const u32 encrypt_object_key[];
#else
const u32 encrypt_object_key[2] = {0x01234567, 0x89abcdef};
#endif // DISABLE_SECURE_CODE
#define UNDEF_CODE 0xe7ffdeff
#define ENCRYPT_DEF_SIZE 0x800
void DecryptObjectFile(void)
{
SharedWork *shwp = GetSharedWorkAddr();
SecureWork *scwp = GetSecureWorkAddr();
RomHeader *rmhp = GetRomHeaderAddr();
BLOWFISH_CTX *tableBufp = &scwp->blowfishCardTable;
u32 *encBufp = (u32 *)&scwp->blowfishFlashTable;
u32 *encDestp = (u32 *)rmhp->arm9.ramAddr;
s32 size = scwp->secureSize;
s32 restSize;
if (size > ENCRYPT_DEF_SIZE) size = ENCRYPT_DEF_SIZE;
restSize = size;
if (scwp->enableReadSecure) {
CpuCopyFast32Fook(encDestp, encBufp, size); // 暗号化オブジェクト 退避
DecryptByBlowfishFook(tableBufp, encBufp); // 暗号化オブジェクトヘッダ プリ復号
}
ChangeObjectTableFook(); // Blowfishテーブル変換
if (scwp->enableReadSecure) {
DecryptByBlowfishFook(tableBufp, encBufp); // 暗号化オブジェクトヘッダ ポスト復号
#ifndef DISABLE_SECURE_CODE
if ((encBufp[0] == encrypt_object_key[0]) // 暗号化オブジェクト有効時
&& (encBufp[1] == encrypt_object_key[1])) {
u32 *bufp = encBufp;
bufp[0] = UNDEF_CODE;
bufp[1] = UNDEF_CODE;
while ((restSize -= 8) > 0) {
bufp += 2; // 復号処理
DecryptByBlowfishFook(tableBufp, bufp);
}
} else
#endif // DISABLE_SECURE_CODE
{
CpuClearFast32(UNDEF_CODE, encBufp, size); // 未定義コードでクリア
shwp->disableEncryptedCardData = 1; // 暗号化オブジェクト無効 通知
}
CpuCopyFast32Fook(encBufp, encDestp, size); // 暗号化オブジェクト 復帰
}
}
//----------------------------------------------------------------------
// 暗号化オブジェクト用Blowfishテーブル変換
//----------------------------------------------------------------------
void ChangeObjectTable(u32 keyLen)
{
#ifndef DISABLE_SECURE_CODE
SecureWork *scwp = GetSecureWorkAddr();
BLOWFISH_CTX *tableBufp = &scwp->blowfishCardTable;
u32 *keyBufp = scwp->cardKeyBuf;
keyBufp[1] = ChangeEncryptKey3(keyBufp[1]);
keyBufp[2] = ChangeEncryptKey4(keyBufp[2]);
InitBlowfishKeyAnaTableFook(tableBufp, keyBufp, keyLen);
#endif // DISABLE_SECURE_CODE
}
//----------------------------------------------------------------------
// ハフマンデータ展開32Bit→32Bit
//----------------------------------------------------------------------
#define TREE_END 0x80
s32 UnCompHuffman32(const u8 *srcp, u32 *destp, u8 *tableBufp, const UC_InternalFuncp *ifp)
{
u8 *treep;// = (u8 *)srcp + 4;
s32 treeSize;// = (*treep + 1) * 2;
u32 treeCheck;
u32 treeShift;
u32 srcTmp;
u32 destTmp = 0;
u32 destTmpCount = 0;
s32 srcCount;
s32 error;
int i;
s32 header = ifp->InitFuncp(srcp, destp, tableBufp); // 初期化(アドレス送信)
s32 size = header >>8;
s32 destCount = size;
s32 dataBit = header & 0x0f;
u32 destTmpDataNum = 4 + (dataBit & 0x7);
u32 destTopShift = 32 - dataBit;
if (header < 0) { size = header;
goto terminate;
}
srcp += 3;
tableBufp[0] = ifp->ByteStreamFuncp(++srcp);
treeSize = (tableBufp[0] + 1) * 2;
for (i=1; i<treeSize; i++)
tableBufp[i] = ifp->ByteStreamFuncp(++srcp);
srcp++;
treep = tableBufp + 1;
while (destCount > 0) {
srcCount = 32;
srcTmp = ifp->WordStreamFuncp(srcp);
srcp += 4;
while (--srcCount >= 0) {
treeShift = (srcTmp >> 31) & 0x1;
treeCheck = *treep;
treeCheck <<= treeShift;
treep = (u8 *)((((u32 )treep>>1) <<1) + (((*treep & 0x3f)+1) <<1) + treeShift);
if (treeCheck & TREE_END) {
destTmp >>= dataBit;
destTmp |= *treep << destTopShift;
treep = tableBufp + 1;
if (++destTmpCount == destTmpDataNum) {
*destp++ = destTmp;
destCount -= 4;
destTmpCount = 0;
}
}
if (destCount <= 0) break;
srcTmp <<= 1;
}
}
terminate:
if (ifp->TerminateFuncp) { // 終了ダミー読み込み
if ((error = ifp->TerminateFuncp(srcp)) < 0) return error;
}
return size;
}
//----------------------------------------------------------------------
// LZバイトデータ展開8Bit→16Bit
//----------------------------------------------------------------------
s32 UnCompLZ77Short(const u8 *srcp, u16 *destp, const void *paramp, const UC_InternalFuncp *ifp)
{
u32 destTmp = 0;
u32 flags;
s32 offset;
s32 offset0_8;
s32 length;
u32 shift = 0;
u8 src;
s32 error;
int i;
s32 header = ifp->InitFuncp(srcp, destp, paramp); // 初期化(アドレス送信)
s32 size = header >>8;
s32 destCount = size;
if (header < 0) { size = header;
goto terminate;
}
srcp += 3;
while (destCount > 0) {
flags = ifp->ByteStreamFuncp(++srcp);
for (i=8; --i>=0; ) {
if (!(flags & 0x80)){ destTmp |= ifp->ByteStreamFuncp(++srcp) <<shift;
destCount--;
if (!(shift ^= 8)){
*destp = destTmp;
destp++;
destTmp = 0;
}
} else { length = ((src = ifp->ByteStreamFuncp(++srcp)) >>4) + 3;
offset = ( src & 0x0f) << 8;
offset = (offset | ifp->ByteStreamFuncp(++srcp)) + 1;
offset0_8 = (8 - shift) ^ ((offset & 1) <<3);
destCount -= length;
while (--length >= 0) { offset0_8 ^= 8;
destTmp |= (destp[-((offset + ((8 - shift) >>3)) >>1)]
& (0xff <<offset0_8)) >>offset0_8 <<shift;
if (!(shift ^= 8)){
*destp = destTmp;
destp++;
destTmp = 0;
}
}
}
if (destCount <= 0) break;
flags <<= 1;
}
}
terminate:
if (ifp->TerminateFuncp) { // 終了ダミー読み込み
if ((error = ifp->TerminateFuncp(++srcp)) < 0) return error;
}
return size;
}
//----------------------------------------------------------------------
// ランレングスデータ展開8Bit→16Bit
//----------------------------------------------------------------------
s32 UnCompRLShort(const u8 *srcp, u16 *destp, const void *paramp, const UC_InternalFuncp *ifp)
{
s32 srcTmp;
s32 destTmp = 0;
u32 flags;
s32 offset;
s32 length;
u32 shift = 0;
s32 error;
s32 header = ifp->InitFuncp(srcp, destp, paramp); // 初期化(アドレス送信)
s32 size = header >>8;
s32 destCount = size;
if (header < 0) { size = header;
goto terminate;
}
srcp += 3;
while (destCount > 0) {
flags = ifp->ByteStreamFuncp(++srcp);
length = flags & 0x7f;
if (!(flags & 0x80)) { length++;
destCount -= length;
while (--length >= 0){ destTmp |= ifp->ByteStreamFuncp(++srcp) << shift;
if (!(shift ^= 8)){ *destp++ = destTmp;
destTmp = 0;
}
}
} else { length += 3;
destCount -= length;
srcTmp = ifp->ByteStreamFuncp(++srcp);
while (--length >= 0){ destTmp |= srcTmp << shift;
if (!(shift ^= 8)){ *destp++ = destTmp;
destTmp = 0;
}
}
}
}
terminate:
if (ifp->TerminateFuncp) { // 終了ダミー読み込み
if ((error = ifp->TerminateFuncp(++srcp)) < 0) return error;
}
return size;
}
//----------------------------------------------------------------------
// サウンドテーブルデータ取得
//----------------------------------------------------------------------
extern s16 snd_sin_table[];
extern u16 snd_ptable[];
extern u8 snd_vtable[];
extern u8 snd_data_start[];
extern u8 snd_data_end[];
static s32 CheckSoundTablep(void *tablep)
{
if ((tablep < (void *)snd_data_start) || (tablep >= (void *)snd_data_end))
return -1;
return 0;
}
u32 GetSoundSinTable(s32 index)
{
s16 *tablep = &snd_sin_table[index];
s32 retval;
if ((retval = CheckSoundTablep(tablep)) != 0) return retval;
return *tablep;
}
u32 GetSoundPitchTable(s32 index)
{
u16 *tablep = &snd_ptable[index];
s32 retval;
if ((retval = CheckSoundTablep(tablep)) != 0) return retval;
return *tablep;
}
u32 GetSoundVolumeTable(s32 index)
{
u8 *tablep = &snd_vtable[index];
s32 retval;
if ((retval = CheckSoundTablep(tablep)) != 0) return retval;
return *tablep;
}
//----------------------------------------------------------------------
// 割り込み終了処理
//----------------------------------------------------------------------
void TerminateIntr(u32 inrtFlags)
{
u32 bakIE = *(vu32 *)REG_IME;
*(vu32 *)REG_IME = 0;
*(vu32 *)REG_IE &= ~inrtFlags;
*(vu32 *)REG_IF = inrtFlags;
*(vu32 *)REG_IME = bakIE;
}
//----------------------------------------------------------------------
// Vブランク待ち
//----------------------------------------------------------------------
#ifdef BOOT_FROM_CARTRIDGE
void WaitVBlank(s32 count)
{
int i;
for (i=0; i<count; i++) {
while (((vDispStat *)REG_DISPSTAT)->blankingV == 1) ;
while (((vDispStat *)REG_DISPSTAT)->blankingV != 1) ;
}
}
#endif // BOOT_FROM_CARTRIDGE
//----------------------------------------------------------------------
// NINTENDOロゴチェック
//----------------------------------------------------------------------
extern const u16 Nin_Char_Diff_Huff[];
#ifdef TEST_AGB_MODE
u8 CheckNintendoLogo(u16 *datap)
{
int i;
for (i=0; i<OFFSET_MON_SOFT_NAME/2; i++) {
u16 cmpMask = 0xffff;
if ( i == OFFSET_MON_FIQ_FLAG/2) cmpMask = 0x84 ^ 0xffff;
else if (i == OFFSET_MON_KEY_GROUP_NO/2) cmpMask = 0x03 ^ 0xffff;
if ((datap[i] & cmpMask) != Nin_Char_Diff_Huff[i]) return 1;
}
return 0;
}
#endif // TEST_AGB_MODE
//----------------------------------------------------------------------
// AGBのNINTENDOロゴ読み込み
//----------------------------------------------------------------------
void key_unlock__nin_logo_copy(void);
#ifdef TEST_AGB_MODE
void ReadNintendoLogo4AGB(void)
{
u8 *srcp;
if (*(u8 *)(CARTRIDGE + 0xb4) & 0x80) srcp = (u8 *)AGB_DACS_KEY_REG0;
else srcp = (u8 *)AGB_DACS_KEY_REG1;
CpuCopy16_32(srcp, CharTmpBuf, 2*10, 16); // セキュリティ解除 前処理
key_unlock__nin_logo_copy(); // DACSセキュリティ解除 ロゴ コピー
}
#endif // TEST_AGB_MODE
//----------------------------------------------------------------------
// AGBモード遷移
//----------------------------------------------------------------------
void SetPause2Agb(void);
#ifdef TEST_AGB_MODE
void Iris2Agb(void)
{
int i;
*(vu32 *)REG_IME = 0;
*(vu16 *)REG_POWCNT = 0; // サウンドOFF
NotifyMainpIntf(7); // モード遷移通知
WaitMainpIntf(7);
WaitByLoop(4096/4); // ARM9 ホールト待ち
SetPause2Agb();
}
#endif // TEST_AGB_MODE