DSハッシュテーブル検証コードのランチャーへの組み込み(DHT_TEST=TRUE指定でフルビルドすると組み込まれる)

git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlIPL/trunk@1127 b08762b0-b915-fc4b-9d8c-17b2551a87ff
This commit is contained in:
yutaka 2008-04-14 08:29:05 +00:00
parent c46e0210b4
commit 698caf92af
12 changed files with 1188 additions and 927 deletions

View File

@ -38,6 +38,11 @@ SRCS = blowfish.c \
TARGET_LIB = libhotsw_sp$(TWL_LIBSUFFIX).a TARGET_LIB = libhotsw_sp$(TWL_LIBSUFFIX).a
ifneq ($(DHT_TEST),)
SRCDIR += ../../../tests/CheckDSHashTable/src
SRCS += dht.c
MACRO_FLAGS += -DDHT_TEST
endif
include $(TWL_IPL_RED_ROOT)/build/buildtools/commondefs include $(TWL_IPL_RED_ROOT)/build/buildtools/commondefs

File diff suppressed because it is too large Load Diff

View File

@ -32,6 +32,10 @@ SRCS = status.c \
TARGET_LIB = libsysmenu_sp$(TWL_LIBSUFFIX).a TARGET_LIB = libsysmenu_sp$(TWL_LIBSUFFIX).a
ifneq ($(DHT_TEST),)
MACRO_FLAGS += -DDHT_TEST
endif
include $(TWL_IPL_RED_ROOT)/build/buildtools/commondefs include $(TWL_IPL_RED_ROOT)/build/buildtools/commondefs
INSTALL_TARGETS = $(TARGETS) INSTALL_TARGETS = $(TARGETS)

View File

@ -28,6 +28,7 @@ TWL_PROC = ARM9
REVISION_SRC = src/revision.c REVISION_SRC = src/revision.c
SRCDIR = src
SRCS = sysmenu_lib.c \ SRCS = sysmenu_lib.c \
util.c \ util.c \
ninLogoFunc.c \ ninLogoFunc.c \
@ -48,6 +49,12 @@ ifdef DO_NOT_SHOW_LAUNCHER
MACRO_FLAGS += -DDO_NOT_SHOW_LAUNCHER MACRO_FLAGS += -DDO_NOT_SHOW_LAUNCHER
endif endif
ifneq ($(DHT_TEST),)
SRCDIR += ../../../tests/CheckDSHashTable/src
SRCS += dht.c
MACRO_FLAGS += -DDHT_TEST
endif
include $(TWL_IPL_RED_ROOT)/build/buildtools/commondefs include $(TWL_IPL_RED_ROOT)/build/buildtools/commondefs
INSTALL_TARGETS = $(TARGETS) INSTALL_TARGETS = $(TARGETS)

View File

