From 309b21be2708b098ece0b95585532e877e74d01d Mon Sep 17 00:00:00 2001 From: miya Date: Fri, 8 May 2009 08:57:05 +0000 Subject: [PATCH] =?UTF-8?q?=E3=83=97=E3=83=AA=E3=83=B3=E3=82=B9=E3=83=88?= =?UTF-8?q?=E3=83=BC=E3=83=AB=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlToolsRED@270 7061adef-622a-194b-ae81-725974e89856 --- build/tools/sctools/common/src/mprintf.c | 5 + build/tools/sctools/common/src/mprintf.h | 1 + build/tools/sctools/common/src/my_fs_util.c | 396 ++- build/tools/sctools/common/src/my_fs_util.h | 29 +- build/tools/sctools/common/src/mydata.h | 4 +- build/tools/sctools/common/src/myimport.c | 2256 +++++++++++++++++ build/tools/sctools/common/src/myimport.h | 16 + build/tools/sctools/common/src/pre_install.c | 693 +++++ build/tools/sctools/common/src/pre_install.h | 30 + build/tools/sctools/copy_dst/Makefile | 14 +- .../sctools/copy_dst/src/hatamotolib.cpp | 298 ++- .../tools/sctools/copy_dst/src/hatamotolib.h | 11 +- build/tools/sctools/copy_dst/src/main.c | 295 +-- build/tools/sctools/copy_org/Makefile | 5 +- build/tools/sctools/copy_org/src/main.c | 81 +- build/tools/sctools/files/tads/tad_table.txt | 18 + 16 files changed, 3849 insertions(+), 303 deletions(-) create mode 100644 build/tools/sctools/common/src/myimport.c create mode 100644 build/tools/sctools/common/src/myimport.h create mode 100644 build/tools/sctools/common/src/pre_install.c create mode 100644 build/tools/sctools/common/src/pre_install.h create mode 100644 build/tools/sctools/files/tads/tad_table.txt diff --git a/build/tools/sctools/common/src/mprintf.c b/build/tools/sctools/common/src/mprintf.c index 720810e..d9bbf0f 100644 --- a/build/tools/sctools/common/src/mprintf.c +++ b/build/tools/sctools/common/src/mprintf.c @@ -115,6 +115,11 @@ static void *proutPrintf(void *txb, const char *buf, size_t n) return ((void *)txb); } +void mputchar(int c) +{ + // TEXT_CTRL *tc; + m_putchar(tc[0], c ); +} void mprintf(const char *fmt, ...) { diff --git a/build/tools/sctools/common/src/mprintf.h b/build/tools/sctools/common/src/mprintf.h index 0480313..0206dee 100644 --- a/build/tools/sctools/common/src/mprintf.h +++ b/build/tools/sctools/common/src/mprintf.h @@ -11,6 +11,7 @@ extern "C" { void mfprintf(TEXT_CTRL *tc, const char *fmt, ...); void mprintf(const char *fmt, ...); +void mputchar(int c); #ifdef __cplusplus } diff --git a/build/tools/sctools/common/src/my_fs_util.c b/build/tools/sctools/common/src/my_fs_util.c index 6c605fd..6616bfa 100644 --- a/build/tools/sctools/common/src/my_fs_util.c +++ b/build/tools/sctools/common/src/my_fs_util.c @@ -28,6 +28,26 @@ void Miya_debug_OFF(void) } +static BOOL print_debug_flag = FALSE; + +void my_fs_print_debug_ON(void) +{ + print_debug_flag = TRUE; +} + +void my_fs_print_debug_OFF(void) +{ + print_debug_flag = FALSE; +} + +BOOL my_fs_get_print_debug_flag(void) +{ + return print_debug_flag; +} + + + + /* NAND -> SDコピーの時、アトリビュートと時間とパーミッションを合わせる必要あり? @@ -154,6 +174,23 @@ char *my_fs_util_get_fs_result_word( FSResult res ) } + +BOOL my_fs_Tid_To_GameCode(u64 tid, char *gcode) +{ + u32 code; + char *str; + // OS_TPrintf("tid = %016X\n",tid); + str = gcode; + code = (u32)(tid & 0xffffffff); + *str++ = (char)((code >> 24) & 0xff); + *str++ = (char)((code >> 16) & 0xff); + *str++ = (char)((code >> 8) & 0xff); + *str++ = (char)(code & 0xff); + *str = '\0'; + return TRUE; +} + + static void PrintAttributes(u32 attributes, FSFile *log_fd) { char buf[7]; @@ -1166,13 +1203,78 @@ static void AppErrorReport(const char *path, char *msg) (void)Error_Report_Printf(" Photo :%s\n", msg); } else if( TRUE == GetAppGameCode(path, game_code, NULL ) ) { - (void)Error_Report_Printf(" %s :%s\n", game_code, msg); + (void)Error_Report_Printf(" [ %s ]:%s\n", game_code, msg); } else { - (void)Error_Report_Printf(" ???? :%s\n path=%s\n",msg, path); + (void)Error_Report_Printf(" [ ???? ]:%s\n path=%s\n",msg, path); } } + +static u64 GetTitleIdFromSrcPath(char path[]) +{ + u64 tid = 0; + int i; + + // 01234567890123456789012345678 + // nand:/title/00030017/484e4141 (ランチャー) + + for( i = 0 ; i < 8 ; i++ ) { + tid |= ( ((u64)a_to_int( path[12+i] )) << (60-(4*i)) ); + } + + for( i = 0 ; i < 8 ; i++ ) { + tid |= ( ((u64)a_to_int( path[21+i] )) << (28-(4*i)) ); + } + return tid; +} + +static BOOL CheckInstallSuccessApp( char *path , MY_USER_APP_TID *title_id_buf, int title_id_count ) +{ + u64 tid; + int i; + MY_USER_APP_TID *temp_title_id_buf; + + temp_title_id_buf = title_id_buf; + + tid = GetTitleIdFromSrcPath( path ); + + for( i = 0 ; i < title_id_count ; i++ ) { + if( tid == temp_title_id_buf[i].tid ) { + if(temp_title_id_buf[i].install_success_flag == TRUE) { + /* このときだけバックアップを復活してやる。 */ + return TRUE; + } + } + } + return FALSE; +} + +static int CheckInstallSuccessAppEx( char *path , MY_USER_APP_TID *title_id_buf, int title_id_count ) +{ + u64 tid; + int i; + MY_USER_APP_TID *temp_title_id_buf; + + temp_title_id_buf = title_id_buf; + + tid = GetTitleIdFromSrcPath( path ); + + for( i = 0 ; i < title_id_count ; i++ ) { + if( tid == temp_title_id_buf[i].tid ) { + if(temp_title_id_buf[i].install_success_flag == TRUE) { + /* このときだけバックアップを復活してやる。 */ + return 1; + } + else { + return 2; + } + } + } + return -1; /* そんなIDない */ +} + + static BOOL CheckSystemApp(char path[]) { char c; @@ -1209,12 +1311,14 @@ static BOOL CheckSystemApp(char path[]) } } -BOOL GetUserAppTitleList( MY_DIR_ENTRY_LIST *head, u64 **pBuffer, int *size, char *log_file_name ) +//BOOL GetUserAppTitleList( MY_DIR_ENTRY_LIST *head, u64 **pBuffer, int *size, char *log_file_name ) +BOOL GetUserAppTitleList( MY_DIR_ENTRY_LIST *head, MY_USER_APP_TID **pBuffer, int *size, char *log_file_name ) { int i; int count = 0; MY_DIR_ENTRY_LIST *list_temp; - u64 *buf = NULL; + // u64 *buf = NULL; + MY_USER_APP_TID *buf = NULL; char c; u8 hex; BOOL log_active = FALSE; @@ -1244,9 +1348,11 @@ BOOL GetUserAppTitleList( MY_DIR_ENTRY_LIST *head, u64 **pBuffer, int *size, cha miya_log_fprintf(log_fd, "User App. count = %d\n", count); if( count ) { - buf = (u64 *)OS_Alloc( (u32)(count * sizeof(u64)) ); + // buf = (u64 *)OS_Alloc( (u32)(count * sizeof(u64)) ); + buf = (MY_USER_APP_TID *)OS_Alloc( (u32)(count * sizeof(MY_USER_APP_TID)) ); if( buf ) { - STD_MemSet((void *)buf, 0, count * sizeof(u64)); + // STD_MemSet((void *)buf, 0, count * sizeof(u64)); + STD_MemSet((void *)buf, 0, count * sizeof(MY_USER_APP_TID)); } else { miya_log_fprintf(log_fd, "%s memory allocate error\n",__FUNCTION__); @@ -1290,7 +1396,8 @@ BOOL GetUserAppTitleList( MY_DIR_ENTRY_LIST *head, u64 **pBuffer, int *size, cha } goto next_loop; } - *buf |= (((u64)hex) << ((7-i)*4 + 32 )); + // *buf |= (((u64)hex) << ((7-i)*4 + 32 )); + buf->tid |= (((u64)hex) << ((7-i)*4 + 32 )); } for( i = 0 ; i < 8 ; i++ ) { c = list_temp->src_path[21 + i]; @@ -1305,7 +1412,8 @@ BOOL GetUserAppTitleList( MY_DIR_ENTRY_LIST *head, u64 **pBuffer, int *size, cha } goto next_loop; } - *buf |= (((u64)hex) << ((7-i)*4 )); + // *buf |= (((u64)hex) << ((7-i)*4 )); + buf->tid |= (((u64)hex) << ((7-i)*4 )); } buf++; count++; @@ -1870,7 +1978,6 @@ BOOL RestoreDirEntryListSystemBackupOnly( char *path , char *log_file_name, int } else { /* ユーザーアプリだった場合。 */ - } } } @@ -1912,6 +2019,249 @@ BOOL RestoreDirEntryListSystemBackupOnly( char *path , char *log_file_name, int } +BOOL RestoreDirEntryList_System_And_InstallSuccessApp(char *path , char *log_file_name, int *list_count, int *error_count, + MY_USER_APP_TID *title_id_buf, int title_id_count ) +{ + FSFile f; + FSFile f_dir; + BOOL bSuccess; + FSResult fsResult; + s32 readSize; + MY_DIR_ENTRY_LIST list_temp; + FSPathInfo path_info; + MY_DIR_ENTRY_LIST *readonly_list_head = NULL; + BOOL copy_error_flag; + FSFile log_fd_real; + FSFile *log_fd; + BOOL log_active = FALSE; + u64 tid; + char game_code_buf[5]; + + log_fd = &log_fd_real; + log_active = Log_File_Open( log_fd, log_file_name ); + if( !log_active ) { + log_fd = NULL; + } + miya_log_fprintf(log_fd, "%s START\n", __FUNCTION__); + + + if( (list_count == NULL) || (error_count == NULL) ) { + miya_log_fprintf(log_fd, "%s Error:invalid argument\n", __FUNCTION__); + miya_log_fprintf(log_fd, " list ptr=0x%08x error ptr=0x%08x\n", list_count, error_count); + return FALSE; + } + + *list_count = 0; + *error_count = 0; + + FS_InitFile(&f); + FS_InitFile(&f_dir); + + if( FS_OpenFileEx(&f, path, FS_FILEMODE_R) == FALSE) { + fsResult = FS_GetArchiveResultCode(path); + miya_log_fprintf(log_fd, "%s %d: Failed Open file\n", __FUNCTION__ , __LINE__ ); + miya_log_fprintf(log_fd, " %s\n", path); + miya_log_fprintf(log_fd, " %s\n", my_fs_util_get_fs_result_word( fsResult ) ); + return FALSE; /* error */ + } + + while( 1 ) { + /* リストはルートディレクトリに近い順から入っている */ + readSize = FS_ReadFile(&f, (void *)&list_temp, (s32)sizeof(MY_DIR_ENTRY_LIST) ); + if( readSize == 0 ) { + /* 終わり */ + break; + } + else if( readSize != (s32)sizeof(MY_DIR_ENTRY_LIST) ) { + miya_log_fprintf(log_fd, "%s %d: Failed Read file\n", __FUNCTION__ , __LINE__ ); + miya_log_fprintf(log_fd, " %s\n", path); + break; + } + + copy_error_flag = TRUE; + + /* NAND側にディレクトリの作成とファイルのコピー */ + if( (list_temp.content.attributes & FS_ATTRIBUTE_IS_DIRECTORY) != 0 ) { + /* ディレクトリの場合 */ + if( TRUE == FS_GetPathInfo(list_temp.src_path, &path_info) ) { + /* 復元される側(NAND)にすでに何かファイルかディレクトリがある場合 */ + if( (path_info.attributes & FS_ATTRIBUTE_IS_DIRECTORY) == 0 ) { + /* ディレクトリでない場合 エラー */ + /* SDにログを残す場合 */ + miya_log_fprintf(log_fd, "%s %d: NOT a directory\n", __FUNCTION__ , __LINE__ ); + miya_log_fprintf(log_fd, " %s\n", list_temp.src_path ); + /* require backup file */ + /* パニック?? */ + /* それとも一度デリートする?? */ + FS_DeleteFile( list_temp.src_path ); /* ちょっと無理やりか? */ + goto label1; + } + /* read onlyディレクトリだった場合の処理は下のほうでやる。 */ + } + else { + label1: + /* 復元される側(NAND)にディレクトリエントリがない場合 */ + bSuccess = FS_CreateDirectory(list_temp.src_path, FS_PERMIT_RW); + if(!bSuccess) { + fsResult = FS_GetArchiveResultCode(list_temp.src_path); + if( fsResult != FS_RESULT_ALREADY_DONE ) { + miya_log_fprintf(log_fd, "%s %d: Failed Create NAND Directory\n", __FUNCTION__,__LINE__); + miya_log_fprintf(log_fd, " %s\n", my_fs_util_get_fs_result_word( fsResult ) ); + miya_log_fprintf(log_fd, " %s\n", list_temp.src_path); + copy_error_flag = FALSE; + } + } + if( FALSE == FS_GetPathInfo(list_temp.src_path, &path_info) ) { + miya_log_fprintf(log_fd, "%s %d: Failed GetPathInfo\n", __FUNCTION__,__LINE__ ); + miya_log_fprintf(log_fd, " %s\n", list_temp.src_path ); + // return FALSE; + } + } + + +#ifdef ATTRIBUTE_BACK + /* このディレクトリを記憶しておき、あとで属性をまとめて戻す */ + if( FALSE == add_entry_list( &readonly_list_head, &list_temp, log_fd ) ) { + miya_log_fprintf(log_fd, "%s %d: ERROR: add_entry_list\n", __FUNCTION__,__LINE__ ); + miya_log_fprintf(log_fd, " %s\n", list_temp.src_path ); + } +#endif + + if( (path_info.attributes & FS_ATTRIBUTE_DOS_READONLY) != 0 ) { + /* リードオンリーの場合,一度リードライト可能にする */ + path_info.attributes &= ~FS_ATTRIBUTE_DOS_READONLY; + if( FALSE == FS_SetPathInfo( list_temp.src_path, &path_info) ) { + fsResult = FS_GetArchiveResultCode(list_temp.src_path); + miya_log_fprintf(log_fd, "%s %d: Failed SetPathInfo\n", __FUNCTION__,__LINE__ ); + miya_log_fprintf(log_fd, " %s\n", list_temp.src_path ); + miya_log_fprintf(log_fd, " %s\n", my_fs_util_get_fs_result_word( fsResult ) ); + } + } + } + else { + /* ファイルの場合 */ + if( !STD_StrCmp( list_temp.src_path, "nand:" ) ) { + /* nandのルートディレクトリはスルーする。 */ + OS_TPrintf("nand: root detect \n"); + } + else { + + // CopyFile( dst <= src ); + if( (TRUE == CheckSystemApp( list_temp.src_path )) || + (TRUE == CheckInstallSuccessApp(list_temp.src_path, title_id_buf, title_id_count)) ) { + + /* 一応拡張子(*.sav)もチェックしといたほうがいいか? */ + miya_log_fprintf(log_fd, "backup %s\n",list_temp.src_path); + + tid = GetTitleIdFromSrcPath( list_temp.src_path ); + (void)my_fs_Tid_To_GameCode(tid, game_code_buf); + + if( print_debug_flag == TRUE ) { + mprintf(" id %08X %08X [%s] ", (u32)(tid >> 32), (u32)tid, game_code_buf); + } + miya_log_fprintf(log_fd, " id %08X %08X [%s] ", (u32)(tid >> 32), (u32)tid, game_code_buf); + +#ifdef COPY_FILE_ENCRYPTION + copy_error_flag = CopyFileCrypto( list_temp.src_path, list_temp.dst_path, log_fd ); +#else + copy_error_flag = CopyFile( list_temp.src_path, list_temp.dst_path, log_fd ); +#endif + + if( TRUE == copy_error_flag ) { + path_info.attributes = list_temp.content.attributes; + path_info.ctime = list_temp.content.ctime; + path_info.mtime = list_temp.content.mtime; + path_info.atime = list_temp.content.atime; + path_info.id = list_temp.content.id; + path_info.filesize = list_temp.content.filesize; + if( FALSE == FS_SetPathInfo( list_temp.src_path, &path_info) ) { + fsResult = FS_GetArchiveResultCode(list_temp.src_path); + miya_log_fprintf(log_fd, "%s %d: Failed SetPathInfo\n", __FUNCTION__,__LINE__ ); + miya_log_fprintf(log_fd, " %s\n", list_temp.src_path ); + miya_log_fprintf(log_fd, " %s\n", my_fs_util_get_fs_result_word( fsResult ) ); + } + else { + } + (*list_count)++; + + /* success */ + if( print_debug_flag == TRUE ) { + m_set_palette(tc[0], M_TEXT_COLOR_GREEN ); /* green */ + mprintf("OK.\n"); + m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); + } + miya_log_fprintf(log_fd, "OK.\n"); + } + else { + /* fail */ + if( print_debug_flag == TRUE ) { + m_set_palette(tc[0], M_TEXT_COLOR_RED ); + mprintf("NG.\n"); + m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); + } + miya_log_fprintf(log_fd, "NG.\n"); + } + } + else { + /* インストール失敗アプリの場合。 */ + if( 2 == CheckInstallSuccessAppEx(list_temp.src_path, title_id_buf, title_id_count) ) { + tid = GetTitleIdFromSrcPath( list_temp.src_path ); + (void)my_fs_Tid_To_GameCode(tid, game_code_buf); + + if( print_debug_flag == TRUE ) { + mprintf(" id %08X %08X [%s] ", (u32)(tid >> 32), (u32)tid, game_code_buf); + /* fail */ + m_set_palette(tc[0], M_TEXT_COLOR_RED ); + mprintf("NG.\n"); + m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); + } + miya_log_fprintf(log_fd, " id %08X %08X [%s] ", (u32)(tid >> 32), (u32)tid, game_code_buf); + miya_log_fprintf(log_fd, "NG.\n"); + copy_error_flag = FALSE; + } + + } + } + } + + if( copy_error_flag == FALSE ) { + (*error_count)++; + AppErrorReport(list_temp.src_path, "copy file failed"); + } + } + + miya_log_fprintf(log_fd, "%s Read entry count %d error count %d\n",__FUNCTION__ , *list_count, *error_count ); + +#ifdef ATTRIBUTE_BACK + /* add_entry_list( &readonly_list_head, &list_temp ); + でリストにしたエントリーのアトリビュートを逆順で元に戻す。*/ + if( FALSE == restore_entry_list(&readonly_list_head, log_fd) ) { + miya_log_fprintf(log_fd, "%s %d: ERROR: restore_entry_list\n", __FUNCTION__,__LINE__ ); + } +#endif + + exit_label: + + // FS_FlushFile(&f); //リードだからいらない + if( FS_CloseFile(&f) == FALSE) { + fsResult = FS_GetArchiveResultCode(path); + miya_log_fprintf(log_fd, "%s %d: Failed Close file\n", __FUNCTION__ , __LINE__ ); + miya_log_fprintf(log_fd, " %s\n", path); + miya_log_fprintf(log_fd, " %s\n", my_fs_util_get_fs_result_word( fsResult ) ); + } + + miya_log_fprintf(log_fd, "%s END\n\n", __FUNCTION__); + if( log_active ) { + Log_File_Close(log_fd); + } + if( *error_count > 0 ) { + return FALSE; + } + return TRUE; +} + + + static BOOL my_fs_is_Title_Hi_dir_name(const char *name) { @@ -2169,7 +2519,8 @@ BOOL MydataSave(const char *path, void *pData, int size, FSFile *log_fd) } #endif -BOOL TitleIDLoad(const char *path, u64 **pBuffer, int *count, char *log_file_name) +//BOOL TitleIDLoad(const char *path, u64 **pBuffer, int *count, char *log_file_name) +BOOL TitleIDLoad(const char *path, MY_USER_APP_TID **pBuffer, int *count, char *log_file_name) { FSFile f; BOOL bSuccess; @@ -2211,16 +2562,18 @@ BOOL TitleIDLoad(const char *path, u64 **pBuffer, int *count, char *log_file_nam *count = id_count; - size = (int)sizeof(u64) * id_count; + // size = (int)sizeof(u64) * id_count; + size = (int)sizeof(MY_USER_APP_TID) * id_count; - *pBuffer = (u64 *)OS_Alloc( (u32)size ); + // *pBuffer = (u64 *)OS_Alloc( (u32)size ); + *pBuffer = (MY_USER_APP_TID *)OS_Alloc( (u32)size ); if( *pBuffer == NULL ) { ret_flag = FALSE; miya_log_fprintf(log_fd, "%s Failed memory alloc size %d\n",__FUNCTION__, size); goto function_end; } - readSize = FS_ReadFile(&f, *pBuffer, (s32)size ); + readSize = FS_ReadFile(&f, (void *)*pBuffer, (s32)size ); if( readSize != size ) { miya_log_fprintf(log_fd, "Failed Read File: %s request size %d read size %d\n",path, size, readSize); if( readSize != size ) { @@ -2245,7 +2598,9 @@ BOOL TitleIDLoad(const char *path, u64 **pBuffer, int *count, char *log_file_nam return ret_flag; } -BOOL TitleIDSave(const char *path, u64 *pData, int count, char *log_file_name ) +// BOOL TitleIDSave(const char *path, u64 *pData, int count, char *log_file_name ) +BOOL TitleIDSave(const char *path, MY_USER_APP_TID *pData, int count, char *log_file_name ) + { FSFile f; @@ -2262,6 +2617,7 @@ BOOL TitleIDSave(const char *path, u64 *pData, int count, char *log_file_name ) FS_InitFile(&f); + //MY_USER_APP_TID log_active = Log_File_Open( log_fd, log_file_name ); if( !log_active ) { @@ -2315,7 +2671,8 @@ BOOL TitleIDSave(const char *path, u64 *pData, int count, char *log_file_name ) if( ( pData != NULL ) && ( count != 0 ) ) { /* 16文字だから */ - if( (count*sizeof(u64)) != FS_WriteFile(&f, pData, (s32)(count*sizeof(u64)) )) { + // if( (count*sizeof(u64)) != FS_WriteFile(&f, pData, (s32)(count*sizeof(u64)) )) { + if( (count*sizeof(MY_USER_APP_TID)) != FS_WriteFile(&f, pData, (s32)(count*sizeof(MY_USER_APP_TID)) )) { res = FS_GetArchiveResultCode( path ); miya_log_fprintf(log_fd, "%s file write error %s\n", __FUNCTION__,path ); miya_log_fprintf(log_fd, " Failed write file:%s\n", my_fs_util_get_fs_result_word( res )); @@ -2324,10 +2681,13 @@ BOOL TitleIDSave(const char *path, u64 *pData, int count, char *log_file_name ) } else { int j; - u64 *ptr = pData; + // u64 *ptr = pData; + MY_USER_APP_TID *ptr = pData; + if( ptr != NULL && count > 0 ) { for( j = 0 ; j < count ; j++ ) { - miya_log_fprintf(log_fd,"No. %d 0x%016llx\n",j,*ptr); + // miya_log_fprintf(log_fd,"No. %d 0x%016llx\n",j,*ptr); + miya_log_fprintf(log_fd,"No. %d 0x%016llx\n",j,ptr->tid); ptr++; } } @@ -2693,7 +3053,7 @@ BOOL CleanSDCardFiles(char *log_file_name) } else if( STD_StrCmp(direntry.longname, "nup_log.txt") == 0 ) { } - else if( STD_StrCmp(direntry.longname, "tad") == 0 ) { + else if( STD_StrCmp(direntry.longname, "tads") == 0 ) { } else if( direntry.attributes & FS_ATTRIBUTE_DOS_VOLUME ) { } diff --git a/build/tools/sctools/common/src/my_fs_util.h b/build/tools/sctools/common/src/my_fs_util.h index 40c4796..7450f02 100644 --- a/build/tools/sctools/common/src/my_fs_util.h +++ b/build/tools/sctools/common/src/my_fs_util.h @@ -12,10 +12,22 @@ typedef struct _MY_DIR_ENTRY_LIST { } MY_DIR_ENTRY_LIST; + #ifdef __cplusplus extern "C" { #endif + +typedef struct { + u64 tid; + int is_personalized; + BOOL install_success_flag; +} MY_USER_APP_TID; + + + +BOOL my_fs_Tid_To_GameCode(u64 tid, char *gcode); + char *my_fs_util_get_fs_result_word( FSResult res ); s32 my_fs_crypto_write(FSFile *f, void *ptr, s32 size); s32 my_fs_crypto_read(FSFile *f, void *ptr, s32 size); @@ -33,8 +45,13 @@ void PrintSrcDirEntryListBackward( MY_DIR_ENTRY_LIST *head, FSFile *log_fd); BOOL SaveDirEntryList( MY_DIR_ENTRY_LIST *head , char *path, int *list_count, int *error_count, char *log_file_name); BOOL RestoreDirEntryList( char *path , char *log_file_name, int *list_count, int *error_count); BOOL RestoreDirEntryListSystemBackupOnly( char *path , char *log_file_name, int *list_count, int *error_count); +BOOL RestoreDirEntryList_System_And_InstallSuccessApp(char *path , char *log_file_name, int *list_count, int *error_count, + MY_USER_APP_TID *title_id_buf, int title_id_count ); + + + //BOOL GetUserAppTitleList( MY_DIR_ENTRY_LIST *head, u64 **pBuffer, int *size, char *log_file_name); +BOOL GetUserAppTitleList( MY_DIR_ENTRY_LIST *head, MY_USER_APP_TID **pBuffer, int *size, char *log_file_name); -BOOL GetUserAppTitleList( MY_DIR_ENTRY_LIST *head, u64 **pBuffer, int *size, char *log_file_name); BOOL ClearDirEntryList( MY_DIR_ENTRY_LIST **headp ); void write_debug_data(void); @@ -52,8 +69,10 @@ BOOL MydataLoadDecrypt(const char *path, void *pBuffer, int size, FSFile *log_fd BOOL MydataSaveEncrypt(const char *path, void *pData, int size, FSFile *log_fd); -BOOL TitleIDSave(const char *path, u64 *pData, int count, char *log_file_name); -BOOL TitleIDLoad(const char *path, u64 **pBuffer, int *count, char *log_file_name); +// BOOL TitleIDSave(const char *path, u64 *pData, int count, char *log_file_name); +// BOOL TitleIDLoad(const char *path, u64 **pBuffer, int *count, char *log_file_name); +BOOL TitleIDSave(const char *path, MY_USER_APP_TID *pData, int count, char *log_file_name); +BOOL TitleIDLoad(const char *path, MY_USER_APP_TID **pBuffer, int *count, char *log_file_name); BOOL CopyFile(const char *dst_path, const char *src_path, FSFile *log_fd ); @@ -63,7 +82,9 @@ BOOL Log_File_Open(FSFile *log_fd, const char *log_file_name); void Miya_debug_OFF(void); void Miya_debug_ON(void); - +void my_fs_print_debug_ON(void); +void my_fs_print_debug_OFF(void); +BOOL my_fs_get_print_debug_flag(void); #ifdef __cplusplus } diff --git a/build/tools/sctools/common/src/mydata.h b/build/tools/sctools/common/src/mydata.h index 812bb41..a01a891 100644 --- a/build/tools/sctools/common/src/mydata.h +++ b/build/tools/sctools/common/src/mydata.h @@ -3,7 +3,7 @@ #define MY_DATA_VERSION_MAJOR 1 -#define MY_DATA_VERSION_MINOR 3 +#define MY_DATA_VERSION_MINOR 4 typedef struct { u8 version_major; @@ -19,7 +19,7 @@ typedef struct { BOOL user_settings_flag; BOOL shop_record_flag; int num_of_user_download_app; - int num_of_user_download_app_by_nam; + int num_of_user_pre_installed_app; int num_of_app_save_data; int num_of_photo_files; int num_of_shared2_files; diff --git a/build/tools/sctools/common/src/myimport.c b/build/tools/sctools/common/src/myimport.c new file mode 100644 index 0000000..6999035 --- /dev/null +++ b/build/tools/sctools/common/src/myimport.c @@ -0,0 +1,2256 @@ +/* + 製品鍵を使った書き込みを行う場合は、 + TwlIPL/build/buildtools/commondefsの + "FIRM_USE_PRODUCT_KEYS=TRUE" + を有効にしてください。 + + + ifneq ($(TWL_IPL_RED_PRIVATE_ROOT),) + ifdef FIRM_USE_PRODUCT_KEYS + MAKEROM_FLAGS += -DHWINFO_PRIVKEY='private_HWInfo.der' \ + -DHWID_PRIVKEY='private_HWID.der' + else + MAKEROM_FLAGS += -DHWINFO_PRIVKEY='private_HWInfo_dev.der' \ + -DHWID_PRIVKEY='private_HWID_dev.der' + endif + endif + + +-*- mode: grep; default-directory: "c:/twl/TwlIPL/trunk/build/" -*- +Grep started at Tue Apr 07 11:10:33 + +/Cygwin/bin/find . "(" -name "*.*" ")" | /Cygwin/bin/xargs C:/Cygwin/bin/grep -n FIRM_USE_PRODUCT_KEYS +./gcdfirm/sdmc-launcher/ARM9/main.c:21:#ifdef FIRM_USE_PRODUCT_KEYS +./gcdfirm/sdmc-launcher/ARM9/main.c:199:#ifdef FIRM_USE_PRODUCT_KEYS +./libraries/os/common/os_boot.c:116:#ifndef FIRM_USE_PRODUCT_KEYS +./libraries/os/common/os_boot.c:123:#else // !FIRM_USE_PRODUCT_KEYS +./libraries/os/common/os_boot.c:130:#endif // !FIRM_USE_PRODUCT_KEYS +./libraries/os/common/os_init_firm.c:170:#ifndef FIRM_USE_PRODUCT_KEYS +./libraries/os/common/os_init_firm.c:177:#else // !FIRM_USE_PRODUCT_KEYS +./libraries/os/common/os_init_firm.c:184:#endif // !FIRM_USE_PRODUCT_KEYS +./nandfirm/menu-launcher/ARM9/main.c:21:#ifdef FIRM_USE_PRODUCT_KEYS +./nandfirm/sdmc-launcher/ARM9/main.c:26:#ifdef FIRM_USE_PRODUCT_KEYS +./nandfirm/sdmc-launcher/ARM9/main.c:209:#ifdef FIRM_USE_PRODUCT_KEYS +./systemMenu_tools/HWInfoWriter/ARM9/src/hwi.c:28:#ifdef FIRM_USE_PRODUCT_KEYS // 鍵選択スイッチ +./systemMenu_tools/HWInfoWriter/ARM9/src/hwi.c:196:#ifdef FIRM_USE_PRODUCT_KEYS + +Grep finished (matches found) at Tue Apr 07 11:12:16 + + +*/ + +#include +#include + +#include +#include +#include +#include + +#include + +#include "font.h" +#include "text.h" +#include "mprintf.h" +#include "logprintf.h" + +#include "myimport.h" + + +// #define MIYA_IMPORT 1 + + + +static s32 my_NAM_ImportTad(const char* path); + +static BOOL NAMUT_GetSoftBoxCount( u8* installed, u8* free ) +{ + u32 installedSoftBoxCount; + + // installedSoftBoxCountの取得 + if ( NAM_OK != NAM_GetInstalledSoftBoxCount( &installedSoftBoxCount ) ) { + return FALSE; + } + + // installed count + *installed = (u8)installedSoftBoxCount; + + // free count + *free = (u8)(LCFG_TWL_FREE_SOFT_BOX_COUNT_MAX - installedSoftBoxCount); + + return TRUE; +} + +static BOOL NAMUT_UpdateSoftBoxCount( void ) +{ + u8 installedSoftBoxCount; + u8 freeSoftBoxCount; + u8 *pBuffer; + BOOL retval = TRUE; + + // InstalledSoftBoxCount, FreeSoftBoxCount を数えなおす + if (!NAMUT_GetSoftBoxCount(&installedSoftBoxCount, &freeSoftBoxCount)) { + return FALSE; + } + + // LCFGライブラリの静的変数に対する更新 + LCFG_TSD_SetInstalledSoftBoxCount( installedSoftBoxCount ); + LCFG_TSD_SetFreeSoftBoxCount( freeSoftBoxCount ); + + // LCFGライブラリの静的変数の値をNANDに反映 + pBuffer = OS_Alloc( LCFG_WRITE_TEMP ); + if (!pBuffer) { return FALSE; } + // ミラーリングデータの両方に書き込みを行う。 + retval &= LCFG_WriteTWLSettings( (u8 (*)[ LCFG_WRITE_TEMP ] )pBuffer ); + retval &= LCFG_WriteTWLSettings( (u8 (*)[ LCFG_WRITE_TEMP ] )pBuffer ); + OS_Free( pBuffer ); + + return retval; +} + + +/*---------------------------------------------------------------------------* + Name: ImportTad + + Description: .tad ファイルインポート + + Arguments: no + + Returns: None. + *---------------------------------------------------------------------------*/ +BOOL myImportTad(char* file_name, FSFile *log_fd) +{ + NAMTadInfo tadInfo; + NAMTitleInfo titleInfoTmp; + char full_path[FS_ENTRY_LONGNAME_MAX+6]; + BOOL ret = FALSE; + s32 nam_result; + BOOL overwrite = FALSE; + + // フルパスを作成 + STD_StrCpy(full_path, file_name); + + miya_log_fprintf(log_fd,"start myImportTad %s\n",full_path); + + // mputchar('.'); + + // tadファイルの情報取得 + if (NAM_ReadTadInfo(&tadInfo, full_path) != NAM_OK) { + miya_log_fprintf(log_fd,"Error:NAM_ReadTadInfo failed %s\n",full_path); + return FALSE; + } + + // mputchar('.'); + /* 1851879012 -> 0x6E616E64 */ + /* HNCAだったらはねる。無線ファーム */ + + // NANDの情報を取得 + if ( NAM_ReadTitleInfo(&titleInfoTmp, tadInfo.titleInfo.titleId) == NAM_OK ) { + // NANDに既にインストールされているかどうか確認する + if (tadInfo.titleInfo.titleId == titleInfoTmp.titleId) { + miya_log_fprintf(log_fd,"id=0x%08x already installed\n",titleInfoTmp.titleId); + miya_log_fprintf(log_fd," (%s)\n",full_path); + +#if 1 + miya_log_fprintf(log_fd," delete title..\n"); + if( NAM_OK != NAM_DeleteTitle( titleInfoTmp.titleId ) ) { + miya_log_fprintf(log_fd," Error: NAM_DeleteTitle id = 0x%08x\n", titleInfoTmp.titleId); + return FALSE; + } +#else + return FALSE; +#endif + } + } + else { + /* インストールされていない。 */ + // miya_log_fprintf(log_fd,"Error:NAM_ReadTitleInfo failed 0x%08x\n",tadInfo.titleInfo.titleId); + // return FALSE; + } + // mputchar('.'); + + // NOT_LAUNCH_FLAG または DATA_ONLY_FLAG が立っていないタイトルの場合 + // freeSoftBoxCountに空きがなければインポートしない + if (!(tadInfo.titleInfo.titleId & (TITLE_ID_NOT_LAUNCH_FLAG_MASK | TITLE_ID_DATA_ONLY_FLAG_MASK))) { + // 上書きインポートの場合はfreeSoftBoxCountはチェックしない + miya_log_fprintf(log_fd,"%s %s %d\n",__FILE__,__FUNCTION__,__LINE__); + if (!overwrite) { + u8 installed, free; + if (!NAMUT_GetSoftBoxCount( &installed, &free )) { + miya_log_fprintf(log_fd,"Error:%s %s %d\n",__FILE__,__FUNCTION__,__LINE__); + return FALSE; + } + + if (free == 0) { + miya_log_fprintf(log_fd,"Error:NAND FreeSoftBoxCount == 0"); + return FALSE; + } + miya_log_fprintf(log_fd,"%s %s %d\n",__FILE__,__FUNCTION__,__LINE__); + } + + // ESの仕様で古い e-ticket があると新しい e-ticket を使ったインポートができない + // 暫定対応として該当タイトルを完全削除してからインポートする + nam_result = NAM_DeleteTitleCompletely(tadInfo.titleInfo.titleId); + if ( nam_result != NAM_OK ) { + miya_log_fprintf(log_fd,"Error:NAM_DeleteTitleCompletely RetCode=%x\n", nam_result); + return FALSE; + } + } + + // mputchar('.'); + + // Import開始 + miya_log_fprintf(log_fd,"Import %s Start.\n", full_path ); + +#ifdef MIYA_IMPORT + nam_result = my_NAM_ImportTad( full_path ); +#else + nam_result = NAM_ImportTad( full_path ); +#endif + + // mputchar('.'); + + if ( nam_result == NAM_OK ) { + miya_log_fprintf(log_fd, "Import Success!\n"); + ret = TRUE; + } + else { + /* + [ES] verify publickey sign failed: 7 + [ES] verify ticket failed rv=7 + Error:NAM_ImportTad RetCode=7 + */ + + miya_log_fprintf(log_fd,"Error:NAM_ImportTad RetCode=%d\n", nam_result); + } + + // mputchar('.'); + + // InstalledSoftBoxCount, FreeSoftBoxCount の値を現在のNANDの状態に合わせて更新します。 + NAMUT_UpdateSoftBoxCount(); + + return ret; +} + +/* */ + +#ifdef MIYA_IMPORT + + +#include "ecdl.h" +#include "c:/twlsdk/build/libraries/nam/ARM9.TWL/include/nam_common.h" +#include "c:/twlsdk/build/libraries/ese/common/include/ese_int.h" + +#ifdef PRINT_RESULT +#undef PRINT_RESULT +#endif + +#define PRINT_RESULT(x) OS_TPrintf("%s: %4d %5d\n", __FILE__, __LINE__, x ) +// #define PRINT_RESULT(x) (void)(0) + + +//#define SD_CARD_TEST +#ifdef SD_CARD_TEST +#define BASE_TICKET_DIR "sdmc:/ticket" +#define BASE_TITLE_DIR "sdmc:/title" +#define BASE_IMPORT_DIR "sdmc:/import" +#define BASE_TMP_DIR "sdmc:/tmp" +#else +#define BASE_TICKET_DIR "nand:/ticket" +#define BASE_TITLE_DIR "nand:/title" +#define BASE_IMPORT_DIR "nand:/import" +#define BASE_TMP_DIR "nand:/tmp" +#endif + + +/* *INDENT-OFF* */ +static const char * const fs_result_strings[] = +{ + "FS_RESULT_SUCCESS", + "FS_RESULT_FAILURE", + "FS_RESULT_BUSY", + "FS_RESULT_CANCELED", + "FS_RESULT_UNSUPPORTED", + "FS_RESULT_ERROR", + "FS_RESULT_INVALID_PARAMETER", + "FS_RESULT_NO_MORE_RESOUCE", + "FS_RESULT_ALREADY_DONE", + "FS_RESULT_PERMISSION_DENIED", + "FS_RESULT_MEDIA_FATAL", + "FS_RESULT_NO_ENTRY", +}; +static const size_t fs_result_string_max = sizeof(fs_result_strings) / sizeof(*fs_result_strings); +/* *INDENT-ON* */ + +// FSのエラーを出力します +static void ReportLastErrorPath(const char *path) +{ + FSResult result = FS_GetArchiveResultCode(path); + + if ((result >= 0) && (result < fs_result_string_max)) + { + OS_TPrintf("FS error:\n \"%s\"\n %s\n", + path, fs_result_strings[result]); + } + else + { + OS_TPrintf("FS error:\n \"%s\"\n (%s result code:%d)\n", + path, ((result >= fs_result_string_max) && (result < FS_RESULT_MAX)) ? "new" : "unknown", result); + } +} + + + +// 指定フォルダを上から順番に作成します(一度に深いフォルダは作成できません) +static BOOL ESi_CreateDirectory(const char* path) +{ + FSFile dir[1]; + const char* marker = "/"; + char tmppath[FS_ENTRY_LONGNAME_MAX]; + + // ルートフォルダは作らない + char* pos = STD_SearchString(path, marker) + 1; + + FS_InitFile(dir); + + for (;;) + { + pos = STD_SearchString(pos, marker); + if (pos == NULL) + { + break; + } + pos++; + (void)STD_CopyLStringZeroFill(tmppath, path, pos - path);// n-1文字コピー + + if (FS_OpenDirectory(dir, tmppath, FS_FILEMODE_R | FS_FILEMODE_W)) + { // 既にフォルダが存在しているので作らない + (void)FS_CloseDirectory(dir); + } + else if (!FS_CreateDirectory(tmppath, FS_PERMIT_R | FS_PERMIT_W)) + { + ReportLastErrorPath(tmppath); + OS_TWarning("FS_CreateDirectory(\"%s\") failed.", tmppath); + return FALSE; + } + } + + return TRUE; +} + +// ファイルを新規に作成して書き込みます。 +static BOOL ESi_CreateFile(const char* path, + const void* src, s32 len) +{ + FSFile file[1]; + + FS_InitFile(file); + + if (!ESi_CreateDirectory(path)) + { + return FALSE; + } + + if (FS_OpenFileEx(file, path, FS_PERMIT_W)) + { // ファイルが存在すれば上書きします + //OS_TPrintf("\"%s\" already exists.\n", path); + } + else if (!FS_CreateFile(path, FS_PERMIT_R | FS_PERMIT_W)) + { + ReportLastErrorPath(path); + OS_TWarning("FS_CreateFile(%s) failed.", path); + return FALSE; + } + else + { + //OS_TPrintf("FS_CreateFile(%s) succeeded.\n", path); + if (!FS_OpenFileEx(file, path, FS_PERMIT_W)) + { + OS_TWarning("FS_OpenFileEx(%s) failed.", path); + return FALSE; + } + } + + if (len > 0 && FS_WriteFile(file, src, len) < 0) + { + OS_TWarning("FS_WritFile() failed."); + return FALSE; + } + else + { + //OS_TPrintf("FS_WritFile() succeeded.\n"); + } + (void)FS_CloseFile(file); + return TRUE; +} + + +static void ESi_GetTicketPath(char* path, ESTitleId titleId) +{ + char titleStr[32]; + char titleIdH[16]; + char titleIdL[16]; + + // titleID取得してHとLに分解 + (void)STD_TSPrintf(titleStr, "%016llx", titleId); + (void)STD_CopyLStringZeroFill(titleIdH, titleStr, 9); // (n - 1) 文字コピーします。 + (void)STD_CopyLStringZeroFill(titleIdL, titleStr + 8, 9); // (n - 1) 文字コピーします。 + + (void)STD_TSPrintf(path, "%s/%s/%s.tik", BASE_TICKET_DIR, titleIdH, titleIdL); +} + + + + +static ESError ES_ImportTicket(const void* ticket, const void* certList, u32 certSizeInBytes, + const void* crlList, u32 crlSizeInBytes, ESTransferType source) +{ +#pragma unused(certList, certSizeInBytes, crlList, crlSizeInBytes, source) + + ESError rv = ES_ERR_OK; + + char tmppath[FS_ENTRY_LONGNAME_MAX]; + const ESTicket* esTicket = (ESTicket*)ticket; + +#ifdef VERBOSE_MODE + ESi_DumpCert(certList); + ESi_DumpTicket((ESTicket*)ticket); +#endif + + if (ticket==NULL || certList==NULL || certSizeInBytes==0) + { + rv = ES_ERR_INVALID; + goto out; + } +#if defined(NEXT_GEN) || defined(BROADWAY_REV) + if ( ((u32)ticket & CACHE_LINE_MASK) || + ((u32)certList & CACHE_LINE_MASK) || + ((u32)crlList & CACHE_LINE_MASK) ) { + rv = ES_ERR_INVALID; + goto out; + } +#endif + +#if 0 + if (!ESi_Initialized) + { + rv = ES_ERR_INVALID; + goto out; + } +#endif + + ESi_GetTicketPath(tmppath, MI_BEToH64(esTicket->titleId)); + + if (!ESi_CreateFile(tmppath, ticket, sizeof(ESTicket))) + { + rv = ES_ERR_FILE_WRITE_FAILED; + } + out: + return rv; +} + +#define TMD_FILE "title.tmd" +#define CID_FORMAT "%08x.app" + +static void ESi_GetTmpPath(char* path) +{ + (void)STD_TSPrintf(path, "%s/%s", BASE_TMP_DIR, TMD_FILE); +} + +static ESError ES_GetTmdSize(void* tmd, u32* size) +{ + ESError rv = ES_ERR_OK; + + if (tmd==NULL) + { + rv = ES_ERR_INVALID; + goto out; + } + + *size = sizeof(IOSCSigRsa2048) + sizeof(ESTitleMetaHeader) + + sizeof(ESContentMeta) * (MI_BEToH16(((ESTitleMeta*)tmd)->head.numContents)); + +out: + PRINT_RESULT(rv); + return rv; +} + + +static ESError ES_ImportTitleInit(const void* tmd, u32 tmdSize, + const void* certList, u32 certSizeInBytes, + const void* crlList, u32 crlSizeInBytes, + ESTransferType source, int safeUpdate) +{ +#pragma unused(certList, certSizeInBytes, crlList, crlSizeInBytes, safeUpdate) + + ESError rv = ES_ERR_OK; + char tmppath[FS_ENTRY_LONGNAME_MAX]; + + u32 size; +#ifdef VERBOSE_MODE + ESi_DumpCert(certList); + ESi_DumpTMD((ESTitleMeta*)tmd); +#endif + /*if ( ((u32)tmd & CACHE_LINE_MASK) || + ((u32)certList & CACHE_LINE_MASK) || + ((u32)crlList & CACHE_LINE_MASK) ) { + rv = ES_ERR_INVALID; + goto out; + }*/ +#if 0 + if (!ESi_Initialized) + { + rv = ES_ERR_INVALID; + goto out; + } +#endif + + switch (source) + { + case ES_TRANSFER_SERVER: + if (tmd==NULL || tmdSize==0 || certList==NULL || certSizeInBytes==0) + { + rv = ES_ERR_INVALID; + goto out; + } + break; + default: + rv = ES_ERR_UNSUPPORTED_TRANSFER_SOURCE; + goto out; + break; + } + + (void)ES_GetTmdSize((void *)tmd, &size); + if (tmdSize != size) + { + rv = ES_ERR_INVALID; + goto out; + } + ESi_GetTmpPath(tmppath); + if (!ESi_CreateFile(tmppath, tmd, (s32)size)) + { + rv = ES_ERR_FILE_WRITE_FAILED; + } + out: + PRINT_RESULT(rv); + return rv; +} + + +static void ESi_GetImportPath(char* path, ESTitleId titleId, const char* file) +{ + char titleStr[32]; + char titleIdH[16]; + char titleIdL[16]; + + // titleID取得してHとLに分解 + (void)STD_TSPrintf(titleStr, "%016llx", titleId); + (void)STD_CopyLStringZeroFill(titleIdH, titleStr, 9); // (n - 1) 文字コピーします。 + (void)STD_CopyLStringZeroFill(titleIdL, titleStr + 8, 9); // (n - 1) 文字コピーします。 + + (void)STD_TSPrintf(path, "%s/%s/%s/content/%s", + BASE_IMPORT_DIR, titleIdH, titleIdL, file); +} + + +static FSFile ContentFile[1]; +#define DUMMY_FILE_DESC 1 + +static s32 ES_ImportContentBegin(ESTitleId titleId, ESContentId cid) +{ + ESError rv = ES_ERR_OK; + + char cidStr[32]; + char tmppath[FS_ENTRY_LONGNAME_MAX]; +#if 0 + if (!ESi_Initialized) + { + rv = ES_ERR_INVALID; + goto out; + } +#endif + (void)STD_TSPrintf(cidStr, CID_FORMAT, cid); + ESi_GetImportPath(tmppath, titleId, cidStr); + + FS_InitFile(ContentFile); + if (FS_OpenFileEx(ContentFile, tmppath, FS_PERMIT_W)) + { + (void)FS_CloseFile(ContentFile); + if (!FS_DeleteFile(tmppath)) + { // ファイルを削除します。 + ReportLastErrorPath(tmppath); + OS_TPrintf("FS_DeleteFile(%s) failed.", tmppath); + return ES_ERR_FILE_OPEN_FAILED; + } + } + + if (!ESi_CreateFile(tmppath, NULL, 0)) + { + ReportLastErrorPath(tmppath); + OS_TPrintf("FS_CreateFile(%s) failed.", tmppath); + return ES_ERR_FILE_OPEN_FAILED; + } + + if (!FS_OpenFileEx(ContentFile, tmppath, FS_PERMIT_W)) + { + ReportLastErrorPath(tmppath); + OS_TPrintf("FS_OpenFileEx(%s) failed.", tmppath); + return ES_ERR_FILE_OPEN_FAILED; + } + +out: + // 暫定的にFSFile構造体のポインタを返す + return DUMMY_FILE_DESC; +} + +static ESError ES_ImportContentData(s32 fd, const void* inBuf, u32 inBufSize) +{ + ESError rv = ES_ERR_OK; + + if (fd<0 || inBuf==NULL || inBufSize==0) + { + rv = ES_ERR_INVALID; + goto out; + } +#if 0 + if (!ESi_Initialized) + { + rv = ES_ERR_INVALID; + goto out; + } +#endif + if (FS_WriteFile(ContentFile, inBuf, (s32)inBufSize) < 0) + { + OS_TPrintf("FS_WritFile() failed."); + rv = ES_ERR_FILE_WRITE_FAILED; + } + +out: + return rv; +} + +/*---------------------------------------------------------------------------* + Name: ES_ImportContentEnd + + Description: The ES_ImportContentEnd function validates the content data + written with the hash in the TMD. If the data is valid, + it commits the data to Flash and closes the file. + + Arguments: None. + + Returns: ESError + *---------------------------------------------------------------------------*/ +static ESError ES_ImportContentEnd(s32 fd) +{ +#pragma unused(fd) + ESError rv = ES_ERR_OK; +#if 0 + if (fd < 0 || !ESi_Initialized) + { + rv = ES_ERR_INVALID; + goto out; + } +#endif + (void)FS_CloseFile(ContentFile); +out: + return rv; +} + + +static ESError ES_ImportTitleDone(void) +{ + ESError rv = ES_ERR_OK; + char srcpath[FS_ENTRY_LONGNAME_MAX]; + char dstpath[FS_ENTRY_LONGNAME_MAX]; + + ESTitleId titleId; + s32 i, numContents; + const ESContentMeta* content; + ESContentId cid; + BOOL isOK; + +#if 0 + if (!ESi_Initialized) + { + rv = ES_ERR_INVALID; + goto out; + } +#endif + + ESi_GetTmpPath(srcpath); + isOK = ESi_ReadFile(srcpath, &TmdBuf, sizeof(TmdBuf)); + if (!isOK) + { // /tmp/title.tmdがない場合、エラーとすべきか不明 + goto out; + } + + titleId = MI_BEToH64(TmdBuf.head.titleId); + ESi_GetTitlePath(dstpath, titleId, TMD_FILE); + + if (!ESi_RenameFile(srcpath, dstpath)) + { + rv = ES_ERR_FILE_OPEN_FAILED; + goto out; + } + + numContents = MI_BEToH16(TmdBuf.head.numContents); + for (i = 0; i < numContents; i++) + { + char cidStr[32]; + + content = &TmdBuf.contents[i]; + cid = MI_BEToH32(content->cid); + + (void)STD_TSPrintf(cidStr, CID_FORMAT, cid); + + ESi_GetImportPath(srcpath, titleId, cidStr); + ESi_GetTitlePath(dstpath, titleId, cidStr); + + if (!ESi_RenameFile(srcpath, dstpath)) + { + rv = ES_ERR_FILE_OPEN_FAILED; + goto out; + } + } + +out: + return rv; +} + + +/* *********************************** */ + + +#define NAM_PUBLIC_SAVE_FILE_NAME "public.sav" +#define NAM_PRIVATE_SAVE_FILE_NAME "private.sav" +#define NAM_SUB_BANNER_FILE_NAME "banner.sav" +#define NAM_SUPPORT_BANNER_FILE_NAME "supbnr.sav" +// パス +#define NAM_ARCHIVE_NAND "nand" +#define NAM_NAND_ROOT NAM_ARCHIVE_NAND ":/" + +#define NAM_SHARED2_FILE_PATH NAM_NAND_ROOT "shared2/%04X" +#define NAM_TICKET_FILE_PATH NAM_NAND_ROOT "ticket/%08x/%08x.tik" +#define NAM_TITLE_ROOT_PATH NAM_NAND_ROOT "title/%08x/%08x" + +#define NAM_CONTENT_DIR_PATH NAM_TITLE_ROOT_PATH "/content" +#define NAM_DATA_DIR_PATH NAM_TITLE_ROOT_PATH "/data" + +#define NAM_TMD_FILE_PATH NAM_CONTENT_DIR_PATH "/title.tmd" +#define NAM_CONTENT_FILE_PATH NAM_CONTENT_DIR_PATH "/%08x.app" + + +static s32 NAMi_GetTitleSaveFilePath(char* savePublic, char* savePrivate, NAMTitleId titleId) +{ + ESError result; + char dataDirPath[FS_ENTRY_LONGNAME_MAX]; + + SDK_POINTER_OR_NULL_ASSERT(savePublic); + SDK_POINTER_OR_NULL_ASSERT(savePrivate); + + // ES_GetDataDir は第2引数に必ず 256 byte 書き込むので別バッファを使用する + result = ES_GetDataDir(titleId, dataDirPath); + PRINT_RESULT(result); + if( result == ES_ERR_OK ) + { + SDK_ASSERT( dataDirPath[STD_GetStringLength(dataDirPath) - 1] != '/' ); + + if( savePublic != NULL ) + { + (void)STD_TSNPrintf(savePublic, NAM_PATH_LEN, "%s/%s", dataDirPath, NAM_PUBLIC_SAVE_FILE_NAME); + } + if( savePrivate != NULL ) + { + (void)STD_TSNPrintf(savePrivate, NAM_PATH_LEN, "%s/%s", dataDirPath, NAM_PRIVATE_SAVE_FILE_NAME); + } + } + + return result; +} + + + + + +static s32 NAMi_GetShared2FilePath(char* path, u16 index) +{ + (void)STD_TSNPrintf(path, NAM_PATH_LEN, NAM_SHARED2_FILE_PATH, index); + + return NAM_OK; +} + + +static s32 NAMi_GetTitleSubBannerFilePath(char* banner, NAMTitleId titleId) +{ + ESError result; + char dataDirPath[FS_ENTRY_LONGNAME_MAX]; + + SDK_POINTER_ASSERT(banner); + + // ES_GetDataDir は第2引数に必ず 256 byte 書き込むので別バッファを使用する + result = ES_GetDataDir(titleId, dataDirPath); + PRINT_RESULT(result); + if( result == ES_ERR_OK ) + { + SDK_ASSERT( dataDirPath[STD_GetStringLength(dataDirPath) - 1] != '/' ); + (void)STD_TSNPrintf(banner, NAM_PATH_LEN, "%s/%s", dataDirPath, NAM_SUB_BANNER_FILE_NAME); + } + + return result; +} + + + + + + + +/* ************************************* */ + + + +typedef s32 (*NAMiTadFunc)(FSFile* pTadFile, void* arg); + + +#define TAD_ALIGN 64 // Please load tads to this alignment in memory + +typedef struct NAMiTADHeader +{ + u32 hdrSize; // Size of TADHeader1 96 + u8 tadType[2]; + u16 tadVersion; // TAD_VERSION_1 + u32 certSize; + u32 crlSize; + u32 ticketSize; + u32 tmdSize; + u32 contentSize; + u32 metaSize; + +} NAMiTADHeader; + +#define NAM_TAD_SIZE_ADJUST_INITLIB 43071 +#define NAM_TAD_SIZE_ADJUST_IMPORTTICKET 68624 +#define NAM_TAD_SIZE_ADJUST_IMPORTTITLEINIT 127238 +#define NAM_TAD_SIZE_ADJUST_IMPORTTITLEDONE 16069 +#define NAM_TAD_SIZE_ADJUST_SUM ( NAM_TAD_SIZE_ADJUST_INITLIB \ + + NAM_TAD_SIZE_ADJUST_IMPORTTICKET \ + + NAM_TAD_SIZE_ADJUST_IMPORTTITLEINIT \ + + NAM_TAD_SIZE_ADJUST_IMPORTTITLEDONE ) + +#define NAM_ARCHIVE_OTHER_PUB "otherPub" +#define NAM_ARCHIVE_OTHER_PRV "otherPrv" +#define NAM_ARCHIVE_SHARE "share" + + +extern FSFATFSArchiveWork sArchiveWork ATTRIBUTE_ALIGN(32); + + +//---- tad 構成情報の要素 +typedef struct NAMiTadParams +{ + u32 cert; + u32 crl; + u32 ticket; + u32 tmd; + u32 content; + u32 meta; +} +NAMiTadParams; + +//---- tad 構成情報 +typedef struct NAMiTadInfo +{ + NAMiTadParams sizes; // 各領域のサイズ + NAMiTadParams offsets; // ファイル先頭から各領域へのオフセット +} +NAMiTadInfo; + +//---- tad のコンテンツインポート時に使用する情報 +typedef struct NAMiTadContentInfo +{ + ESContentId id; // コンテンツ ID + u32 index; // コンテンツ番号 + u32 size; // コンテンツサイズ + u32 offset; // コンテンツ領域先頭から各コンテンツへのオフセット +} +NAMiTadContentInfo; + +//---- tad のインポート時に使用する情報 +typedef struct NAMiTadImportContext +{ + void* cert; // tad から読み込んだ cert + void* crl; // tad から読み込んだ crl + ESTitleId titleId; // Title ID + u32 publicSaveSize; // バックアップ可能セーブデータサイズ + u32 privateSaveSize; // バックアップ禁止セーブデータサイズ + BOOL bCreateBanner; // バナーファイルを作成する + u32 numContents; // コンテンツ数 + NAMiTadContentInfo* pContentInfo; // コンテンツインポート情報へのポインタ。numContents ぶんのサイズがある +} +NAMiTadImportContext; + +static BOOL IsValidTadHeader(NAMiTadInfo* pInfo, const NAMiTADHeader* pHeader, u32 tadFileSize) +{ + u32 sizeCheck; + + //---- ヘッダサイズの確認 + if( NAMi_EndianU32(pHeader->hdrSize) != sizeof(*pHeader) ) + { + OS_TPrintf("NAM: tad header check failed (%d != %d)", NAMi_EndianU32(pHeader->hdrSize), sizeof(*pHeader) ); + return FALSE; + } + + //---- サイズ/オフセットの取得 + pInfo->sizes.cert = NAMi_EndianU32(pHeader->certSize); + pInfo->sizes.crl = NAMi_EndianU32(pHeader->crlSize); + pInfo->sizes.ticket = NAMi_EndianU32(pHeader->ticketSize); + pInfo->sizes.tmd = NAMi_EndianU32(pHeader->tmdSize); + pInfo->sizes.content = NAMi_EndianU32(pHeader->contentSize); + pInfo->sizes.meta = NAMi_EndianU32(pHeader->metaSize); + + pInfo->offsets.cert = MATH_ROUNDUP(sizeof(NAMiTADHeader), TAD_ALIGN); + pInfo->offsets.crl = pInfo->offsets.cert + MATH_ROUNDUP(pInfo->sizes.cert, TAD_ALIGN); + pInfo->offsets.ticket = pInfo->offsets.crl + MATH_ROUNDUP(pInfo->sizes.crl, TAD_ALIGN); + pInfo->offsets.tmd = pInfo->offsets.ticket + MATH_ROUNDUP(pInfo->sizes.ticket, TAD_ALIGN); + pInfo->offsets.content = pInfo->offsets.tmd + MATH_ROUNDUP(pInfo->sizes.tmd, TAD_ALIGN); + pInfo->offsets.meta = pInfo->offsets.content + MATH_ROUNDUP(pInfo->sizes.content, TAD_ALIGN); + sizeCheck = pInfo->offsets.meta + MATH_ROUNDUP(pInfo->sizes.meta, TAD_ALIGN); + + + //---- サイズ/オフセットの検証 + if( (pInfo->sizes.cert == 0) +// || (pInfo->sizes.crl == 0) // crl は 0 でもよい + || (pInfo->sizes.ticket == 0) + || (pInfo->sizes.tmd == 0) + || (pInfo->sizes.content == 0) +// || (pInfo->sizes.meta == 0) // meta は 0 でもよい + || (pInfo->offsets.cert >= pInfo->offsets.crl) + || (pInfo->offsets.crl > pInfo->offsets.ticket) // crl は 0 も受け付けるので >= でない + || (pInfo->offsets.ticket >= pInfo->offsets.tmd) + || (pInfo->offsets.tmd >= pInfo->offsets.content) + || (pInfo->offsets.content >= pInfo->offsets.meta) + || (pInfo->offsets.meta > sizeCheck) // meta は 0 も受け付けるので >= でない + || (sizeCheck != tadFileSize) ) + { + OS_TPrintf("NAM: tad header check failed"); + OS_TPrintf(" size.cert: %8d (0x%08X)", pInfo->sizes.cert, pInfo->sizes.cert); + OS_TPrintf(" size.crl: %8d (0x%08X)", pInfo->sizes.crl, pInfo->sizes.crl); + OS_TPrintf(" size.ticket: %8d (0x%08X)", pInfo->sizes.ticket, pInfo->sizes.ticket); + OS_TPrintf(" size.tmd: %8d (0x%08X)", pInfo->sizes.tmd, pInfo->sizes.tmd); + OS_TPrintf(" size.content: %8d (0x%08X)", pInfo->sizes.content, pInfo->sizes.content); + OS_TPrintf(" size.meta: %8d (0x%08X)", pInfo->sizes.meta, pInfo->sizes.meta); + OS_TPrintf(" offsets.cert: %8d (0x%08X)", pInfo->offsets.cert, pInfo->offsets.cert); + OS_TPrintf(" offsets.crl: %8d (0x%08X)", pInfo->offsets.crl, pInfo->offsets.crl); + OS_TPrintf(" offsets.ticket: %8d (0x%08X)", pInfo->offsets.ticket, pInfo->offsets.ticket); + OS_TPrintf(" offsets.tmd: %8d (0x%08X)", pInfo->offsets.tmd, pInfo->offsets.tmd); + OS_TPrintf(" offsets.content: %8d (0x%08X)", pInfo->offsets.content, pInfo->offsets.content); + OS_TPrintf(" offsets.meta: %8d (0x%08X)", pInfo->offsets.meta, pInfo->offsets.meta); + OS_TPrintf(" sizeCheck: %8d (0x%08X)", sizeCheck, sizeCheck); + OS_TPrintf(" fileSize: %8d (0x%08X)", tadFileSize, tadFileSize); + return FALSE; + } + + return TRUE; +} + +static s32 LoadCertCrl(NAMiTadImportContext* pContext, FSFile* pTadFile, const NAMiTadInfo* pInfo) +{ + s32 result1; + s32 result2; + void* cert = NULL; + void* crl = NULL; + + result1 = NAMi_Load(pTadFile, &cert, pInfo->sizes.cert, pInfo->offsets.cert, FALSE); + NAMi_Work.currentSize += pInfo->sizes.cert; + result2 = NAMi_Load(pTadFile, &crl, pInfo->sizes.crl, pInfo->offsets.crl, FALSE); + NAMi_Work.currentSize += pInfo->sizes.crl; + + if( (result1 != NAM_OK) || (result2 != NAM_OK) ) + { + NAMi_Free(crl); + NAMi_Free(cert); + return (result1 != NAM_OK) ? result1: result2; + } + + pContext->cert = cert; + pContext->crl = crl; + + return NAM_OK; +} + + +static void UnloadCertCrl(NAMiTadImportContext* pContext) +{ + NAMi_Free(pContext->crl); + NAMi_Free(pContext->cert); + + pContext->cert = NULL; + pContext->crl = NULL; +} + +static s32 SetupContentInfo(NAMiTadImportContext* pContext, const ESTitleMeta* tmd) +{ + u32 i; + u32 offset; + NAMiTadContentInfo* pContentInfo = NULL; + const u16 numContents = NAMi_EndianU16(tmd->head.numContents); + + //---- コンテンツごとに NAMiTadContentInfo を確保し情報を格納します。 + + pContentInfo = NAMi_Alloc(sizeof(NAMiTadContentInfo) * numContents); + + if( pContentInfo == NULL ) + { + OS_TPrintf("NAM::SetupContentInfo NAM_NO_MEMORY (%d)", sizeof(NAMiTadContentInfo) * numContents); + NAMi_Free(pContentInfo); + return NAM_NO_MEMORY; + } + + offset = 0; + for( i = 0; i < numContents; ++i ) + { + const ESContentMeta* pSrc = &tmd->contents[i]; + NAMiTadContentInfo* pDst = &pContentInfo[i]; + u64 contentSize = NAMi_EndianU64(pSrc->size); + u32 contentIndex = NAMi_EndianU16(pSrc->index); + + //---- tmd 中の ESContentMeta の並びと contentIndex は一致しているものとします。 + if( contentIndex != i ) + { + OS_TPrintf("NAM::SetupContentInfo NAM_INVALID_CONTENT_INDEX: (%d != %d)", i, contentIndex); + NAMi_Free(pContentInfo); + return NAM_INVALID_CONTENT_INDEX; + } + //---- 32bit を超えるサイズのコンテンツはエラーとします。 + if( contentSize >= (1ull << 32) ) + { + OS_TPrintf("NAM::SetupContentInfo NAM_TOO_LARGE_CONTENT_SIZE: %016llX %lld", contentSize, contentSize); + NAMi_Free(pContentInfo); + return NAM_TOO_LARGE_CONTENT_SIZE; + } + + pDst->id = NAMi_EndianU32(pSrc->cid); + pDst->index = contentIndex; + pDst->size = (u32)contentSize; + pDst->offset = offset; + + offset += MATH_ROUNDUP(pDst->size, 64); + } + + { + NAMiTmdReserved tmdReserved; + + // アライメントを気にしなくて良いように一旦コピーする + MI_CpuCopy8(tmd->head.reserved, &tmdReserved, sizeof(tmdReserved)); + + pContext->titleId = NAMi_EndianU64(tmd->head.titleId); + pContext->publicSaveSize = tmdReserved.publicSaveSize; + pContext->privateSaveSize = tmdReserved.privateSaveSize; + pContext->bCreateBanner = ((tmdReserved.flags & NAM_TMD_FLAG_NAND_BANNER) != 0); + pContext->numContents = numContents; + pContext->pContentInfo = pContentInfo; + } + + return NAM_OK; +} + +static void UnloadContentInfo(NAMiTadImportContext* pContext) +{ + NAMi_Free(pContext->pContentInfo); + pContext->pContentInfo = NULL; +} + + + +static s32 ReadTadHeader(FSFile* pTadFile, NAMiTadInfo* pInfo) +{ + s32 result; + u32 fileSize; + NAMiTADHeader* pHeader; + BOOL isValid; + + fileSize = FS_GetLength(pTadFile); + if( fileSize < sizeof(*pHeader) ) + { + OS_TPrintf("NAM::ReadTadHeader NAM_TOO_SMALL_FILE_USER (%d)", fileSize); + return NAM_TOO_SMALL_FILE_USER; + } + + // ヘッダを読む + result = NAMi_Load(pTadFile, (void**)&pHeader, sizeof(*pHeader), 0, FALSE); + PRINT_RESULT(result); + if( result != NAM_OK ) + { + return result; + } + + isValid = IsValidTadHeader(pInfo, pHeader, fileSize); + NAMi_Free(pHeader); + + if( ! isValid ) + { + return NAM_INVALID_TAD_FORMAT; + } + + return NAM_OK; +} + + + +static s32 ImportTicket(FSFile* pTadFile, const NAMiTadInfo* pInfo, const NAMiTadImportContext* pContext) +{ + s32 result; + void* ticket = NULL; + + result = NAMi_Load(pTadFile, &ticket, pInfo->sizes.ticket, pInfo->offsets.ticket, FALSE); + PRINT_RESULT(result); + NAMi_Work.currentSize += pInfo->sizes.ticket; + + if( result != NAM_OK ) + { + return result; + } + + DC_FlushRange( ticket, pInfo->sizes.ticket ); + result = ES_ImportTicket( ticket, + pContext->cert, pInfo->sizes.cert, + pContext->crl, pInfo->sizes.crl, + ES_TRANSFER_SERVER ); + PRINT_RESULT(result); + NAMi_Work.currentSize += NAM_TAD_SIZE_ADJUST_IMPORTTICKET; + NAMi_Free(ticket); + + return result; +} + + +static s32 ImportTitleInit(FSFile* pTadFile, const NAMiTadInfo* pInfo, NAMiTadImportContext* pContext) +{ + s32 result; + void* tmd = NULL; + + result = NAMi_Load(pTadFile, &tmd, pInfo->sizes.tmd, pInfo->offsets.tmd, FALSE); + PRINT_RESULT(result); + NAMi_Work.currentSize += pInfo->sizes.tmd; + + if( result != NAM_OK ) + { + return result; + } + + //---- コンテンツインポート用の情報をキャッシュしておきます + result = SetupContentInfo(pContext, (ESTitleMeta*)tmd); + PRINT_RESULT(result); + + if( result != NAM_OK ) + { + NAMi_Free(tmd); + return result; + } + + DC_FlushRange( tmd, pInfo->sizes.tmd ); + result = ES_ImportTitleInit( tmd, pInfo->sizes.tmd, + pContext->cert, pInfo->sizes.cert, + pContext->crl, pInfo->sizes.crl, + ES_TRANSFER_SERVER, + 1 ); + PRINT_RESULT(result); + NAMi_Work.currentSize += NAM_TAD_SIZE_ADJUST_IMPORTTITLEINIT; + NAMi_Free(tmd); + + return result; +} + + +static s32 ImportTitleFinish(NAMiTadImportContext* pContext, s32 result) +{ + UnloadContentInfo(pContext); + + if( result == NAM_OK ) + { + result = ES_ImportTitleDone(); + PRINT_RESULT(result); + NAMi_Work.currentSize += NAM_TAD_SIZE_ADJUST_IMPORTTITLEDONE; + } + else + { + s32 check = ES_ImportTitleCancel();; +#pragma unused(check) + SDK_WARNING( check == ES_ERR_OK, "ES_ImportTitleCancel failed %d", check ); + } + + return result; +} + + + +static s32 ImportContent(FSFile* pTadFile, const NAMiTadInfo* pInfo, const NAMiTadImportContext* pContext, int idx) +{ + s32 fd; + const NAMiTadContentInfo* pContentInfo; + void* readBuffer; + u32 processedSize; + BOOL bSuccess; + s32 result; + s32 result2; + u32 offset; + + pContentInfo = &pContext->pContentInfo[idx]; + + offset = pInfo->offsets.content + pContentInfo->offset; + bSuccess = FS_SeekFile(pTadFile, (s32)offset, FS_SEEK_SET); + + if( ! bSuccess ) + { + OS_TPrintf("NAM::ImportContent NAM_SEEK_FILE_FAILED_USER (%d)", offset); + return NAM_SEEK_FILE_FAILED_USER; + } + + + readBuffer = NAMi_Alloc(NAM_STREAMING_BUFFER_SIZE); + + if( readBuffer == NULL ) + { + OS_TPrintf("NAM::ImportContent NAM_NO_MEMORY (%d)", NAM_STREAMING_BUFFER_SIZE); + return NAM_NO_MEMORY; + } + + //---- コンテンツインポート前処理 + fd = ES_ImportContentBegin(pContext->titleId, pContentInfo->id); + + + if( fd < 0 ) + { + NAMi_Free(readBuffer); + OS_TPrintf("%s: %s %5d\n", __FILE__, __FUNCTION__, __LINE__ ); + return fd; + } + + + processedSize = 0; + + //---- コンテンツインポート処理 + while( processedSize < pContentInfo->size ) + { + u32 nextSize = MATH_MIN(NAM_STREAMING_BUFFER_SIZE, pContentInfo->size - processedSize); + u32 readSize; + + DC_InvalidateRange(readBuffer, NAM_STREAMING_BUFFER_SIZE); + readSize = (u32)FS_ReadFile(pTadFile, readBuffer, (s32)nextSize); + + if( readSize != nextSize ) + { + result = NAM_READ_FILE_FAILED_USER; + PRINT_RESULT(result); + break; + } + + DC_FlushRange( readBuffer, readSize ); + + result = ES_ImportContentData(fd, readBuffer, readSize); + PRINT_RESULT(result); + NAMi_Work.currentSize += readSize; + + if( result != ES_ERR_OK ) + { + break; + } + + processedSize += readSize; + } + +OS_TPrintf("%s: %s %5d\n", __FILE__, __FUNCTION__, __LINE__ ); + + //---- コンテンツインポート後処理 + result2 = ES_ImportContentEnd(fd); + NAMi_Free(readBuffer); + + return (result == ES_ERR_OK) ? result2: result; +} + + +static s32 CheckFileSize(const char* path, u32 size) +{ + FSFileInfo info; + FSResult fsResult; + + fsResult = FS_GetFileInfo(path, &info); + + if( fsResult != FS_RESULT_SUCCESS ) + { + return NAM_GET_FILE_INFO_FAILED; + } + + return (info.filesize == size) ? NAM_OK: NAM_SIZE_MISMATCH; +} + +static s32 CheckFatFile(ESTitleId titleId, const char* archName) +{ + FSResult fsResult; + s32 result; + + fsResult = FSi_MountSpecialArchive(titleId, archName, &sArchiveWork); + + if( fsResult == FS_RESULT_SUCCESS ) + { + char tmpArchPath[OS_MOUNT_ARCHIVE_NAME_LEN + 3]; // 3 = ":/\0" + BOOL bSuccess; + FSFile dir; + + (void)STD_TSNPrintf(tmpArchPath, sizeof(tmpArchPath), "%s:/", archName); + + FS_InitFile(&dir); + bSuccess = FS_OpenDirectory(&dir, tmpArchPath, FS_FILEMODE_R); + + if( bSuccess ) + { + (void)FS_CloseDirectory(&dir); + result = NAM_OK; + } + else + { + result = NAM_OPEN_DIRECTORY_FAILED; + } + + // アンマウント + (void)FSi_MountSpecialArchive(titleId, NULL, &sArchiveWork); + } + else + { + result = NAM_MOUNT_DRIVE_FAILED; + PRINT_RESULT(result); + } + + return result; +} + +static s32 ConvertCheckResult(s32 result, BOOL bCreate) +{ + if( bCreate ) + { + if( (result == NAM_SIZE_MISMATCH) + || (result == NAM_GET_FILE_INFO_FAILED) ) + { + // エラー or サイズが違うなら要 Setup + return NAM_REQUIRE_SETUP; + } + if( result != NAM_OK ) + { + // 未知のエラー + OS_TPrintf("ConvertCheckResult: unknown result %d\n", result); + return result; + } + } + else + { + if( result != NAM_GET_FILE_INFO_FAILED ) + { + // エラー=ファイルが存在しない でなければ要 Setup + return NAM_REQUIRE_SETUP; + } + } + + return NAM_OK; +} + +static s32 CheckSaveDataFile(ESTitleId titleId, BOOL bPrivate, u32 size) +{ + char path[NAM_PATH_LEN]; + s32 result; + + if( bPrivate ) + { + result = NAMi_GetTitleSaveFilePath(NULL, path, titleId); + PRINT_RESULT(result); + } + else + { + result = NAMi_GetTitleSaveFilePath(path, NULL, titleId); + PRINT_RESULT(result); + } + + if( result != NAM_OK ) + { + return result; + } + + result = ConvertCheckResult(CheckFileSize(path, size), (size > 0)); + if( result != NAM_OK ) + { + return result; + } + + if( size > 0 ) + { + result = CheckFatFile(titleId, (bPrivate ? NAM_ARCHIVE_OTHER_PRV: NAM_ARCHIVE_OTHER_PUB)); + if( result != NAM_OK ) + { + result = NAM_REQUIRE_SETUP; + } + } + + return result; +} + +static s32 CheckShared2(u16 index, u32 size) +{ + char path[NAM_PATH_LEN]; + s32 result; + + // パス生成 + result = NAMi_GetShared2FilePath(path, index); + PRINT_RESULT(result); + + if( result != NAM_OK ) + { + return result; + } + + result = CheckFileSize(path, size); + + // ファイルが存在しないなら NG + if( result == NAM_GET_FILE_INFO_FAILED ) + { + return result; + } + + // FAT in File かどうかをチェック + result = CheckFatFile(index, NAM_ARCHIVE_SHARE); + + if( result != NAM_OK ) + { + return result; + } + + return result; +} + + +static s32 CheckSubBannerFile(ESTitleId titleId, BOOL bCreate) +{ + char path[NAM_PATH_LEN]; + const u32 size = (u32)(bCreate ? NAM_SUB_BANNER_FILE_SIZE: 0); + s32 result; + + result = NAMi_GetTitleSubBannerFilePath(path, titleId); + PRINT_RESULT(result); + + if( result != NAM_OK ) + { + return result; + } + + return ConvertCheckResult(CheckFileSize(path, size), bCreate); +} + + +static s32 NAMi_CheckTitleDataFile( ESTitleId titleId, + u32 targetMask, + u32 publicSize, + u32 privateSize, + BOOL bCreateBanner ) +{ + s32 result; + + // public セーブデータファイルをチェック + if( (targetMask & NAM_DATA_FILE_PUBLIC) != 0 ) + { + result = CheckSaveDataFile(titleId, FALSE, publicSize); + PRINT_RESULT(result); + + if( result != NAM_OK ) + { + return result; + } + } + + // private セーブデータファイルをチェック + if( (targetMask & NAM_DATA_FILE_PRIVATE) != 0 ) + { + result = CheckSaveDataFile(titleId, TRUE, privateSize); + PRINT_RESULT(result); + + if( result != NAM_OK ) + { + return result; + } + } + + // NAND バナーファイルをチェック + if( (targetMask & NAM_DATA_FILE_BANNER) != 0 ) + { + result = CheckSubBannerFile(titleId, bCreateBanner); + PRINT_RESULT(result); + + if( result != NAM_OK ) + { + return result; + } + } + return NAM_OK; +} + + +static s32 FormatFatFile(ESTitleId titleId, const char* archName) +{ + FSResult fsResult; + s32 result; + + fsResult = FSi_MountSpecialArchive(titleId, archName, &sArchiveWork); + + if( fsResult == FS_RESULT_SUCCESS ) + { + char tmpArchPath[OS_MOUNT_ARCHIVE_NAME_LEN + 3]; // 3 = ":/\0" + BOOL bSuccess; + + (void)STD_TSNPrintf(tmpArchPath, sizeof(tmpArchPath), "%s:/", archName); + + bSuccess = FATFSi_FormatMedia(tmpArchPath); + + if( bSuccess ) + { + bSuccess = FATFS_FormatDrive(tmpArchPath); + result = bSuccess ? NAM_OK: NAM_FORMAT_DRIVE_FAILED; + PRINT_RESULT(result); + } + else + { + result = NAM_FORMAT_MEDIA_FAILED; + PRINT_RESULT(result); + } + + // アンマウント + (void)FSi_MountSpecialArchive(titleId, NULL, &sArchiveWork); + } + else + { + result = NAM_MOUNT_DRIVE_FAILED; + PRINT_RESULT(result); + } + + return result; +} + + +static s32 CreateSizedFile(const char* path, u32 size) +{ + s32 result; + + result = CheckFileSize(path, size); + PRINT_RESULT(result); + + switch( result ) + { + case NAM_OK: + // ファイルサイズが一致するなら処理完了 + return NAM_OK; + + case NAM_SIZE_MISMATCH: + // ファイルが存在するなら次へ + break; + + case NAM_GET_FILE_INFO_FAILED: + { + // エラーならファイルが存在しないとみなして新規に作成 + BOOL bSuccess; + + bSuccess = FS_CreateFileAuto(path, (FS_PERMIT_R|FS_PERMIT_W)); + + if( ! bSuccess ) + { + return NAM_CREATE_FILE_FAILED_SYSTEM; + } + } + break; + + default: + // 未知のエラー + return result; + } + + // ファイルサイズを変更 + { + FSFile f; + BOOL bSuccess; + FSResult fsResult; + + FS_InitFile(&f); + + bSuccess = FS_OpenFileEx(&f, path, (FS_FILEMODE_R|FS_FILEMODE_W)); + + if( ! bSuccess ) + { + (void)FS_DeleteFile(path); + return NAM_OPEN_FILE_FAILED_SYSTEM; + } + + fsResult = FS_SetFileLength(&f, size); + result = NAMi_CloseFile(&f, TRUE); + + if( fsResult != FS_RESULT_SUCCESS ) + { + (void)FS_DeleteFile(path); + return NAM_SET_FILE_LENGTH_FAILED_SYSTEM; + } + } + + return result; +} + +static s32 FillFileRandom(const char* path) +{ + u64 seed; + MATHRandContext32 rndctx; + u32* pBuffer; + s32 result; + AESResult aesResult; + + aesResult = AES_Rand(&seed, sizeof(seed)); + if( aesResult != AES_RESULT_SUCCESS ) + { + return NAM_RAND_FAILED; + } + MATH_InitRand32(&rndctx, seed); + + result = NAMi_Alloc2((void**)&pBuffer, NAM_STREAMING_BUFFER_SIZE); + if( result == NAM_OK ) + { + BOOL bSuccess; + FSFile f; + + FS_InitFile(&f); + + bSuccess = FS_OpenFileEx(&f, path, FS_FILEMODE_RWL); + if( bSuccess ) + { + s32 resultClose; + u32 fileSize; + u32 current; + + fileSize = FS_GetFileLength(&f); + + for( current = 0; current < fileSize; current += NAM_STREAMING_BUFFER_SIZE ) + { + const u32 nextSize = MATH_MIN(NAM_STREAMING_BUFFER_SIZE, fileSize - current); + const u32 nextU32 = MATH_DIVUP(nextSize, sizeof(u32)); + u32* p = pBuffer; + u32 i; + s32 writtenSize; + + for( i = 0; i < nextU32; ++i ) + { + *p++ = MATH_Rand32(&rndctx, 0); + } + + writtenSize = FS_WriteFile(&f, pBuffer, (s32)nextSize); + if( writtenSize != (s32)nextSize ) + { + result = NAM_WRITE_FILE_FAILED_SYSTEM; + break; + } + } + + resultClose = NAMi_CloseFile(&f, TRUE); + } + else + { + result = NAM_OPEN_FILE_FAILED_SYSTEM; + } + + NAMi_Free(pBuffer); + } + + return result; +} + +static inline s32 DeleteFile(const char* path) +{ + BOOL bSuccess; + bSuccess = FS_DeleteFile(path); + if( bSuccess ) + { + return NAM_OK; + } + else + { + if( FS_GetArchiveResultCode(path) == FS_RESULT_ALREADY_DONE ) + { + return NAM_OK; + } + else + { + return NAM_DELETE_FILE_FAILED; + } + } +} + + +static s32 UpdateSaveDataFileSecure(ESTitleId titleId, BOOL bPrivate, u32 size) +{ + char path[NAM_PATH_LEN]; + s32 result; + + if( bPrivate ) + { + result = NAMi_GetTitleSaveFilePath(NULL, path, titleId); + PRINT_RESULT(result); + } + else + { + result = NAMi_GetTitleSaveFilePath(path, NULL, titleId); + PRINT_RESULT(result); + } + + if( result != NAM_OK ) + { + return result; + } + + if( size > 0 ) + { + // ファイルを作成 + result = CreateSizedFile(path, size); + PRINT_RESULT(result); + + if( result != NAM_OK ) + { + return result; + } + + // ファイルをランダムクリア + result = FillFileRandom(path); + PRINT_RESULT(result); + + if( result != NAM_OK ) + { + return result; + } + + // ファイルをフォーマット + result = FormatFatFile(titleId, (bPrivate ? NAM_ARCHIVE_OTHER_PRV: NAM_ARCHIVE_OTHER_PUB)); + PRINT_RESULT(result); + + if( result != NAM_OK ) + { + (void)FS_DeleteFile(path); + return result; + } + } + else + { + return DeleteFile(path); + } + + + return NAM_OK; +} + +static s32 MakeSubBannerFillData(void* pBuffer) +{ + TWLSubBannerFile* pBanner; + u16 crc; + s32 result; + + { + AESResult aesResult; + + aesResult = AES_Rand(pBuffer, NAM_SUB_BANNER_FILE_SIZE); + if( aesResult != AES_RESULT_SUCCESS ) + { + return NAM_RAND_FAILED; + } + } + + pBanner = (TWLSubBannerFile*)pBuffer; + + result = NAMi_CalcSubBannerCRC(&crc, pBanner); + if( result != NAM_OK ) + { + return NAM_OK; + } + + if( pBanner->h.crc16_anime == 0 ) + { + pBanner->h.crc16_anime = 0xFFFF; + } + + pBanner->h.crc16_anime ^= crc; + + return NAM_OK; +} + +static s32 CreateSubBannerFile(const char* path) +{ + s32 result; + FSFile f; + void* pFillData; + + result = CreateSizedFile(path, NAM_SUB_BANNER_FILE_SIZE); + PRINT_RESULT(result); + + if( result != NAM_OK ) + { + return result; + } + + { + BOOL bSuccess; + s32 written; + + pFillData = NAMi_Alloc(NAM_SUB_BANNER_FILE_SIZE); + if( pFillData == NULL ) + { + result = NAM_NO_MEMORY; + PRINT_RESULT(result); + goto fail_on_alloc; + } + + result = MakeSubBannerFillData(pFillData); + if( result != NAM_OK ) + { + goto fail_on_open; + } + + FS_InitFile(&f); + + bSuccess = FS_OpenFileEx(&f, path, (FS_FILEMODE_R|FS_FILEMODE_W)); + if( ! bSuccess ) + { + result = NAM_OPEN_FILE_FAILED_SYSTEM; + PRINT_RESULT(result); + goto fail_on_open; + } + + written = FS_WriteFile(&f, pFillData, NAM_SUB_BANNER_FILE_SIZE); + if( written != NAM_SUB_BANNER_FILE_SIZE ) + { + result = NAM_WRITE_FILE_FAILED_SYSTEM; + PRINT_RESULT(result); + goto fail_on_write; + } + + result = NAMi_CloseFile(&f, TRUE); + if( result != NAM_OK ) + { + goto fail_on_open; + } + + NAMi_Free(pFillData); + } + + return NAM_OK; +//------------------------- +fail_on_write: + (void)FS_CloseFile(&f); +fail_on_open: + NAMi_Free(pFillData); +fail_on_alloc: + (void)FS_DeleteFile(path); + + return result; +} + +static s32 UpdateSubBannerFile(ESTitleId titleId, BOOL bCreate) +{ + char bannerPath[NAM_PATH_LEN]; + s32 result; + + result = NAMi_GetTitleSubBannerFilePath(bannerPath, titleId); + PRINT_RESULT(result); + + if( result != NAM_OK ) + { + return result; + } + + if( bCreate ) + { + return CreateSubBannerFile(bannerPath); + } + else + { + return DeleteFile(bannerPath); + } +} + + + +static s32 NAMi_SetupTitleDataFileSecure( ESTitleId titleId, + u32 targetMask, + u32 publicSize, + u32 privateSize, + BOOL bCreateBanner ) +{ + s32 result; + + // public セーブデータファイルを作成 + if( (targetMask & NAM_DATA_FILE_PUBLIC) != 0 ) + { + result = UpdateSaveDataFileSecure(titleId, FALSE, publicSize); + PRINT_RESULT(result); + + if( result != NAM_OK ) + { + return result; + } + } + + // private セーブデータファイルを作成 + if( (targetMask & NAM_DATA_FILE_PRIVATE) != 0 ) + { + result = UpdateSaveDataFileSecure(titleId, TRUE, privateSize); + PRINT_RESULT(result); + + if( result != NAM_OK ) + { + return result; + } + } + + // NAND バナーファイルを作成 + if( (targetMask & NAM_DATA_FILE_BANNER) != 0 ) + { + result = UpdateSubBannerFile(titleId, bCreateBanner); + PRINT_RESULT(result); + + if( result != NAM_OK ) + { + return result; + } + } + + return NAM_OK; +} + +static s32 CreateShared2Secure(u16 index, u32 size) +{ + char path[NAM_PATH_LEN]; + s32 result; + + // パス生成 + result = NAMi_GetShared2FilePath(path, index); + PRINT_RESULT(result); + + if( result != NAM_OK ) + { + return result; + } + + // ファイルを作成 + result = CreateSizedFile(path, size); + PRINT_RESULT(result); + + if( result != NAM_OK ) + { + return result; + } + + // ファイルをランダムクリア + result = FillFileRandom(path); + PRINT_RESULT(result); + + if( result != NAM_OK ) + { + return result; + } + + // ファイルをフォーマット + result = FormatFatFile(index, NAM_ARCHIVE_SHARE); + PRINT_RESULT(result); + + if( result != NAM_OK ) + { + (void)FS_DeleteFile(path); + return result; + } + return result; +} + + +static s32 NAMi_SetupShared2Secure(u16 index, u32 size) +{ + s32 result; + + // FS ブロックサイズより小さいなら何もしないで NAM_OK + if( size < 16 * 1024 ) + { + return NAM_OK; + } + + result = CheckShared2(index, size); + + if( result != NAM_OK ) + { + result = CreateShared2Secure(index, size); + } + + return result; +} + +#define NAM_SHARED2_NUM 6 + +typedef struct NAMShared2Param +{ + u32 sizes[NAM_SHARED2_NUM]; +} +NAMShared2Param; + + +static inline u32 ExtendShared2Size(u8 x) +{ + return (x == 0) ? 0: (u32)((x + 1) * 16 * 1024); +} + + +static s32 ReadShared2Param(NAMShared2Param* psp, NAMTitleId titleId) +{ + char path[NAM_PATH_LEN]; + s32 result; + + MI_CpuClear8(psp, sizeof(*psp)); + + result = NAMi_GetBootContentPath(path, titleId); + if( result == NAM_OK ) + { + FSFile f; + ROM_Header_Short* pHeader; + BOOL bSuccess; + + bSuccess = FS_OpenFileEx(&f, path, FS_FILEMODE_R); + if( bSuccess ) + { + s32 resultClose; + + result = NAMi_Load(&f, (void**)&pHeader, sizeof(ROM_Header_Short), 0, TRUE); + resultClose = NAMi_CloseFile(&f, TRUE); + + if( result == NAM_OK ) + { + if( pHeader->access_control.shared2_file ) + { + psp->sizes[0] = ExtendShared2Size(pHeader->shared2_file0_size); + psp->sizes[1] = ExtendShared2Size(pHeader->shared2_file1_size); + psp->sizes[2] = ExtendShared2Size(pHeader->shared2_file2_size); + psp->sizes[3] = ExtendShared2Size(pHeader->shared2_file3_size); + psp->sizes[4] = ExtendShared2Size(pHeader->shared2_file4_size); + psp->sizes[5] = ExtendShared2Size(pHeader->shared2_file5_size); + } + + NAMi_Free(pHeader); + result = resultClose; + } + } + else + { + result = NAM_OPEN_FILE_FAILED_SYSTEM; + } + } + + return result; +} + + +static s32 NAMi_SetupTitleShared2Secure(NAMTitleId titleId) +{ + s32 result = NAM_OK; + + if( NAM_IsExecTitle(titleId) ) + { + NAMShared2Param sp; + + // SRL から shared2 情報を取得 + result = ReadShared2Param(&sp, titleId); + if( result == NAM_OK ) + { + // shared2 ファイルを準備 + u16 i; + + for( i = 0; i < NAM_SHARED2_NUM; ++i ) + { + if( sp.sizes[i] > 0 ) + { + result = NAMi_SetupShared2Secure(i, sp.sizes[i]); + + if( result != NAM_OK ) + { + break; + } + } + } + } + } + + return result; +} + + + + + +static s32 ImportTad(FSFile* pTadFile, const NAMiTadInfo* pInfo) +{ + s32 result; + int idx; + NAMiTadImportContext tadContext; + + // cert と crl をメモリに読み込み + result = LoadCertCrl(&tadContext, pTadFile, pInfo); + PRINT_RESULT(result); + + if( result != NAM_OK ) + { + return result; + } + + // eTicket をインポート + result = ImportTicket(pTadFile, pInfo, &tadContext); + PRINT_RESULT(result); + + if( result != NAM_OK ) + { + UnloadCertCrl(&tadContext); + return result; + } + + // 本体のインポート準備 + result = ImportTitleInit(pTadFile, pInfo, &tadContext); + PRINT_RESULT(result); + + if( result == NAM_OK ) + { + // コンテンツのインポート + for( idx = 0; idx < tadContext.numContents; ++idx ) + { + result = ImportContent(pTadFile, pInfo, &tadContext, idx); + PRINT_RESULT(result); + + if( result != NAM_OK ) + { + break; + } + } + } + + // インポートの完了 + result = ImportTitleFinish(&tadContext, result); + PRINT_RESULT(result); + UnloadCertCrl(&tadContext); + + if( result != NAM_OK ) + { + return result; + } + + // セーブデータファイルのチェック + result = NAMi_CheckTitleDataFile( tadContext.titleId, + NAM_DATA_FILE_ALL, + tadContext.publicSaveSize, + tadContext.privateSaveSize, + tadContext.bCreateBanner ); + PRINT_RESULT(result); + + // Setup が必要なら行う + if( result == NAM_REQUIRE_SETUP ) + { + result = NAMi_SetupTitleDataFileSecure( tadContext.titleId, + NAM_DATA_FILE_ALL, + tadContext.publicSaveSize, + tadContext.privateSaveSize, + tadContext.bCreateBanner ); + PRINT_RESULT(result); + } + + // shared2 ファイルの準備 + if( result == NAM_OK ) + { + result = NAMi_SetupTitleShared2Secure(tadContext.titleId); + } + + if( result != NAM_OK ) + { + // 失敗したのならタイトルを削除 + (void)NAM_DeleteTitle(tadContext.titleId); + return result; + } + return result; +} + + + +static s32 my_NAM_ImportTadWithFile(FSFile* pTadFile) +{ + extern NAMiWork NAMi_Work; + s32 result; + NAMiTadInfo tadInfo; + + SDK_POINTER_ASSERT(pTadFile); + (void)FS_SeekFileToBegin(pTadFile); + + NAMi_Lock(); + + NAMi_Work.totalSize = 0; + NAMi_Work.currentSize = 0; + NAMi_Work.bRunning = TRUE; + + result = ReadTadHeader(pTadFile, &tadInfo); + PRINT_RESULT(result); + if( result == NAM_OK ) + { + NAMi_Work.totalSize = tadInfo.sizes.cert + + tadInfo.sizes.crl + + tadInfo.sizes.ticket + + tadInfo.sizes.tmd + + tadInfo.sizes.content + + tadInfo.sizes.meta + + NAM_TAD_SIZE_ADJUST_SUM; + + NAMi_Work.currentSize += NAM_TAD_SIZE_ADJUST_INITLIB; + result = ImportTad(pTadFile, &tadInfo); + PRINT_RESULT(result); + } + + NAMi_Unlock(); + + NAMi_Work.bRunning = FALSE; + + return result; +} + + + +static s32 FuncImportTad(FSFile* pTadFile, void* arg) +{ +#pragma unused(arg) + return my_NAM_ImportTadWithFile(pTadFile); +} + +static s32 TadFramework(const char* path, NAMiTadFunc pTadFunc, void* arg) +{ + FSFile tadFile; + BOOL bSuccess; + s32 result; + s32 resultClose; + + FS_InitFile(&tadFile); + + bSuccess = FS_OpenFile(&tadFile, path); + if( ! bSuccess ) + { + return NAM_OPEN_FILE_FAILED_USER; + } + + result = pTadFunc(&tadFile, arg); + PRINT_RESULT(result); + + resultClose = NAMi_CloseFile(&tadFile, FALSE); + PRINT_RESULT(resultClose); + + return (result == NAM_OK) ? resultClose: result; +} + +static s32 my_NAM_ImportTad(const char* path) +{ + return TadFramework(path, &FuncImportTad, NULL); +} + +#endif diff --git a/build/tools/sctools/common/src/myimport.h b/build/tools/sctools/common/src/myimport.h new file mode 100644 index 0000000..0e8a45c --- /dev/null +++ b/build/tools/sctools/common/src/myimport.h @@ -0,0 +1,16 @@ +#ifndef _MYIMPORT_H_ +#define _MYIMPORT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +BOOL myImportTad(char* file_name, FSFile *log_fd); + + +#ifdef __cplusplus +} +#endif + + +#endif /* _MYIMPORT_H_ */ diff --git a/build/tools/sctools/common/src/pre_install.c b/build/tools/sctools/common/src/pre_install.c new file mode 100644 index 0000000..7ed4483 --- /dev/null +++ b/build/tools/sctools/common/src/pre_install.c @@ -0,0 +1,693 @@ +#include +#include +#include +#include +#include +#include + +#include "font.h" +#include "text.h" +#include "mprintf.h" +#include "logprintf.h" + +#include "my_fs_util.h" +#include "myimport.h" + +#include "pre_install.h" + +#define PRE_INSTALL_TABLE_FILE_NAND "rom:/tads/tad_table.txt" +#define PRE_INSTALL_TABLE_FILE_SD "sdmc:/tads/tad_table.txt" + +static PRE_INSTALL_FILE *pre_install_file_list = NULL; + + +BOOL pre_install_check_download_or_pre_install(u64 tid, int *flag, FSFile *log_fd) +{ + ESError rv; + ESTicketView *ticketViews; + u32 numTickets; + + +#if 0 + typedef u32 ESId; /* 32-bit device identity */ + + typedef struct { + ESVersion version; /* eTicket data structure version */ + ESTicketId ticketId; /* eTicket ID */ + ESId deviceId; /* device ID 0->common else->personalized */ + ESTitleId titleId; /* title ID */ + ESSysAccessMask sysAccessMask; /* 16 bit cidx mask */ + u16 ticketVersion; /* 16 bit ticket version */ + u32 accessTitleId; /* 32 bit title id for access control*/ + u32 accessTitleMask; /* 32 bit title id mask */ + u8 licenseType; /* for infrastructure use */ + ESTicketReserved reserved; /* 48 bytes reserved info */ + u8 audit; /* for infrastructure use */ + ESCidxMask cidxMask; /* 512 bits of cidx mask */ + ESLpEntry limits[ES_MAX_LIMIT_TYPE]; /* limit algorithm and limit */ + } ESTicketView; + + + ESError ES_GetTicketViews(ESTitleId titleId, ESTicketView* ticketViewList, u32* ticketViewCnt); +#endif + + if( flag == NULL ) { + return FALSE; + } + + *flag = 0; + + rv = ES_GetTicketViews(tid, NULL, &numTickets); + if (rv != ES_ERR_OK) { + miya_log_fprintf(log_fd,"ES_GetTicketViews failed: %d tid=0x%08x%08x\n", + rv, (u32)(tid >> 32) , (u32)(tid & 0xffffffff)); + return FALSE; + } + + if(numTickets) { + ticketViews = OS_Alloc(sizeof(ESTicketView) * numTickets); + rv = ES_GetTicketViews(tid, ticketViews, &numTickets); + if (rv != ES_ERR_OK) { + miya_log_fprintf(log_fd,"ES_GetTicketViews failed: %d tid=0x%08x%08x\n", + rv, (u32)(tid >> 32) , (u32)(tid & 0xffffffff) ); + return FALSE; + + } + } + + +#if 0 + /* c:/twlsdk/add-ins/es/es-sdk-20090216/twl/build/demos/sysmenu/src/list.c */ + /* Just use first ticket view for now */ + OS_Printf("Attempting to launch %08x\n", (u32)(t->titleId & 0xffffffff)); + rv = ES_CheckLaunchRights(t->titleId, &t->ticketViews[0]); +#endif + + if( ticketViews[0].deviceId == 0 ) { + /* common */ + *flag = 1; + } + else { + /* personalized */ + *flag = 2; + } + + return TRUE; +} + + +static BOOL pre_install_add_list(u64 tid, u8 region, u8 country_code, char *temp_file_name, FSFile *log_fd) +{ + PRE_INSTALL_FILE *temp_pre_install_file = NULL; + PRE_INSTALL_FILE *temp_list; + + if( temp_file_name == NULL ) { + return FALSE; + } + + temp_pre_install_file = (PRE_INSTALL_FILE *)OS_Alloc( sizeof(PRE_INSTALL_FILE) ); + if( temp_pre_install_file == NULL ) { + miya_log_fprintf(log_fd,"Error: %s %s %d\n", __FILE__,__FUNCTION__,__LINE__); + return FALSE; + } + temp_pre_install_file->tid = tid; + temp_pre_install_file->region = region; + temp_pre_install_file->country = country_code; + temp_pre_install_file->next = NULL; + + STD_StrCpy(temp_pre_install_file->file_name, temp_file_name); + + miya_log_fprintf(log_fd,"add list tid=0x%08x %08x %s\n", (u32)(tid >> 32) , (u32)(tid & 0xffffffff) , temp_file_name); + + + if( pre_install_file_list == NULL ) { + pre_install_file_list = temp_pre_install_file; + } + else { + for( temp_list = pre_install_file_list ; temp_list->next != NULL ; temp_list = temp_list->next ) { + ; + } + temp_list->next = temp_pre_install_file; + } + + return TRUE; +} + + +char *pre_install_search_tid(u64 tid, FSFile *log_fd) +{ + PRE_INSTALL_FILE *temp_list; + + for( temp_list = pre_install_file_list ; temp_list != NULL ; temp_list = temp_list->next ) { + if( temp_list->tid == tid ) { + miya_log_fprintf(log_fd,"tad file entry tid=0x%08x%08x %s\n", + (u32)(tid >> 32) , (u32)(tid & 0xffffffff), temp_list->file_name ); + + return temp_list->file_name; + } + } + miya_log_fprintf(log_fd,"%s %s:No entry tid 0x%08x%08x\n",__FILE__,__FUNCTION__, + (u32)(tid >> 32) , (u32)(tid & 0xffffffff)); + return NULL; + +} + +BOOL pre_install_discard_list(void) +{ + PRE_INSTALL_FILE *temp_list; + PRE_INSTALL_FILE *temp_list2; + + temp_list = pre_install_file_list; + while( temp_list != NULL ) { + temp_list2 = temp_list->next; + OS_Free( temp_list ); + temp_list = temp_list2; + } + return TRUE; +} + + + + +static int ReadLine(FSFile *f, char *buf, int buf_size) +{ + char c; + s32 readSize; + int count = 0; + while( 1 ) { + readSize = FS_ReadFile(f, (void *)&c, (s32)1 ); + if( readSize == 0 ) { + /* EOF */ + break; + } + count++; + if( c == '\r' ) { + *buf = '\0'; + break; + } + else if(c == '\n' ) { + *buf = '\0'; + break; + } + + *buf = c; + buf++; + if( count > buf_size ) { + buf--; + *buf = '\0'; + break; + } + + + } + return count; +} + + + + +static int my_char_to_hex(char c) +{ + if( '0' <= c && c <= '9' ) { + return (int)( c - '0'); + } + else if( 'A' <= c && c <= 'F' ) { + return (int)( c - 'A' + 10 ); + } + else if( 'a' <= c && c <= 'f' ) { + return (int)( c - 'a' + 10 ); + } + return -1; /* error */ +} + + +BOOL pre_install_load_file(char *path, FSFile *log_fd) +{ + FSFile file; + BOOL bSuccess = TRUE; + // s32 result; + s32 readSize; + FSResult fsres; + + int buf_counter; + int buf_state; + +#define LINE_BUF_SIZE 512 + char line_buf[LINE_BUF_SIZE]; + // PRE_INSTALL_FILE temp_pre_install_file; + char temp_file_name[FS_FILE_NAME_MAX]; + + + u64 temp_tid; + u8 temp_region; + u8 temp_country_code; + int temp_hex; + int temp_filename_count; + char c; + + FS_InitFile(&file); + + bSuccess = FS_OpenFile(&file, path); + if( ! bSuccess ) { + fsres = FS_GetArchiveResultCode(path); + miya_log_fprintf(log_fd,"Error:%s %s open file\n",__FILE__,__FUNCTION__); + miya_log_fprintf(log_fd, " Failed open file:%s\n", my_fs_util_get_fs_result_word( fsres )); + return FALSE; /* open error! */ + } + + /* + title id + 0x00000000 00000000, region , country code, file name, + */ + + while( 1 ) { + next_line_read: + buf_state = 0; + readSize = ReadLine(&file, line_buf, LINE_BUF_SIZE ); + if( readSize == 0 ) { + /* EOF */ + OS_TPrintf("%s %s %d : End of File\n", __FILE__,__FUNCTION__,__LINE__); + break; + } + + if( !STD_StrNCmp( line_buf, "0x" , STD_StrLen("0x")) ) { + + OS_TPrintf("%s\n", line_buf); + + buf_counter = STD_StrLen("0x"); + buf_state = 1; + temp_tid = 0; + temp_region = 0; + temp_country_code = 0; + temp_filename_count = 0; + + while( readSize > buf_counter ) { + c = line_buf[buf_counter]; + + switch( buf_state ) { + case 1: /* TID */ + if( c == ',') { + if( buf_counter == 18 ) { + // OS_TPrintf("temp_tid=0x%08x %08x\n", (u32)(temp_tid >> 32) , (u32)(temp_tid & 0xffffffff)); + buf_state = 2; /* next state */ + } + else { + /* format error */ + miya_log_fprintf(log_fd,"Error:%s %s %d format error \n",__FILE__,__FUNCTION__,__LINE__); + goto next_line_read; + // break; + } + } + else { + temp_hex = my_char_to_hex(c); + if( temp_hex != -1 ) { + temp_tid |= ( ((u64)temp_hex) << (64 - (4 * (buf_counter-1))) ); + } + else { + /* format error */ + miya_log_fprintf(log_fd,"Error:%s %s %d format error\n",__FILE__,__FUNCTION__,__LINE__); + goto next_line_read; + // break; + } + } + break; + case 2: /* region */ + if( c == ' ' ) { + } + else if( c == ',' ) { + buf_state = 3; /* next state */ + } + else { + temp_hex = my_char_to_hex(c); + if( temp_hex != -1 ) { + temp_region = (u8)temp_hex; + } + else { + /* format error */ + miya_log_fprintf(log_fd,"Error:%s %s %d format error\n",__FILE__,__FUNCTION__,__LINE__); + goto next_line_read; + } + } + break; + case 3: /* country code */ + if( c == ' ' ) { + } + else if( c == ',' ) { + buf_state = 4; /* next state */ + } + else { + temp_hex = my_char_to_hex(c); + if( temp_hex != -1 ) { + temp_country_code = (u8)temp_hex; + } + else { + /* format error */ + miya_log_fprintf(log_fd,"Error:%s %s %d format error\n",__FILE__,__FUNCTION__,__LINE__); + goto next_line_read; + } + } + break; + + case 4: /* file name */ + if( c == ',' ) { + temp_file_name[temp_filename_count] = '\0'; + /* add list */ + if( TRUE != pre_install_add_list(temp_tid, temp_region, temp_country_code, temp_file_name, log_fd) ) { + OS_TPrintf("Error: add list error %s %s %d\n", __FILE__,__FUNCTION__,__LINE__); + } + buf_state = 5; /* next state */ + } + else { + temp_file_name[temp_filename_count] = c; + temp_filename_count++; + } + break; + case 5: /* until line end */ + break; + default: + /* error */ + break; + } + buf_counter++; + } + + + } + else { + /* 妙なフォーマットは全部コメント扱い. */ + } + } + +label_last: + (void)FS_CloseFile(&file); + + return bSuccess; +} + + + +BOOL pre_install_Cleanup_User_Titles( FSFile *log_fd ) +{ +#define NAM_TITLE_ID_S 128 + + NAMTitleId pArray[NAM_TITLE_ID_S]; + s32 i; + BOOL ret_flag = TRUE; + s32 num = 0; + u64 tid; + char game_code_buf[5]; + + num = NAM_GetNumTitles(); + if( num > 0 ) { + if( NAM_OK != NAM_GetTitleList( pArray , NAM_TITLE_ID_S ) ) { + return FALSE; + } + miya_log_fprintf(log_fd, "NAND Installed titles\n"); + + mprintf("Clean-up NAND installed titles\n"); + + for( i = 0 ; i < num ; i++ ) { + tid = pArray[i]; + + /* + No. 0 0003000f484e4c41 + No. 1 0003000f484e4841 + No. 2 0003000f484e4341 + No. 3 00030015484e4241 + No. 4 00030017484e4141 launcher + ^ + | ここの最下位ビットが1のやつがシステムアプリ + | + システムアプリはダウンロード対象外 + */ + (void)my_fs_Tid_To_GameCode(tid, game_code_buf); + if( tid & 0x0000000100000000 ) { + /* system app. */ + miya_log_fprintf(log_fd, " sys.id %08X %08X [%s]\n", (u32)(tid >> 32), (u32)tid, game_code_buf); + } + else { + /* user app. */ + mprintf(" id %08X %08X [%s] ", (u32)(tid >> 32), (u32)tid, game_code_buf); + miya_log_fprintf(log_fd, " usr.id %08X %08X [%s] ", (u32)(tid >> 32), (u32)tid, game_code_buf); + + + if( NAM_OK != NAM_DeleteTitle( tid ) ) { + m_set_palette(tc[0], M_TEXT_COLOR_RED ); /* green */ + mprintf("NG.\n"); + m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); + + miya_log_fprintf(log_fd, "NG.\n"); + miya_log_fprintf(log_fd, " Error: NAM_DeleteTitle id = %08X%08X\n", (u32)(tid >> 32), (u32)tid); + ret_flag = FALSE; + } + else { + m_set_palette(tc[0], M_TEXT_COLOR_GREEN ); /* green */ + mprintf("OK.\n"); + m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); + miya_log_fprintf(log_fd, "OK.\n"); + } + } + } + } + return ret_flag; +} + + +BOOL pre_install_process( FSFile *log_fd, MY_USER_APP_TID *title_id_buf_ptr, int title_id_count ) +{ + char *tad_file_name; + int i; + u64 tid; + char game_code_buf[5]; + BOOL ret_flag = TRUE; + + +#if 0 + /* セキュリティ的にちょっと・・・ */ + (void)pre_install_load_file(PRE_INSTALL_TABLE_FILE_SD, log_fd); +#endif + + (void)pre_install_load_file(PRE_INSTALL_TABLE_FILE_NAND, log_fd); + + for( i = 0 ; i < title_id_count ; i++ ) { + /* + pTitleIds[i].is_personalized = 1 -> common (pre installed) + pTitleIds[i].is_personalized = 2 -> personalized + */ + if( title_id_buf_ptr[i].is_personalized == 1 ) { + /* common e-ticketのやつ */ + /* + 0x00030004484E474A "rom:/tads/TWL-KGUJ-v257.tad.out" + 0x000300044B32444A "rom:/tads/TWL-K2DJ-v0.tad.out" + 0x000300044B47554A "rom:/tads/TWL-HNGJ-v256.tad.out" + */ + tid = title_id_buf_ptr[i].tid; + (void)my_fs_Tid_To_GameCode(tid, game_code_buf); + mprintf(" id %08X %08X [%s] ", (u32)(tid >> 32), (u32)tid, game_code_buf); + miya_log_fprintf(log_fd, " id %08X %08X [%s] ", (u32)(tid >> 32), (u32)tid, game_code_buf); + + tad_file_name = pre_install_search_tid( tid , log_fd); + if( tad_file_name ) { + if( FALSE == myImportTad( tad_file_name , log_fd) ) { + miya_log_fprintf(log_fd, "NG.\n"); + m_set_palette(tc[0], M_TEXT_COLOR_RED ); /* green */ + mprintf("NG.\n"); + m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); + miya_log_fprintf(log_fd, "error: import tid=0x%08x%08x %s\n", + (u32)(tid >> 32) , (u32)(tid & 0xffffffff), tad_file_name); + ret_flag = FALSE; + } + else { + miya_log_fprintf(log_fd, "OK.\n"); + m_set_palette(tc[0], M_TEXT_COLOR_GREEN ); /* green */ + mprintf("OK.\n"); + m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); + title_id_buf_ptr[i].install_success_flag = TRUE; + } + } + else { + miya_log_fprintf(log_fd, "No file\n"); + m_set_palette(tc[0], M_TEXT_COLOR_RED ); /* green */ + mprintf("No file\n"); + m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); + miya_log_fprintf(log_fd, "error: no file\n"); + ret_flag = FALSE; + } + } + else { + /* personalized e-ticketのやつ */ + } + } + (void)pre_install_discard_list(); + return ret_flag; +} + + + +#if 0 + +// リージョンコード +typedef enum OSTWLRegionCode +{ + OS_TWL_REGION_JAPAN = 0, + OS_TWL_REGION_AMERICA = 1, + OS_TWL_REGION_EUROPE = 2, + OS_TWL_REGION_AUSTRALIA = 3, + OS_TWL_REGION_CHINA = 4, + OS_TWL_REGION_KOREA = 5, + OS_TWL_REGION_MAX +} OSTWLRegion; + + +// 言語設定コード +typedef enum LCFGTWLCountryCode +{ + LCFG_TWL_COUNTRY_UNDEFINED = 0, // 未設定 + + // JPNリージョン + LCFG_TWL_COUNTRY_JAPAN = 1, // 日本 + + // USAリージョン + LCFG_TWL_COUNTRY_Anguilla = 8, // アンギラ + LCFG_TWL_COUNTRY_ANTIGUA_AND_BARBUDA, // アンティグア・バーブーダ + LCFG_TWL_COUNTRY_ARGENTINA = 10, // アルゼンチン + LCFG_TWL_COUNTRY_ARUBA, // アルバ + LCFG_TWL_COUNTRY_BAHAMAS, // バハマ + LCFG_TWL_COUNTRY_BARBADOS, // バルバドス + LCFG_TWL_COUNTRY_BELIZE, // ベリーズ + LCFG_TWL_COUNTRY_BOLIVIA, // ボリビア + LCFG_TWL_COUNTRY_BRAZIL, // ブラジル + LCFG_TWL_COUNTRY_BRITISH_VIRGIN_ISLANDS, // 英領ヴァージン諸島 + LCFG_TWL_COUNTRY_CANADA, // カナダ + LCFG_TWL_COUNTRY_CAYMAN_ISLANDS, // ケイマン諸島 + LCFG_TWL_COUNTRY_CHILE = 20, // チリ + LCFG_TWL_COUNTRY_COLOMBIA, // コロンビア + LCFG_TWL_COUNTRY_COSTA_RICA, // コスタリカ + LCFG_TWL_COUNTRY_DOMINICA, // ドミニカ国 + LCFG_TWL_COUNTRY_DOMINICAN_REPUBLIC, // ドミニカ共和国 + LCFG_TWL_COUNTRY_ECUADOR, // エクアドル + LCFG_TWL_COUNTRY_EL_SALVADOR, // エルサルバドル + LCFG_TWL_COUNTRY_FRENCH_GUIANA, // フランス領ギアナ + LCFG_TWL_COUNTRY_GRENADA, // グレナダ + LCFG_TWL_COUNTRY_GUADELOUPE, // グアドループ + LCFG_TWL_COUNTRY_GUATEMALA = 30, // グアテマラ + LCFG_TWL_COUNTRY_GUYANA, // ガイアナ + LCFG_TWL_COUNTRY_HAITI, // ハイチ + LCFG_TWL_COUNTRY_HONDURAS, // ホンジュラス + LCFG_TWL_COUNTRY_JAMAICA, // ジャマイカ + LCFG_TWL_COUNTRY_MARTINIQUE, // マルティニーク + LCFG_TWL_COUNTRY_MEXICO, // メキシコ + LCFG_TWL_COUNTRY_MONTSERRAT, // モントセラト + LCFG_TWL_COUNTRY_NETHERLANDS_ANTILLES, // オランダ領アンティル + LCFG_TWL_COUNTRY_NICARAGUA, // ニカラグア + LCFG_TWL_COUNTRY_PANAMA = 40, // パナマ + LCFG_TWL_COUNTRY_PARAGUAY, // パラグアイ + LCFG_TWL_COUNTRY_PERU, // ペルー + LCFG_TWL_COUNTRY_ST_KITTS_AND_NEVIS, // セントキッツ・ネイビス + LCFG_TWL_COUNTRY_ST_LUCIA, // セントルシア + LCFG_TWL_COUNTRY_ST_VINCENT_AND_THE_GRENADINES, // セントビンセント・グレナディーン + LCFG_TWL_COUNTRY_SURINAME, // スリナム + LCFG_TWL_COUNTRY_TRINIDAD_AND_TOBAGO, // トリニダード・トバゴ + LCFG_TWL_COUNTRY_TURKS_AND_CAICOS_ISLANDS, // タークス・カイコス諸島 + LCFG_TWL_COUNTRY_UNITED_STATES, // アメリカ + LCFG_TWL_COUNTRY_URUGUAY = 50, // ウルグアイ + LCFG_TWL_COUNTRY_US_VIRGIN_ISLANDS, // 米領バージン諸島 + LCFG_TWL_COUNTRY_VENEZUELA, // ベネズエラ + + // EUR, NAL リージョン + LCFG_TWL_COUNTRY_ALBANIA = 64, // アルバニア + LCFG_TWL_COUNTRY_AUSTRALIA, // オーストラリア + LCFG_TWL_COUNTRY_AUSTRIA, // オーストリア + LCFG_TWL_COUNTRY_BELGIUM, // ベルギー + LCFG_TWL_COUNTRY_BOSNIA_AND_HERZEGOVINA, // ボスニア・ヘルツェゴビナ + LCFG_TWL_COUNTRY_BOTSWANA, // ボツワナ + LCFG_TWL_COUNTRY_BULGARIA = 70, // ブルガリア + LCFG_TWL_COUNTRY_CROATIA, // クロアチア + LCFG_TWL_COUNTRY_CYPRUS, // キプロス + LCFG_TWL_COUNTRY_CZECH_REPUBLIC, // チェコ + LCFG_TWL_COUNTRY_DENMARK, // デンマーク + LCFG_TWL_COUNTRY_ESTONIA, // エストニア + LCFG_TWL_COUNTRY_FINLAND, // フィンランド + LCFG_TWL_COUNTRY_FRANCE, // フランス + LCFG_TWL_COUNTRY_GERMANY, // ドイツ + LCFG_TWL_COUNTRY_GREECE, // ギリシャ + LCFG_TWL_COUNTRY_HUNGARY = 80, // ハンガリー + LCFG_TWL_COUNTRY_ICELAND, // アイスランド + LCFG_TWL_COUNTRY_IRELAND, // アイルランド + LCFG_TWL_COUNTRY_ITALY, // イタリア + LCFG_TWL_COUNTRY_LATVIA, // ラトビア + LCFG_TWL_COUNTRY_LESOTHO, // レソト + LCFG_TWL_COUNTRY_LIECHTENSTEIN, // リヒテンシュタイン + LCFG_TWL_COUNTRY_LITHUANIA, // リトアニア + LCFG_TWL_COUNTRY_LUXEMBOURG, // ルクセンブルク + LCFG_TWL_COUNTRY_MACEDONIA, // マケドニア + LCFG_TWL_COUNTRY_MALTA = 90, // マルタ + LCFG_TWL_COUNTRY_MONTENEGRO, // モンテネグロ + LCFG_TWL_COUNTRY_MOZAMBIQUE, // モザンビーク + LCFG_TWL_COUNTRY_NAMIBIA, // ナミビア + LCFG_TWL_COUNTRY_NETHERLANDS, // オランダ + LCFG_TWL_COUNTRY_NEW_ZEALAND, // ニュージーランド + LCFG_TWL_COUNTRY_NORWAY, // ノルウェー + LCFG_TWL_COUNTRY_POLAND, // ポーランド + LCFG_TWL_COUNTRY_PORTUGAL, // ポルトガル + LCFG_TWL_COUNTRY_ROMANIA, // ルーマニア + LCFG_TWL_COUNTRY_RUSSIA = 100, // ロシア + LCFG_TWL_COUNTRY_SERBIA, // セルビア + LCFG_TWL_COUNTRY_SLOVAKIA, // スロバキア + LCFG_TWL_COUNTRY_SLOVENIA, // スロベニア + LCFG_TWL_COUNTRY_SOUTH_AFRICA, // 南アフリカ + LCFG_TWL_COUNTRY_SPAIN, // スペイン + LCFG_TWL_COUNTRY_SWAZILAND, // スワジランド + LCFG_TWL_COUNTRY_SWEDEN, // スウェーデン + LCFG_TWL_COUNTRY_SWITZERLAND, // スイス + LCFG_TWL_COUNTRY_TURKEY, // トルコ + LCFG_TWL_COUNTRY_UNITED_KINGDOM = 110, // イギリス + LCFG_TWL_COUNTRY_ZAMBIA, // ザンビア + LCFG_TWL_COUNTRY_ZIMBABWE, // ジンバブエ + + // TWNリージョン + LCFG_TWL_COUNTRY_TAIWAN = 128, // 台湾 + + // KORリージョン + LCFG_TWL_COUNTRY_SOUTH_KOREA = 136, // 韓国 + + // HKGリージョン(Wiiの国リストに存在) + LCFG_TWL_COUNTRY_HONG_KONG = 144, // ホンコン + LCFG_TWL_COUNTRY_MACAU, // マカオ + + // ASIリージョン(Wiiの国リストに存在) + LCFG_TWL_COUNTRY_INDONESIA = 152, // インドネシア + + // USAリージョン + LCFG_TWL_COUNTRY_SINGAPORE = 153, // シンガポール + + // ASIリージョン(再び) + LCFG_TWL_COUNTRY_THAILAND = 154, // タイ + LCFG_TWL_COUNTRY_PHILIPPINES, // フィリピン + LCFG_TWL_COUNTRY_MALAYSIA, // マレーシア + + // 未定義リージョン(IQueリージョン?) + LCFG_TWL_COUNTRY_CHINA = 160, // 中国 + + // USAリージョン + LCFG_TWL_COUNTRY_UAE = 168, // アラブ首長国連邦 + + // 未定義リージョン + LCFG_TWL_COUNTRY_INDIA = 169, // インド + LCFG_TWL_COUNTRY_EGYPT = 170, // エジプト + LCFG_TWL_COUNTRY_OMAN, // オマーン + LCFG_TWL_COUNTRY_QATAR, // カタール + LCFG_TWL_COUNTRY_KUWAIT, // クウェート + LCFG_TWL_COUNTRY_SAUDI_ARABIA, // サウジアラビア + LCFG_TWL_COUNTRY_SYRIA, // シリア + LCFG_TWL_COUNTRY_BAHRAIN, // バーレーン + LCFG_TWL_COUNTRY_JORDAN, // ヨルダン + + LCFG_TWL_COUNTRY_OTHERS = 254, + LCFG_TWL_COUNTRY_UNKNOWN = 255, + + LCFG_TWL_COUNTRY_MAX + +} LCFGTWLCountryCode; + +#endif diff --git a/build/tools/sctools/common/src/pre_install.h b/build/tools/sctools/common/src/pre_install.h new file mode 100644 index 0000000..e8bc827 --- /dev/null +++ b/build/tools/sctools/common/src/pre_install.h @@ -0,0 +1,30 @@ +#ifndef _PRE_INSTALL_H_ +#define _PRE_INSTALL_H_ + + +typedef struct _PRE_INSTALL_FILE { + struct _PRE_INSTALL_FILE *next; + u64 tid; + u8 region; + u8 country; + char file_name[FS_FILE_NAME_MAX]; +} PRE_INSTALL_FILE; + + +#ifdef __cplusplus +extern "C" { +#endif + +BOOL pre_install_Cleanup_User_Titles( FSFile *log_fd ); +BOOL pre_install_load_file(char *path, FSFile *log_fd); +char *pre_install_search_tid(u64 tid, FSFile *log_fd); +BOOL pre_install_discard_list(void); +BOOL pre_install_process( FSFile *log_fd, MY_USER_APP_TID *title_id_buf_ptr, int tile_id_count ); +BOOL pre_install_check_download_or_pre_install(u64 tid, int *flag, FSFile *log_fd); + +#ifdef __cplusplus +} +#endif + + +#endif /* _PRE_INSTALL_H_ */ diff --git a/build/tools/sctools/copy_dst/Makefile b/build/tools/sctools/copy_dst/Makefile index ad47037..5ca67cf 100644 --- a/build/tools/sctools/copy_dst/Makefile +++ b/build/tools/sctools/copy_dst/Makefile @@ -27,7 +27,7 @@ SRCS = main.c mfiler.c key.c font.c text.c mprintf.c logprintf.c \ hatamotolib.cpp miya_mcu.c error_report.c \ sitedefs.c wcm_control.c netconnect.c mywlan.c \ mynuc.c nuc_error_msg.c stream.c myfilename.c menu_version.c \ - ntp.c myimport.c + ntp.c myimport.c pre_install.c TARGET_BIN = copy_dst.srl ROM_SPEC = copy_dst.rsf @@ -48,7 +48,6 @@ LLIBRARY_DIRS += $(ES_ROOT)/twl/lib/$(TWL_BUILDTYPE) ../wifilib/$(TWL_BUILDTYPE) LLIBRARIES += libecx$(TWL_LIBSUFFIX).a \ liblcfg$(TWL_LIBSUFFIX).a \ libnhttp.nssl$(TWL_LIBSUFFIX).a \ - libnssl$(TWL_LIBSUFFIX).a \ libshr$(TWL_LIBSUFFIX).a \ libnuc$(TWL_LIBSUFFIX).a \ libnup$(TWL_LIBSUFFIX).a \ @@ -59,11 +58,20 @@ LLIBRARIES += libecx$(TWL_LIBSUFFIX).a \ libsfs$(TWL_LIBSUFFIX).a \ libna$(TWL_LIBSUFFIX).a \ +# libnssl$(TWL_LIBSUFFIX).a \ # libnhttp$(TWL_LIBSUFFIX).a \ MAKEROM_ROMROOT = ../files -MAKEROM_ROMFILES = fanfare.32.wav ok.wav ng.wav cursor.wav +MAKEROM_TAD_ROMFILES = tads/tad_table.txt \ + tads/nandAppSample.tad tads/backupSample.tad tads/encodeSD.tad \ + tads/TWL-KGUJ-v257.tad.out \ + tads/TWL-K2DJ-v0.tad.out \ + tads/TWL-HNGJ-v256.tad.out + +MAKEROM_ROMFILES = fanfare.32.wav ok.wav ng.wav cursor.wav $(MAKEROM_TAD_ROMFILES) + + MY_TWL_COMPONENTSDIR = ../my_armadillo.TWL/bin COMPONENT_NAME = armadillo diff --git a/build/tools/sctools/copy_dst/src/hatamotolib.cpp b/build/tools/sctools/copy_dst/src/hatamotolib.cpp index 11fe318..cf27ded 100644 --- a/build/tools/sctools/copy_dst/src/hatamotolib.cpp +++ b/build/tools/sctools/copy_dst/src/hatamotolib.cpp @@ -18,13 +18,17 @@ #include "sitedefs.h" #include "wcm_control.h" +#include "my_fs_util.h" #include "hatamotolib.h" + #include "text.h" #include "mprintf.h" #include "logprintf.h" +#include "error_report.h" -#include "my_fs_util.h" + +static BOOL WaitEC(ECOpId opId); #ifdef SDK_DEBUG #define ECDL_LOG(msg) OS_TPrintf("----\nECDL-LOG: %s\n----\n", msg); @@ -203,12 +207,14 @@ BOOL SetupVerData(void) -void SetupTitlesDataFile(const NAMTitleId* pTitleIds, u32 numTitleIds) +//void SetupTitlesDataFile(const NAMTitleId* pTitleIds, u32 numTitleIds) +void SetupTitlesDataFile(const MY_USER_APP_TID* pTitleIds, u32 numTitleIds) { NAMTitleId tid; for( u32 i = 0; i < numTitleIds; i++ ) { - tid = pTitleIds[i]; + // tid = pTitleIds[i]; + tid = pTitleIds[i].tid; NAM_SetupTitleDataFile(tid); } } @@ -283,13 +289,11 @@ GetDeviceCode(char *deviceCode, u32 bufSize) deviceCode[bufSize - 1] = '\0'; } -static void -Dummy_WWW_AddJSPlugin() +static void Dummy_WWW_AddJSPlugin() { } -static BOOL -LoadCert(void** ppCert, u32* pSize, const char* name) +static BOOL LoadCert(void** ppCert, u32* pSize, const char* name) { FSFile f; BOOL bSuccess; @@ -307,8 +311,8 @@ LoadCert(void** ppCert, u32* pSize, const char* name) bSuccess = FS_OpenFile(&f, path); if( ! bSuccess ) { - miya_log_fprintf(log_fd, "Cannot open %s\n", path); - mprintf("Cannot open %s\n", path); + miya_log_fprintf(log_fd, "%s Cannot open %s\n", __FUNCTION__, path); + mprintf("%s Cannot open %s\n", __FUNCTION__,path); return FALSE; } @@ -316,8 +320,8 @@ LoadCert(void** ppCert, u32* pSize, const char* name) pCert = OS_Alloc(certSize); if ( pCert == NULL ) { - miya_log_fprintf(log_fd, "Cannot allocate work memroy\n"); - mprintf("Cannot allocate work memroy\n"); + miya_log_fprintf(log_fd, "%s Cannot allocate work memroy\n",__FUNCTION__); + mprintf("%s Cannot allocate work memroy \n",__FUNCTION__); return FALSE; } @@ -325,17 +329,54 @@ LoadCert(void** ppCert, u32* pSize, const char* name) if( readSize != certSize ) { miya_log_fprintf(log_fd, "%s fail to read file\n", __FUNCTION__); - mprintf("fail to read file\n"); + mprintf("%s fail to read file\n",__FUNCTION__); return FALSE; } FS_CloseFile(&f); + + // LoadCert(&pClientCert, &clientCertSize, ".twl-nup-cert.der"); + // LoadCert(&pClientKey, &clientKeySize, ".twl-nup-prvkey.der"); + + // static inline s32 NA_DecodeVersionData(const void* src, u32 srcSize, void* dst, u32 dstSize) + // { return OS_IsRunOnTwl() ? NAi_DecodeVersionData(src, srcSize, dst, dstSize): -4; } + + /* + s32 NAi_DecodeVersionData(const void* src, u32 srcSize, void* dst, u32 dstSize) + { + u32 decryptedSize; + AESResult result; + + if ( !SEAi_IsHWInitialized() ) + { + return -1; + } + + decryptedSize = srcSize - AES_SIGN_HEADER_SIZE; + + if ( src == NULL || dst == NULL || decryptedSize > dstSize ) + { + return -2; + } + + SEA_UseWeakKeyTemporary(SEA_WEAK_KEY_VERSION); + result = SEA_Decrypt(src, srcSize, dst); + + if( result != AES_RESULT_SUCCESS ) + { + return -3; + } + + return (s32)decryptedSize; + } + */ + result = NA_DecodeVersionData(pCert, certSize, pCert, certSize); if( result <= 0 ) { miya_log_fprintf(log_fd, "%s fail to decode version info %d\n",__FUNCTION__,result); - mprintf("fail to decode version info %d\n", result); + mprintf("%s fail to decode version info %d\n", __FUNCTION__,result); return FALSE; } @@ -419,7 +460,8 @@ BOOL SetupEC(void) } static ECError WaitEC_result; -BOOL WaitEC(ECOpId opId) + +static BOOL WaitEC(ECOpId opId) { ECError result; ECProgress progress; @@ -507,45 +549,128 @@ BOOL WaitEC(ECOpId opId) } +static BOOL WaitEC_with_NG_print(ECOpId opId) +{ + ECError result; + ECProgress progress; + ECProgress progress_prev; + + if( opId < 0 ) + { + miya_log_fprintf(log_fd, "NG.\n"); + miya_log_fprintf(log_fd, " %s WaitEC error %d\n %s\n", __FUNCTION__,opId, GetECErrorString(opId)); + + m_set_palette(tc[0], M_TEXT_COLOR_RED ); + mprintf("NG.\n"); + m_set_palette(tc[0], M_TEXT_COLOR_YELLOW ); + mprintf(" WaitEC error %d\n %s\n", opId, GetECErrorString(opId)); + m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); + return FALSE; + } + + MI_CpuClear(&progress_prev, sizeof(progress_prev)); + + for(;;) + { + result = EC_GetProgress(opId, &progress); + WaitEC_result = result; + if( (result != EC_ERROR_OK) && (result != EC_ERROR_NOT_DONE) ) { + + miya_log_fprintf(log_fd, "NG.\n"); + m_set_palette(tc[0], M_TEXT_COLOR_RED ); + mprintf("NG.\n"); + m_set_palette(tc[0], M_TEXT_COLOR_YELLOW ); + + if( result == EC_ERROR_NOT_ACTIVE ) { + miya_log_fprintf(log_fd, " %s opId=%d\n", __FUNCTION__, opId); + mprintf(" %s opId=%d\n", __FUNCTION__, opId); + } + miya_log_fprintf(log_fd, " %s Failed to EC_GetProgress, result=%d %s\n", + __FUNCTION__, result, GetECErrorString(result)); + mprintf(" EC_GetProgress failed %d\n %s\n", result, GetECErrorString(result)); + + m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); + + + if( MI_CpuComp8(&progress_prev, &progress, sizeof(progress)) != 0 ) { + miya_log_fprintf(log_fd, "---------\n"); + miya_log_fprintf(log_fd, "progress report\n"); + miya_log_fprintf(log_fd, " status %5d %s\n", progress.status, + GetECErrorString(progress.status)); + miya_log_fprintf(log_fd, " operation %5d %s\n", progress.operation, + GetECOperationString(progress.operation)); + miya_log_fprintf(log_fd, " phase %5d %s\n", progress.phase, + GetECOpPhaseString(progress.phase)); + miya_log_fprintf(log_fd, " isCancelRequested %5d\n", progress.isCancelRequested); + miya_log_fprintf(log_fd, " totalSize %5d\n", progress.totalSize); + miya_log_fprintf(log_fd, " downloadedSize %5d\n", progress.downloadedSize); + miya_log_fprintf(log_fd, " errCode %5d\n", progress.errCode); + miya_log_fprintf(log_fd, " errInfo %s\n", progress.errInfo); + progress_prev = progress; + /* + progress report + status -4015 EC_ERROR_WS_REPORT + operation 12 EC_OP_Transfer + phase 2 EC_PHASE_Done + isCancelRequested 0 + totalSize 0 + downloadedSize 553 + errCode -5986 + errInfo IAS - TWL device unmatched + */ + } + return FALSE; + } + + if( progress.phase == EC_PHASE_Done ) { + break; + } + OS_Sleep(100); + } + return TRUE;; +} -static char CheckRegistration() + + +static BOOL CheckRegistration( char *status ) { s32 progress; ECError ecError; ECDeviceInfo di; BOOL printf_status_flag = FALSE; - //ECDL_LOG("check registeration"); progress = EC_CheckRegistration(); - if( FALSE == WaitEC(progress) ) { - return '\0'; // 微妙・・ + if( FALSE == WaitEC_with_NG_print(progress) ) { + return FALSE; } ecError = EC_GetDeviceInfo(&di); - // SDK_ASSERT( ecError == EC_ERROR_OK ); if( ecError != EC_ERROR_OK ) { - return '\0'; // 微妙・・ + miya_log_fprintf(log_fd, "NG.\n"); + miya_log_fprintf(log_fd, " GetDeviceInfo failed\n"); + + m_set_palette(tc[0], M_TEXT_COLOR_RED ); + mprintf("NG.\n"); + m_set_palette(tc[0], M_TEXT_COLOR_YELLOW ); + mprintf(" GetDeviceInfo failed\n"); + m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); + return FALSE; } switch( di.registrationStatus[0] ) { case '\0': - // mprintf(" my error.\n"); printf_status_flag = TRUE; break; case 'U': - // mprintf(" acount not transfered yet,\n"); - // mprintf(" OR, acount already cleared\n\n"); printf_status_flag = TRUE; break; case 'R': - // mprintf(" already registered. please delete acount.\n"); printf_status_flag = TRUE; break; case 'P': case 'T': - // mprintf(" invalid registration status '%c'\n", status ); printf_status_flag = TRUE; break; default: @@ -586,7 +711,8 @@ static char CheckRegistration() miya_log_fprintf(log_fd, ECDL_DI_FMT " %d\n", "isNeedTicketSyncImportAll", di.isNeedTicketSyncImportAll); } - return di.registrationStatus[0]; + *status = di.registrationStatus[0]; + return TRUE; } static BOOL GetChallenge(char* challenge) @@ -596,15 +722,22 @@ static BOOL GetChallenge(char* challenge) //ECDL_LOG("get challenge"); progress = EC_SendChallengeReq(); - if( FALSE == WaitEC(progress) ) { + if( FALSE == WaitEC_with_NG_print(progress) ) { return FALSE; } ecError = EC_GetChallengeResp(challenge); - if( ecError == EC_ERROR_OK ) { - return TRUE; + if( ecError != EC_ERROR_OK ) { + miya_log_fprintf(log_fd, "NG.\n"); + miya_log_fprintf(log_fd, " EC_GetChallengeResp error.\n"); + m_set_palette(tc[0], M_TEXT_COLOR_RED ); + mprintf("NG.\n"); + m_set_palette(tc[0], M_TEXT_COLOR_YELLOW ); + mprintf(" EC_GetChallengeResp error.\n"); + m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); + return FALSE; } - return FALSE; + return TRUE; } static BOOL SyncRegistration(const char* challenge) @@ -613,7 +746,7 @@ static BOOL SyncRegistration(const char* challenge) // ECDL_LOG("sync registration"); progress = EC_SyncRegistration(challenge); - if( FALSE == WaitEC(progress) ) { + if( FALSE == WaitEC_with_NG_print(progress) ) { return FALSE; } return TRUE; @@ -637,7 +770,7 @@ static BOOL Transfer(const char* challenge) // ECDL_LOG("transfer"); progress = EC_Transfer(challenge); - if( FALSE == WaitEC(progress) ) { + if( FALSE == WaitEC_with_NG_print(progress) ) { return FALSE; } return TRUE; @@ -649,7 +782,7 @@ static BOOL SyncTickets() // ECDL_LOG("sync tickets"); progress = EC_SyncTickets(EC_SYNC_TYPE_IMPORT_ALL); - if( FALSE == WaitEC(progress) ) { + if( FALSE == WaitEC_with_NG_print(progress) ) { return FALSE; } return TRUE; @@ -669,22 +802,10 @@ static int a_to_int(char c) return -1; } -BOOL Tid_To_GameCode(u64 tid, char *gcode) -{ - u32 code; - char *str; - OS_TPrintf("tid = %016X\n",tid); - str = gcode; - code = (u32)(tid & 0xffffffff); - *str++ = (char)((code >> 24) & 0xff); - *str++ = (char)((code >> 16) & 0xff); - *str++ = (char)((code >> 8) & 0xff); - *str++ = (char)(code & 0xff); - return TRUE; -} -static BOOL DownloadTitles(const NAMTitleId* pTitleIds, u32 numTitleIds) +// static BOOL DownloadTitles(const NAMTitleId* pTitleIds, u32 numTitleIds) +static BOOL DownloadTitles(MY_USER_APP_TID* pTitleIds, u32 numTitleIds) { s32 progress; NAMTitleId tid; @@ -693,38 +814,59 @@ static BOOL DownloadTitles(const NAMTitleId* pTitleIds, u32 numTitleIds) char game_code_buf[5]; for( u32 i = 0; i < numTitleIds; i++ ) { - tid = pTitleIds[i]; + // tid = pTitleIds[i]; + if( pTitleIds[i].is_personalized == 1 ) { + /* + personalized ticketのときは何もしない、というかプリンストールもの + pTitleIds[i].is_personalized = 1 -> common + pTitleIds[i].is_personalized = 2 -> personalized + */ + } + else { + tid = pTitleIds[i].tid; progress = EC_DownloadTitle(tid, EC_DT_UPDATE_REQUIRED_CONTENTS); // mprintf("-check registration.. "); - (void)Tid_To_GameCode((u64)tid, game_code_buf); + (void)my_fs_Tid_To_GameCode((u64)tid, game_code_buf); game_code_buf[4] = '\0'; mprintf(" downloading.. [%s] ", game_code_buf); +#if 0 if( FALSE == WaitEC(progress) ) { - + /* EC_ERROR_NET_CONTENTはずす?エラーにせずにバックアップだけ復活してやるか? */ /* if( WaitEC_result == EC_ERROR_NET_CONTENT ) { - tid を記録だけしてエラーにしない。 + tid を記録だけしてエラーにしない。 } - - */ + + */ m_set_palette(tc[0], M_TEXT_COLOR_RED ); mprintf("NG.\n"); m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); miya_log_fprintf(log_fd, " %s download NG.\n",game_code_buf); ret_flag = FALSE; } +#else + if( FALSE == WaitEC_with_NG_print(progress) ) { + /* EC_ERROR_NET_CONTENTはずす?エラーにせずにバックアップだけ復活してやるか? */ + miya_log_fprintf(log_fd, " %s download NG.\n",game_code_buf); + ret_flag = FALSE; + } +#endif else { + pTitleIds[i].install_success_flag = TRUE; + m_set_palette(tc[0], M_TEXT_COLOR_GREEN ); /* green */ mprintf("OK.\n"); m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); miya_log_fprintf(log_fd, " %s download OK.\n",game_code_buf); } } + } return ret_flag; } -int ECDownload(const NAMTitleId* pTitleIds, u32 numTitleIds) +//int ECDownload(const NAMTitleId* pTitleIds, u32 numTitleIds) +int ECDownload(MY_USER_APP_TID *pTitleIds, u32 numTitleIds) { char challenge[EC_CHALLENGE_BUF_SIZE]; char status; @@ -732,9 +874,13 @@ int ECDownload(const NAMTitleId* pTitleIds, u32 numTitleIds) STD_MemSet((void *)challenge,(int)0, EC_CHALLENGE_BUF_SIZE); + /*********************************/ mprintf("-check registration.. "); miya_log_fprintf(log_fd, "-check registration..."); - status = CheckRegistration(); + + if( FALSE == CheckRegistration( &status ) ) { + return ECDOWNLOAD_FAILURE; + } // U unregistered // R registered @@ -745,6 +891,7 @@ int ECDownload(const NAMTitleId* pTitleIds, u32 numTitleIds) m_set_palette(tc[0], M_TEXT_COLOR_RED ); mprintf("NG.\n"); m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); + mprintf(" my error.\n"); miya_log_fprintf(log_fd, " my error.\n"); return ECDOWNLOAD_FAILURE; @@ -790,13 +937,11 @@ int ECDownload(const NAMTitleId* pTitleIds, u32 numTitleIds) m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); } + + /*********************************/ miya_log_fprintf(log_fd, "-get challenge1.."); mprintf("-get challenge1 "); if( FALSE == GetChallenge(challenge) ) { - miya_log_fprintf(log_fd, "NG.\n"); - m_set_palette(tc[0], M_TEXT_COLOR_RED ); - mprintf("NG.\n"); - m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); return ECDOWNLOAD_FAILURE; } else { @@ -806,13 +951,10 @@ int ECDownload(const NAMTitleId* pTitleIds, u32 numTitleIds) m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); } + /*********************************/ miya_log_fprintf(log_fd, "-transfer.. "); mprintf("-transfer "); if( FALSE == Transfer(challenge) ) { - miya_log_fprintf(log_fd, "NG.\n"); - m_set_palette(tc[0], M_TEXT_COLOR_RED ); - mprintf("NG.\n"); - m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); return ECDOWNLOAD_FAILURE; } else { @@ -822,14 +964,10 @@ int ECDownload(const NAMTitleId* pTitleIds, u32 numTitleIds) m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); } - + /*********************************/ miya_log_fprintf(log_fd, "-get challenge.. "); mprintf("-get challenge2 "); if( FALSE == GetChallenge(challenge) ) { - miya_log_fprintf(log_fd, "NG.\n"); - m_set_palette(tc[0], M_TEXT_COLOR_RED ); - mprintf("NG.\n"); - m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); return ECDOWNLOAD_FAILURE; } else { @@ -839,14 +977,10 @@ int ECDownload(const NAMTitleId* pTitleIds, u32 numTitleIds) m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); } - + /*********************************/ miya_log_fprintf(log_fd, "-sync registration.."); mprintf("-sync registration "); if( FALSE == SyncRegistration(challenge) ) { - miya_log_fprintf(log_fd, "NG.\n"); - m_set_palette(tc[0], M_TEXT_COLOR_RED ); - mprintf("NG.\n"); - m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); return ECDOWNLOAD_FAILURE; } else { @@ -856,13 +990,10 @@ int ECDownload(const NAMTitleId* pTitleIds, u32 numTitleIds) m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); } + /*********************************/ miya_log_fprintf(log_fd, "-sync tickets.."); mprintf("-sync tickets "); if( FALSE == SyncTickets() ) { - miya_log_fprintf(log_fd, "NG.\n"); - m_set_palette(tc[0], M_TEXT_COLOR_RED ); - mprintf("NG.\n"); - m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); return ECDOWNLOAD_FAILURE; } else { @@ -872,6 +1003,7 @@ int ECDownload(const NAMTitleId* pTitleIds, u32 numTitleIds) m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); } + /*********************************/ // ここでアプリをダウンロードしている miya_log_fprintf(log_fd, "-download titles\n"); mprintf("-download titles\n"); @@ -896,11 +1028,7 @@ BOOL KPSClient() miya_log_fprintf(log_fd, "-generate key pair .."); mprintf("-generate key pair "); progress = EC_GenerateKeyPair(); - if( FALSE == WaitEC(progress) ) { - miya_log_fprintf(log_fd, "NG.\n"); - m_set_palette(tc[0], M_TEXT_COLOR_RED ); - mprintf("NG.\n"); - m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); + if( FALSE == WaitEC_with_NG_print(progress) ) { return FALSE; } else { @@ -914,11 +1042,7 @@ BOOL KPSClient() miya_log_fprintf(log_fd, "-confirm key pair .. "); mprintf("-confirm key pair "); progress = EC_ConfirmKeyPair(); - if( FALSE == WaitEC(progress) ) { - miya_log_fprintf(log_fd, "NG.\n"); - m_set_palette(tc[0], M_TEXT_COLOR_RED ); - mprintf("NG.\n"); - m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); + if( FALSE == WaitEC_with_NG_print(progress) ) { return FALSE; } else { diff --git a/build/tools/sctools/copy_dst/src/hatamotolib.h b/build/tools/sctools/copy_dst/src/hatamotolib.h index 9b896db..59b0761 100644 --- a/build/tools/sctools/copy_dst/src/hatamotolib.h +++ b/build/tools/sctools/copy_dst/src/hatamotolib.h @@ -11,9 +11,11 @@ extern "C" { // #define ECDOWNLOAD_NO_REGISTER 2 #define ECDOWNLOAD_FAILURE 3 -int ECDownload(const NAMTitleId* pTitleIds, u32 numTitleIds); +// int ECDownload(const NAMTitleId* pTitleIds, u32 numTitleIds); +int ECDownload(MY_USER_APP_TID * pTitleIds, u32 numTitleIds); + BOOL KPSClient(); -BOOL WaitEC(ECOpId opId); + // BOOL WaitEC(ECOpId opId); void PrintDeviceInfo(void); @@ -24,7 +26,10 @@ void SetupNSSL(void); BOOL SetupNHTTP(void); BOOL SetupEC(void); void DeleteECDirectory(void); -void SetupTitlesDataFile(const NAMTitleId* pTitleIds, u32 numTitleIds); + +// void SetupTitlesDataFile(const NAMTitleId* pTitleIds, u32 numTitleIds); +void SetupTitlesDataFile(const MY_USER_APP_TID * pTitleIds, u32 numTitleIds); + FSFile *hatamotolib_log_start(char *log_file_name ); void hatamotolib_log_end(void); BOOL Tid_To_GameCode(u64 tid, char *gcode); diff --git a/build/tools/sctools/copy_dst/src/main.c b/build/tools/sctools/copy_dst/src/main.c index 2d2ece9..a4d2ff0 100644 --- a/build/tools/sctools/copy_dst/src/main.c +++ b/build/tools/sctools/copy_dst/src/main.c @@ -56,6 +56,7 @@ #include "ntp.h" #include "myimport.h" +#include "pre_install.h" // #define PRE_INSTALL 1 @@ -80,8 +81,6 @@ static BOOL completed_flag = FALSE; static FSEventHook sSDHook; static BOOL sd_card_flag = FALSE; -static BOOL ec_download_success_flag = TRUE; - static BOOL wlan_active_flag = TRUE; static BOOL development_console_flag = FALSE; @@ -96,6 +95,10 @@ static int miya_debug_level = 0; static OSHeapHandle hHeap; static u32 allocator_total_size = 0; +static MY_USER_APP_TID *title_id_buf_ptr = NULL; +static int title_id_count = 0; + + static u8 WorkForNA[NA_VERSION_DATA_WORK_SIZE]; @@ -255,61 +258,6 @@ static void DeleteKnownTitles(NAMTitleId* pTitleIds, int num) #endif -static BOOL Clean_User_Titles(void) -{ -#define NAM_TITLE_ID_S 128 - - NAMTitleId pArray[NAM_TITLE_ID_S]; - s32 i; - BOOL ret_flag = TRUE; - s32 num = 0; - u64 id; - - num = NAM_GetNumTitles(); - if( num > 0 ) { - if( NAM_OK != NAM_GetTitleList( pArray , NAM_TITLE_ID_S ) ) { - return FALSE; - } - OS_TPrintf("NAND Installed titles\n"); - for( i = 0 ; i < num ; i++ ) { - id = pArray[i]; - - /* - No. 0 0003000f484e4c41 - No. 1 0003000f484e4841 - No. 2 0003000f484e4341 - No. 3 00030015484e4241 - No. 4 00030017484e4141 launcher - ^ - | ここの最下位ビットが1のやつがシステムアプリ - | - システムアプリはダウンロード対象外 - */ - if( id & 0x0000000100000000 ) { - /* system app. */ - OS_TPrintf(" sys.:%3d:0x%llx\n", i, id); - - } - else { - /* user app. */ - OS_TPrintf(" usr.:%3d:0x%llx\n", i, id); - if( NAM_OK != NAM_DeleteTitle( id ) ) { - OS_TPrintf(" Error: NAM_DeleteTitle id = 0x%llx\n", id); - ret_flag = FALSE; - } - else { - OS_TPrintf(" Delete Title id = 0x%llx\n", id); - } - } - } - } - return ret_flag; -} - - - - - static void RTC_NTP_SYNC(void) @@ -708,47 +656,33 @@ static BOOL RestoreFromSDCard6(void) static BOOL RestoreFromSDCard7(void) { - u64 *title_id_buf_ptr; - int title_id_count; int i; ECError rv; BOOL ret_flag = TRUE; FSFile *log_fd; int ec_download_ret; char game_code_buf[5]; + int is_personalized; + u64 tid; + + title_id_count = 0; + if( title_id_buf_ptr != NULL ) { + OS_Free( title_id_buf_ptr ); + title_id_buf_ptr = NULL; + } - title_id_buf_ptr = NULL; title_id_count = 0; rv = EC_ERROR_OK; /* hws_info.serialNoは戻せない */ - if( no_network_flag == TRUE ) { - return TRUE; - } - log_fd = hatamotolib_log_start( MyFile_GetEcDownloadLogFileName() ); - if( mydata.shop_record_flag == FALSE && mydata.num_of_user_download_app == 0 ) { - /* ネットワークにつながなくていいか? */ - miya_log_fprintf(log_fd,"no shop record \n"); - mprintf(" (--no shop record--)\n"); - } - else { -#ifdef PRE_INSTALLED_APP - /* miya 2009/03/03 */ - if( mydata.shop_record_flag == FALSE ) { - miya_log_fprintf(log_fd,"only pre-installed apps\n"); - mprintf("only pre-installed apps\n"); - } -#endif - miya_log_fprintf(log_fd,"EC download\n"); - mprintf("EC download\n"); - + if( mydata.num_of_user_download_app > 0 ) { if( mydata.num_of_user_download_app > 0 ) { - miya_log_fprintf(log_fd,"-user title list loading\n"); - mprintf("-user title list load "); + miya_log_fprintf(log_fd,"User title list loading\n"); + mprintf("User title list load "); if( TRUE == TitleIDLoad( MyFile_GetDownloadTitleIDFileName(), &title_id_buf_ptr, &title_id_count, MyFile_GetDownloadTitleIDRestoreLogFileName()) ) { @@ -756,11 +690,25 @@ static BOOL RestoreFromSDCard7(void) mprintf("OK.\n"); m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); for( i = 0; i < title_id_count ; i++ ) { - u64 tid = *(title_id_buf_ptr + i ); - (void)Tid_To_GameCode(tid, game_code_buf); - game_code_buf[4] = '\0'; - mprintf(" id %08X %08X [%s]\n", (u32)(tid >> 32), (u32)tid, game_code_buf); - miya_log_fprintf(log_fd," id %08X %08X [%s]\n", (u32)(tid >> 32), (u32)tid, game_code_buf); + /* + インストール成功フラグの初期化 + とりあえず全部失敗状態にする。 + */ + title_id_buf_ptr[i].install_success_flag = FALSE; + tid = title_id_buf_ptr[i].tid; + is_personalized = title_id_buf_ptr[i].is_personalized; + + (void)my_fs_Tid_To_GameCode(tid, game_code_buf); + mprintf(" id %08X %08X [%s] ", (u32)(tid >> 32), (u32)tid, game_code_buf); + if( is_personalized == 1 ) { + mprintf("Pre\n"); + } + else { + mprintf("Dwn\n"); + } + + miya_log_fprintf(log_fd," id %08X %08X [%s] %c\n", (u32)(tid >> 32), (u32)tid, game_code_buf, + (is_personalized == 1)? 'P':'D'); } } else { @@ -770,24 +718,47 @@ static BOOL RestoreFromSDCard7(void) m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); } } - else if( mydata.num_of_user_download_app == 0 ) { - miya_log_fprintf(log_fd,"Original device has no user download app.\n"); - mprintf("Original device has no user download app.\n"); - } - else { - miya_log_fprintf(log_fd,"Original user download app. list saving failed\n"); - mprintf("Original user download app. list saving failed\n"); - } + } + else if( mydata.num_of_user_download_app == 0 ) { + miya_log_fprintf(log_fd,"Original device has no user download app.\n"); + mprintf("Original device has no user download app.\n"); + } + else { + miya_log_fprintf(log_fd,"Original user download app. list saving failed\n"); + mprintf("Original user download app. list saving failed\n"); + } -#ifdef PRE_INSTALL - /* ここでプリンストールする。 */ - miya_log_fprintf(log_fd,"start Import Tad..\n"); - (void)myImportTad("sdmc:/tad/HNLJ.tad"); - miya_log_fprintf(log_fd,"end Import Tad.\n"); -#endif + + /* + miya 2009/5/8 + ここで書き込み側に入ってるプリンインストールものを全部消す! + もっと前でもいい + */ + if( my_fs_get_print_debug_flag() == FALSE ) { + (void)pre_install_Cleanup_User_Titles( log_fd ); + } - // mprintf(" "); + if( no_network_flag == TRUE ) { + miya_log_fprintf(log_fd,"no network flag ON\n"); + goto pre_install_label; + } + + + /* + EC downloadの後にNAM_ImportをやらないとLoadCertのSEA_Decryptでこける。 + 理由はAESエンジンのスロットをNAM_Importでつぶしちゃうから。 + */ + + if( mydata.shop_record_flag == FALSE ) { + /* ネットワークにつながなくていいか? */ + miya_log_fprintf(log_fd,"no shop record \n"); + mprintf(" (--no shop record--)\n"); + } + else { + miya_log_fprintf(log_fd,"EC download\n"); + mprintf("EC download\n"); + miya_log_fprintf(log_fd,"-wireless AP conf. load.. "); mprintf("-wireless AP conf. load "); if( TRUE == LoadWlanConfig() ) { @@ -796,11 +767,9 @@ static BOOL RestoreFromSDCard7(void) mprintf("OK.\n"); m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); - /* nand:/ticketはチケット同期でダウンロード */ // 不要:デバイス情報の表示 // PrintDeviceInfo(); - // setup // 必須:タイトル ID の偽装 SetupShopTitleId(); /* エラーはない */ @@ -809,15 +778,12 @@ static BOOL RestoreFromSDCard7(void) // ?:ユーザ設定がされていないと接続できないので適当に設定 // SetupUserInfo(); - // 必須:バージョンデータのマウント if( FALSE == SetupVerData() ) { miya_log_fprintf(log_fd, "%s failed SetupVerData\n", __FUNCTION__); ret_flag = FALSE; goto end_log_e; } - - // 必須:ネットワークへの接続 if( 0 != NcStart(SITEDEFS_DEFAULTCLASS) ) { @@ -826,9 +792,7 @@ static BOOL RestoreFromSDCard7(void) goto end_log_e; } - /******** ネットワークにつないだ *************/ - // 必須:HTTP と SSL の初期化 miya_log_fprintf(log_fd,"-setup NSSL & NHTTP\n"); SetupNSSL(); @@ -840,7 +804,6 @@ static BOOL RestoreFromSDCard7(void) } /******** NHTTP & NSSLにつないだ *************/ - // 必須:EC の初期化 miya_log_fprintf(log_fd,"-setup EC\n"); if( FALSE == SetupEC() ) { @@ -857,7 +820,8 @@ static BOOL RestoreFromSDCard7(void) goto end_ec_f; } - ec_download_ret = ECDownload((NAMTitleId *)title_id_buf_ptr , (u32)title_id_count); + ec_download_ret = ECDownload((MY_USER_APP_TID *)title_id_buf_ptr , (u32)title_id_count); + if( ec_download_ret == ECDOWNLOAD_FAILURE ) { ret_flag = FALSE; miya_log_fprintf(log_fd, "%s failed ECDownload 1\n", __FUNCTION__); @@ -870,14 +834,15 @@ static BOOL RestoreFromSDCard7(void) } // 不要:セーブデータ領域を作成 // NAM_Init を忘れてた - SetupTitlesDataFile((NAMTitleId *)title_id_buf_ptr , (u32)title_id_count); + + // SetupTitlesDataFile((NAMTitleId *)title_id_buf_ptr , (u32)title_id_count); + SetupTitlesDataFile((MY_USER_APP_TID *)title_id_buf_ptr , (u32)title_id_count); end_ec_f: // cleanup // EC の終了処理 mprintf("-ec shutdown.. "); rv = EC_Shutdown(); - // SDK_WARNING(rv == EC_ERROR_OK, "Failed to shutdown EC, rv=%d\n", rv); if( rv != EC_ERROR_OK ) { ret_flag = FALSE; m_set_palette(tc[0], M_TEXT_COLOR_RED ); @@ -908,10 +873,6 @@ static BOOL RestoreFromSDCard7(void) miya_log_fprintf(log_fd,"done.\n"); mprintf("done.\n"); - - if( title_id_buf_ptr != NULL && title_id_count != 0 ) { - OS_Free( title_id_buf_ptr ); - } // EC が自分の Title ID のディレクトリを作成してしまうため、削除する DeleteECDirectory(); end_log_e: @@ -927,14 +888,18 @@ static BOOL RestoreFromSDCard7(void) m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); } - - if( ret_flag == TRUE ) { - ec_download_success_flag = TRUE; - } - else { - ec_download_success_flag = FALSE; + pre_install_label: + + if( mydata.num_of_user_pre_installed_app > 0 ) { + /* プリンストール対応 */ + miya_log_fprintf(log_fd,"Import Pre-installed apps.\n"); + mprintf("Import Pre-installed apps..\n"); + if( FALSE == pre_install_process( log_fd, title_id_buf_ptr, title_id_count ) ) { + ret_flag = FALSE; + } } + hatamotolib_log_end(); return ret_flag; @@ -952,41 +917,25 @@ static BOOL RestoreFromSDCard8(void) if( mydata.num_of_app_save_data > 0 ) { - if( (no_network_flag == TRUE) - || (ec_download_success_flag == FALSE) - || ( mydata.shop_record_flag == FALSE && mydata.num_of_user_download_app == 0 ) ) { - mprintf("Sys-App. save data restore "); - if( TRUE == RestoreDirEntryListSystemBackupOnly( MyFile_GetSaveDataListFileName() , - MyFile_GetSaveDataRestoreLogFileName(), - &list_count, &error_count )) { - m_set_palette(tc[0], M_TEXT_COLOR_GREEN ); - mprintf("OK.\n"); - m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); - } - else { - // error - m_set_palette(tc[0], M_TEXT_COLOR_RED ); - mprintf("NG.\n"); - m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); - ret_flag = FALSE; - } + //miya 2009.05.07 + /* システムアプリ、プリインストールアプリのバックアップデータを復活させるとき */ + /* きっちり作り直した方がええかも */ + + mprintf("App. save data restore "); + if( TRUE == RestoreDirEntryList_System_And_InstallSuccessApp( MyFile_GetSaveDataListFileName() , + MyFile_GetSaveDataRestoreLogFileName(), + &list_count, &error_count, + title_id_buf_ptr, title_id_count )) { + m_set_palette(tc[0], M_TEXT_COLOR_GREEN ); + mprintf("OK.\n"); + m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); } else { - mprintf("App. save data restore "); - if( TRUE == RestoreDirEntryList( MyFile_GetSaveDataListFileName() , - MyFile_GetSaveDataRestoreLogFileName(), - &list_count, &error_count )) { - m_set_palette(tc[0], M_TEXT_COLOR_GREEN ); - mprintf("OK.\n"); - m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); - } - else { - // error - m_set_palette(tc[0], M_TEXT_COLOR_RED ); - mprintf("NG.\n"); - m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); - ret_flag = FALSE; - } + // error + m_set_palette(tc[0], M_TEXT_COLOR_RED ); + mprintf("NG.\n"); + m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); + ret_flag = FALSE; } } else if( mydata.num_of_app_save_data == 0 ) { @@ -996,6 +945,14 @@ static BOOL RestoreFromSDCard8(void) mprintf("Original app. save data saving failed\n"); } + + if( title_id_buf_ptr != NULL ) { + OS_Free( title_id_buf_ptr ); + title_id_buf_ptr = NULL; + } + title_id_count = 0; + + if( TRUE == Error_Report_Display(tc[0]) ) { mprintf("\n"); } @@ -1044,22 +1001,8 @@ static void MyThreadProc(void *arg) switch( command ) { case THREAD_COMMAND_FULL_FUNCTION: -#ifdef PRE_INSTALLED_APP - /* miya 2009/2/23 */ - mprintf("CleanUp installed user titles "); - if( TRUE == Clean_User_Titles() ) { - m_set_palette(tc[0], M_TEXT_COLOR_GREEN ); - mprintf("OK.\n"); - } - else { - m_set_palette(tc[0], M_TEXT_COLOR_RED ); /* red */ - mprintf("NG.\n"); - flag = FALSE; - } -#endif m_set_palette(tc[0], M_TEXT_COLOR_WHITE ); - if( miya_debug_level == 1 ) { m_set_palette(tc[0], M_TEXT_COLOR_PINK ); mprintf("Free mem size %d bytes\n", OS_GetTotalFreeSize(OS_ARENA_MAIN, hHeap)); @@ -1155,7 +1098,6 @@ static void MyThreadProc(void *arg) } OS_Sleep(200); } - } else { m_set_palette(tc[0], M_TEXT_COLOR_RED ); @@ -1916,10 +1858,10 @@ void TwlMain(void) only_wifi_config_data_trans_flag = FALSE; user_and_wifi_config_data_trans_flag = FALSE; Miya_debug_OFF(); - + my_fs_print_debug_OFF(); select_mode++; - select_mode %= 5; + select_mode %= 6; switch( select_mode ) { case 0: /* restore mode : default */ @@ -1936,6 +1878,9 @@ void TwlMain(void) case 4: Miya_debug_ON(); break; + case 5: + my_fs_print_debug_ON(); + break; default: break; } @@ -2125,6 +2070,10 @@ void TwlMain(void) m_set_palette(tc[1], M_TEXT_COLOR_RED ); /* red */ mfprintf(tc[1],"-- NG mode --\n"); break; + case 5: + m_set_palette(tc[1], M_TEXT_COLOR_YELLOW ); /* red */ + mfprintf(tc[1],"-- debug mode --\n"); + break; default: break; } diff --git a/build/tools/sctools/copy_org/Makefile b/build/tools/sctools/copy_org/Makefile index 0d23c26..843b775 100644 --- a/build/tools/sctools/copy_org/Makefile +++ b/build/tools/sctools/copy_org/Makefile @@ -25,7 +25,7 @@ SRCDIR = ../common/src ./src SRCS = main.c key.c font.c text.c mprintf.c logprintf.c \ gfx.c hwi.c mynvram.c my_fs_util.c miya_mcu.c error_report.c \ sitedefs.c wcm_control.c netconnect.c mywlan.c \ - stream.c myfilename.c menu_version.c + stream.c myfilename.c menu_version.c pre_install.c myimport.c TARGET_BIN = copy_org.srl ROM_SPEC = copy_org.rsf @@ -48,7 +48,6 @@ LLIBRARIES += libecx$(TWL_LIBSUFFIX).a \ liblcfg$(TWL_LIBSUFFIX).a \ libshr$(TWL_LIBSUFFIX).a \ libnhttp.nssl$(TWL_LIBSUFFIX).a \ - libnssl$(TWL_LIBSUFFIX).a \ libnuc$(TWL_LIBSUFFIX).a \ libnup$(TWL_LIBSUFFIX).a \ libnam$(TWL_LIBSUFFIX).a \ @@ -58,7 +57,7 @@ LLIBRARIES += libecx$(TWL_LIBSUFFIX).a \ libsfs$(TWL_LIBSUFFIX).a \ libna$(TWL_LIBSUFFIX).a \ - +# libnssl$(TWL_LIBSUFFIX).a \ # libnhttp$(TWL_LIBSUFFIX).a \ diff --git a/build/tools/sctools/copy_org/src/main.c b/build/tools/sctools/copy_org/src/main.c index dd3d064..7510e86 100644 --- a/build/tools/sctools/copy_org/src/main.c +++ b/build/tools/sctools/copy_org/src/main.c @@ -37,6 +37,8 @@ #include "myfilename.h" #include "menu_version.h" +#include "pre_install.h" + //================================================================================ #define LCD_UPPER_LOWER_FLIP 1 @@ -156,7 +158,7 @@ static int Check_User_Titles(void) s32 num = 0; int user_tilte_count = 0; u64 id; - + char game_code[5]; num = NAM_GetNumTitles(); if( num > 0 ) { @@ -178,14 +180,16 @@ static int Check_User_Titles(void) | システムアプリはダウンロード対象外 */ + (void)my_fs_Tid_To_GameCode(id, game_code); + if( id & 0x0000000100000000 ) { /* system app. */ - OS_TPrintf(" sys.:%3d:0x%llx\n", i, id); + OS_TPrintf(" sys.:%3d:0x%llx %s\n", i, id, game_code); } else { /* user app. */ - OS_TPrintf(" usr.:%3d:0x%llx\n", i, id); + OS_TPrintf(" usr.:%3d:0x%llx %s\n", i, id, game_code); user_tilte_count++; } } @@ -433,11 +437,16 @@ static BOOL SDBackupToSDCard7(void) { MY_DIR_ENTRY_LIST *dir_entry_list_head = NULL; int save_dir_info = 0; - u64 *pBuffer; + // u64 *pBuffer; + // u64 *ptr; + + MY_USER_APP_TID *pBuffer; + MY_USER_APP_TID *ptr; + int count; int j; - u64 *ptr; BOOL flag = TRUE; + int common_or_presonalized_flag; /* タイトルリストの生成 */ /* @@ -477,11 +486,63 @@ static BOOL SDBackupToSDCard7(void) ptr = pBuffer; mydata.num_of_user_download_app = count; mydata.num_of_error_user_download_app = 0; + mydata.num_of_user_pre_installed_app = 0; + + if( no_sd_clean_flag == TRUE ) { + mprintf("\n"); + } + if( ptr != NULL && count != 0 ) { for( j = 0 ; j < count ; j++ ) { - OS_TPrintf("No. %d 0x%016llx\n",j,*ptr); - mfprintf(tc[2],"No. %d 0x%016llx\n",j,*ptr); + // OS_TPrintf("No. %d 0x%016llx\n",j, *ptr); + // mfprintf(tc[2],"No. %d 0x%016llx\n",j,*ptr); + OS_TPrintf("No. %d 0x%016llx",j, ptr->tid); + mfprintf(tc[2],"No. %d 0x%016llx",j,ptr->tid); + + if( no_sd_clean_flag == TRUE ) { + mprintf("No. %d 0x%016llx",j,ptr->tid); + } + + if( TRUE == pre_install_check_download_or_pre_install(ptr->tid, &common_or_presonalized_flag, NULL) ) { + ptr->is_personalized = common_or_presonalized_flag; + if( ptr->is_personalized == 1 ) { + OS_TPrintf(" common"); + mfprintf(tc[2]," common"); + if( no_sd_clean_flag == TRUE ) { + mprintf(" common"); + } + mydata.num_of_user_pre_installed_app++; + + } + else if( ptr->is_personalized == 2 ) { + OS_TPrintf(" personalized"); + mfprintf(tc[2]," personalized"); + if( no_sd_clean_flag == TRUE ) { + mprintf(" personalized"); + } + } + else { + OS_TPrintf(" ?=%d",ptr->is_personalized); + mfprintf(tc[2]," ?=%d",ptr->is_personalized); + if( no_sd_clean_flag == TRUE ) { + mprintf(" ?=%d",ptr->is_personalized); + } + } + } + else { + OS_TPrintf(" ticketv fail"); + mfprintf(tc[2]," ticketv fail"); + if( no_sd_clean_flag == TRUE ) { + mprintf(" ticketv fail"); + } + ptr->is_personalized = 0; + } + OS_TPrintf("\n"); + mfprintf(tc[2],"\n"); + if( no_sd_clean_flag == TRUE ) { + mprintf("\n"); + } ptr++; } } @@ -899,9 +960,9 @@ void TwlMain(void) NAM_Init(&AllocForNAM, &FreeForNAM); - mydata.num_of_user_download_app_by_nam = Check_User_Titles(); - mprintf("num of user tiltes = %d\n",mydata.num_of_user_download_app_by_nam); - + // mydata.num_of_user_download_app_by_nam = Check_User_Titles(); + // mprintf("num of user tiltes = %d\n",mydata.num_of_user_download_app_by_nam); + mprintf("num of user tiltes = %d\n",Check_User_Titles()); mprintf("\n"); diff --git a/build/tools/sctools/files/tads/tad_table.txt b/build/tools/sctools/files/tads/tad_table.txt new file mode 100644 index 0000000..a0afc58 --- /dev/null +++ b/build/tools/sctools/files/tads/tad_table.txt @@ -0,0 +1,18 @@ +/* + title id + 0x00000000 00000000, region , country code, file name, +*/ + +--00030004_484E47?? [HNG?] DSiブラウザ +--00030004_4B4755?? [KGU?] うごくメモ帳 + +-- TitleID_Loの4桁目(言語コード) +-- ?=[J, E, P, U]=[4A, 45, 50, 55] + + +0x00030004484E474A, 0 , 0 ,rom:/tads/TWL-HNGJ-v256.tad.out, +0x000300044B32444A, 0 , 0 ,rom:/tads/TWL-K2DJ-v0.tad.out, +0x000300044B47554A, 0 , 0 ,rom:/tads/TWL-KGUJ-v257.tad.out, + + +