/*---------------------------------------------------------------------------* Project: TwlIPL - NAMUT File: namut.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$ *---------------------------------------------------------------------------*/ // Nand Application Management UTility ライブラリ、略してNAMUTライブラリです。 // レイヤー的にはNAMと重なりますのでNAMに吸収しても良いと思います。 #include #include #include #include #include #include /*---------------------------------------------------------------------------* 定数定義 *---------------------------------------------------------------------------*/ // 擬似フォーマットで消去しないタイトルを // TitleProperty (TitleID Hiの下位16bit)のビットで指定します。 // どれか1つでもビットが立っていれば消去の対象から外します。 #define PROTECT_TITLE_PROPERTY (TITLE_ID_HI_APP_TYPE_MASK) #define DIRECTORY_DEPTH_MAX 16 // ディレクトリの深さの最大(NANDの正規構成としては最大6) #define TITLE_ID_HI_SIZE 8 #define TITLE_LIST_MAX 256 #define CLEAR_DATA_SIZE 256 // 擬似フォーマット実行時に // 指定ディレクトリ以下は全て消去されます。 // 指定ディレクトリ自体は残ります。 static const char* sDeleteDirectoryList[] = { "nand:/shared2", "nand2:/photo", "nand:/tmp" }; // 擬似フォーマット実行時に // 指定ディレクトリ以下のNonProtectedなタイトルは全て消去されます。 // 指定ディレクトリ自体は残ります。 static const char* sDeleteNonProtecedDirectoryList[] = { "nand:/title", "nand:/ticket", "nand:/import" }; // 擬似フォーマット実行時に // 指定ファイルは0xffでFillされます。 static const char* sFillFileList[] = { "nand:/shared1/TWLCFG0.dat", "nand:/shared1/TWLCFG1.dat" }; static const u8 sClearData[CLEAR_DATA_SIZE] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; /*---------------------------------------------------------------------------* 内部変数定義 *---------------------------------------------------------------------------*/ static FSDirectoryEntryInfo sEntryInfo; static NAMTitleId sTitleIdArray[TITLE_LIST_MAX]; static char sCurrentFullPath[FS_ENTRY_LONGNAME_MAX]; /*---------------------------------------------------------------------------* 内部関数宣言 *---------------------------------------------------------------------------*/ static BOOL NAMUTi_DeleteNonprotectedTitle(void); static BOOL NAMUTi_DeleteNonprotectedTitleEntity(const char* path); static BOOL NAMUTi_ClearSavedataAll(void); static BOOL NAMUTi_DeleteNandDirectory(const char *path); static BOOL NAMUTi_MountAndFormatOtherTitleSaveData(u64 titleID, const char *arcname); static void NAMUTi_DrawNandTree(s32 depth, const char *path); static BOOL NAMUTi_FillFile(const char* path); static void PrintDirectory(s32 depth, const char* path); static void PrintFile(s32 depth, const char* path); /*---------------------------------------------------------------------------* Name: NAMUT_Format Description: NANDの擬似フォーマット (システム系の必要なファイルのみを残し他を消去します) Arguments: None Returns: None *---------------------------------------------------------------------------*/ BOOL NAMUT_Format(void) { int i; BOOL ret = TRUE; // プロテクトされていないタイトルの削除を行います if (!NAMUTi_DeleteNonprotectedTitle()) { ret = FALSE; OS_TWarning("Fail! NAMUTi_DeleteNonprotectedTitle()\n"); } // プロテクトタイトルのセーブデータをフォーマットします if (!NAMUTi_ClearSavedataAll()) { ret = FALSE; OS_TWarning("Fail! NAMUTi_ClearSavedataAll()\n"); } // 指定ファイルを0xffでクリアします for (i=0; i= ('a'-'0')) { titlePropety -= 0x27; } // プロテクト対象でない場合ディレクトリごと消去する if (!(titlePropety & PROTECT_TITLE_PROPERTY)) { STD_CopyLString( sCurrentFullPath, path, FS_ENTRY_LONGNAME_MAX ); STD_ConcatenateLString(sCurrentFullPath, "/", FS_ENTRY_LONGNAME_MAX); STD_ConcatenateLString(sCurrentFullPath, entryInfo.longname, FS_ENTRY_LONGNAME_MAX); if (!FS_DeleteDirectoryAuto(sCurrentFullPath)) { ret = FALSE; OS_TWarning("Fail! FS_DeleteDirectoryAuto(%s) in %s\n", sCurrentFullPath, __func__); } } } } // ディレクトリを閉じる if (!FS_CloseDirectory(&dir)) { ret = FALSE; OS_TWarning("Fail! FS_CloseDirectory() in %s\n", __func__); } return ret; } /*---------------------------------------------------------------------------* Name: NAMUTi_ClearSavedataAll Description: 全セーブデータのFFクリア&フォーマットを行います Arguments: None Returns: None *---------------------------------------------------------------------------*/ static BOOL NAMUTi_ClearSavedataAll( void ) { s32 title_num; NAMTitleInfo namTitleInfo; char savePublicPath[ FS_ENTRY_LONGNAME_MAX ]; char savePrivatePath[ FS_ENTRY_LONGNAME_MAX ]; char subBannerPath[ FS_ENTRY_LONGNAME_MAX ]; BOOL ret = TRUE; s32 i; // タイトルリスト取得 if (NAM_GetTitleList(sTitleIdArray, TITLE_LIST_MAX) != NAM_OK) { return FALSE; } // タイトル数取得 title_num = NAM_GetNumTitles(); for (i=0;i 0) { ret &= NAMUTi_ClearSavedataPublic(savePublicPath, namTitleInfo.titleId); } // privateSaveSizeが0以上なら0xFFクリア&フォーマット if (namTitleInfo.privateSaveSize > 0) { ret &= NAMUTi_ClearSavedataPrivate(savePrivatePath, namTitleInfo.titleId); } } else { ret = FALSE; } // サブバナーファイルパス取得 if (NAM_GetTitleBannerFilePath( subBannerPath, namTitleInfo.titleId) == NAM_OK) { NAMUTi_DestroySubBanner( subBannerPath ); } else { ret = FALSE; } } else { ret = FALSE; } } return ret; } /*---------------------------------------------------------------------------* Name: NAMUTi_ClearSavedataPublic Description: 指定したセーブデータファイルに対して FFクリア&フォーマットを行います。 Arguments: None Returns: None *---------------------------------------------------------------------------*/ BOOL NAMUTi_ClearSavedataPublic(const char* path, u64 titleID) { //----- FFクリア if (NAMUTi_FillFile(path) == FALSE) { OS_Warning(" Fail NAMUTi_FillFile"); return FALSE; } //----- NANDアプリのセーブデータファイルをマウントかつフォーマット return NAMUTi_MountAndFormatOtherTitleSaveData(titleID, "otherPub"); } /*---------------------------------------------------------------------------* Name: NAMUTi_ClearSavedataPrivate Description: 指定したセーブデータファイルに対して FFクリア&フォーマットを行います。 Arguments: None Returns: None *---------------------------------------------------------------------------*/ BOOL NAMUTi_ClearSavedataPrivate(const char* path, u64 titleID) { //----- FFクリア if (NAMUTi_FillFile(path) == FALSE) { OS_Warning(" Fail NAMUTi_FillFile"); return FALSE; } //----- NANDアプリのセーブデータファイルをマウントかつフォーマット return NAMUTi_MountAndFormatOtherTitleSaveData(titleID, "otherPrv"); } /*---------------------------------------------------------------------------* Name: NAMUTi_DestroySubBanner Description: 指定したサブバナーのCRC破壊を試みます。 指定したサブバナーが存在しない可能性もありますが その場合でもTRUEを返します。(コードはOS_DeleteSubBannerFileのパクリ) Arguments: None Returns: None *---------------------------------------------------------------------------*/ BOOL NAMUTi_DestroySubBanner(const char* path) { TWLSubBannerFile buf[1]; // 4KBあるのでよくない。NAM関数のアロケータが使いたい・・ u16 crc, solt; FSFile file[1]; BOOL ret = FALSE; // R属性でファイルをオープンを試みてファイルの存在有無を確認する // 存在しない場合はTRUEで返す FS_InitFile(file); if ( !FS_OpenFileEx(file, path, FS_FILEMODE_R) ) { return TRUE; } // RWL属性で開きなおす FS_InitFile(file); if ( !FS_OpenFileEx(file, path, FS_FILEMODE_RWL) ) { OS_TPrintf("OS_DeleteSubBannerFile : banner file open failed.\n"); return FALSE; } // CRCを改竄して書き戻す if( FS_ReadFile( file, buf, sizeof(TWLSubBannerFile) ) != -1 ) { crc = SVC_GetCRC16( 0xffff, &buf->anime, sizeof(BannerAnime) ); solt = 1; crc += solt; buf->h.crc16_anime = crc; FS_SeekFile( file, 0, FS_SEEK_SET ); if( sizeof(BannerHeader) == FS_WriteFile(file, &buf->h, sizeof(BannerHeader)) ) { OS_TPrintf("OS_DeleteSubBannerFile : banner file write succeed.\n"); ret = TRUE; }else { OS_TPrintf("OS_DeleteSubBannerFile : banner file write failed.\n"); } }else { OS_TPrintf("OS_DeleteSubBannerFile : banner file read failed.\n"); } FS_CloseFile(file); return ret; } /*---------------------------------------------------------------------------* Name: NAMUTi_MountAndFormatOtherTitleSaveData Description: 指定NANDアプリのセーブデータファイルをマウントかつフォーマット。 Arguments: titleID : タイトルID arcname : "otherPub"、"otherPriv"、またはNULL Returns: 成功すればTRUE *---------------------------------------------------------------------------*/ static BOOL NAMUTi_MountAndFormatOtherTitleSaveData(u64 titleID, const char *arcname) { BOOL succeeded = FALSE; // マウント試行。 FSResult result = FS_MountOtherTitleArchive(titleID, arcname); if (result != FS_RESULT_SUCCESS) { OS_TWarning("FS_MountOtherTitleArchive failed. (%d)\n", result); } else { // 成功したらフォーマット試行。 char path[FS_ENTRY_LONGNAME_MAX]; (void)STD_TSPrintf(path, "%s:/", arcname); if (!FATFSi_FormatMedia(path)) { OS_TWarning("FATFSi_FormatMedia failed. (%d)\n", FATFS_GetLastError()); } else if (!FATFS_FormatDrive(path)) { OS_TWarning("FATFS_FormatDrive failed. (%d)\n", FATFS_GetLastError()); } else { succeeded = TRUE; } // ドライブ情報をダンプ。 // DumpArchiveResource(path); // アンマウント。 (void)FS_MountOtherTitleArchive(titleID, NULL); } return succeeded; } /*---------------------------------------------------------------------------* Name: NAMUTi_FillFile Description: 指定したファイルを0xFFで埋めます。 Arguments: path Returns: None *---------------------------------------------------------------------------*/ static BOOL NAMUTi_FillFile(const char* path) { FSFile file; // ファイル構造体初期化 FS_InitFile(&file); // ファイルオープン if (FS_OpenFileEx(&file, path, (FS_FILEMODE_RWL))) { // ファイルを0xFFでクリア u32 filesize = FS_GetFileLength(&file); for (; filesize > CLEAR_DATA_SIZE; filesize -= CLEAR_DATA_SIZE) { FS_WriteFile(&file, sClearData, CLEAR_DATA_SIZE); } FS_WriteFile(&file, sClearData, (s32)filesize); FS_CloseFile(&file); } else { return FALSE; } return TRUE; } /*---------------------------------------------------------------------------* Name: NAMUT_SearchInstalledSoftBoxCount Description: InstalledSoftBoxCountの数を調べて返します。 Arguments: None Returns: None *---------------------------------------------------------------------------*/ u32 NAMUT_SearchInstalledSoftBoxCount( void ) { s32 title_num; NAMTitleInfo namTitleInfo; u32 count = 0; s32 i; // タイトルリスト取得 if (NAM_GetTitleList(sTitleIdArray, TITLE_LIST_MAX) != NAM_OK) { OS_TWarning("Fail! NAM_GetTitleList() in %s\n", __func__); return 0; } // タイトル数取得 title_num = NAM_GetNumTitles(); for (i=0;i DIRECTORY_DEPTH_MAX) { OS_TPrintf("Fail! Depth is too deep.\n"); return; } // カレントパスを設定 STD_CopyLString( sCurrentFullPath, path, FS_ENTRY_LONGNAME_MAX ); FS_InitFile(&dir); // 引数で指定されたディレクトリを開く if (!FS_OpenDirectory(&dir, sCurrentFullPath, (FS_FILEMODE_R))) { OS_TPrintf("%d Fail! FS_OpenDirectory(%s)\n", __LINE__, sCurrentFullPath); return; } // ディレクトリの中身を読む while (FS_ReadDirectory(&dir, &sEntryInfo)) { if (STD_CompareString(sEntryInfo.longname, ".") == 0 || STD_CompareString(sEntryInfo.longname, "..") == 0) { continue; } // ディレクトリであれば再帰呼び出し if (!(sEntryInfo.attributes & FS_ATTRIBUTE_IS_DIRECTORY)) { PrintFile(depth, sEntryInfo.longname); } else { STD_ConcatenateLString(sCurrentFullPath, "/", FS_ENTRY_LONGNAME_MAX); STD_ConcatenateLString(sCurrentFullPath, sEntryInfo.longname, FS_ENTRY_LONGNAME_MAX); NAMUTi_DrawNandTree(depth + 1, sCurrentFullPath); } } // カレントパスを削る if (pSlash != NULL) { *pSlash = '\0'; } FS_CloseDirectory(&dir); } /*---------------------------------------------------------------------------* Name: PrintDirectory Description: ツリー情報をプリント出力します(ディレクトリ用) Arguments: ... Returns: None. *---------------------------------------------------------------------------*/ static void PrintDirectory(s32 depth, const char* path) { int i; for (i=0; i