/*---------------------------------------------------------------------------* Project: SystemUpdater File: main.c Copyright 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. $Date:: $ $Rev$ $Author$ *---------------------------------------------------------------------------*/ #include // atoi #include #include #include #include #include #include #include "kami_pxi.h" #include "kami_font.h" #include "kami_write_nandfirm.h" #include "kami_copy_file.h" #include "import.h" #include "hw_info.h" #include "graphics.h" #include "hwi.h" #include "keypad.h" #include "debugger_hw_reset_control.h" #include "debugger_card_rom.h" #define SCRAMBLE_MASK 0x00406000 extern const char *g_strIPLSvnRevision; extern const char *g_strSDKSvnRevision; /*---------------------------------------------------------------------------* 型定義 *---------------------------------------------------------------------------*/ typedef struct _SystemUpdaterLog { int magic_code; int sdk_version; int ipl_version; int reserve[5]; } SystemUpdaterLog; typedef struct _CopyFileList { char* srcPath; char* dstPath; } CopyFileList; /*---------------------------------------------------------------------------* 内部定数定義 *---------------------------------------------------------------------------*/ #define SYSTEM_UPDATER_LOG_PATH "nand:/sys/log/updater.log" #define NAND_FIRM_PATH_IN_ROM "rom:/data/menu_launcher.nand" #define SYSTEM_UPDATER_MAGIC_CODE 44001111 // リトライ回数 #define MAX_RETRY_COUNT 2 static const char* ImportTadFileList[] = { "rom:/data/HNAA.tad", "rom:/data/HNBA.tad", "rom:/data/HNCA.tad", "rom:/data/HNHA.tad", "rom:/data/HNLA.tad", }; static const CopyFileList sCopyFileList[] = { { "rom:/data/TWLFontTable.dat", "nand:sys/TWLFontTable.dat" }, { "rom:/data/cert.sys", "nand:/sys/cert.sys" } }; /*---------------------------------------------------------------------------* 内部変数定義 *---------------------------------------------------------------------------*/ static NAMTitleId titleId; static s16 printLine; static vu8 sIsFormatFinish; static u8 sFormatResult; static s32 sLockId; /*---------------------------------------------------------------------------* 内部関数定義 *---------------------------------------------------------------------------*/ static void VBlankIntr(void); static void InitAllocation(void); static BOOL IgnoreRemoval(void); static void DrawWaitButtonA(void); static void DrawInvalidConsole(void); static void DrawCancel(void); static void DrawAlready(SystemUpdaterLog* log); static void DrawResult(BOOL result); static void FormatCallback(KAMIResult result, void* arg); /*---------------------------------------------------------------------------* Name: TwlMain Description: main Arguments: None Returns: None *---------------------------------------------------------------------------*/ void TwlMain() { BOOL result; BOOL hw_info_result; BOOL nand_firm_result; int tadNum; int i,j; // 製品ビルドランチャー&デバッガ上での起動対応 if ( OS_GetRunningConsoleType() & OS_CONSOLE_TWLDEBUGGER ) { ROM_Header *dh = (void *)HW_ROM_HEADER_BUF; dh->s.game_cmd_param &= ~SCRAMBLE_MASK; } OS_Init(); OS_InitThread(); OS_InitTick(); OS_InitAlarm(); OS_InitArena(); PXI_Init(); OS_InitLock(); OS_InitArenaEx(); OS_InitIrqTable(); OS_SetIrqStackChecker(); MI_Init(); OS_InitVAlarm(); OSi_InitVramExclusive(); OS_InitThread(); OS_InitReset(); GX_Init(); FX_Init(); SND_Init(); TP_Init(); RTC_Init(); KamiPxiInit(); /* 独自PXI初期化 */ // Vブランク割り込み設定 OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr); (void)OS_EnableIrqMask(OS_IE_V_BLANK); (void)OS_EnableIrqMask(OS_IE_FIFO_RECV); (void)OS_EnableIrq(); (void)GX_VBlankIntr(TRUE); // initialize file-system FS_Init(FS_DMA_NOT_USE); InitAllocation(); // NAMライブラリ初期化 NAM_Init( OS_AllocFromMain, OS_FreeToMain ); NAMUT_Init( OS_AllocFromMain, OS_FreeToMain ); // SoftBoxCountの計算に必要 // 表示関連初期化 InitGraphics(); kamiFontInit(); // メインスレッドのカードロックID取得 sLockId = OS_GetLockID(); /* always preload FS table for faster directory access. */ { u32 need_size = FS_GetTableSize(); void *p_table = OS_Alloc(need_size); SDK_ASSERT(p_table != NULL); (void)FS_LoadTable(p_table, need_size); } // コンソールチェック { u32 console = OS_GetRunningConsoleType(); enum { IS_TWL_DEBUGGER=0, IS_TWL_CAPTURE, TWL, UNKNOWN }; int running = UNKNOWN; // SystemUpdaterはデバッグ不可で作成されるためOS_CONSOLE_TWLが取得される // 赤箱にカードを挿してSystemUpdaterを実行した場合も同様(但しOS_CONSOLE_TWLTYPE_RETAILにはならない) // デバッガかどうかの判定はメモリサイズチェックにより行う // 念のためOS_CONSOLE_TWLTYPE_RETAILでないことも確認する if ((console & OS_CONSOLE_SIZE_MASK) == OS_CONSOLE_SIZE_32MB) { if ((console & OS_CONSOLE_TWLTYPE_MASK) != OS_CONSOLE_TWLTYPE_RETAIL) { IsToolType type; kamiGetIsToolType(&type); if (type == IS_TOOL_TYPE_DEBUGGER) { running = IS_TWL_DEBUGGER; } else if (type == IS_TOOL_TYPE_ERROR) // TSボードプラス + 旧仕様デバッガ { running = IS_TWL_DEBUGGER; } else if (type == IS_TOOL_TYPE_CAPTURE) { running = IS_TWL_CAPTURE; } } } else if ((console & OS_CONSOLE_MASK) == OS_CONSOLE_TWL) { IsToolType type; kamiGetIsToolType(&type); if (type == IS_TOOL_TYPE_CAPTURE) { running = IS_TWL_CAPTURE; } else { running = TWL; } } switch (running) { case IS_TWL_DEBUGGER: kamiFontPrintf( 0, printLine++, FONT_COLOR_GREEN, "Running on IS_TWL_DEBUGGER."); break; case IS_TWL_CAPTURE: kamiFontPrintf( 0, printLine++, FONT_COLOR_GREEN, "Running on IS_TWL_CAPTURE."); break; case TWL: kamiFontPrintf( 0, printLine++, FONT_COLOR_GREEN, "Running on TWL CONSOLE."); break; case UNKNOWN: kamiFontPrintf( 0, printLine++, FONT_COLOR_GREEN, "Running on UNKNOWN."); break; } #ifdef SYSM_BUILD_FOR_DEBUGGER // デバッガ向けSystemUpdaterは実機とキャプチャでは動作させない if (running != IS_TWL_DEBUGGER) { kamiFontPrintfMain( 2, 9, 3, " Sorry, "); kamiFontPrintfMain( 2, 10, 3, " This SystemUpdater can not "); kamiFontPrintfMain( 2, 11, 3, " execute on TWL-CONSOLE. "); DrawInvalidConsole(); } #else // 実機向けSystemUpdaterはデバッガでは動作させない if (running == IS_TWL_DEBUGGER) { kamiFontPrintfMain( 2, 9, 3, " Sorry, "); kamiFontPrintfMain( 2, 10, 3, " This SystemUpdater can not "); kamiFontPrintfMain( 2, 11, 3, " execute on IS-TWL-DEBUGGER."); DrawInvalidConsole(); } #endif // SYSM_BUILD_FOR_DEBUGGER // UNKNOWNはは動作させない if (running == UNKNOWN) { kamiFontPrintfMain( 2, 9, 3, " Sorry, "); kamiFontPrintfMain( 2, 10, 3, " This SystemUpdater can not "); kamiFontPrintfMain( 2, 11, 3, " execute on UNKNOWN CONSOLE."); DrawInvalidConsole(); } } // (更新可能条件) // 1.ログが存在しない // 2.ログが存在し、ログに記載のマジックコードが不正(初版SystemUpdater実行後の状態) // 2.ログが存在し、ログに記載のマジックコードが正しくかつログに記載の // SDK & IPL のバージョンが SystemUpdater のそれ以下である #ifdef IGNORE_VERSION_CHECK if( 0 ) #endif // IGNORE_VERSION_CHECK { SystemUpdaterLog log; FSFile file; FS_InitFile( &file ); if (FS_OpenFileEx(&file, SYSTEM_UPDATER_LOG_PATH, FS_FILEMODE_R) == TRUE) { DC_InvalidateRange(&log, sizeof(log)); if (FS_ReadFile(&file, &log, sizeof(log)) == sizeof(log)) { // ログリード成功 OS_Printf("[%d, %d]\n", log.sdk_version, log.ipl_version); // 初版SystemUpdater実行状態でないことをマジックコードで判別する if (log.magic_code == SYSTEM_UPDATER_MAGIC_CODE) { // マジックコード、SDKバージョン、IPLバージョンの確認 if (log.sdk_version > atoi(g_strSDKSvnRevision) || log.ipl_version > atoi(g_strIPLSvnRevision)) { // 更新不可 DrawAlready(&log); } } } else { // ログリード失敗 OS_Warning("Failure! FS_ReadFile"); } FS_CloseFile(&file); } } // Aボタン待ち DrawWaitButtonA(); // TWLの更新処理を実行中です CARD_LockRom((u16)sLockId); (void)CARDi_ReadRomIDCoreEx(DEBUGGER_COMMAND_NOW_UPDATE); CARD_UnlockRom((u16)sLockId); // ISデバッガのハードウェアリセットを禁止する DEBUGGER_HwResetDisable(); // HWInfo関連の前準備 switch (HWI_Init( OS_AllocFromMain, OS_FreeToMain )) { case HWI_INIT_FAILURE: OS_Warning(" Fail! : HWI_INIT()"); break; case HWI_INIT_SUCCESS_PRO_SIGNATURE_MODE: break; case HWI_INIT_SUCCESS_DEV_SIGNATURE_MODE: break; case HWI_INIT_SUCCESS_NO_SIGNATRUE_MODE: break; } result = TRUE; // フォーマット実行 sIsFormatFinish = FALSE; ExeFormatAsync(FORMAT_MODE_QUICK, FormatCallback); kamiFontPrintfMain( 7, 11, 8, "Now Format..."); while(!sIsFormatFinish){}; if (sFormatResult) { kamiFontPrintf( 0, printLine++, FONT_COLOR_GREEN, "NAND Format Success."); } else { kamiFontPrintf( 0, printLine++, FONT_COLOR_RED, "NAND Format Failure!"); } kamiFontPrintfMain( 7, 11, 8, " "); // フォーマット後はESに必要なファイルがなくなっているため // ES_InitLibを呼び出すことで作成しておく NAM_End( NULL, NULL ); NAM_Init( OS_AllocFromMain, OS_FreeToMain ); // 全ハードウェア情報の更新 for (i=0;isdk_version, log->ipl_version ); kamiFontPrintfMain( 3, 13, 1, "--------------------------"); while(1) { G3X_Reset(); G3_Identity(); G3_PolygonAttr(GX_LIGHTMASK_NONE, GX_POLYGONMODE_DECAL, GX_CULL_NONE, 0, 31, 0); DrawQuad( 10, 50, 246, 128, GX_RGB(28, 28, 28)); G3_SwapBuffers(GX_SORTMODE_AUTO, GX_BUFFERMODE_W); OS_WaitVBlankIntr(); } } /*---------------------------------------------------------------------------* Name: DrawResult Description: 処理結果を表示します。 Arguments: Returns: None. *---------------------------------------------------------------------------*/ static void DrawResult(BOOL result) { // 3D初期化 G3X_Reset(); G3_Identity(); G3_PolygonAttr(GX_LIGHTMASK_NONE, GX_POLYGONMODE_DECAL, GX_CULL_NONE, 0, 31, 0); // "Now Updating.." を消去 kamiFontPrintfMain( 0, 9, 7, " "); if (result) { kamiFontPrintfMain( 9, 10, 7, "Update Success!"); // グリーンダイアログ DrawQuad( 50, 50, 206, 120, GX_RGB(12, 25, 12)); } else { kamiFontPrintfMain( 9, 10, 7, "Update Failure!"); // レッドダイアログ DrawQuad( 50, 50, 206, 120, GX_RGB(31, 0, 0)); } kamiFontLoadScreenData(); // 3Dスワップ G3_SwapBuffers(GX_SORTMODE_AUTO, GX_BUFFERMODE_W); } /*---------------------------------------------------------------------------* Name: FormatCallback Description: フォーマットコールバック Arguments: Returns: None. *---------------------------------------------------------------------------*/ static void FormatCallback(KAMIResult result, void* /*arg*/) { if ( result == KAMI_RESULT_SUCCESS_TRUE ) { sFormatResult = TRUE; } else { sFormatResult = FALSE; } sIsFormatFinish = TRUE; }