@ -24,19 +24,29 @@
#include <pm_pmic.h> #include <pm_pmic.h>
#endif // SDK_ARM7 #endif // SDK_ARM7
#ifdef DHT_TEST
#include <sysmenu/dht/dht.h>
#ifdef SDK_ARM9
#define DS_HASH_TABLE_SIZE (128*1024)
static u8 dht_buffer[DS_HASH_TABLE_SIZE] ATTRIBUTE_ALIGN(256);
static DHTFile *const dht = (DHTFile*)dht_buffer;
#else
extern DHTFile* dht;
#endif
#endif
// define data----------------------------------------------------------------- // define data-----------------------------------------------------------------
#define SYSM_PXI_COMM_STAT_REQ 0 #define SYSM_PXI_COMM_STAT_REQ 0
#define SYSM_PXI_COMM_STAT_ACK 1 #define SYSM_PXI_COMM_STAT_ACK 1
// PXIƒRƒ}ƒ“ƒh // PXIƒRƒ}ƒ“ƒh
typedef union SYSMPXIPacket { typedef union SYSMPXIPacket {
struct { struct {
u16 data; u16 data;
u8 cmd; // PXI_FIFOMESSAGE_BITSZ_DATA = 26 u8 cmd; // PXI_FIFOMESSAGE_BITSZ_DATA = 26
u8 stat : 2; u8 stat : 2;
}; };
u32 raw; u32 raw;
}SYSMPXIPacket; }SYSMPXIPacket;
@ -82,7 +92,7 @@ void SYSM_InitPXI( u32 mcu_prio )
{ {
} }
while ( ! PXI_IsCallbackReady( PXI_FIFO_TAG_HOTSW, PXI_PROC_ARM7 ) ) while ( ! PXI_IsCallbackReady( PXI_FIFO_TAG_HOTSW, PXI_PROC_ARM7 ) )
{ {
} }
#endif // SDK_ARM9 #endif // SDK_ARM9
@ -90,132 +100,150 @@ void SYSM_InitPXI( u32 mcu_prio )
SYSM_InitDecryptAESPXICallback(); SYSM_InitDecryptAESPXICallback();
} }
#ifdef DHT_TEST
#ifdef SDK_ARM9
void SYSMi_PrepareDatabase(void)
{
DHT_PrepareDatabase(dht);
DC_FlushRange(dht, DHT_GetDatabaseLength(dht));
OS_TPrintf("[ARM9] dht address: %08X\n", dht);
SYSMi_SendPXICommand( SYSM_PXI_COMM_DS_HASH_TABLE, (u16)(((u32)dht - 0x2000000) >> 8) );
}
#endif
#endif
// PXIƒRƒ}ƒ“ƒh<E28098>M // PXIƒRƒ}ƒ“ƒh<E28098>M
BOOL SYSMi_TrySendPXICommand( SYSMPXICommand cmd, u16 data ) BOOL SYSMi_TrySendPXICommand( SYSMPXICommand cmd, u16 data )
{ {
SYSMPXIPacket packet; SYSMPXIPacket packet;
OSIntrMode saved = OS_DisableInterrupts(); OSIntrMode saved = OS_DisableInterrupts();
if( s_sending[cmd] ) if( s_sending[cmd] )
{ {
OS_RestoreInterrupts( saved ); OS_RestoreInterrupts( saved );
return FALSE; return FALSE;
} }
s_sending[cmd] = TRUE; s_sending[cmd] = TRUE;
OS_RestoreInterrupts( saved ); OS_RestoreInterrupts( saved );
packet.stat = SYSM_PXI_COMM_STAT_REQ; packet.stat = SYSM_PXI_COMM_STAT_REQ;
packet.cmd = cmd; packet.cmd = cmd;
packet.data = data; packet.data = data;
while( PXI_SendWordByFifo( SYSMENU_PXI_FIFO_TAG, packet.raw, FALSE) != PXI_FIFO_SUCCESS ) while( PXI_SendWordByFifo( SYSMENU_PXI_FIFO_TAG, packet.raw, FALSE) != PXI_FIFO_SUCCESS )
{ {
SVC_WaitByLoop(1); SVC_WaitByLoop(1);
} }
return TRUE; return TRUE;
} }
BOOL SYSMi_SendPXICommand( SYSMPXICommand cmd, u16 data ) BOOL SYSMi_SendPXICommand( SYSMPXICommand cmd, u16 data )
{ {
while( ! SYSMi_TrySendPXICommand( cmd, data ) ) while( ! SYSMi_TrySendPXICommand( cmd, data ) )
{ {
OS_WaitAnyIrq(); OS_WaitAnyIrq();
} }
while( s_sending[cmd] ) while( s_sending[cmd] )
{ {
OS_WaitAnyIrq(); OS_WaitAnyIrq();
} }
return TRUE; return TRUE;
} }
void SYSMi_PXIFifoRecvCallback( PXIFifoTag tag, u32 data, BOOL err ) void SYSMi_PXIFifoRecvCallback( PXIFifoTag tag, u32 data, BOOL err )
{ {
#pragma unused( tag, err ) #pragma unused( tag, err )
SYSMPXIPacket packet; SYSMPXIPacket packet;
u8 cmd; u8 cmd;
packet.raw = data; packet.raw = data;
cmd = packet.cmd; cmd = packet.cmd;
if( packet.stat == SYSM_PXI_COMM_STAT_ACK ) if( packet.stat == SYSM_PXI_COMM_STAT_ACK )
{ {
s_sending[cmd] = FALSE; s_sending[cmd] = FALSE;
} }
if( packet.stat == SYSM_PXI_COMM_STAT_REQ ) if( packet.stat == SYSM_PXI_COMM_STAT_REQ )
{ {
packet.stat = SYSM_PXI_COMM_STAT_ACK; packet.stat = SYSM_PXI_COMM_STAT_ACK;
} }
#ifdef SDK_ARM7 #ifdef SDK_ARM7
switch( cmd ) switch( cmd )
{ {
case SYSM_PXI_COMM_BL_BRIGHT: case SYSM_PXI_COMM_BL_BRIGHT:
#ifdef SDK_SUPPORT_PMIC_2 #ifdef SDK_SUPPORT_PMIC_2
if ( SYSMi_GetMcuVersion() <= 1 ) if ( SYSMi_GetMcuVersion() <= 1 )
{ {
PMi_SetRegister( REG_PMIC_BL_BRT_B_ADDR, (u8)packet.data ); PMi_SetRegister( REG_PMIC_BL_BRT_B_ADDR, (u8)packet.data );
} }
else else
#endif // SDK_SUPPORT_PMIC_2 #endif // SDK_SUPPORT_PMIC_2
{ {
MCU_WriteRegister( MCU_REG_BL_ADDR, (u8)packet.data ); MCU_WriteRegister( MCU_REG_BL_ADDR, (u8)packet.data );
} }
break; break;
default: #ifdef DHT_TEST
case SYSM_PXI_COMM_DS_HASH_TABLE:
dht = (void*)(0x2000000 + (packet.data << 8));
OS_TPrintf("[ARM7] dht address: %08X\n", dht);
break;
#endif
default:
#ifndef SDK_FINALROM #ifndef SDK_FINALROM
OS_Panic( "illegal SYSM pxi command." ); OS_Panic( "illegal SYSM pxi command." );
#else #else
OS_Panic(""); OS_Panic("");
#endif #endif
break; break;
} }
// PXI‰ž“š•Ô<E280A2>M // PXI‰ž“š•Ô<E280A2>M
PXI_SendWordByFifo( SYSMENU_PXI_FIFO_TAG, packet.raw, FALSE ); PXI_SendWordByFifo( SYSMENU_PXI_FIFO_TAG, packet.raw, FALSE );
#endif // SDK_ARM7 #endif // SDK_ARM7
#if 0 #if 0
#ifdef SDK_ARM9 #ifdef SDK_ARM9
if( packet.stat == SYSM_PXI_COMM_STAT_ACK ) { if( packet.stat == SYSM_PXI_COMM_STAT_ACK ) {
switch( data ) { switch( data ) {
case SYSM_PXI_COMM_DISABLE_HOTSW: case SYSM_PXI_COMM_DISABLE_HOTSW:
SYSMi_GetWork()->flags.arm9.isEnableHotSW = 0; SYSMi_GetWork()->flags.arm9.isEnableHotSW = 0;
break; break;
default: default:
break; break;
} }
}else { // SYSM_PXI_COMM_STAT_REQ }else { // SYSM_PXI_COMM_STAT_REQ
switch( data ) { switch( data ) {
default: default:
break; break;
} }
} }
#else // !SDK_ARM9 #else // !SDK_ARM9
if( packet.stat == SYSM_PXI_COMM_STAT_REQ ) { if( packet.stat == SYSM_PXI_COMM_STAT_REQ ) {
switch( data ) { switch( data ) {
case SYSM_PXI_COMM_DISABLE_HOTSW: case SYSM_PXI_COMM_DISABLE_HOTSW:
if( SYSMi_GetWork()->flags.arm7.isBusyHotSW ) { if( SYSMi_GetWork()->flags.arm7.isBusyHotSW ) {
SYSMi_GetWork()->flags.arm7.disableHotSW_REQ = 1; SYSMi_GetWork()->flags.arm7.disableHotSW_REQ = 1;
}else { }else {
SYSMi_GetWork()->flags.arm7.isEnableHotSW = 0; SYSMi_GetWork()->flags.arm7.isEnableHotSW = 0;
// PXIÅ•Ô<E280A2>M // PXIÅ•Ô<E280A2>M
} }
break; break;
default: default:
break; break;
} }
}else { // SYSM_PXI_COMM_STAT_ACK }else { // SYSM_PXI_COMM_STAT_ACK
switch( data ) { switch( data ) {
default: default:
break; break;
} }
} }
#endif // SDK_ARM9 #endif // SDK_ARM9
#endif #endif
} }

View File

