TwlToolsRED/build/tools/sctools/common/src/myimport.c
miya fd1ea05039 tadファイルのタイトルversion情報を取得。
git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlToolsRED@389 7061adef-622a-194b-ae81-725974e89856
2009-07-31 09:17:10 +00:00

2072 lines
60 KiB
C

/*
製品鍵を使った書き込みを行う場合は、
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
typedef struct NAMTitleInfo
{
NAMTitleId titleId;
u16 companyCode;
u16 version;
u32 publicSaveSize;
u32 privateSaveSize;
u32 blockSize;
}
NAMTitleInfo;
typedef struct NAMTadInfo
{
NAMTitleInfo titleInfo;
u32 fileSize;
}
NAMTadInfo;
c:/twlsdk/add-ins/es/es-sdk-20090216/twl/include/estypes.h
typedef u32 ESContentId; // 32-bit content identity
typedef u64 ESTitleId; // 64-bit title identity
typedef u8 ESVersion; // 8-bit data structure version
typedef u16 ESTitleVersion; // 16-bit title version
typedef ESTitleId ESSysVersion; // 64-bit system software version
typedef u32 ESTitleType; // title type
typedef u16 ESContentType; // content type
typedef u8 IOSCHash[20];
*/
#if 0
/* TMD */
typedef struct {
4 ESContentId cid; /* 32 bit content id */
2 u16 index; /* content index, unique per title */
2 ESContentType type; /* content type*/
8 u64 size; /* unencrypted content size in bytes */
IOSCHash hash; /* 160-bit SHA1 hash of the content */
} ESContentMeta;
typedef struct {
1 ESVersion version; /* TMD version number */
1 ESVersion caCrlVersion; /* CA CRL version number */
1 ESVersion signerCrlVersion; /* signer CRL version number */
8 ESSysVersion sysVersion; /* required system software version number */
8 ESTitleId titleId; /* 64 bit title id */
4 ESTitleType type; /* 32 bit title type */
2 u16 groupId;
62 ESTmdReserved reserved; /* 62 bytes reserved info for Nintendo */
4 u32 accessRights; /* title's access rights to use
system resources */
8 ESTitleVersion titleVersion; /* 16 bit title version */
2 u16 numContents; /* number of contents per title */
2 u16 bootIndex; /* boot content index */
} ESTitleMetaHeader; 104
typedef struct {
256 IOSCSigRsa2048 sig; /* RSA 2048bit sign of all the data in
the TMD file */
ESTitleMetaHeader head;
ESContentMeta contents[ES_MAX_CONTENT];
} ESTitleMeta;
typedef struct {
1 ESVersion version; /* TMD data structure version */
8 ESSysVersion sysVersion; /* required system software
version number */
8 ESTitleId titleId; /* 64 bit title id */
4 ESTitleType type; /* 32 bit title type */
2 u16 groupId;
62 ESTmdReserved reserved; /* 62 bytes reserved info */
2 ESTitleVersion titleVersion; /* 16 bit title version */
2 u16 numContents; /* number of contents in the title */
} ESTmdViewHeader;
typedef struct {
ESContentId cid; /* 32 bit content id */
u16 index; /* 16 bit content index */
ESContentType type; /* 16 bit content type */
u64 size; /* 64 bit content size */
} ESCmdView;
typedef struct {
ESTmdViewHeader head;
ESCmdView contents[ES_MAX_CONTENT];
} ESTmdView;
#endif
#include <twl.h>
#include <nitro/nvram/nvram.h>
#include <twl/sea.h>
#include <twl/lcfg.h>
#include <twl/na.h>
#include <twl/nam.h>
#include <twl/os/common/format_rom.h>
#include "font.h"
#include "text.h"
#include "mprintf.h"
#include "logprintf.h"
#include "my_fs_util.h"
#include "my_sign.h"
#include "myimport.h"
#include "ecdl.h"
#include "nam_common.h"
#include "nam_setup.h"
#include "ese_int.h"
/* miyamoto */
#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 BASE_TICKET_DIR "nand:/ticket"
#define BASE_TITLE_DIR "nand:/title"
#define BASE_IMPORT_DIR "nand:/import"
#define BASE_TMP_DIR "nand:/tmp"
*/
/* ************************************* */
typedef s32 (*NAMiTadFunc)(FSFile* pTadFile, void* arg);
typedef s32 (*NAMiSignTadFunc)(MY_SIGN_File* 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 )
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 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;
}
BOOL myDeleteTitle(u64 tid, BOOL with_ticket, FSFile *log_fd)
{
NAMTitleInfo titleInfoTmp;
s32 nam_result;
miya_log_fprintf(log_fd,"start %s\n",__FUNCTION__);
/* 1851879012 -> 0x6E616E64 */
/* HNCAだったらはねる。無線ファーム */
// NANDの情報を取得
if ( NAM_ReadTitleInfo(&titleInfoTmp, tid) == NAM_OK ) {
// NANDに既にインストールされているかどうか確認する
if (tid == titleInfoTmp.titleId) {
// miya_log_fprintf(log_fd,"id=0x%08x already installed\n",titleInfoTmp.titleId);
// miya_log_fprintf(log_fd," delete title..\n");
if( with_ticket ) {
nam_result = NAM_DeleteTitleCompletely( titleInfoTmp.titleId );
}
else {
nam_result = NAM_DeleteTitle( titleInfoTmp.titleId );
}
if ( nam_result != NAM_OK ) {
miya_log_fprintf(log_fd,"Error:NAM_DeleteTitleCompletely RetCode=%x\n", nam_result);
return FALSE;
}
}
else {
/* インストールされていない。 */
// miya_log_fprintf(log_fd,"Error:NAM_ReadTitleInfo failed 0x%08x\n",tadInfo.titleInfo.titleId);
// return FALSE;
OS_TPrintf("%s %s %d\n",__FILE__,__FUNCTION__,__LINE__);
return TRUE;
}
}
else {
/* インストールされていない。 */ /* NAM_ReadTitleInfo失敗 */
OS_TPrintf("%s %s %d\n",__FILE__,__FUNCTION__,__LINE__);
return TRUE;
// return FALSE;
}
// InstalledSoftBoxCount, FreeSoftBoxCount の値を現在のNANDの状態に合わせて更新します。
NAMUT_UpdateSoftBoxCount();
return TRUE;
}
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 NAMi_Load_sign(MY_SIGN_File* my_pf, void** ppBuffer, u32 size, u32 offset, BOOL isSystem)
{
*ppBuffer = NULL;
if( size > 0 )
{
void* buffer;
BOOL bSuccess;
s32 readLen;
buffer = NAMi_Alloc(size);
if( buffer == NULL )
{
OS_TWarning("NAM::Load NAM_NO_MEMORY (%d)", size);
return NAM_NO_MEMORY;
}
bSuccess = my_sign_FS_SeekFile(my_pf, (s32)offset, FS_SEEK_SET);
if( ! bSuccess )
{
OS_TWarning("NAM::Load NAM_SEEK_FILE_FAILED (%d)", offset);
NAMi_Free(buffer);
return isSystem ? NAM_SEEK_FILE_FAILED_SYSTEM: NAM_SEEK_FILE_FAILED_USER;
}
readLen = my_sign_FS_ReadFile(my_pf, buffer, (s32)size);
if( readLen != (s32)size )
{
OS_TWarning("NAM::Load NAM_READ_FILE_FAILED (%d != %d)", readLen, size);
NAMi_Free(buffer);
return isSystem ? NAM_READ_FILE_FAILED_SYSTEM: NAM_READ_FILE_FAILED_USER;
}
*ppBuffer = buffer;
}
return NAM_OK;
}
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 s32 my_sign_LoadCertCrl(NAMiTadImportContext* pContext, MY_SIGN_File* pTadFile, const NAMiTadInfo* pInfo)
{
s32 result1;
s32 result2;
void* cert = NULL;
void* crl = NULL;
result1 = NAMi_Load_sign(pTadFile, &cert, pInfo->sizes.cert, pInfo->offsets.cert, FALSE);
NAMi_Work.currentSize += pInfo->sizes.cert;
result2 = NAMi_Load_sign(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 myReadTadHeader(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);
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 my_sign_ReadTadHeader(MY_SIGN_File* pTadFile, NAMiTadInfo* pInfo)
{
s32 result;
u32 fileSize;
NAMiTADHeader* pHeader;
BOOL isValid;
fileSize = my_sign_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_sign(pTadFile, (void**)&pHeader, sizeof(*pHeader), 0, FALSE);
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 my_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);
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 );
NAMi_Work.currentSize += NAM_TAD_SIZE_ADJUST_IMPORTTICKET;
NAMi_Free(ticket);
return result;
}
static s32 my_sign_ImportTicket(MY_SIGN_File* pTadFile, const NAMiTadInfo* pInfo, const NAMiTadImportContext* pContext)
{
s32 result;
void* ticket = NULL;
result = NAMi_Load_sign(pTadFile, &ticket, pInfo->sizes.ticket, pInfo->offsets.ticket, FALSE);
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 );
NAMi_Work.currentSize += NAM_TAD_SIZE_ADJUST_IMPORTTICKET;
NAMi_Free(ticket);
return result;
}
/* **************************** */
static s32 ImportTadTicketOnly(FSFile* pTadFile, const NAMiTadInfo* pInfo)
{
s32 result;
// int idx;
NAMiTadImportContext tadContext;
// cert と crl をメモリに読み込み
result = LoadCertCrl(&tadContext, pTadFile, pInfo);
if( result != NAM_OK )
{
return result;
}
// eTicket をインポート
result = my_ImportTicket(pTadFile, pInfo, &tadContext);
if( result != NAM_OK )
{
UnloadCertCrl(&tadContext);
return result;
}
UnloadCertCrl(&tadContext);
if( result != NAM_OK )
{
return result;
}
// セーブデータファイルのチェック
// Setup が必要なら行う
// shared2 ファイルの準備
return result;
}
static s32 my_sign_ImportTadTicketOnly(MY_SIGN_File* pTadFile, const NAMiTadInfo* pInfo)
{
s32 result;
// int idx;
NAMiTadImportContext tadContext;
// cert と crl をメモリに読み込み
result = my_sign_LoadCertCrl(&tadContext, pTadFile, pInfo);
if( result != NAM_OK )
{
return result;
}
// eTicket をインポート
result = my_sign_ImportTicket(pTadFile, pInfo, &tadContext);
if( result != NAM_OK )
{
UnloadCertCrl(&tadContext);
return result;
}
UnloadCertCrl(&tadContext);
if( result != NAM_OK )
{
return result;
}
// セーブデータファイルのチェック
// Setup が必要なら行う
// shared2 ファイルの準備
return result;
}
static s32 my_NAM_ImportTadWithFileTicketOnly(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 = myReadTadHeader(pTadFile, &tadInfo);
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 = ImportTadTicketOnly(pTadFile, &tadInfo);
}
NAMi_Unlock();
NAMi_Work.bRunning = FALSE;
return result;
}
static s32 my_sign_NAM_ImportTadWithFileTicketOnly(MY_SIGN_File* pTadFile)
{
extern NAMiWork NAMi_Work;
s32 result;
NAMiTadInfo tadInfo;
SDK_POINTER_ASSERT(pTadFile);
(void)my_sign_FS_SeekFileToBegin(pTadFile);
NAMi_Lock();
NAMi_Work.totalSize = 0;
NAMi_Work.currentSize = 0;
NAMi_Work.bRunning = TRUE;
result = my_sign_ReadTadHeader(pTadFile, &tadInfo);
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 = my_sign_ImportTadTicketOnly(pTadFile, &tadInfo);
}
NAMi_Unlock();
NAMi_Work.bRunning = FALSE;
return result;
}
static s32 FuncImportTadTicketOnly(FSFile* pTadFile, void* arg)
{
#pragma unused(arg)
return my_NAM_ImportTadWithFileTicketOnly(pTadFile);
}
static s32 FuncImportTadTicketOnly_sign(MY_SIGN_File* pTadFile, void* arg)
{
#pragma unused(arg)
return my_sign_NAM_ImportTadWithFileTicketOnly(pTadFile);
}
static s32 NAMi_sign_CloseFile(MY_SIGN_File* pFile, BOOL isSystem)
{
if( my_sign_FS_CloseFile(pFile) )
{
return NAM_OK;
}
else
{
return isSystem ? NAM_CLOSE_FILE_FAILED_SYSTEM: NAM_CLOSE_FILE_FAILED_USER;
}
}
static s32 TadFrameworkTicketOnly(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);
resultClose = NAMi_CloseFile(&tadFile, FALSE);
return (result == NAM_OK) ? resultClose: result;
}
static s32 TadFrameworkTicketOnly_sign(const char* path, NAMiSignTadFunc pTadFunc, void* arg)
{
MY_SIGN_File tadFile;
BOOL bSuccess;
s32 result;
s32 resultClose;
my_sign_FS_InitFile(&tadFile);
bSuccess = my_sign_FS_OpenFile(&tadFile, (char *)path);
if( ! bSuccess )
{
return NAM_OPEN_FILE_FAILED_USER;
}
result = pTadFunc(&tadFile, arg);
resultClose = NAMi_sign_CloseFile(&tadFile, FALSE);
return (result == NAM_OK) ? resultClose: result;
}
BOOL my_NAM_ImportTadTicketOnly(const char* path)
{
#if 1
s32 result;
result = TadFrameworkTicketOnly(path, &FuncImportTadTicketOnly, NULL);
if(result != NAM_OK) {
return result;
}
return TRUE;
#else
FSFile tadFile;
BOOL bSuccess;
s32 result;
s32 resultClose;
FS_InitFile(&tadFile);
bSuccess = FS_OpenFile(&tadFile, path);
if( !bSuccess )
{
OS_TPrintf("open file error:%s %s %d\n", __FILE__,__FUNCTION__,__LINE__);
return FALSE;
}
result = FuncImportTadTicketOnly(&tadFile, NULL);
resultClose = NAMi_CloseFile(&tadFile, FALSE);
if( result != NAM_OK) {
return FALSE;
}
return TRUE;
#endif
}
BOOL my_NAM_ImportTadTicketOnly_sign(const char* path)
{
s32 result;
result = TadFrameworkTicketOnly_sign(path, &FuncImportTadTicketOnly_sign, NULL);
if(result != NAM_OK) {
return result;
}
return TRUE;
}
#define DEFINE_CALC_CONTENTS_BLOCKS(name,type,endianU16,endianU64) \
static u32 \
CalcContentsBlocksFrom##name(const type* pTmd) \
{ \
u32 fsBlocks = 0; \
u32 tmdSize; \
\
{ \
const u16 numContents = endianU16(pTmd->head.numContents); \
int i; \
\
for( i = 0; i < numContents; ++i ) \
{ \
const u32 contentSize = (u32)endianU64(pTmd->contents[i].size); \
fsBlocks += MATH_DIVUP(contentSize, NAMi_Work.nandClusterSize); \
} \
\
tmdSize = sizeof(ESTitleMeta) \
- sizeof(((ESTitleMeta*)0)->contents) \
+ sizeof(ESContentMeta) * numContents; \
} \
\
fsBlocks += MATH_DIVUP(tmdSize, NAMi_Work.nandClusterSize); \
\
return fsBlocks; \
}
SDK_COMPILER_ASSERT( sizeof(((ESTitleMeta*)0)->contents) == sizeof(ESContentMeta) * ES_MAX_CONTENT );
DEFINE_CALC_CONTENTS_BLOCKS(Tmd, ESTitleMeta, NAMi_EndianU16, NAMi_EndianU64)
static u32
CalcTitleBlocksWithoutContents(const void* pReserved)
{
NAMiTmdReserved tmdReserved;
u32 fsBlocks = 0;
BOOL hasSubBanner;
MI_CpuCopy8(pReserved, &tmdReserved, sizeof(tmdReserved));
hasSubBanner = (tmdReserved.flags & NAM_TMD_FLAG_NAND_BANNER);
fsBlocks += MATH_DIVUP(tmdReserved.publicSaveSize, NAMi_Work.nandClusterSize);
fsBlocks += MATH_DIVUP(tmdReserved.privateSaveSize, NAMi_Work.nandClusterSize);
if( hasSubBanner )
{
fsBlocks += MATH_DIVUP(NAM_SUB_BANNER_FILE_SIZE, NAMi_Work.nandClusterSize);
}
return fsBlocks;
}
static u32
my_NAMi_CalcTitleBlocksFromTmd(const ESTitleMeta* pTmd)
{
u32 fsBlocks = CalcTitleBlocksWithoutContents(&pTmd->head.reserved)
+ CalcContentsBlocksFromTmd(pTmd);
return fsBlocks;
}
static s32 my_NAM_ReadTadInfoWithFile(NAMTadInfo* pInfo, FSFile* pTadFile)
{
s32 result;
NAMiTadInfo tadInfo;
ESTitleMeta* pTmd;
SDK_POINTER_ASSERT(pInfo);
SDK_POINTER_ASSERT(pTadFile);
(void)FS_SeekFileToBegin(pTadFile);
result = myReadTadHeader(pTadFile, &tadInfo);
if( result != NAM_OK )
{
OS_TPrintf("ERROR:%s %s %d\n", __FILE__,__FUNCTION__,__LINE__);
return result;
}
// TMD を読む
result = NAMi_Load( pTadFile,
(void**)&pTmd,
tadInfo.sizes.tmd,
tadInfo.offsets.tmd,
FALSE );
if( result != NAM_OK )
{
OS_TPrintf("ERROR:%s %s %d\n", __FILE__,__FUNCTION__,__LINE__);
return result;
}
NAMi_CopyTmdReservedInfo(&pInfo->titleInfo, &pTmd->head.reserved);
pInfo->titleInfo.titleId = NAMi_EndianU64(pTmd->head.titleId);
pInfo->titleInfo.companyCode = NAMi_EndianU16(pTmd->head.groupId);
pInfo->titleInfo.version = NAMi_EndianU16(pTmd->head.titleVersion);
pInfo->titleInfo.blockSize = my_NAMi_CalcTitleBlocksFromTmd(pTmd);
pInfo->fileSize = FS_GetLength(pTadFile);
NAMi_Free(pTmd);
return NAM_OK;
}
static s32 my_sign_NAM_ReadTadInfoWithFile(NAMTadInfo* pInfo, MY_SIGN_File* pTadFile)
{
s32 result;
NAMiTadInfo tadInfo;
ESTitleMeta* pTmd;
SDK_POINTER_ASSERT(pInfo);
SDK_POINTER_ASSERT(pTadFile);
(void)my_sign_FS_SeekFileToBegin(pTadFile);
result = my_sign_ReadTadHeader(pTadFile, &tadInfo);
if( result != NAM_OK )
{
OS_TPrintf("ERROR:%s %s %d\n", __FILE__,__FUNCTION__,__LINE__);
return result;
}
// TMD を読む
result = NAMi_Load_sign( pTadFile,
(void**)&pTmd,
tadInfo.sizes.tmd,
tadInfo.offsets.tmd,
FALSE );
if( result != NAM_OK )
{
OS_TPrintf("ERROR:%s %s %d\n", __FILE__,__FUNCTION__,__LINE__);
return result;
}
NAMi_CopyTmdReservedInfo(&pInfo->titleInfo, &pTmd->head.reserved);
pInfo->titleInfo.titleId = NAMi_EndianU64(pTmd->head.titleId);
pInfo->titleInfo.companyCode = NAMi_EndianU16(pTmd->head.groupId);
pInfo->titleInfo.version = NAMi_EndianU16(pTmd->head.titleVersion);
pInfo->titleInfo.blockSize = my_NAMi_CalcTitleBlocksFromTmd(pTmd);
pInfo->fileSize = my_sign_FS_GetLength(pTadFile);
NAMi_Free(pTmd);
return NAM_OK;
}
static s32 FuncReadTadInfo(FSFile* pTadFile, void* arg)
{
return my_NAM_ReadTadInfoWithFile((NAMTadInfo*)arg, pTadFile);
}
static s32 FuncSignReadTadInfo(MY_SIGN_File* pTadFile, void* arg)
{
return my_sign_NAM_ReadTadInfoWithFile((NAMTadInfo*)arg, pTadFile);
}
static s32 myTadFramework(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);
resultClose = NAMi_CloseFile(&tadFile, FALSE);
return (result == NAM_OK) ? resultClose: result;
}
static s32 my_sign_TadFramework(const char* path, NAMiSignTadFunc pTadFunc, void* arg)
{
MY_SIGN_File tadFile;
BOOL bSuccess;
s32 result;
s32 resultClose;
my_sign_FS_InitFile(&tadFile);
bSuccess = my_sign_FS_OpenFile(&tadFile, (char *)path);
if( ! bSuccess )
{
return NAM_OPEN_FILE_FAILED_USER;
}
result = pTadFunc(&tadFile, arg);
resultClose = NAMi_sign_CloseFile(&tadFile, FALSE);
return (result == NAM_OK) ? resultClose: result;
}
static BOOL my_NAM_ReadTadInfo(NAMTadInfo* pInfo, const char* path)
{
if( NAM_OK == myTadFramework(path, &FuncReadTadInfo, pInfo )) {
return TRUE;
}
return FALSE;
}
static BOOL my_sign_NAM_ReadTadInfo(NAMTadInfo* pInfo, const char* path)
{
if( NAM_OK == my_sign_TadFramework(path, &FuncSignReadTadInfo, pInfo )) {
return TRUE;
}
return FALSE;
}
/*
### mwccarm.exe Compiler:
# 1104: result = NAMi_CheckTitleDataFile( tadContext.titleId,
# Error: ^^^^^^^^^^^^^^^^^^^^^^^
# function has no prototype
### mwccarm.exe Compiler:
# 1114: result = NAMi_SetupTitleDataFileSecure( tadContext.titleId,
# Error: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# function has no prototype
### mwccarm.exe Compiler:
# 1125: result = NAMi_SetupTitleShared2Secure(tadContext.titleId);
*/
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_TWarning("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_TWarning("NAM::SetupContentInfo NAM_INVALID_CONTENT_INDEX: (%d != %d)", i, contentIndex);
NAMi_Free(pContentInfo);
return NAM_INVALID_CONTENT_INDEX;
}
//---- 32bit を超えるサイズのコンテンツはエラーとします。
if( contentSize >= (1ull << 32) )
{
OS_TWarning("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;
}
/*---------------------------------------------------------------------------*
Name: UnloadContentInfo
Description: SetupContentInfo で行った前処理の解放を行います。
Arguments: pContext: 対象の ImportContext。
Returns: なし。
*---------------------------------------------------------------------------*/
static void UnloadContentInfo(NAMiTadImportContext* pContext)
{
NAMi_Free(pContext->pContentInfo);
pContext->pContentInfo = NULL;
}
static s32 my_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 my_sign_ImportTitleInit(MY_SIGN_File* pTadFile, const NAMiTadInfo* pInfo, NAMiTadImportContext* pContext)
{
s32 result;
void* tmd = NULL;
result = NAMi_Load_sign(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;
}
/*---------------------------------------------------------------------------*
Name: ImportTitleFinish
Description: tad からの NAND アプリインポート後処理を行います。
Arguments: pContext: ImportContext。
result: コンテンツインポート処理の結果。
Returns: 正常に処理が行われたなら NAM_OK を返します。
*---------------------------------------------------------------------------*/
static s32 my_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;
}
/*---------------------------------------------------------------------------*
Name: ImportContent
Description: tad から NAND アプリコンテンツをインポートします。
Arguments: pTadFile: tad ファイル。
pInfo: tad 構成情報。
pContext: ImportContext。
idx: インポートするコンテンツ番号。
Returns: 正常に処理が行われたなら NAM_OK を返します。
*---------------------------------------------------------------------------*/
static s32 my_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_TWarning("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_TWarning("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);
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;
}
//---- コンテンツインポート後処理
result2 = ES_ImportContentEnd(fd);
NAMi_Free(readBuffer);
return (result == ES_ERR_OK) ? result2: result;
}
static s32 my_sign_ImportContent(MY_SIGN_File* 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 = my_sign_FS_SeekFile(pTadFile, (s32)offset, FS_SEEK_SET);
if( ! bSuccess )
{
OS_TWarning("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_TWarning("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);
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)my_sign_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;
}
//---- コンテンツインポート後処理
result2 = ES_ImportContentEnd(fd);
NAMi_Free(readBuffer);
return (result == ES_ERR_OK) ? result2: result;
}
static s32 my_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 = my_ImportTicket(pTadFile, pInfo, &tadContext);
PRINT_RESULT(result);
if( result != NAM_OK )
{
UnloadCertCrl(&tadContext);
return result;
}
// 本体のインポート準備
result = my_ImportTitleInit(pTadFile, pInfo, &tadContext);
PRINT_RESULT(result);
if( result == NAM_OK )
{
// コンテンツのインポート
for( idx = 0; idx < tadContext.numContents; ++idx )
{
result = my_ImportContent(pTadFile, pInfo, &tadContext, idx);
PRINT_RESULT(result);
if( result != NAM_OK )
{
break;
}
}
}
// インポートの完了
result = my_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_sign_ImportTad(MY_SIGN_File* pTadFile, const NAMiTadInfo* pInfo)
{
s32 result;
int idx;
NAMiTadImportContext tadContext;
// cert と crl をメモリに読み込み
result = my_sign_LoadCertCrl(&tadContext, pTadFile, pInfo);
PRINT_RESULT(result);
if( result != NAM_OK )
{
return result;
}
// eTicket をインポート
result = my_sign_ImportTicket(pTadFile, pInfo, &tadContext);
PRINT_RESULT(result);
if( result != NAM_OK )
{
UnloadCertCrl(&tadContext);
return result;
}
// 本体のインポート準備
result = my_sign_ImportTitleInit(pTadFile, pInfo, &tadContext);
PRINT_RESULT(result);
if( result == NAM_OK )
{
// コンテンツのインポート
for( idx = 0; idx < tadContext.numContents; ++idx )
{
result = my_sign_ImportContent(pTadFile, pInfo, &tadContext, idx);
PRINT_RESULT(result);
if( result != NAM_OK )
{
break;
}
}
}
// インポートの完了
result = my_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)
{
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 = myReadTadHeader(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 = my_ImportTad(pTadFile, &tadInfo);
PRINT_RESULT(result);
}
NAMi_Unlock();
NAMi_Work.bRunning = FALSE;
return result;
}
static s32 my_sign_NAM_ImportTadWithFile(MY_SIGN_File* pTadFile)
{
s32 result;
NAMiTadInfo tadInfo;
SDK_POINTER_ASSERT(pTadFile);
(void)my_sign_FS_SeekFileToBegin(pTadFile);
NAMi_Lock();
NAMi_Work.totalSize = 0;
NAMi_Work.currentSize = 0;
NAMi_Work.bRunning = TRUE;
result = my_sign_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 = my_sign_ImportTad(pTadFile, &tadInfo);
PRINT_RESULT(result);
}
NAMi_Unlock();
NAMi_Work.bRunning = FALSE;
return result;
}
static s32 my_FuncImportTad(FSFile* pTadFile, void* arg)
{
#pragma unused(arg)
return my_NAM_ImportTadWithFile(pTadFile);
}
static s32 my_sign_FuncImportTad(MY_SIGN_File* pTadFile, void* arg)
{
#pragma unused(arg)
return my_sign_NAM_ImportTadWithFile(pTadFile);
}
static s32 my_NAM_ImportTad(const char* path)
{
return myTadFramework(path, &my_FuncImportTad, NULL);
}
static s32 my_sign_NAM_ImportTad(const char* path)
{
return my_sign_TadFramework(path, &my_sign_FuncImportTad, NULL);
}
/*---------------------------------------------------------------------------*
Name: ImportTad
Description: .tad ファイルインポート
Arguments: no
Returns: None.
*---------------------------------------------------------------------------*/
BOOL myImportTad(char* full_path, int org_version, 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);
// OS_TPrintf("import from ROM(%s)\n", full_path);
miya_log_fprintf(log_fd,"start myImportTad %s\n",full_path);
// tadファイルの情報取得
if ( my_NAM_ReadTadInfo(&tadInfo, full_path) != TRUE ) {
miya_log_fprintf(log_fd,"Error:NAM_ReadTadInfo failed %s\n",full_path);
return FALSE;
}
miya_log_fprintf(log_fd,"tadfile.ver=%d org.ver=%d\n", tadInfo.titleInfo.version, org_version);
if( org_version > tadInfo.titleInfo.version ) {
miya_log_fprintf(log_fd,"Error:org.ver=%d tadfile.ver=%d %s\n",org_version, tadInfo.titleInfo.version, full_path);
return FALSE;
}
/* 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);
miya_log_fprintf(log_fd," delete title..\n");
if( NAM_OK != NAM_DeleteTitleCompletely( titleInfoTmp.titleId ) ) {
miya_log_fprintf(log_fd," Error: NAM_DeleteTitle id = 0x%08x\n", titleInfoTmp.titleId);
return FALSE;
}
}
}
else {
/* インストールされていない。 */
// miya_log_fprintf(log_fd,"Error:NAM_ReadTitleInfo failed 0x%08x\n",tadInfo.titleInfo.titleId);
// return FALSE;
}
// 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;
}
}
miya_log_fprintf(log_fd,"Import %s Start.\n", full_path );
// nam_result = NAM_ImportTad( full_path );
nam_result = my_NAM_ImportTad( full_path );
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);
}
// InstalledSoftBoxCount, FreeSoftBoxCount の値を現在のNANDの状態に合わせて更新します。
NAMUT_UpdateSoftBoxCount();
return ret;
}
BOOL myImportTad_sign(char* full_path, int org_version, 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);
// OS_TPrintf("import from SD Card(%s)\n", full_path);
miya_log_fprintf(log_fd,"start my_sign_ImportTad %s\n",full_path);
// tadファイルの情報取得
if ( my_sign_NAM_ReadTadInfo(&tadInfo, full_path) != TRUE ) {
miya_log_fprintf(log_fd,"Error:NAM_ReadTadInfo failed %s\n",full_path);
return FALSE;
}
miya_log_fprintf(log_fd,"tadfile.ver=%d org.ver=%d\n", tadInfo.titleInfo.version,org_version);
if( org_version > tadInfo.titleInfo.version ) {
miya_log_fprintf(log_fd,"Error:org.ver=%d tadfile.ver=%d %s\n",org_version, tadInfo.titleInfo.version, full_path);
return FALSE;
}
/* 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);
miya_log_fprintf(log_fd," delete title..\n");
if( NAM_OK != NAM_DeleteTitleCompletely( titleInfoTmp.titleId ) ) {
miya_log_fprintf(log_fd," Error: NAM_DeleteTitle id = 0x%08x\n", titleInfoTmp.titleId);
return FALSE;
}
}
}
else {
/* インストールされていない。 */
// miya_log_fprintf(log_fd,"Error:NAM_ReadTitleInfo failed 0x%08x\n",tadInfo.titleInfo.titleId);
// return FALSE;
}
// 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;
}
}
miya_log_fprintf(log_fd,"Import %s Start.\n", full_path );
// nam_result = NAM_ImportTad( full_path );
nam_result = my_sign_NAM_ImportTad( full_path );
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);
}
// InstalledSoftBoxCount, FreeSoftBoxCount の値を現在のNANDの状態に合わせて更新します。
NAMUT_UpdateSoftBoxCount();
return ret;
}