@ -92,6 +92,14 @@ ifdef DO_NOT_SHOW_LAUNCHER
MACRO_FLAGS += -DDO_NOT_SHOW_LAUNCHER MACRO_FLAGS += -DDO_NOT_SHOW_LAUNCHER
endif endif
ifneq ($(DHT_TEST),)
MACRO_FLAGS += -DDHT_TEST
MAKEROM_FLAGS += -DDS_HASH_TABLE_FILE=DSHashTable.bin \
-DDS_HASH_TABLE_DIR=$(TWL_IPL_RED_PRIVATE_ROOT)/build/tools/MakeDSHashTable
else
MAKEROM_FLAGS += -DDS_HASH_TABLE_DIR=data
endif
include $(TWL_IPL_RED_ROOT)/build/buildtools/commondefs include $(TWL_IPL_RED_ROOT)/build/buildtools/commondefs
include $(TWLSDK_ROOT)/build/libraries/reboot/commondefs.reboot include $(TWLSDK_ROOT)/build/libraries/reboot/commondefs.reboot

View File

@ -213,4 +213,7 @@ RomSpec
HostRoot ../../data HostRoot ../../data
Root /data Root /data
File NTR_IPL_font_m.NFTR NoCardBanner.bnr EmptyBanner.bnr NoBanner.bnr fanfare.32.wav File NTR_IPL_font_m.NFTR NoCardBanner.bnr EmptyBanner.bnr NoBanner.bnr fanfare.32.wav
HostRoot $(DS_HASH_TABLE_DIR)
Root /sign
File $(DS_HASH_TABLE_FILE)
} }

View File

@ -102,7 +102,7 @@ void TwlMain( void )
(void)OS_EnableInterrupts(); (void)OS_EnableInterrupts();
SYSM_InitPXI(); // 割り込み許可後にコールする必要あり。 SYSM_InitPXI(); // 割り込み許可後にコールする必要あり。
FS_Init( FS_DMA_NOT_USE ); FS_Init( FS_DMA_NOT_USE );
#ifdef DEBUG_LAUNCHER_DUMP #ifdef DEBUG_LAUNCHER_DUMP
@ -129,14 +129,18 @@ void TwlMain( void )
// 各種パラメータの取得------------ // 各種パラメータの取得------------
pBootTitle = SYSM_ReadParameters(); // 本体設定データ、リセットパラメータのリード、検査用オート起動カード判定、量産ライン用キーショートカット起動判定等のリード pBootTitle = SYSM_ReadParameters(); // 本体設定データ、リセットパラメータのリード、検査用オート起動カード判定、量産ライン用キーショートカット起動判定等のリード
if( SYSM_IsFatalError() ) { #ifdef DHT_TEST
// FATALエラー処理 SYSMi_PrepareDatabase();
} #endif
if( !LCFG_TSD_IsFinishedInitialSetting() ) {
// 初回起動シーケンス判定 if( SYSM_IsFatalError() ) {
} // FATALエラー処理
}
if( !LCFG_TSD_IsFinishedInitialSetting() ) {
// 初回起動シーケンス判定
}
(void)SYSM_GetCardTitleList( s_titleList ); // カードアプリリストの取得カードアプリはs_titleList[0]に格納される) (void)SYSM_GetCardTitleList( s_titleList ); // カードアプリリストの取得カードアプリはs_titleList[0]に格納される)
@ -145,7 +149,7 @@ void TwlMain( void )
{ {
deleteTmp(); deleteTmp();
} }
// NANDタイトルリストの準備 // NANDタイトルリストの準備
SYSM_InitNandTitleList(); SYSM_InitNandTitleList();
@ -186,16 +190,16 @@ void TwlMain( void )
} }
// ランチャー画面を絶対表示しないバージョン // ランチャー画面を絶対表示しないバージョン
if( SYSM_IsLauncherHidden() ) if( SYSM_IsLauncherHidden() )
{ {
if(direct_boot == FALSE) if(direct_boot == FALSE)
{ {
state = STOP; state = STOP;
}else }else
{ {
state = LOAD_START; state = LOAD_START;
} }
} }
// チャンネルをロックする // チャンネルをロックする
SND_LockChannel((1 << L_CHANNEL) | (1 << R_CHANNEL), 0); SND_LockChannel((1 << L_CHANNEL) | (1 << R_CHANNEL), 0);
@ -216,9 +220,9 @@ void TwlMain( void )
} }
#endif #endif
if( SYSM_IsFatalError() ) { if( SYSM_IsFatalError() ) {
// FATALエラー処理 // FATALエラー処理
} }
// メインループ-------------------- // メインループ--------------------
while( 1 ) { while( 1 ) {
@ -270,13 +274,13 @@ void TwlMain( void )
break; break;
case LOADING: case LOADING:
if( SYSM_IsLoadTitleFinished() ) { if( SYSM_IsLoadTitleFinished() ) {
SYSM_StartAuthenticateTitle( pBootTitle ); SYSM_StartAuthenticateTitle( pBootTitle );
state = AUTHENTICATE; state = AUTHENTICATE;
} }
if( !direct_boot ) if( !direct_boot )
{ {
(void)LauncherFadeout( s_titleList ); // ダイレクトブートでないときはフェードアウトも行う (void)LauncherFadeout( s_titleList ); // ダイレクトブートでないときはフェードアウトも行う
} }
if( ( end == 0 ) && if( ( end == 0 ) &&
SYSM_IsLoadTitleFinished() ) { SYSM_IsLoadTitleFinished() ) {
end = OS_GetTick(); end = OS_GetTick();
@ -285,22 +289,22 @@ void TwlMain( void )
break; break;
case AUTHENTICATE: case AUTHENTICATE:
if( ( direct_boot || ( !direct_boot && LauncherFadeout( s_titleList ) ) ) && if( ( direct_boot || ( !direct_boot && LauncherFadeout( s_titleList ) ) ) &&
PollingInstallWlanFirmware() && // アプリブート前に無線ファームのロードは完了しておく必要がある PollingInstallWlanFirmware() && // アプリブート前に無線ファームのロードは完了しておく必要がある
SYSM_IsAuthenticateTitleFinished() ) SYSM_IsAuthenticateTitleFinished() )
{ {
if( SYSM_IsFatalError() ) { if( SYSM_IsFatalError() ) {
// FATALエラー処理 // FATALエラー処理
} }
switch ( SYSM_TryToBootTitle( pBootTitle ) ) { // アプリ認証結果取得orブート 成功時never return switch ( SYSM_TryToBootTitle( pBootTitle ) ) { // アプリ認証結果取得orブート 成功時never return
case AUTH_RESULT_TITLE_LOAD_FAILED: case AUTH_RESULT_TITLE_LOAD_FAILED:
case AUTH_RESULT_TITLE_POINTER_ERROR: case AUTH_RESULT_TITLE_POINTER_ERROR:
case AUTH_RESULT_AUTHENTICATE_FAILED: case AUTH_RESULT_AUTHENTICATE_FAILED:
case AUTH_RESULT_ENTRY_ADDRESS_ERROR: case AUTH_RESULT_ENTRY_ADDRESS_ERROR:
state = STOP; state = STOP;
// [TODO:]クリアしたほうが良いデータ(鍵など)があれば消す // [TODO:]クリアしたほうが良いデータ(鍵など)があれば消す
break; break;
} }
} }
break; break;
case STOP: // 停止 case STOP: // 停止
@ -310,9 +314,9 @@ void TwlMain( void )
// カードアプリリストの取得(スレッドで随時カード挿抜を通知されるものをメインループで取得) // カードアプリリストの取得(スレッドで随時カード挿抜を通知されるものをメインループで取得)
(void)SYSM_GetCardTitleList( s_titleList ); (void)SYSM_GetCardTitleList( s_titleList );
// 無線ファームロードのポーリング // 無線ファームロードのポーリング
(void)PollingInstallWlanFirmware(); (void)PollingInstallWlanFirmware();
// コマンドフラッシュ // コマンドフラッシュ
(void)SND_FlushCommand(SND_COMMAND_NOBLOCK); (void)SND_FlushCommand(SND_COMMAND_NOBLOCK);
@ -321,9 +325,9 @@ void TwlMain( void )
if ( PAD_DetectFold() ) if ( PAD_DetectFold() )
{ {
SYSM_GoSleepMode(); SYSM_GoSleepMode();
}
#endif // DISABLE_SLEEP
} }
#endif // DISABLE_SLEEP
}
} }
@ -344,18 +348,18 @@ static void INTR_VBlank(void)
// nandのtmpディレクトリの中身を消す // nandのtmpディレクトリの中身を消す
static void deleteTmp() static void deleteTmp()
{ {
if( FS_DeleteFile( OS_TMP_APP_PATH ) ) if( FS_DeleteFile( OS_TMP_APP_PATH ) )
{ {
OS_TPrintf( "deleteTmp: deleted File '%s' \n", OS_TMP_APP_PATH ); OS_TPrintf( "deleteTmp: deleted File '%s' \n", OS_TMP_APP_PATH );
}else }else
{ {
FSResult res = FS_GetArchiveResultCode("nand"); FSResult res = FS_GetArchiveResultCode("nand");
if( FS_RESULT_SUCCESS == res ) if( FS_RESULT_SUCCESS == res )
{ {
OS_TPrintf( "deleteTmp: File '%s' not exists.\n", OS_TMP_APP_PATH ); OS_TPrintf( "deleteTmp: File '%s' not exists.\n", OS_TMP_APP_PATH );
}else }else
{ {
OS_TPrintf( "deleteTmp: delete File '%s' failed. Error code = %d.\n", OS_TMP_APP_PATH, res ); OS_TPrintf( "deleteTmp: delete File '%s' failed. Error code = %d.\n", OS_TMP_APP_PATH, res );
} }
} }
} }

View File

@ -52,6 +52,9 @@ static const u8 g_pubkey_DER[ 0xa2 ] = {
static const u8 hmac_key[] = DHT_HMAC_KEY; static const u8 hmac_key[] = DHT_HMAC_KEY;
static DHTReadFunc ReadFunc;
static void* readArg;
#define PAGE_SIZE 512
/* /*
bsearch bsearch
@ -102,15 +105,45 @@ static int CompareGameCodeAndVersion(const void* a, const void* b)
/* /*
() ()
*/ */
u32 DHT_GetDatabaseLength(const DHTFile* pDHT)
{
if ( pDHT->header.magic_code != DHT_MAGIC_CODE ) // magic codeチェック
{
OS_TPrintf("Invalid " HASH_PATH " magic code (magic=0x%08X).\n", pDHT->header.magic_code);
return 0;
}
return sizeof(DHTHeader) + pDHT->header.nums * sizeof(DHTDatabase);
}
BOOL DHT_CheckDatabase(const DHTFile* pDHT)
{
SVCSignHeapContext pool;
u8 heap[4*1024];
u8 md1[20];
u8 md2[20];
s32 result;
// ファイル署名取り出し
SVC_InitSignHeap(&pool, heap, sizeof(heap));
SVC_DecryptSign(&pool, md1, pDHT->header.sign, &g_pubkey_DER[29]);
// ハッシュ計算
SVC_CalcSHA1(md2, DHT_GET_SIGN_TARGET_ADDR(&pDHT->header), DHT_GET_SIGN_TARGET_SIZE(&pDHT->header));
// 検証
result = SVC_CompareSHA1(md1, md2);
if ( !result )
{
OS_TPrintf("\n");
OS_TPrintfEx("SIGN = % 20B\n", md1);
OS_TPrintfEx("HASH = % 20B\n", md2);
OS_TPrintf("Signature is not valid.\n");
return FALSE;
}
return TRUE;
}
BOOL DHT_PrepareDatabase(DHTFile* pDHT) BOOL DHT_PrepareDatabase(DHTFile* pDHT)
{ {
FSFile file; FSFile file;
u32 length; u32 length;
s32 result; s32 result;
SVCSignHeapContext pool;
u8 heap[4*1024];
u8 md1[20];
u8 md2[20];
PROFILE_INIT(); PROFILE_INIT();
// ファイルオープン // ファイルオープン
@ -128,21 +161,16 @@ BOOL DHT_PrepareDatabase(DHTFile* pDHT)
OS_TPrintf("Cannot read the header of " HASH_PATH " (result=%d).\n", result); OS_TPrintf("Cannot read the header of " HASH_PATH " (result=%d).\n", result);
return FALSE; return FALSE;
} }
if ( pDHT->header.magic_code != DHT_MAGIC_CODE )
{
OS_TPrintf("Invalid " HASH_PATH " magic code (magic=0x%08X).\n", pDHT->header.magic_code);
return FALSE;
}
// サイズチェック // サイズチェック
PROFILE_COUNT(); PROFILE_COUNT();
length = FS_GetFileLength(&file); length = FS_GetFileLength(&file);
if ( length != sizeof(DHTHeader) + pDHT->header.nums * sizeof(DHTDatabase) ) if ( length != DHT_GetDatabaseLength(pDHT) )
{ {
OS_TPrintf("Invalid " HASH_PATH " size (%d != %d).\n", length, sizeof(DHTHeader) + pDHT->header.nums * sizeof(DHTDatabase)); OS_TPrintf("Invalid " HASH_PATH " size (%d != %d).\n", length, DHT_GetDatabaseLength(pDHT));
return FALSE; return FALSE;
} }
// databaseサイズの保存 // databaseサイズの保存
length = pDHT->header.nums * sizeof(DHTDatabase); length -= sizeof(DHTHeader);
// データベース読み込み // データベース読み込み
PROFILE_COUNT(); PROFILE_COUNT();
result = FS_ReadFile(&file, pDHT->database, (s32)length); result = FS_ReadFile(&file, pDHT->database, (s32)length);
@ -152,23 +180,11 @@ BOOL DHT_PrepareDatabase(DHTFile* pDHT)
return FALSE; return FALSE;
} }
FS_CloseFile(&file); FS_CloseFile(&file);
// ファイル署名取り出し
// データベースの検証
PROFILE_COUNT(); PROFILE_COUNT();
SVC_InitSignHeap(&pool, heap, sizeof(heap)); result = DHT_CheckDatabase(pDHT);
SVC_DecryptSign(&pool, md1, pDHT->header.sign, &g_pubkey_DER[29]);
// ハッシュ計算
PROFILE_COUNT();
SVC_CalcSHA1(md2, DHT_GET_SIGN_TARGET_ADDR(&pDHT->header), DHT_GET_SIGN_TARGET_SIZE(&pDHT->header));
// 検証
PROFILE_COUNT();
result = SVC_CompareSHA1(md1, md2);
if ( !result )
{
OS_TPrintfEx("SIGN = % 20B\n", md1);
OS_TPrintfEx("HASH = % 20B\n", md2);
OS_TPrintf("Signature is not valid.\n");
return FALSE;
}
// 結果報告 // 結果報告
#ifdef PRINT_PROFILE #ifdef PRINT_PROFILE
PROFILE_COUNT(); PROFILE_COUNT();
@ -177,12 +193,10 @@ BOOL DHT_PrepareDatabase(DHTFile* pDHT)
OS_TPrintf("%10d msec for reading header.\n", (int)OS_TicksToMilliSeconds(profile[2]-profile[1])); OS_TPrintf("%10d msec for reading header.\n", (int)OS_TicksToMilliSeconds(profile[2]-profile[1]));
OS_TPrintf("%10d msec for size check.\n", (int)OS_TicksToMilliSeconds(profile[3]-profile[2])); OS_TPrintf("%10d msec for size check.\n", (int)OS_TicksToMilliSeconds(profile[3]-profile[2]));
OS_TPrintf("%10d msec for reading database.\n", (int)OS_TicksToMilliSeconds(profile[4]-profile[3])); OS_TPrintf("%10d msec for reading database.\n", (int)OS_TicksToMilliSeconds(profile[4]-profile[3]));
OS_TPrintf("%10d msec for decrypt sign.\n", (int)OS_TicksToMilliSeconds(profile[5]-profile[4])); OS_TPrintf("%10d msec for comparing hash.\n", (int)OS_TicksToMilliSeconds(profile[5]-profile[4]));
OS_TPrintf("%10d msec for hashing database.\n", (int)OS_TicksToMilliSeconds(profile[6]-profile[5])); OS_TPrintf("\nTotal: %10d msec.\n", (int)OS_TicksToMilliSeconds(profile[5]-profile[0]));
OS_TPrintf("%10d msec for comparing hash.\n", (int)OS_TicksToMilliSeconds(profile[7]-profile[6]));
OS_TPrintf("\nTotal: %10d msec.\n", (int)OS_TicksToMilliSeconds(profile[7]-profile[0]));
#endif #endif
return TRUE; return result;
} }
/* /*
ROMヘッダに対応するデータベースを手に入れる ROMヘッダに対応するデータベースを手に入れる
@ -212,85 +226,73 @@ const DHTDatabase* DHT_GetDatabase(const DHTFile* pDHT, const ROM_Header_Short*
(1) (1)
*/ */
BOOL DHT_CheckHashPhase1(const DHTDatabase *db, const ROM_Header_Short* pROMHeader, const void* pARM9, const void* pARM7) void DHT_CheckHashPhase1Init(SVCHMACSHA1Context* ctx, const ROM_Header_Short* pROMHeader)
{
// 準備
SVC_HMACSHA1Init(ctx, hmac_key, sizeof(hmac_key));
// ヘッダ
SVC_HMACSHA1Update(ctx, pROMHeader, DHT_DS_HEADER_SIZE);
}
void DHT_CheckHashPhase1Update(SVCHMACSHA1Context* ctx, const void* ptr, u32 length)
{
// ARM9 or ARM7 static
SVC_HMACSHA1Update(ctx, ptr, length);
}
BOOL DHT_CheckHashPhase1Final(SVCHMACSHA1Context* ctx, const DHTDatabase *db)
{ {
SVCHMACSHA1Context ctx;
u8 md[20]; u8 md[20];
BOOL result; BOOL result;
PROFILE_INIT(); SVC_HMACSHA1GetHash(ctx, md);
// 準備
PROFILE_COUNT();
SVC_HMACSHA1Init(&ctx, hmac_key, sizeof(hmac_key));
// ヘッダ
PROFILE_COUNT();
SVC_HMACSHA1Update(&ctx, pROMHeader, DHT_DS_HEADER_SIZE);
// ARM9 Static
PROFILE_COUNT();
SVC_HMACSHA1Update(&ctx, pARM9, pROMHeader->main_size);
// ARM7 Static
PROFILE_COUNT();
SVC_HMACSHA1Update(&ctx, pARM7, pROMHeader->sub_size);
// 検証
PROFILE_COUNT();
SVC_HMACSHA1GetHash(&ctx, md);
result = SVC_CompareSHA1(db->hash[0], md); result = SVC_CompareSHA1(db->hash[0], md);
if ( !result ) if ( !result )
{ {
OS_TPrintf("\n");
OS_TPrintfEx("DB = % 20B\n", db->hash[0]); OS_TPrintfEx("DB = % 20B\n", db->hash[0]);
OS_TPrintfEx("HASH = % 20B\n", md); OS_TPrintfEx("HASH = % 20B\n", md);
OS_TPrintf("%s: hash[0] is not valid.\n", __func__); OS_TPrintf("%s: hash[0] is not valid.\n", __func__);
} }
return result;
}
BOOL DHT_CheckHashPhase1(const DHTDatabase *db, const ROM_Header_Short* pROMHeader, const void* pARM9, const void* pARM7)
{
SVCHMACSHA1Context ctx;
BOOL result;
PROFILE_INIT();
// 準備&ヘッダ
PROFILE_COUNT();
DHT_CheckHashPhase1Init(&ctx, pROMHeader);
// ARM9 Static
PROFILE_COUNT();
DHT_CheckHashPhase1Update(&ctx, pARM9, pROMHeader->main_size);
// ARM7 Static
PROFILE_COUNT();
DHT_CheckHashPhase1Update(&ctx, pARM7, pROMHeader->sub_size);
// 検証
PROFILE_COUNT();
result = DHT_CheckHashPhase1Final(&ctx, db);
// 結果報告 // 結果報告
#ifdef PRINT_PROFILE #ifdef PRINT_PROFILE
PROFILE_COUNT(); PROFILE_COUNT();
OS_TPrintf("\nDone to check the hash (phase 1).\n"); OS_TPrintf("\nDone to check the hash (phase 1).\n");
OS_TPrintf("%10d msec for preparing hash.\n", (int)OS_TicksToMilliSeconds(profile[1]-profile[0])); OS_TPrintf("%10d msec for scanning header.\n", (int)OS_TicksToMilliSeconds(profile[1]-profile[0]));
OS_TPrintf("%10d msec for scanning header.\n", (int)OS_TicksToMilliSeconds(profile[2]-profile[1])); OS_TPrintf("%10d msec for scanning ARM9.\n", (int)OS_TicksToMilliSeconds(profile[2]-profile[1]));
OS_TPrintf("%10d msec for scanning ARM9.\n", (int)OS_TicksToMilliSeconds(profile[3]-profile[2])); OS_TPrintf("%10d msec for scanning ARM7.\n", (int)OS_TicksToMilliSeconds(profile[3]-profile[2]));
OS_TPrintf("%10d msec for scanning ARM7.\n", (int)OS_TicksToMilliSeconds(profile[4]-profile[3])); OS_TPrintf("%10d msec for comparing hash.\n", (int)OS_TicksToMilliSeconds(profile[4]-profile[3]));
OS_TPrintf("%10d msec for comparing hash.\n", (int)OS_TicksToMilliSeconds(profile[5]-profile[4])); OS_TPrintf("\nTotal: %10d msec.\n", (int)OS_TicksToMilliSeconds(profile[4]-profile[0]));
OS_TPrintf("\nTotal: %10d msec.\n", (int)OS_TicksToMilliSeconds(profile[5]-profile[0]));
#endif #endif
return result; return result;
} }
/* /*
(2) (2)
FSを用いたテストの場合とCARDアプリの場合で異なる FSを用いたテストの場合とCARDアプリの場合で異なる
*/ */
#if 1 static BOOL ImageHMACSHA1Update(SVCHMACSHA1Context* ctx, s32 offset, s32 length, void* buffer)
// FS版 (fctx == FSFile*)
static BOOL ReadImage(void* fctx, void* dest, s32 offset, s32 length)
{ {
FSFile* fp = fctx; if ( !ReadFunc(buffer, offset, length, readArg) )
s32 result;
if ( !FS_SeekFile(fp, offset, FS_SEEK_SET) )
{
OS_TPrintf("Cannot seek to the offset (%d bytes).\n", offset);
return FALSE;
}
result = FS_ReadFile(fp, dest, length);
if ( result != length )
{
OS_TPrintf("Cannot read the data (%d bytes).\n", length);
return FALSE;
}
return TRUE;
}
#else
// CARD版 (fctx == dma no)
static BOOL ReadImage(void* fctx, void* dest, s32 offset, s32 length)
{
u32 dma = (u32)fctx;
CARD_ReadRom(dma, (void*)offset, dest, (u32)length);
return TRUE;
}
#endif
static BOOL ImageHMACSHA1Update(SVCHMACSHA1Context* ctx, void* fctx, s32 offset, s32 length, void* buffer)
{
if ( !ReadImage(fctx, buffer, offset, length) )
{ {
return FALSE; return FALSE;
} }
@ -298,25 +300,33 @@ static BOOL ImageHMACSHA1Update(SVCHMACSHA1Context* ctx, void* fctx, s32 offset,
return TRUE; return TRUE;
} }
static BOOL GetOverlayInfo(int no, void* fctx, int fat_offset, int* pOffset, int* pLength) static BOOL GetOverlayInfo(int no, int fat_offset, int* pOffset, int* pLength)
{ {
ROM_FAT fat; ROM_FAT *fat;
if ( !ReadImage(fctx, &fat, fat_offset + no * (s32)sizeof(ROM_FAT), sizeof(ROM_FAT)) ) static u8 fat_cache[PAGE_SIZE];
static int last_page = 0;
int page = (fat_offset + no * (s32)sizeof(ROM_FAT)) / PAGE_SIZE;
if ( last_page != page )
{ {
return FALSE; if ( !ReadFunc(&fat_cache, page * PAGE_SIZE, PAGE_SIZE, readArg) )
{
return FALSE;
}
last_page = page;
} }
fat = (ROM_FAT*)(fat_cache + fat_offset + no * sizeof(ROM_FAT) - page * PAGE_SIZE);
if ( pOffset ) if ( pOffset )
{ {
*pOffset = (s32)fat.top.offset; *pOffset = (s32)fat->top.offset;
} }
if ( pLength ) if ( pLength )
{ {
*pLength = (s32)(fat.bottom.offset - fat.top.offset); *pLength = (s32)(fat->bottom.offset - fat->top.offset);
} }
return TRUE; return TRUE;
} }
BOOL DHT_CheckHashPhase2(const DHTDatabase *db, const ROM_Header_Short* pROMHeader, void* fctx, void* buffer) BOOL DHT_CheckHashPhase2(const DHTDatabase *db, const ROM_Header_Short* pROMHeader, void* buffer, DHTReadFunc func, void* arg)
{ {
int overlay_nums = (int)(pROMHeader->main_ovt_size / sizeof(ROM_OVT)); int overlay_nums = (int)(pROMHeader->main_ovt_size / sizeof(ROM_OVT));
u8 md[20]; u8 md[20];
@ -328,19 +338,26 @@ BOOL DHT_CheckHashPhase2(const DHTDatabase *db, const ROM_Header_Short* pROMHead
int total_sectors; int total_sectors;
int i; int i;
if ( !func )
{
return FALSE;
}
ReadFunc = func;
readArg = arg;
// 準備 // 準備
PROFILE_COUNT(); PROFILE_COUNT();
SVC_HMACSHA1Init(&ctx, hmac_key, sizeof(hmac_key)); SVC_HMACSHA1Init(&ctx, hmac_key, sizeof(hmac_key));
// OVT // OVT
PROFILE_COUNT(); PROFILE_COUNT();
if ( !ImageHMACSHA1Update(&ctx, fctx, (s32)pROMHeader->main_ovt_offset, (s32)pROMHeader->main_ovt_size, buffer) ) if ( !ImageHMACSHA1Update(&ctx, (s32)pROMHeader->main_ovt_offset, (s32)pROMHeader->main_ovt_size, buffer) )
{ {
OS_TPrintf("Cannot calc HMAC-SHA1 for OVT.\n"); OS_TPrintf("Cannot calc HMAC-SHA1 for OVT.\n");
return FALSE; return FALSE;
} }
// FAT // FAT
PROFILE_COUNT(); PROFILE_COUNT();
if ( !ImageHMACSHA1Update(&ctx, fctx, (s32)pROMHeader->fat_offset, overlay_nums * (s32)sizeof(ROM_FAT), buffer) ) if ( !ImageHMACSHA1Update(&ctx, (s32)pROMHeader->fat_offset, overlay_nums * (s32)sizeof(ROM_FAT), buffer) )
{ {
OS_TPrintf("Cannot calc HMAC-SHA1 for %d of FAT.\n", overlay_nums); OS_TPrintf("Cannot calc HMAC-SHA1 for %d of FAT.\n", overlay_nums);
return FALSE; return FALSE;
@ -353,7 +370,7 @@ BOOL DHT_CheckHashPhase2(const DHTDatabase *db, const ROM_Header_Short* pROMHead
int max_sectors = (DHT_OVERLAY_MAX/512 - total_sectors) / (overlay_nums - i); int max_sectors = (DHT_OVERLAY_MAX/512 - total_sectors) / (overlay_nums - i);
int offset; int offset;
int length; int length;
if ( !GetOverlayInfo(i, fctx, (s32)pROMHeader->fat_offset, &offset, &length) ) if ( !GetOverlayInfo(i, (s32)pROMHeader->fat_offset, &offset, &length) )
{ {
OS_TPrintf("Cannot get %d of overlay info.\n", i); OS_TPrintf("Cannot get %d of overlay info.\n", i);
return FALSE; return FALSE;
@ -363,7 +380,7 @@ BOOL DHT_CheckHashPhase2(const DHTDatabase *db, const ROM_Header_Short* pROMHead
{ {
length = max_sectors; length = max_sectors;
} }
if ( !ImageHMACSHA1Update(&ctx, fctx, offset, length * 512, buffer) ) if ( !ImageHMACSHA1Update(&ctx, offset, length * 512, buffer) )
{ {
OS_TPrintf("Cannot calc HMAC-SHA1 for %d of overlay.\n", i); OS_TPrintf("Cannot calc HMAC-SHA1 for %d of overlay.\n", i);
return FALSE; return FALSE;
@ -385,6 +402,7 @@ BOOL DHT_CheckHashPhase2(const DHTDatabase *db, const ROM_Header_Short* pROMHead
} }
if ( !SVC_CompareSHA1(md, db->hash[1]) ) if ( !SVC_CompareSHA1(md, db->hash[1]) )
{ {
OS_TPrintf("\n");
OS_TPrintfEx("DB = % 20B\n", db->hash[1]); OS_TPrintfEx("DB = % 20B\n", db->hash[1]);
OS_TPrintfEx("HASH = % 20B\n", md); OS_TPrintfEx("HASH = % 20B\n", md);
OS_TPrintf("%s: hash[1] is not valid.\n", __func__); OS_TPrintf("%s: hash[1] is not valid.\n", __func__);

View File

@ -47,6 +47,49 @@ static u8 rom_arm9[3*1024*1024] ATTRIBUTE_ALIGN(32);
static u8 rom_arm7[1024*1024] ATTRIBUTE_ALIGN(32); static u8 rom_arm7[1024*1024] ATTRIBUTE_ALIGN(32);
#include <twl/ltdmain_end.h> #include <twl/ltdmain_end.h>
/*
API
*/
#if 0
// FS版 (fctx == FSFile*)
static BOOL ReadImage(void* dest, s32 offset, s32 length, void* arg)
{
FSFile* fp = arg;
s32 result;
if ( !FS_SeekFile(fp, offset, FS_SEEK_SET) )
{
OS_TPrintf("Cannot seek to the offset (%d bytes).\n", offset);
return FALSE;
}
result = FS_ReadFile(fp, dest, length);
if ( result != length )
{
OS_TPrintf("Cannot read the data (%d bytes).\n", length);
return FALSE;
}
return TRUE;
}
#else
#ifdef SDK_ARM9
#define PAGE_SIZE 512
// CARD版 (fctx == dma no)
static BOOL ReadImage(void* dest, s32 offset, s32 length, void* arg)
{
u32 dma = (u32)arg;
CARD_ReadRom(dma, (void*)offset, dest, (u32)length);
return TRUE;
}
#else
// HOTSW版 (fctx == CardBootData* cdb)
#include <hotswTypes.h>
#include <dsCardCommon.h>
static BOOL ReadImage(void* dest, s32 offset, s32 length, void* arg)
{
HotSwState retval = ReadPageGame((CardBootData*)arg, (u32)offset, dest, (u32)length);
return (retval == HOTSW_SUCCESS);
}
#endif
#endif
static void VBlankIntr( void ) static void VBlankIntr( void )
{ {
@ -116,7 +159,7 @@ static BOOL CheckValidation(FSFile* fp)
return FALSE; return FALSE;
} }
// ハッシュ計算 (2) - 隠蔽は難しいか // ハッシュ計算 (2) - 隠蔽は難しいか
if ( !DHT_CheckHashPhase2(db, &rom_header, fp, ov_buffer) ) if ( !DHT_CheckHashPhase2(db, &rom_header, ov_buffer, ReadImage, fp) )
{ {
return FALSE; return FALSE;
} }

View File

@ -25,10 +25,35 @@
extern "C" { extern "C" {
#endif #endif
typedef BOOL (*DHTReadFunc)(void* dest, s32 offset, s32 length, void* arg);
/*---------------------------------------------------------------------------* /*---------------------------------------------------------------------------*
Name: DHT_PrepareDatabase Name: DHT_PrepareDatabase
Description: Description:
Arguments: pDHT
Returns: 0
*---------------------------------------------------------------------------*/
u32 DHT_GetDatabaseLength(const DHTFile* pDHT);
/*---------------------------------------------------------------------------*
Name: DHT_PrepareDatabase
Description:
Arguments: pDHT
Returns: TRUE
*---------------------------------------------------------------------------*/
BOOL DHT_CheckDatabase(const DHTFile* pDHT);
/*---------------------------------------------------------------------------*
Name: DHT_PrepareDatabase
Description: FS関数を利用して全データベースを読み込み検証まで行う
/sign/DSHashTable.bin固定
Arguments: pDHT Arguments: pDHT
@ -48,6 +73,45 @@ BOOL DHT_PrepareDatabase(DHTFile* pDHT);
*---------------------------------------------------------------------------*/ *---------------------------------------------------------------------------*/
const DHTDatabase* DHT_GetDatabase(const DHTFile* pDHT, const ROM_Header_Short* pROMHeader); const DHTDatabase* DHT_GetDatabase(const DHTFile* pDHT, const ROM_Header_Short* pROMHeader);
/*---------------------------------------------------------------------------*
Name: DHT_CheckHashPhase1Init
Description: ROMヘッダおよびARM9/ARM7スタティック領域の検証の準備
Arguments: ctx SVCHMACSHA1コンテキスト
pROMHeader ROMヘッダ格納先
Returns: None
*---------------------------------------------------------------------------*/
void DHT_CheckHashPhase1Init(SVCHMACSHA1Context* ctx, const ROM_Header_Short* pROMHeader);
/*---------------------------------------------------------------------------*
Name: DHT_CheckHashPhase1Update
Description: ROMヘッダおよびARM9/ARM7スタティック領域の検証のスタティック部分
ARM9スタティックARM7スタティックの順に
Arguments: ctx SVCHMACSHA1コンテキスト
ptr
length
Returns: None
*---------------------------------------------------------------------------*/
void DHT_CheckHashPhase1Update(SVCHMACSHA1Context* ctx, const void* ptr, u32 length);
/*---------------------------------------------------------------------------*
Name: DHT_CheckHashPhase1
Description: ROMヘッダおよびARM9/ARM7スタティック領域の検証の結果判定
Arguments: ctx SVCHMACSHA1コンテキスト
db
Returns: TRUE
*---------------------------------------------------------------------------*/
BOOL DHT_CheckHashPhase1Final(SVCHMACSHA1Context* ctx, const DHTDatabase *db);
/*---------------------------------------------------------------------------* /*---------------------------------------------------------------------------*
Name: DHT_CheckHashPhase1 Name: DHT_CheckHashPhase1
@ -65,17 +129,19 @@ BOOL DHT_CheckHashPhase1(const DHTDatabase *db, const ROM_Header_Short* pROMHead
/*---------------------------------------------------------------------------* /*---------------------------------------------------------------------------*
Name: DHT_CheckHashPhase2 Name: DHT_CheckHashPhase2
Description: Description:
(Read APIを登録できるべき)
Arguments: db Arguments: db
pROMHeader ROMヘッダ格納先 pROMHeader ROMヘッダ格納先
fctx (FS版) FSFile構造体へのポインタ fctx (FS版) FSFile構造体へのポインタ
(CARD版) dma番号をvoid* (CARD版) dma番号をvoid*
(HOTSW版) CardBootData構造体へのポインタ
buffer APIで使用するワーク (DHT_OVERLAY_MAXだけ必要) buffer APIで使用するワーク (DHT_OVERLAY_MAXだけ必要)
Returns: TRUE Returns: TRUE
*---------------------------------------------------------------------------*/ *---------------------------------------------------------------------------*/
BOOL DHT_CheckHashPhase2(const DHTDatabase *db, const ROM_Header_Short* pROMHeader, void* fctx, void* buffer); BOOL DHT_CheckHashPhase2(const DHTDatabase *db, const ROM_Header_Short* pROMHeader, void* buffer, DHTReadFunc func, void* arg);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View File

@ -27,16 +27,20 @@ extern "C" {
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// PXIコマンド // PXIコマンド
//---------------------------------------------------------------------- //----------------------------------------------------------------------
#define SYSMENU_PXI_FIFO_TAG (PXI_MAX_FIFO_TAG - 1) // (PXI_MAX_FIFO_TAG - 1) is used by SEA
#define PXI_FIFO_TAG_MCUTEST (PXI_MAX_FIFO_TAG - 2) #define PXI_FIFO_TAG_MCUTEST (PXI_MAX_FIFO_TAG - 2)
#define PXI_FIFO_TAG_HOTSW (PXI_MAX_FIFO_TAG - 3) #define PXI_FIFO_TAG_HOTSW (PXI_MAX_FIFO_TAG - 3)
#define PXI_FIFO_TAG_DECRYPTAES (PXI_MAX_FIFO_TAG - 4) #define PXI_FIFO_TAG_DECRYPTAES (PXI_MAX_FIFO_TAG - 4)
#define SYSMENU_PXI_FIFO_TAG (PXI_MAX_FIFO_TAG - 5)
typedef enum SYSMPXICommand { typedef enum SYSMPXICommand {
SYSM_PXI_COMM_BL_BRIGHT = 0, SYSM_PXI_COMM_BL_BRIGHT = 0,
SYSM_PXI_COMM_DISABLE_HOTSW = 1, SYSM_PXI_COMM_DISABLE_HOTSW = 1,
#ifdef DHT_TEST
SYSM_PXI_COMM_DS_HASH_TABLE = 2,
#endif
SYSM_PXI_COMM_NUM SYSM_PXI_COMM_NUM
}SYSMPXICommand; }SYSMPXICommand;
/*---------------------------------------------------------------------------* /*---------------------------------------------------------------------------*
@ -50,6 +54,12 @@ void SYSM_InitPXI( void );
void SYSM_InitPXI( u32 mcu_prio ); void SYSM_InitPXI( u32 mcu_prio );
#endif // SDK_ARM7 #endif // SDK_ARM7
#ifdef DHT_TEST
#ifdef SDK_ARM9
void SYSMi_PrepareDatabase(void);
#endif
#endif
// PXIコマンド送信 // PXIコマンド送信
BOOL SYSMi_TrySendPXICommand( SYSMPXICommand cmd, u16 data ); BOOL SYSMi_TrySendPXICommand( SYSMPXICommand cmd, u16 data );
BOOL SYSMi_SendPXICommand( SYSMPXICommand command, u16 data ); BOOL SYSMi_SendPXICommand( SYSMPXICommand command, u16 data );