新しいROMヘッダの鍵対応

SD独自ドライバが動かなくなり、メンテなすするのも面倒なので、削除

git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlIPL/trunk@457 b08762b0-b915-fc4b-9d8c-17b2551a87ff
This commit is contained in:
yutaka 2008-01-11 05:46:56 +00:00
parent 954b313f5d
commit 2daa7b919e
14 changed files with 661 additions and 2577 deletions

View File

@ -96,7 +96,6 @@ FIRM_LIBS_BASE ?= \
libfs_sp \
libaes_sp \
libpm_sp \
libfatfs_sp \
endif

View File

@ -1,5 +1,5 @@
/*---------------------------------------------------------------------------*
Project: TwlFirm - nandfirm - sdmc-launcher
Project: TwlFirm - gcdfirm - sdmc-launcher
File: main.c
Copyright 2007 Nintendo. All rights reserved.
@ -16,41 +16,57 @@
*---------------------------------------------------------------------------*/
#include <firm.h>
#include <twl/mcu.h>
#include <twl/os/ARM7/debugLED.h>
#define FATFS_HEAP_SIZE (64*1024) // FATFS用ヒープ (サイズ調整必要)
#define BOOT_DEVICE FATFS_MEDIA_TYPE_SD
#define PARTITION_NO 0 // 0固定
#define MENU_FILE (char*)L"A:\\menu.srl" // 対象ファイル(DRIVE_LETTERと合わせること)
#define MENU_FILE_A (char*)L"A:\\menu_a.srl" // 対象ファイル(DRIVE_LETTERと合わせること)
#define MENU_FILE_B (char*)L"A:\\menu_b.srl" // 対象ファイル(DRIVE_LETTERと合わせること)
#define MENU_FILE_L (char*)L"A:\\menu_l.srl" // 対象ファイル(DRIVE_LETTERと合わせること)
#define MENU_FILE_R (char*)L"A:\\menu_r.srl" // 対象ファイル(DRIVE_LETTERと合わせること)
#define DRIVE_LETTER 'A' // マウント先ドライブ名
#define DRIVE_NO (DRIVE_LETTER - 'A') // マウント先ドライブ番号
static u8 fatfsHeap[FATFS_HEAP_SIZE] __attribute__ ((aligned (32)));
#ifndef SDK_FINALROM
static u8 step = 0x80;
#endif
/*
Profile
PROFILE_ENABLE
main.cかどこかにu32 profile[256]; u32 pf_cnt = 0;
*/
#ifndef SDK_FINALROM
#define PROFILE_MAX 0x100
#define PROFILE_ENABLE
/*
LEDをFINALROMとは別にOn/Offできます
*/
#define USE_DEBUG_LED
/*
PRINT_MEMORY_ADDR SPrintfを行います()
FINALROM版でもコードが残るので注意してください
*/
#define PRINT_MEMORY_ADDR 0x02000600
#ifdef PROFILE_ENABLE
#define PROFILE_MAX 16
u32 profile[PROFILE_MAX];
u32 pf_cnt = 0;
#define PUSH_PROFILE() (profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()))
#else
#define PUSH_PROFILE() ((void)0)
#endif
/*
Production check
*/
//#define PRODUCTION_CHECK() do { if (reg_SCFG_OP == 0) goto end; } while (0)
#define PRODUCTION_CHECK() ((void)0)
#ifdef USE_DEBUG_LED
static u8 step = 0x80;
#define InitDebugLED() I2Ci_WriteRegister(I2C_SLAVE_DEBUG_LED, 0x03, 0x00)
#define SetDebugLED(pattern) I2Ci_WriteRegister(I2C_SLAVE_DEBUG_LED, 0x01, (pattern));
#else
#define InitDebugLED() ((void)0)
#define SetDebugLED(pattern) ((void)0)
#endif
#ifdef PRINT_MEMORY_ADDR
static char* debugPtr = (char*)PRINT_MEMORY_ADDR;
#undef OS_TPrintf
//#define OS_TPrintf(...) (debugPtr = (char*)((u32)(debugPtr + STD_TSPrintf(debugPtr, __VA_ARGS__) + 0xf) & ~0xf))
#define OS_TPrintf(...) (debugPtr += STD_TSPrintf(debugPtr, __VA_ARGS__))
#endif
#define THREAD_PRIO_FATFS 8
#define DMA_NO_FATFS 3
extern void* SDNandContext; /* NAND初期化パラメータ */
static ROM_Header* const rh= (ROM_Header*)HW_TWL_ROM_HEADER_BUF;
/***************************************************************
PreInit
@ -72,6 +88,18 @@ static void PreInit(void)
*/
#define FIRM_AVAILABLE_BIT 0x80000000UL
*(u32*)HW_RESET_PARAMETER_BUF = (u32)MCUi_ReadRegister( MCU_REG_TEMP_ADDR ) | FIRM_AVAILABLE_BIT;
/*
*/
//if ( MCUi_ReadRegister( MCU_REG_BATTELY ) < 0x02 )
//if ( MCUi_ReadRegister( MCU_REG_IRQ ) & MCU_IRQ_NO_BATTELY )
/*
TWLと識別できているかチェック
#ifdef USE_DEBUG_LED
SetDebugLED(OS_IsRunOnTwl() ? 0xC3 : 0xff);
OS_SpinWaitCpuCycles(0x1000000);
#endif
*/
}
/***************************************************************
@ -90,172 +118,172 @@ static void EraseAll(void)
#endif
}
/***************************************************************
Fatfs4sdmcInit
FATFS周りの初期化 for SDカード
***************************************************************/
static BOOL Fatfs4sdmcInit(void)
{
BOOL result;
/* FATFSライブラリ用にカレントヒープを設定 */
/* WRAM上のfatfsHeapをメインメモリヒープとして登録している */
OSHeapHandle hh;
u8 *lo = (u8*)fatfsHeap;
u8 *hi = (u8*)fatfsHeap + FATFS_HEAP_SIZE;
lo = OS_InitAlloc(OS_ARENA_MAIN_SUBPRIV, lo, hi, 1);
OS_SetArenaLo(OS_ARENA_MAIN_SUBPRIV, lo);
hh = OS_CreateHeap(OS_ARENA_MAIN_SUBPRIV, OS_GetSubPrivArenaLo(), hi);
OS_SetCurrentHeap(OS_ARENA_MAIN_SUBPRIV, hh);
OS_SetDebugLED(++step);
if ( !FATFS_InitFIRM( NULL ) )
{
return FALSE;
}
#ifndef SDK_FINALROM
// 3: after FATFS
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
OS_SetDebugLED(++step);
PM_BackLightOn( FALSE );
if ( !FATFS_MountDriveFIRM( DRIVE_NO, BOOT_DEVICE, PARTITION_NO ) )
{
return FALSE;
}
#ifndef SDK_FINALROM
// 4: after Mount
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
OS_SetDebugLED(++step);
PM_BackLightOn( FALSE );
#if 0
switch ( PAD_Read() & PAD_KEYPORT_MASK )
{
case 0:
#endif
result = FATFS_OpenSpecifiedSrl( MENU_FILE ) && FATFS_SaveSrlFilename( BOOT_DEVICE, MENU_FILE );
#if 0
break;
case PAD_BUTTON_A:
result = FATFS_OpenSpecifiedSrl( MENU_FILE_A ) && FATFS_SaveSrlFilename( BOOT_DEVICE, MENU_FILE_A );
break;
case PAD_BUTTON_B:
result = FATFS_OpenSpecifiedSrl( MENU_FILE_B ) && FATFS_SaveSrlFilename( BOOT_DEVICE, MENU_FILE_B );
break;
case PAD_BUTTON_L:
result = FATFS_OpenSpecifiedSrl( MENU_FILE_L ) && FATFS_SaveSrlFilename( BOOT_DEVICE, MENU_FILE_L );
break;
case PAD_BUTTON_R:
result = FATFS_OpenSpecifiedSrl( MENU_FILE_R ) && FATFS_SaveSrlFilename( BOOT_DEVICE, MENU_FILE_R );
break;
default:
OS_SetDebugLED( (u8)(PAD_Read() & PAD_KEYPORT_MASK) );
result = FALSE;
break;
}
#endif
return result;
}
void TwlSpMain( void )
{
// OS_InitDebugLED and OS_SetDebugLED are able to call after OS_Init
#ifndef SDK_FINALROM
I2Ci_WriteRegister(I2C_SLAVE_DEBUG_LED, 0x03, 0x00);
I2Ci_WriteRegister(I2C_SLAVE_DEBUG_LED, 0x01, ++step);
#endif
int fd; // menu file descriptor
InitDebugLED();
SetDebugLED(++step); // 0x81
PreInit();
#ifndef SDK_FINALROM
I2Ci_WriteRegister(I2C_SLAVE_DEBUG_LED, 0x01, ++step);
// 0: before PXI
profile[pf_cnt++] = (u32)OS_TicksToMicroSecondsBROM(OS_GetTick());
#endif
PUSH_PROFILE();
SetDebugLED(++step); // 0x82
OS_InitFIRM();
PRODUCTION_CHECK();
OS_EnableIrq();
OS_EnableInterrupts();
#ifndef SDK_FINALROM
//OS_EnableIrq();
// 1: after PXI
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
OS_SetDebugLED(++step);
PUSH_PROFILE();
SetDebugLED(++step); // 0x83
PM_InitFIRM();
PM_BackLightOn( FALSE );
#ifndef SDK_FINALROM
// 2: after PM
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
OS_SetDebugLED(++step);
PRODUCTION_CHECK();
if ( !Fatfs4sdmcInit() )
{
goto end;
}
#ifndef SDK_FINALROM
// 5: after Open
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
OS_SetDebugLED(++step);
// 2: after PM_InitFIRM
PUSH_PROFILE();
SetDebugLED(++step); // 0x84
PM_BackLightOn( FALSE );
if ( !FATFS_LoadHeader() || !FATFS_LoadStatic() )
SDNandContext = &OSi_GetFromFirmAddr()->SDNandContext;
if ( !FATFS_Init( DMA_NO_FATFS, THREAD_PRIO_FATFS ) )
{
OS_TPrintf("Failed to call FATFS_Init().\n");
goto end;
}
#ifndef SDK_FINALROM
// 127: before Boot
pf_cnt = PROFILE_MAX-1;
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
// 3: after FS_Init
PUSH_PROFILE();
SetDebugLED(++step); // 0x85
PM_BackLightOn( FALSE );
PXI_RecvID();
SetDebugLED(0x01);
PXI_RecvID();
SetDebugLED(0x02);
if ( PXI_RecvID() != FIRM_PXI_ID_SET_PATH )
{
OS_TPrintf("PXI_RecvID() was received invalid value (!=FIRM_PXI_ID_SET_PATH).\n");
goto end;
}
#ifdef USE_IDLE_THREAD
CreateIdleThread();
#endif
// 4: after PXI
PUSH_PROFILE();
SetDebugLED(++step); // 0x86
PM_BackLightOn( FALSE );
if ( (fd = FS_OpenSrl()) < 0 )
{
OS_TPrintf("Failed to call FS_OpenSrl().\n");
goto end;
}
// 5: after FS_OpenSrl
PUSH_PROFILE();
SetDebugLED(++step); // 0x87
PM_BackLightOn( FALSE );
if ( !FS_LoadHeader( fd ) )
{
OS_TPrintf("Failed to call FS_LoadHeader().\n");
goto end;
}
// 6: after FS_LoadHeader
PUSH_PROFILE();
SetDebugLED(++step); // 0x88
PM_BackLightOn( FALSE );
if ( PXI_RecvID() != FIRM_PXI_ID_DONE_HEADER )
{
OS_TPrintf("PXI_RecvID() was received invalid value (!=FIRM_PXI_ID_DONE_HEADER).\n");
goto end;
}
// 7: after PXI
PUSH_PROFILE();
SetDebugLED(++step); // 0x89
PM_BackLightOn( FALSE );
AESi_InitKeysFIRM();
AESi_RecvSeed( rh->s.developer_encrypt );
// 8: after AESi_RecvSeed
PUSH_PROFILE();
SetDebugLED(++step); // 0x8a
PM_BackLightOn( FALSE );
if ( !FS_LoadStatic( fd ) )
{
OS_TPrintf("Failed to call FS_LoadStatic().\n");
goto end;
}
// 9: after FS_LoadStatic
PUSH_PROFILE();
SetDebugLED(++step); // 0x8b
PM_BackLightOn( FALSE );
if ( PXI_RecvID() != FIRM_PXI_ID_DONE_STATIC )
{
OS_TPrintf("PXI_RecvID() was received invalid value (!=FIRM_PXI_ID_DONE_STATIC).\n");
goto end;
}
// 10: after PXI
PUSH_PROFILE();
#ifdef PROFILE_ENABLE
{
int i;
PXI_RecvID();
OS_TPrintf("\n[ARM7] Begin\n");
for (i = 0; i < PROFILE_MAX; i++)
{
OS_TPrintf("0x%08X\n", profile[i]);
// OS_TPrintf("0x%08X\n", profile[i]);
if ( !profile[i] ) break;
OS_TPrintf("%2d: %7d usec", i, profile[i]);
if (i)
{
OS_TPrintf(" ( %7d usec )\n", profile[i]-profile[i-1]);
}
else
{
OS_TPrintf("\n");
}
}
OS_TPrintf("\n[ARM7] End\n");
}
#endif
OS_SetDebugLED(0);
PRODUCTION_CHECK();
SetDebugLED( 0 );
PM_BackLightOn( TRUE ); // last chance
PMi_SetParams( REG_PMIC_BL_BRT_A_ADDR, 22, PMIC_BL_BRT_A_MASK ); // brighter
PMi_SetParams( REG_PMIC_BL_BRT_B_ADDR, 22, PMIC_BL_BRT_B_MASK ); // brighter
OS_BootFromFIRM();
end:
OS_SetDebugLED( (u8)(0xF0 | step));
SetDebugLED( (u8)(0xF0 | step));
EraseAll();
// failed
while (1)
{
PXI_NotifyID( FIRM_PXI_ID_NULL );
}
PXI_NotifyID( FIRM_PXI_ID_ERR );
PXI_NotifyID( FIRM_PXI_ID_ERR );
PXI_NotifyID( FIRM_PXI_ID_ERR );
PXI_NotifyID( FIRM_PXI_ID_ERR );
OS_Terminate();
}

View File

@ -1,5 +1,5 @@
/*---------------------------------------------------------------------------*
Project: TwlFirm - nandfirm - sdmc-launcher
Project: TwlFirm - gcdfirm - sdmc-launcher
File: main.c
Copyright 2007 Nintendo. All rights reserved.
@ -22,15 +22,15 @@
#define RSA_KEY_ADDR rsa_key
static const u8 rsa_key[128] =
{
0xdf, 0x56, 0x30,
0xc9, 0xae, 0x05, 0x55, 0xe8, 0xdf, 0xbe, 0xe6, 0xb9, 0x30, 0xb9, 0x76, 0x93, 0xb4, 0xc2, 0x20,
0xe7, 0xae, 0x4c, 0x3e, 0xc3, 0xed, 0x27, 0xcf, 0x5d, 0x4f, 0xb5, 0x7d, 0xde, 0x38, 0xbc, 0xfe,
0x25, 0x32, 0xd8, 0x23, 0x98, 0x52, 0xb5, 0xda, 0xf7, 0x39, 0xdc, 0xb3, 0x0a, 0x94, 0x7a, 0x2b,
0x79, 0xe6, 0xe0, 0x4c, 0xbc, 0x21, 0xbd, 0x59, 0xb2, 0xc7, 0xf1, 0xc0, 0xf1, 0xfb, 0x29, 0x75,
0xa1, 0x21, 0x93, 0x01, 0x29, 0x1c, 0x9a, 0xe1, 0x2d, 0x55, 0xfc, 0x7b, 0xb8, 0xcb, 0x07, 0x33,
0xc5, 0x91, 0x0d, 0xc8, 0x45, 0x59, 0xef, 0xbe, 0x58, 0xc7, 0xc1, 0x1d, 0xd5, 0xf2, 0xcf, 0x1f,
0xe0, 0x6d, 0x21, 0x00, 0xcd, 0x42, 0xd8, 0x84, 0x85, 0xe3, 0xb2, 0x02, 0x1a, 0xa5, 0x89, 0x02,
0xa1, 0x96, 0xc6, 0xf7, 0x61, 0x68, 0x66, 0xe6, 0x65, 0x12, 0xb7, 0xf1, 0x49
0xAC, 0x93, 0xBB,
0x3C, 0x15, 0x5C, 0x5F, 0x25, 0xB0, 0x4C, 0x37, 0xA4, 0x2D, 0x85, 0x29, 0x1D, 0x7A, 0x9D, 0x2D,
0xD5, 0x79, 0xB5, 0x5D, 0xB1, 0x08, 0x20, 0x9C, 0xF0, 0x4C, 0x56, 0x27, 0x97, 0xF8, 0x7E, 0x3E,
0xCB, 0x94, 0x06, 0x05, 0x94, 0x00, 0x92, 0x9B, 0xB0, 0x5B, 0x06, 0xF6, 0xAF, 0xAA, 0x9C, 0xA5,
0xF0, 0x11, 0xA7, 0x8A, 0xCB, 0x0C, 0x11, 0xD6, 0x0C, 0x3D, 0x30, 0xAC, 0x51, 0x79, 0x5A, 0xB5,
0x7F, 0x11, 0x92, 0x74, 0x48, 0x82, 0x81, 0xBF, 0x3B, 0xFA, 0x93, 0xBF, 0x6B, 0x5B, 0x3F, 0x86,
0x96, 0x4F, 0xCC, 0x90, 0x12, 0xB2, 0x39, 0x8D, 0x68, 0x16, 0x7B, 0xC6, 0x87, 0xF1, 0xF5, 0x60,
0x62, 0x39, 0xFB, 0x10, 0x7E, 0x48, 0x7F, 0xDD, 0x82, 0x38, 0x38, 0x76, 0xB5, 0xCE, 0x21, 0x4B,
0xC9, 0x6F, 0x31, 0x8D, 0x23, 0x57, 0x3D, 0xB6, 0x6C, 0xEE, 0xC2, 0x0D, 0x11
};
#endif
@ -39,13 +39,39 @@ static const u8 rsa_key[128] =
static u8 acHeap[RSA_HEAP_SIZE] __attribute__ ((aligned (32)));
static SVCSignHeapContext acPool;
#define MENU_FILE "sdmc:/menu.srl"
/*
Profile
PROFILE_ENABLE
main.cかどこかにu32 profile[256]; u32 pf_cnt = 0;
*/
#ifndef SDK_FINALROM
#define PROFILE_MAX 0x100
#define PROFILE_ENABLE
/*
PRINT_MEMORY_ADDR SPrintfを行います()
FINALROM版でもコードが残るので注意してください
*/
#define PRINT_MEMORY_ADDR 0x02000200
//#ifdef SDK_FINALROM // FINALROMで無効化
//#undef PROFILE_ENABLE
//#endif
#ifdef PROFILE_ENABLE
#define PROFILE_MAX 16
u32 profile[PROFILE_MAX];
u32 pf_cnt = 0;
#define PUSH_PROFILE() (profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()))
#else
#define PUSH_PROFILE() ((void)0)
#endif
#ifdef PRINT_MEMORY_ADDR
static char* debugPtr = (char*)PRINT_MEMORY_ADDR;
#undef OS_TPrintf
//#define OS_TPrintf(...) (debugPtr = (char*)((u32)(debugPtr + STD_TSPrintf(debugPtr, __VA_ARGS__) + 0xf) & ~0xf))
#define OS_TPrintf(...) (debugPtr += STD_TSPrintf(debugPtr, __VA_ARGS__))
#endif
/***************************************************************
@ -57,7 +83,7 @@ static void PreInit(void)
{
static const OSMountInfo firmSettings[] =
{
{ 'A', OS_MOUNT_DEVICE_SD, OS_MOUNT_TGT_ROOT, 0, OS_MOUNT_RSC_MMEM, (OS_MOUNT_USR_R|OS_MOUNT_USR_W), 0, 0, "sdmc", "/" },
{ 'A', OS_MOUNT_DEVICE_SD, OS_MOUNT_TGT_ROOT, 0, OS_MOUNT_RSC_WRAM, (OS_MOUNT_USR_R|OS_MOUNT_USR_W), 0, 0, "sdmc", "/" },
{ 0 }
};
/*
@ -84,26 +110,16 @@ static void PreInit(void)
/***************************************************************
PostInit
MI_LoadHeader前にかなり(100msec)
OS_Init後にいろいろ処理したい
***************************************************************/
static void PostInit(void)
{
/*
*/
// ARM9領域を全クリア
if ( OS_GetResetParameter() )
{
MI_CpuClearFast( (void*)HW_FIRM_RESET_BUF_END, HW_TWL_MAIN_MEM_MAIN_END-HW_FIRM_RESET_BUF_END );
}
else
{
MI_CpuClearFast( (void*)HW_MAIN_MEM_MAIN, HW_MAIN_MEM_MAIN_SIZE );
}
DC_FlushAll();
// RSA用ヒープ設定
SVC_InitSignHeap( &acPool, acHeap, sizeof(acHeap) );
// HMAC用鍵準備
FS_SetDigestKey( NULL );
// FS/FATFS初期化
FS_InitFIRM();
}
/***************************************************************
@ -143,11 +159,11 @@ static BOOL CheckHeader(void)
// <20><EFBFBD>˜ÙÚ<E2809A>Å“K‰»<E280B0>ÏÝ
#ifndef FIRM_USE_TWLSDK_KEYS
if ( rhs->platform_code != PLATFORM_CODE_TWL_LIMITED || // TWL Limited only
!rhs->codec_mode || // TWL mode only
!rhs->enable_signature || // Should be use ROM header signature
#else
if ( // no check
if ( // no check
#endif
!rhs->codec_mode || // TWL mode only
// should be in main memory
HW_TWL_MAIN_MEM > (u32)rhs->main_ram_address ||
HW_TWL_MAIN_MEM > (u32)rhs->sub_ram_address ||
@ -166,7 +182,7 @@ static BOOL CheckHeader(void)
(u32)rhs->sub_ram_address + rhs->sub_size <= (u32)rhs->sub_entry_address ||
0 )
{
OS_TPrintf("Invalid ROM header for MENU Launcher!\n");
OS_TPrintf("Invalid ROM header for SDMC Launcher!\n");
return FALSE;
}
return TRUE;
@ -193,50 +209,95 @@ void TwlMain( void )
{
PreInit();
#ifndef SDK_FINALROM
// 0: before PXI
profile[pf_cnt++] = (u32)OS_TicksToMicroSecondsBROM(OS_GetTick());
#endif
PUSH_PROFILE();
OS_InitFIRM();
OS_EnableIrq();
#ifndef SDK_FINALROM
OS_InitTick();
// 1: after PXI
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
OS_EnableInterrupts();
SVC_InitSignHeap( &acPool, acHeap, sizeof(acHeap) );
#ifdef PROFILE_ENABLE
OS_InitTick();
#endif
// 1: after PXI
PUSH_PROFILE();
PXI_NotifyID( FIRM_PXI_ID_NULL );
PostInit();
#ifndef SDK_FINALROM
// 2: after PostInit
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
// 2: after PostInit
PUSH_PROFILE();
PXI_NotifyID( FIRM_PXI_ID_NULL );
// load menu
if ( MI_LoadHeader( &acPool, RSA_KEY_ADDR ) && CheckHeader() && MI_LoadStatic() )
STD_CopyString((char*)HW_TWL_FS_BOOT_SRL_PATH_BUF, MENU_FILE);
// 3: after FS_ResolveSrl
PUSH_PROFILE();
PXI_NotifyID( FIRM_PXI_ID_SET_PATH );
// 4: after PXI
PUSH_PROFILE();
if ( !FS_LoadHeader(&acPool, RSA_KEY_ADDR ) || !CheckHeader() )
{
#ifndef SDK_FINALROM
// 127: before Boot
pf_cnt = PROFILE_MAX-1;
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
{
int i;
OS_TPrintf("\n[ARM9] Begin\n");
for (i = 0; i < PROFILE_MAX; i++)
{
OS_TPrintf("0x%08X\n", profile[i]);
}
OS_TPrintf("\n[ARM9] End\n");
PXI_NotifyID( FIRM_PXI_ID_NULL );
}
#endif
OS_BootFromFIRM();
OS_TPrintf("Failed to call FS_LoadHeader() and/or CheckHeader().\n");
goto end;
}
// 5: after FS_LoadHeader
PUSH_PROFILE();
PXI_NotifyID( FIRM_PXI_ID_DONE_HEADER );
// 6: after PXI
PUSH_PROFILE();
AESi_SendSeed( FS_GetAesKeySeed() );
FS_DeleteAesKeySeed();
// 7: after AESi_SendSeed
PUSH_PROFILE();
if ( !FS_LoadStatic() )
{
OS_TPrintf("Failed to call FS_LoadStatic().\n");
goto end;
}
// 8: after FS_LoadStatic
PUSH_PROFILE();
PXI_NotifyID( FIRM_PXI_ID_DONE_STATIC );
// 9: after PXI
PUSH_PROFILE();
#ifdef PROFILE_ENABLE
{
int i;
OS_TPrintf("\n[ARM9] Begin\n");
for (i = 0; i < PROFILE_MAX; i++)
{
// OS_TPrintf("0x%08X\n", profile[i]);
if ( !profile[i] ) break;
OS_TPrintf("%2d: %7d usec", i, profile[i]);
if (i)
{
OS_TPrintf(" ( %7d usec )\n", profile[i]-profile[i-1]);
}
else
{
OS_TPrintf("\n");
}
}
OS_TPrintf("\n[ARM9] End\n");
PXI_NotifyID( FIRM_PXI_ID_NULL );
}
#endif
OS_BootFromFIRM();
end:
EraseAll();
// failed

View File

@ -1,58 +0,0 @@
#! make -f
#----------------------------------------------------------------------------
# Project: TwlFirm - libraries - fatfs
# File: Makefile
#
# Copyright 2007 Nintendo. All rights reserved.
#
# These coded instructions, statements, and computer programs contain
# proprietary information of Nintendo of America Inc. and/or Nintendo
# Company Ltd., and are protected by Federal copyright law. They may
# not be disclosed to third parties or copied or duplicated in any form,
# in whole or in part, without the prior written consent of Nintendo.
#
# $Date:: $
# $Rev:$
# $Author:$
#----------------------------------------------------------------------------
SUBDIRS =
SUBMAKES =
#----------------------------------------------------------------------------
# build ARM & THUMB libraries
TWL_CODEGEN_ALL ?= TRUE
# Codegen for sub processer
TWL_PROC = ARM7
INCDIR = \
$(ROOT)/build/libraries/fatfs/ARM7.TWL/include \
$(ROOT)/build/libraries/fatfs/ARM7.TWL/include/twl/fatfs/ARM7
SRCDIR = src
SRCS = \
fatfs_loader.c \
fatfs_firm.c \
TARGET_LIB = libfatfs_sp$(FIRM_LIBSUFFIX).a
#----------------------------------------------------------------------------
include $(TWL_IPL_RED_ROOT)/build/buildtools/commondefs
INSTALL_TARGETS = $(TARGETS)
INSTALL_DIR = $(FIRM_INSTALL_LIBDIR)
#----------------------------------------------------------------------------
do-build: $(TARGETS)
include $(TWL_IPL_RED_ROOT)/build/buildtools/modulerules
#===== End of Makefile =====

View File

@ -1,661 +0,0 @@
/*---------------------------------------------------------------------------*
Project: TwlIPL - libraries - fatfs
File: fatfs_firm.c
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Date:: $
$Rev$
$Author$
*---------------------------------------------------------------------------*/
#include <symbols.h>
#include <firm.h>
#include <rtfs.h>
#include <devices/sdif_reg.h>
#include <devices/sdif_ip.h>
#include <devices/sdmc_config.h>
#include <twl/devices/sdmc/ARM7/sdmc.h>
//#define USE_SPECULATIVE_READ
extern u32 NAND_FAT_PARTITION_COUNT;
#define DMA_PIPE 2
#define DMA_RECV 3
/*
SD関数
*/
extern volatile SDMC_ERR_CODE SDCARD_ErrStatus;
extern s16 SDCARD_SDHCFlag; /* SDHCカードフラグ */
extern SDPortContext* SDNandContext; /* NAND初期化パラメータ */
#ifdef USE_SPECULATIVE_READ
static u32 currentSector;
#endif
/*---------------------------------------------------------------------------*
Name: WaitFifoFull
Description: waiting to fill the SD FIFO
SDカードからの読み込みデータがFIFOから読み込める状態になるまで
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
static inline void WaitFifoFull( void )
{
while( (*SDIF_CNT & SDIF_CNT_FULL) == 0 )
{
if ( SDCARD_ErrStatus != SDMC_NORMAL ) // an error was occurred
{
break;
}
}
}
/*---------------------------------------------------------------------------*
Name: StopToRead
Description: stop to read from SD I/F
SDカードからの読み込みの完了処理を行います
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
static void StopToRead( void )
{
#ifdef NAND_FAT_PARTITION_COUNT
if ( *SDIF_CNT & SDIF_CNT_USEFIFO )
{
SD_AndFPGA( SD_INFO2,(~(SD_INFO2_ERROR_SET))); /* SD_INFO2のエラーフラグを全て落とす */
SD_OrFPGA( SD_INFO2_MASK, SD_INFO2_MASK_ERRSET); /* 全てのエラー割り込みを禁止 */
SD_OrFPGA( SD_INFO1_MASK, SD_INFO1_MASK_ALL_END); /* INFO1の access all end 割込み禁止 */
SD_TransEndFPGA(); /* 強制的にカード転送の終了処理 */
SD_StopTransmission(); /* 強制的にカード転送終了設定 */
// SDCARD_EndFlag
if ( SDCARD_ErrStatus )
{
//OS_TPrintf("R1_STATUS (1st).\n");
SD_SendStatus(); /* CMD13 addressed card sends its status register 発行、レスポンス待ち */
if( !SDCARD_ErrStatus ) /* エラーステータスの確認(エラー有り?)*/
{
u16 usRSP0;
//OS_TPrintf("R1_STATUS (2nd).\n");
SD_GetFPGA( usRSP0, SD_RSP0);
usRSP0 = (u16)(( usRSP0 & RSP_R1_CURRENT_STATE) >> 1); /* カレントステートを取り出す */
if((usRSP0 == CURRENT_STATE_DATA) || (usRSP0 == CURRENT_STATE_RCV)){ /* SDCARD Status が data rcv の時 */
SD_Command(SD_CMD_CMD | STOP_TRANSMISSION); /* CMD12StopTransmission発行処理 */
}
}
}
if(!(SDCARD_ErrStatus & SDMC_ERR_R1_STATUS)) /* コマンドレスポンス(R1)のカードステータスがエラーでないか? */
{
//OS_TPrintf("R1_STATUS (3rd).\n");
SD_CheckStatus(TRUE); /* コマンドレスポンス(R1)の Card Status チェック */
if(!(SDCARD_ErrStatus & SDMC_ERR_R1_STATUS)) /* コマンドレスポンス(R1)のカードステータスがエラーでないか? */
{
//OS_TPrintf("R1_STATUS (4th).\n");
SD_SendStatus(); /* カードステータスの取得コマンド発行 */
SD_CheckStatus(TRUE); /* コマンドレスポンス(R1)の Card Status チェック */
}
}
if( !SD_CheckFPGAReg( SD_STOP,SD_STOP_SEC_ENABLE ) ){
//OS_TPrintf("SD_StopTransmission.\n");
SD_StopTransmission(); /* カード転送終了をFPGAに通知CMD12発行 */
}
SD_DisableClock(); /* クロック供給停止 */
*SDIF_CNT = (*SDIF_CNT & ~SDIF_CNT_USEFIFO) | SDIF_CNT_FCLR; /* FIFO使用フラグOFF */
CC_EXT_MODE = CC_EXT_MODE_PIO; /* PIOモード(DMAモードOFF) */
//OS_TPrintf("DONE\n");
}
#else
if ( *SDIF_CNT & SDIF_CNT_USEFIFO )
{
if( !SD_CheckFPGAReg( SD_STOP,SD_STOP_SEC_ENABLE ) ){
SD_StopTransmission(); /* カード転送終了をFPGAに通知CMD12発行 */
}
SD_TransEndFPGA(); /* 転送終了処理(割り込みマスクを禁止に戻す) */
SD_DisableClock(); /* クロック供給停止 */
*SDIF_CNT = (*SDIF_CNT & ~SDIF_CNT_USEFIFO) | SDIF_CNT_FCLR; /* FIFO使用フラグOFF */
CC_EXT_MODE = CC_EXT_MODE_PIO; /* PIOモード(DMAモードOFF) */
}
#endif
}
/*---------------------------------------------------------------------------*
Name: StartToRead
Description: start to read from SD I/F
SDカードからの読み込みの開始処理を行います
Arguments: block begining sector to transfer
count number of setctors to transfer
Returns: None
*---------------------------------------------------------------------------*/
static void StartToRead(u32 block, u32 count)
{
#ifdef USE_SPECULATIVE_READ
if ( currentSector == block )
{
return;
}
StopToRead();
currentSector = block;
count = 0xFFFF;
#endif
*SDIF_FSC = count;
*SDIF_FDS = SECTOR_SIZE;
*SDIF_CNT = (*SDIF_CNT & ~(SDIF_CNT_FEIE | SDIF_CNT_FFIE)) | SDIF_CNT_FCLR | SDIF_CNT_USEFIFO;
CC_EXT_MODE = CC_EXT_MODE_DMA;
SDCARD_ErrStatus = SDMC_NORMAL;
SD_EnableClock();
SD_EnableSeccnt(count);
if ( SDCARD_SDHCFlag )
{
SD_MultiReadBlock( block );
}
else
{
SD_MultiReadBlock( block * SECTOR_SIZE );
}
}
/*
FATFS-SDMCの間にAESを組み込む
FATFSを迂回して設定することになる
*/
#define AES_GET_CNT_BITS(regValue, name) \
((regValue) & (REG_AES_AES_CNT_##name##_MASK))
static BOOL useAES = FALSE;
static AESCounter aesCounter;
/*---------------------------------------------------------------------------*
Name: FATFS_EnableAES
Description: enable AES data path
AES暗号化されていることを
IO関数に通知するためのAPIです
APIを呼び出した直後に読み込むデータのAESの初期値を指定
APIを呼び出す
Arguments: counter initial counter value
Returns: None
*---------------------------------------------------------------------------*/
void FATFS_EnableAES( const AESCounter* pCounter )
{
useAES = TRUE;
aesCounter = *pCounter;
}
/*---------------------------------------------------------------------------*
Name: FATFS_DisableAES
Description: bypass AES
AES暗号化されていないことを
IO関数に通知するためのAPIです
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
void FATFS_DisableAES( void )
{
useAES = FALSE;
}
/*---------------------------------------------------------------------------*
Name: ReadNormal
Description: normal read
NAND/SDカードを読み込みます
Arguments: block: source sector number in NAND
dest: dest address (4 bytes alignment)
count: sectors to transfer
Returns: 0 if success
*---------------------------------------------------------------------------*/
static u16 ReadNormal(u32 block, void *dest, u16 count)
{
#if 1 // use TIMING_SD_1 or not
MINDmaConfig config =
{
MI_NDMA_NO_INTERVAL,
MI_NDMA_INTERVAL_PS_1,
MI_NDMA_BWORD_128,
SECTOR_SIZE/4
};
// OS_TPrintf("ReadNormal(0x%X, 0x%08X, 0x%X) is calling.\n", block, dest, count);
#ifdef USE_SPECULATIVE_READ
if (block == currentSector)
{
//StartToRead( block, 1 );
WaitFifoFull();
MI_NDmaRecvAsync( DMA_PIPE, SDIF_FI, dest, SECTOR_SIZE, NULL, NULL );
block++;
dest = (u8*)dest + SECTOR_SIZE;
count--;
currentSector++;
if (count == 0)
{
MI_WaitNDma( DMA_PIPE );
return SDCARD_ErrStatus;
}
// ここまでで次のFIFO FULL前であると仮定しているが、問題ない
}
#endif
MI_NDmaRecvExAsync_Dev( DMA_RECV, SDIF_FI, dest, (u32)(count * SECTOR_SIZE), NULL, NULL, &config, MI_NDMA_TIMING_SD_1 );
StartToRead( block, count );
if ( SDCARD_ErrStatus != SDMC_NORMAL )
{
goto err;
}
#else
u32 offset = 0; // in bytes
// OS_TPrintf("ReadNormal(0x%X, 0x%08X, 0x%X) is calling.\n", block, dest, count);
MI_NDmaRecvAsync_SetUp( DMA_RECV, (void*)SDIF_FI, dest, SECTOR_SIZE, NULL, NULL );
StartToRead( block, count );
if ( SDCARD_ErrStatus != SDMC_NORMAL )
{
goto err;
}
while ( count * SECTOR_SIZE > offset )
{
WaitFifoFull();
if ( SDCARD_ErrStatus != SDMC_NORMAL )
{
goto err;
}
// MI_NDMA_REG( DMA_RECV, MI_NDMA_REG_DAD_WOFFSET ) = (u32)dest + offset;
MIi_SetNDmaDest( DMA_RECV, (u8*)dest + offset );
MI_NDmaRestart( DMA_RECV );
offset += SECTOR_SIZE;
}
#endif
MI_WaitNDma( DMA_RECV );
#ifdef USE_SPECULATIVE_READ
currentSector += count;
#else
StopToRead();
#endif
return SDCARD_ErrStatus;
err:
MI_StopNDma( DMA_RECV );
#ifdef USE_SPECULATIVE_READ
currentSector = 0xFFFFFFFF;
#endif
StopToRead();
return SDCARD_ErrStatus;
}
/*---------------------------------------------------------------------------*
Name: ReadAES
Description: AES read
AESをかけながらNAND/SDカードを読み込みます
AESの鍵の設定はあらかじめ行っておく必要があります
AESの初期値の設定はFATFS_EnableAESの引数から計算されます
Arguments: block: source sector number in NAND
dest: dest address (4 bytes alignment)
count: sectors to transfer
Returns: 0 if success
*---------------------------------------------------------------------------*/
#define PIPE_SIZE 64
static u16 ReadAES(u32 block, void *dest, u16 count)
{
u32 offset = 0; // in bytes
// OS_TPrintf("ReadAES(0x%X, 0x%08X, 0x%X) is calling.\n", block, dest, count);
MI_NDmaPipeAsync_SetUp( DMA_PIPE, (void*)SDIF_FI, (void*)REG_AES_IFIFO_ADDR, PIPE_SIZE, NULL, NULL );
StartToRead( block, count );
if ( SDCARD_ErrStatus != SDMC_NORMAL )
{
goto err;
}
/*
AESのセットアップDMA設定
*/
AES_Reset();
AES_Reset();
AES_DmaRecv( DMA_RECV, dest, (u32)(count * SECTOR_SIZE), NULL, NULL );
AES_SetCounter( &aesCounter );
AES_Run( AES_MODE_CTR, 0, (u32)(count * (SECTOR_SIZE/AES_BLOCK_SIZE)), NULL, NULL );
// update for next read
AES_AddToCounter( &aesCounter, (u32)(count * (SECTOR_SIZE/AES_BLOCK_SIZE)) );
while ( count * SECTOR_SIZE > offset )
{
while ( AES_GET_CNT_BITS( reg_AES_AES_CNT, IFIFO_CNT ) )
{
}
if ( (offset & (SECTOR_SIZE-1)) == 0 )
{
WaitFifoFull();
if ( SDCARD_ErrStatus != SDMC_NORMAL )
{
goto err;
}
}
MI_NDmaRestart( DMA_PIPE );
offset += PIPE_SIZE;
}
MI_WaitNDma( DMA_PIPE );
#ifdef USE_SPECULATIVE_READ
currentSector += count;
#else
StopToRead();
#endif
MI_WaitNDma( DMA_RECV );
return SDCARD_ErrStatus;
err:
MI_StopNDma( DMA_RECV );
MI_StopNDma( DMA_PIPE );
#ifdef USE_SPECULATIVE_READ
currentSector = 0xFFFFFFFF;
#endif
StopToRead();
AES_Reset();
return SDCARD_ErrStatus;
}
/*---------------------------------------------------------------------------*
Name: nandRtfsIoFirm
Description:
Readに対してのみ使IO関数です
AESの有無の判定は断片化時に未検証です
()
Arguments: driveno :
block :
buffer :
count :
reading : TRUE
Returns: TRUE/FALSE
*---------------------------------------------------------------------------*/
static BOOL nandRtfsIoFirm( int driveno, u32 block, void* buffer, u16 count, BOOL reading )
{
u16 result;
#pragma unused( driveno)
sdmcSelect( (u16)SDMC_PORT_NAND);
if( reading )
{
result = useAES ?
ReadAES( block, buffer, count ) :
ReadNormal( block, buffer, count );
}
else
{
SdmcResultInfo SdResult;
result = sdmcWriteFifo( buffer, count, block, NULL, &SdResult );
}
return result ? FALSE : TRUE;
}
/*---------------------------------------------------------------------------*
Name: sdmcRtfsIoFirm
Description:
Readに対してのみ使IO関数です
Arguments: driveno :
block :
buffer :
count :
reading : TRUE
Returns: TRUE/FALSE
*---------------------------------------------------------------------------*/
static BOOL sdmcRtfsIoFirm( int driveno, u32 block, void* buffer, u16 count, BOOL reading )
{
u16 result;
#pragma unused( driveno)
sdmcSelect( (u16)SDMC_PORT_CARD );
if( reading )
{
result = useAES ?
ReadAES( block, buffer, count ) :
ReadNormal( block, buffer, count );
}
else
{
SdmcResultInfo SdResult;
result = sdmcWriteFifo( buffer, count, block, NULL, &SdResult );
}
return result ? FALSE : TRUE;
}
/*---------------------------------------------------------------------------*
Name: nandRtfsAttachFirm
Description: sdmcドライバをドライブに割り当てる
IO関数を使用するように初期化します
Arguments: driveno :
Returns:
*---------------------------------------------------------------------------*/
#define nandRtfsCtrl FATFSi_nandRtfsCtrl
extern int nandRtfsCtrl( int driveno, int opcode, void* pargs);
static BOOL nandRtfsAttachFirm( int driveno, int partition_no)
{
BOOLEAN result;
DDRIVE pdr;
pdr.dev_table_drive_io = nandRtfsIoFirm;
pdr.dev_table_perform_device_ioctl = nandRtfsCtrl;
pdr.register_file_address = (dword) 0; /* Not used */
pdr.interrupt_number = 0; /* Not used */
pdr.drive_flags = (DRIVE_FLAGS_VALID | DRIVE_FLAGS_PARTITIONED);//DRIVE_FLAGS_FAILSAFE;
pdr.partition_number = partition_no; /* Not used */
pdr.pcmcia_slot_number = 0; /* Not used */
pdr.controller_number = 0;
pdr.logical_unit_number = 0;
switch( partition_no )
{
case 0:
result = rtfs_attach( driveno, &pdr, "SD1p0" ); //構造体がFSライブラリ側にコピーされる
break;
case 1:
result = rtfs_attach( driveno, &pdr, "SD1p1" ); //構造体がFSライブラリ側にコピーされる
break;
case 2:
result = rtfs_attach( driveno, &pdr, "SD1p2" ); //構造体がFSライブラリ側にコピーされる
break;
case 3:
result = rtfs_attach( driveno, &pdr, "SD1p3" ); //構造体がFSライブラリ側にコピーされる
break;
default:
result = FALSE;
break;
}
return result;
}
/*---------------------------------------------------------------------------*
Name: sdmcRtfsAttachFirm
Description: sdmcドライバをドライブに割り当てる
IO関数を使用するように初期化します
Arguments: driveno :
Returns:
*---------------------------------------------------------------------------*/
#define sdmcRtfsCtrl FATFSi_sdmcRtfsCtrl
extern int sdmcRtfsCtrl( int driveno, int opcode, void* pargs);
static BOOL sdmcRtfsAttachFirm( int driveno)
{
BOOLEAN result;
DDRIVE pdr;
pdr.dev_table_drive_io = sdmcRtfsIoFirm;
pdr.dev_table_perform_device_ioctl = sdmcRtfsCtrl;
pdr.register_file_address = (dword) 0; /* Not used */
pdr.interrupt_number = 0; /* Not used */
pdr.drive_flags = 0;//DRIVE_FLAGS_FAILSAFE;
pdr.partition_number = 0; /* Not used */
pdr.pcmcia_slot_number = 0; /* Not used */
pdr.controller_number = 0;
pdr.logical_unit_number = 0;
result = rtfs_attach( driveno, &pdr, "SD0" ); //構造体がFSライブラリ側にコピーされる
return result;
}
/*---------------------------------------------------------------------------*
Name: FATFS_InitFIRM
Description: init file system
FATFSを初期化します
FATFS_Initの使用しない部分を省略しているだけです
NANDコンテキストが残っているなら
FATFS用のメモリヒープ(OS_ARENA_MAIN_SUBPRIVの関連とヒープ)
Arguments: nandContext context of nand driver's previous life
Returns: None
*---------------------------------------------------------------------------*/
BOOL FATFS_InitFIRM( void* nandContext )
{
/* RTFSライブラリを初期化 */
if( !rtfs_init() )
{
return FALSE;
}
/* NAND初期化パラメータの設定 */
SDNandContext = (SDPortContext*)nandContext;
#ifdef USE_SPECULATIVE_READ
currentSector = 0xFFFFFFFF;
#endif
/* SDドライバ初期化 */
if ( sdmcInit( SDMC_NOUSE_DMA, SDMC_NOUSE_DMA ) != SDMC_NORMAL )
{
return FALSE;
}
return TRUE;
}
/*---------------------------------------------------------------------------*
Name: FATFS_MountDriveFIRM
Description: mount specified partition
NANDまたはSDカードのみ対応しています
APIでマウントした場合IO関数を使用するようになります
Arguments: driveno drive number "A:" is 0
media media type
partition_no pertition number
Returns: None
*---------------------------------------------------------------------------*/
BOOL FATFS_MountDriveFIRM( int driveno, FATFSMediaType media, int partition_no )
{
if ( media == FATFS_MEDIA_TYPE_NAND )
{
// CAUTION!: 同じ関数を2回呼び出す理由について要確認。
if ( !nandRtfsAttachFirm( driveno, partition_no ) || nandRtfsAttachFirm( driveno, partition_no ) )
{
return FALSE;
}
}
else
{
if ( partition_no ) // support only 0
{
return FALSE;
}
// CAUTION!: 同じ関数を2回呼び出す理由について要確認。
if ( !sdmcRtfsAttachFirm( driveno ) || sdmcRtfsAttachFirm( driveno ) )
{
return FALSE;
}
}
return TRUE;
}
/*---------------------------------------------------------------------------*
Name: FATFS_UnmountDriveFIRM
Description: unmount specified partition
Arguments: driveno drive number "A:" is 0
Returns: None
*---------------------------------------------------------------------------*/
BOOL FATFS_UnmountDriveFIRM( int driveno )
{
#ifdef USE_SPECULATIVE_READ
StopToRead();
currentSector = 0xFFFFFFFF;
#endif
return TRUE;
return rtfs_detach( driveno );
}

View File

@ -1,607 +0,0 @@
/*---------------------------------------------------------------------------*
Project: TwlIPL - libraries - fatfs
File: fatfs_loader.c
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Date:: $
$Rev$
$Author$
*---------------------------------------------------------------------------*/
#include <symbols.h>
#include <firm.h>
#include <twl/os/common/format_rom.h>
#include <rtfs.h>
#include <devices/sdif_reg.h>
/*
PROFILE_ENABLE
main.cかどこかにu32 profile[256]; u32 pf_cnt;
*/
//#define PROFILE_ENABLE
#define MODULE_ALIGNMENT 0x10 // 16バイト単位で読み込む
//#define MODULE_ALIGNMENT 0x200 // 512バイト単位で読み込む
#define RoundUpModuleSize(value) (((value) + MODULE_ALIGNMENT - 1) & -MODULE_ALIGNMENT)
#ifdef SDK_FINALROM // FINALROMで無効化
#undef PROFILE_ENABLE
#endif
#ifdef PROFILE_ENABLE
#define PROFILE_PXI_SEND 0x10000000
#define PROFILE_PXI_RECV 0x20000000
extern u32 profile[];
extern u32 pf_cnt;
#endif
static ROM_Header* const rh= (ROM_Header*)HW_TWL_ROM_HEADER_BUF;
static int menu_fd = -1;
/*---------------------------------------------------------------------------*
Name: FATFS_OpenRecentMenu
Description: open recent menu file
IDを
menu_fdにセットします
eTicketの処理
Arguments: driveno drive number ('A' is 0)
Returns: None
*---------------------------------------------------------------------------*/
BOOL FATFS_OpenRecentMenu( int driveno )
{
char *menufile = (char*)L"A:\\title\\00010001\\52434e4c\\content\\12123434.app";
if (driveno < 0 || driveno >= 26)
{
return FALSE;
}
menufile[0] = (char)('A' + driveno);
menu_fd = po_open((u8*)menufile, PO_BINARY, 0);
if (menu_fd < 0)
{
return FALSE;
}
FATFS_SaveSrlFilename(FATFS_MEDIA_TYPE_NAND, menufile);
return TRUE;
}
/*---------------------------------------------------------------------------*
Name: FATFS_OpenSpecifiedSrl
Description: open specified menu file
IDをmenu_fdにセットします
Arguments: menufile target filename
Returns: None
*---------------------------------------------------------------------------*/
BOOL FATFS_OpenSpecifiedSrl( const char* menufile )
{
menu_fd = po_open((u8*)menufile, PO_BINARY, 0);
if (menu_fd < 0)
{
return FALSE;
}
FATFS_SaveSrlFilename(FATFS_MEDIA_TYPE_SD, menufile);
return TRUE;
}
static void OverrideDefaultMountInfo( void )
{
static const OSMountInfo DefaultSettings[] =
{
{ 'A', OS_MOUNT_DEVICE_SD, OS_MOUNT_TGT_ROOT, 0, OS_MOUNT_RSC_MMEM, (OS_MOUNT_USR_R|OS_MOUNT_USR_W), 0, 0, "sdmc", "/" },
{ 'B', OS_MOUNT_DEVICE_NAND, OS_MOUNT_TGT_ROOT, 0, OS_MOUNT_RSC_WRAM, 0, 0, 0, "nand", "/" }, // ユーザーはこのアーカイブを使えない(RW不可)
{ 'C', OS_MOUNT_DEVICE_NAND, OS_MOUNT_TGT_ROOT, 1, OS_MOUNT_RSC_WRAM, 0, 0, 0, "nand2", "/" }, // ユーザーはこのアーカイブを使えない(RW不可)
{ 'D', OS_MOUNT_DEVICE_NAND, OS_MOUNT_TGT_DIR, 0, OS_MOUNT_RSC_MMEM, (OS_MOUNT_USR_R|OS_MOUNT_USR_W), 0, 0, "shared2", "nand2:/shared2" },
{ 'E', OS_MOUNT_DEVICE_NAND, OS_MOUNT_TGT_DIR, 0, OS_MOUNT_RSC_MMEM, (OS_MOUNT_USR_R|OS_MOUNT_USR_W), 0, 0, "photo", "nand2:/photo" },
{ 'F', OS_MOUNT_DEVICE_NAND, OS_MOUNT_TGT_FILE, 0, OS_MOUNT_RSC_MMEM, (OS_MOUNT_USR_R|OS_MOUNT_USR_W), 0, 0, "dataPrv", NULL },
{ 'G', OS_MOUNT_DEVICE_NAND, OS_MOUNT_TGT_FILE, 0, OS_MOUNT_RSC_MMEM, (OS_MOUNT_USR_R|OS_MOUNT_USR_W), 0, 0, "dataPub", NULL },
{ 0, },
};
MI_CpuCopy8(DefaultSettings, (char*)HW_TWL_FS_MOUNT_INFO_BUF, sizeof(DefaultSettings));
}
/*---------------------------------------------------------------------------*
Name: FATFS_SaveSrlFilename
Description: store filename to HW_TWL_FS_BOOT_SRL_PATH_BUF
HW_TWL_FS_BOOT_SRL_PATH_BUFに書き込みます
Arguments: media media type
filename target filename
Returns: None
*---------------------------------------------------------------------------*/
BOOL FATFS_SaveSrlFilename( FATFSMediaType media, const char* filename )
{
char* dest = (char*)HW_TWL_FS_BOOT_SRL_PATH_BUF;
const char nandStr[] = "nand:/";
const char sdmcStr[] = "sdmc:/";
if ( filename[2] == ':' ) // ドライブレターは削除
{
filename += 4;
}
if ( filename[0] == '\\' ) // 先頭のパス記号は削除
{
filename += 2;
}
switch( media )
{
case FATFS_MEDIA_TYPE_NAND:
MI_CpuCopy8(nandStr, dest, sizeof(nandStr)-1);
dest += sizeof(nandStr)-1;
break;
case FATFS_MEDIA_TYPE_SD:
MI_CpuCopy8(sdmcStr, dest, sizeof(sdmcStr)-1);
dest += sizeof(sdmcStr)-1;
break;
default:
return FALSE;
}
// unicode詰め (ASCII only)
while ( dest < (char*)HW_TWL_ROM_HEADER_BUF )
{
if ( *filename == '\\' ) // パス記号変換
{
*dest++ = '/';
filename++;
}
else if ( *filename != 0 ) // 通常コピー
{
*dest++ = *filename++;
}
else if ( *(filename + 1) != 0 ) // \0が連続していないならunicodeの詰めるべき隙間
{
filename++; // omit
}
else // \0が連続しているなら終端
{
MI_CpuClear8( dest, HW_TWL_ROM_HEADER_BUF - (u32)dest ); // 残りバッファのクリア
OverrideDefaultMountInfo(); // デフォルトマウント情報を書いておく
break;
}
}
OS_TPrintf("Stored: %s\n", (char*)HW_TWL_FS_BOOT_SRL_PATH_BUF);
return TRUE;
}
/*---------------------------------------------------------------------------*
Name: FATFS_GetSrlDescriptor
Description: retrieve current file descriptor
menu_fdを返します
Arguments: None
Returns: int
*---------------------------------------------------------------------------*/
int FATFS_GetSrlDescriptor( void )
{
return menu_fd;
}
/*---------------------------------------------------------------------------*
Name: FATFS_SetSrlDescriptor
Description: set current file descriptor that was opened outside
IDをmenu_fdにセットします
Arguments: None
Returns: int
*---------------------------------------------------------------------------*/
void FATFS_SetSrlDescriptor( int fd )
{
menu_fd = fd;
}
#define HEADER_SIZE 0x1000
#define AUTH_SIZE ROM_HEADER_SIGN_TARGET_SIZE
/*---------------------------------------------------------------------------*
Name: FATFS_LoadBuffer
Description: load data and pass to ARM9 via WRAM[B]
LoadBufferメカニズムでFAT中のファイルの内容をARM9に転送します
[LoadBufferメカニズム]
WRAM[B]ARM7,ARM9間のデータ転送を行います
WRAM[B]
1ARM9へ
FIRM_PXI_ID_LOAD_PIRIODを送信します
2使
使ARM9側に割り当てられているときはARM7側に
[使]
WRAM[B]ARM7側に倒しておくこと
[]
offsetとsizeはARM9に通知されません
SRLファイルを読み込む場合はROMヘッダを参照できれば十分です
(ROMヘッダ部分は元から知っているはず)
:
ARM7/ARM9側で歩調を合わせられることを
()
PXIコールバック
APIがデータをWRAMに格納した後
destとsizeを通知するという形でOKではないか
()
使po_readした方が速い
ARM9からデータ内容を触る予定がないならAPIを使わず
Arguments: offset offset of the file to load (512 bytes alignment)
size size to load
Returns: None
*---------------------------------------------------------------------------*/
BOOL FATFS_LoadBuffer(u32 offset, u32 size)
{
u8* base = (u8*)HW_FIRM_LOAD_BUFFER_BASE;
static int count = 0;
// seek first
//OS_TPrintf("po_lseek(offset=0x%x);\n", offset);
if (po_lseek(menu_fd, (s32)offset, PSEEK_SET) < 0)
{
return FALSE;
}
#ifdef PROFILE_ENABLE
// x2: after Seek
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
// loading loop
while (size > 0)
{
u8* dest = base + count * HW_FIRM_LOAD_BUFFER_UNIT_SIZE; // target buffer address
u32 unit = size < HW_FIRM_LOAD_BUFFER_UNIT_SIZE ? size : HW_FIRM_LOAD_BUFFER_UNIT_SIZE; // size
while (MI_GetWramBankMaster_B(count) != MI_WRAM_ARM7) // waiting to be master
{
}
#ifdef PROFILE_ENABLE
// x3...: after to wait ARM9
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
//OS_TPrintf("po_read(dest=%p, unit=0x%x);\n", dest, unit);
#if 1 /* 0: 2KBバグパッチ */
if (po_read(menu_fd, (u8*)dest, (int)unit) < 0) // reading
{
return FALSE;
}
#else
{
u32 done = 0;
while (done < unit)
{
u8* dest2 = dest + done;
u32 unit2 = (unit - done) < 2048 ? (unit - done) : 2048;
//OS_TPrintf(" po_read(dest=%p, unit=0x%x) ... ", dest2, unit2);
if (po_read(menu_fd, (u8*)dest2, (int)unit2) < 0) // reading
{
return FALSE;
}
done += unit2;
//OS_TPrintf("done\n");
}
}
#endif
#ifdef PROFILE_ENABLE
// x4...: before PXI
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
profile[pf_cnt++] = (u32)PROFILE_PXI_SEND | FIRM_PXI_ID_LOAD_PIRIOD; // checkpoint
#endif
PXI_NotifyID( FIRM_PXI_ID_LOAD_PIRIOD );
count = (count + 1) % HW_FIRM_LOAD_BUFFER_UNIT_NUMS;
size -= unit;
}
return TRUE;
}
/*---------------------------------------------------------------------------*
Name: FATFS_LoadHeader
Description: load header
SRLのROMヘッダ部分を読み込みARM9に渡します
ARM9へ FIRM_PXI_ID_LOAD_HEADER
ARM9から FIRM_PXI_ID_AUTH_HEADER
ROMヘッダが格納されたと
seedデータを16バイト受信します
seedはSeedAとKeyCに設定されます
makerom.TWLまたはIPLの仕様に依存します
Arguments: None
Returns: TRUE if success
*---------------------------------------------------------------------------*/
BOOL FATFS_LoadHeader( void )
{
// open the file in FATFS_InitFIRM()
if (menu_fd < 0)
{
return FALSE;
}
#ifdef PROFILE_ENABLE
// 10: before PXI
pf_cnt = 0x10;
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
profile[pf_cnt++] = (u32)PROFILE_PXI_SEND | FIRM_PXI_ID_LOAD_HEADER; // checkpoint
#endif
// load header without AES
PXI_NotifyID( FIRM_PXI_ID_LOAD_HEADER );
FATFS_DisableAES();
if (!FATFS_LoadBuffer(0, AUTH_SIZE) ||
#ifdef PROFILE_ENABLE
// 12: after to load half
((profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick())), FALSE) ||
#endif
!FATFS_LoadBuffer(AUTH_SIZE, HEADER_SIZE - AUTH_SIZE) ||
#ifdef PROFILE_ENABLE
// 1x: after to load remain
((profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick())), FALSE) ||
#endif
PXI_RecvID() != FIRM_PXI_ID_AUTH_HEADER )
{
return FALSE;
}
#ifdef PROFILE_ENABLE
// 1x: after PXI
profile[pf_cnt++] = (u32)PROFILE_PXI_RECV | FIRM_PXI_ID_AUTH_HEADER; // checkpoint
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
// set id depends on game_code and seed to use (or all?)
AESi_InitKeysForApp((u8*)rh->s.game_code);
AESi_RecvSeed( rh->s.developer_encrypt );
return TRUE;
}
/*---------------------------------------------------------------------------*
Name: FATFSi_GetCounter
Description: get counter
offsetに対応したAESのカウンタ値を計算します
makerom.TWL内のコードに依存します
Arguments: offset offset from head of ROM_Header
Returns: counter
*---------------------------------------------------------------------------*/
static AESCounter* FATFSi_GetCounter( u32 offset )
{
static AESCounter counter;
MI_CpuCopy8( rh->s.main_static_digest, &counter, 16 );
AES_AddToCounter( &counter, (offset - rh->s.aes_target_rom_offset) / AES_BLOCK_SIZE );
return &counter;
}
/*---------------------------------------------------------------------------*
Name: FATFSi_SetupAES
Description: setup whiere to use AES
AES暗号化されたデータを読み込むためのセットアップを行います
fatfs_sdmc.cのドライバを使用していることが条件となります
(TwlSDK標準で行う場合は)
APIを呼び出す前にROMヘッダが
AES領域をまたぐ場合は (
)
makerom.TWLまたはIPLの使用に依存します
Arguments: offset offset of region from head of ROM_Header
size size of region
Returns: size to transfer once
*---------------------------------------------------------------------------*/
static u32 FATFSi_SetupAES( u32 offset, u32 size )
{
u32 aes_offset = rh->s.aes_target_rom_offset;
u32 aes_end = aes_offset + RoundUpModuleSize(rh->s.aes_target_size);
u32 end = offset + RoundUpModuleSize(size);
if ( rh->s.enable_aes )
{
if ( offset >= aes_offset && offset < aes_end )
{
if ( end > aes_end )
{
size = aes_end - offset;
}
AES_WaitKey();
AES_LoadKey( AES_KEY_SLOT_A );
FATFS_EnableAES( FATFSi_GetCounter( offset ) );
}
else
{
if ( offset < aes_offset && offset + size > aes_offset )
{
size = aes_offset - offset;
}
FATFS_DisableAES();
}
}
else
{
FATFS_DisableAES();
}
return size;
}
/*---------------------------------------------------------------------------*
Name: FATFSi_LoadModule
Description: transfer module to ARM9 via WRAM[B]
FATFSi_LoadBufferの上位APIです
AES境界をまたぐときに2回に分けるだけです
Arguments: offset offset from head of ROM_Header
size size to load
Returns: TRUE if success
*---------------------------------------------------------------------------*/
static /*inline*/ BOOL FATFSi_LoadModule(u32 offset, u32 size)
{
size = RoundUpModuleSize( size ); // アラインメント調整
while ( size > 0 )
{
u32 unit = FATFSi_SetupAES( offset, size ); // 一度の転送サイズ
if ( !FATFS_LoadBuffer( offset, unit ) )
{
return FALSE;
}
offset += unit;
size -= unit;
}
return TRUE;
}
/*---------------------------------------------------------------------------*
Name: FATFS_LoadStatic
Description: load static binary
ARM9/ARM7のStaticおよびLTD Staticを読み込みます
ARM9へFIRM_PXI_ID_LOAD_*_STATICを送信します
ARM9からFIRM_PXI_ID_AUTH_*_STATICを受信します
0PXI通信すら行いません
APIを呼び出す前にROMヘッダが
ARM9側と異なり
()
Arguments: None
Returns: TRUE if success
*---------------------------------------------------------------------------*/
BOOL FATFS_LoadStatic( void )
{
#ifdef PROFILE_ENABLE
// 30: LoadStatic
pf_cnt = 0x30;
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
profile[pf_cnt++] = (u32)PROFILE_PXI_SEND | FIRM_PXI_ID_LOAD_STATIC; // checkpoint
#endif
PXI_NotifyID( FIRM_PXI_ID_LOAD_STATIC );
// load ARM9 static region without AES
if ( rh->s.main_size > 0 )
{
#ifdef PROFILE_ENABLE
// 31: before PXI
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
if ( !FATFSi_LoadModule( rh->s.main_rom_offset, rh->s.main_size ) )
{
return FALSE;
}
}
// load ARM7 static region without AES
if ( rh->s.sub_size > 0 )
{
#ifdef PROFILE_ENABLE
// 50: before PXI
pf_cnt = 0x50;
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
if ( !FATFSi_LoadModule( rh->s.sub_rom_offset, rh->s.sub_size ) )
{
return FALSE;
}
}
// load ARM9 extended static region with AES
if ( rh->s.main_ltd_size > 0 )
{
#ifdef PROFILE_ENABLE
// 70: before PXI
pf_cnt = 0x70;
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
if ( !FATFSi_LoadModule( rh->s.main_ltd_rom_offset, rh->s.main_ltd_size ) )
{
return FALSE;
}
}
// load ARM7 extended static region with AES
if ( rh->s.sub_ltd_size > 0 )
{
#ifdef PROFILE_ENABLE
// 90: before PXI
pf_cnt = 0x90;
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
if ( !FATFSi_LoadModule( rh->s.sub_ltd_rom_offset, rh->s.sub_ltd_size ) )
{
return FALSE;
}
}
// waiting result
if ( PXI_RecvID() != FIRM_PXI_ID_AUTH_STATIC )
{
return FALSE;
}
#ifdef PROFILE_ENABLE
// 9x: after PXI
profile[pf_cnt++] = (u32)PROFILE_PXI_RECV | FIRM_PXI_ID_AUTH_STATIC; // checkpoint
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
return TRUE;
}
/*---------------------------------------------------------------------------*
Name: FATFS_Boot
Description: boot
ROMヘッダの情報を引数にOSi_Bootを呼び出すだけです
APIを呼び出す前にROMヘッダが
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
void FATFS_Boot( void )
{
OS_BootWithRomHeaderFromFIRM( rh );
}

View File

@ -21,7 +21,7 @@ include $(TWL_IPL_RED_ROOT)/build/buildtools/commondefs
#----------------------------------------------------------------------------
SUBDIRS = ARM9 ARM7
SUBDIRS = ARM9
#----------------------------------------------------------------------------

View File

@ -29,8 +29,6 @@ SRCDIR = . ../common
SRCS = \
mi_init_mainMemory.c \
mi_loader.c \
mi_exDma.c \
TARGET_LIB = libmi$(FIRM_LIBSUFFIX).a

View File

@ -1,507 +0,0 @@
/*---------------------------------------------------------------------------*
Project: TwlIPL - libraries - mi
File: mi_loader.c
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Date:: $
$Rev$
$Author$
*---------------------------------------------------------------------------*/
#include <twl.h>
#include <firm.h>
#include <twl/os/common/format_rom.h>
/*
PROFILE_ENABLE
main.cかどこかにu32 profile[256]; u32 pf_cnt;
*/
//#define PROFILE_ENABLE
#ifdef SDK_FINALROM // FINALROMで無効化
#undef PROFILE_ENABLE
#endif
#ifdef PROFILE_ENABLE
#define PROFILE_PXI_SEND 0x10000000
#define PROFILE_PXI_RECV 0x20000000
#define PROFILE_SHA1 0xa0000000
#define PROFILE_RSA 0xb0000000
extern u32 profile[];
extern u32 pf_cnt;
#endif
static ROM_Header* const rh = (ROM_Header*)HW_TWL_ROM_HEADER_BUF;
#define HEADER_SIZE 0x1000
#define AUTH_SIZE 0xe00
#define RSA_BLOCK_SIZE 128
#define HASH_UNIT 0x1000 // TODO: optimizing to maximize cache efficiency
static const u8 s_digestDefaultKey[ SVC_SHA1_BLOCK_SIZE ] = {
0x21, 0x06, 0xc0, 0xde,
0xba, 0x98, 0xce, 0x3f,
0xa6, 0x92, 0xe3, 0x9d,
0x46, 0xf2, 0xed, 0x01,
0x76, 0xe3, 0xcc, 0x08,
0x56, 0x23, 0x63, 0xfa,
0xca, 0xd4, 0xec, 0xdf,
0x9a, 0x62, 0x78, 0x34,
0x8f, 0x6d, 0x63, 0x3c,
0xfe, 0x22, 0xca, 0x92,
0x20, 0x88, 0x97, 0x23,
0xd2, 0xcf, 0xae, 0xc2,
0x32, 0x67, 0x8d, 0xfe,
0xca, 0x83, 0x64, 0x98,
0xac, 0xfd, 0x3e, 0x37,
0x87, 0x46, 0x58, 0x24,
};
/*---------------------------------------------------------------------------*
Name: CheckRomCertificate
Description: check the certification in the ROM
ROMヘッダに付加された証明書のチェックを行います
makerom.TWL内のコードに依存します
Arguments: pool pointer to the SVCSignHeapContext
pCert pointer to the certification
pCAPubKey pointer to the public key for the certification
gameCode initial code
Returns: TRUE if success
*---------------------------------------------------------------------------*/
static BOOL CheckRomCertificate( SVCSignHeapContext* pool, const RomCertificate *pCert, const void* pCAPubKey, u32 gameCode )
{
u8 digest[SVC_SHA1_DIGEST_SIZE];
u8 md[SVC_SHA1_DIGEST_SIZE];
int i;
BOOL result = TRUE;
// 証明書ヘッダのマジックナンバーチェック
if( pCert->header.magicNumber != TWL_ROM_CERT_MAGIC_NUMBER ||
// 証明書ヘッダとROMヘッダのゲームコード一致チェック
pCert->header.gameCode != gameCode )
{
result = FALSE;
}
// 証明書署名チェック
SVC_DecryptSign( pool, &digest, pCert->sign, pCAPubKey );
// ダイジェストの計算
SVC_CalcSHA1( md, pCert, ROM_CERT_SIGN_OFFSET );
// 比較
for (i = 0; i < SVC_SHA1_DIGEST_SIZE; i++)
{
if ( md[i] != digest[i] )
{
result = FALSE;
}
}
return result;
}
/*---------------------------------------------------------------------------*
Name: MI_LoadBuffer
Description: receive data from ARM7 and store(move) via WRAM[B]
LoadBufferメカニズムでARM7から受け取ります
SVCSHA1Contextを指定していた場合SHA1の
[LoadBufferメカニズム]
WRAM[B]ARM7,ARM9間のデータ転送を行います
WRAM[B]
1ARM7から
FIRM_PXI_ID_LOAD_PIRIODを受信します
ARM9は受信後にそのスロットの使用権をARM9に変更してデータを
()使
ARM7に戻します
[使]
WRAM[B]ARM7側に倒しておくこと
[]
offsetとsizeはARM7から通知されません
SRLファイルを読み込む場合はROMヘッダを参照できれば十分です
(ROMヘッダ部分は元から知っているはず)
:
ARM7/ARM9側で歩調を合わせられることを
()
PXIコールバック
APIがデータをWRAMに格納した後
destとsizeを通知するという形でOKではないか
()
Arguments: dest destination address for received data
size size to load
ctx context for SHA1 if execute SVC_SHA1Update
Returns: TRUE if success
*---------------------------------------------------------------------------*/
BOOL MI_LoadBuffer(u8* dest, u32 size, SVCSHA1Context *ctx)
{
u8* base = (u8*)HW_FIRM_LOAD_BUFFER_BASE;
static int count = 0;
while (size > 0)
{
u8* src = base + count * HW_FIRM_LOAD_BUFFER_UNIT_SIZE;
u32 unit = size < HW_FIRM_LOAD_BUFFER_UNIT_SIZE ? size : HW_FIRM_LOAD_BUFFER_UNIT_SIZE;
//OS_TPrintf("%s: src=%X, unit=%X\n", __func__, src, unit);
if ( PXI_RecvID() != FIRM_PXI_ID_LOAD_PIRIOD )
{
return FALSE;
}
#ifdef PROFILE_ENABLE
// x2...: after PXI
profile[pf_cnt++] = PROFILE_PXI_RECV | FIRM_PXI_ID_LOAD_PIRIOD;
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
MIi_SetWramBankMaster_B(count, MI_WRAM_ARM9);
if (ctx)
{
int done;
for (done = 0; done < unit; done += HASH_UNIT)
{
u8* s = src + done;
u8* d = dest + done;
u32 u = unit < done + HASH_UNIT ? unit - done : HASH_UNIT;
SVC_SHA1Update( ctx, s, u );
MI_CpuCopyFast( s, d, u );
}
}
else
{
MI_CpuCopyFast( src, dest, unit );
}
MI_CpuClearFast( src, unit );
DC_FlushRange( src, unit );
#ifdef PROFILE_ENABLE
// x2...: after copy & clear
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
MIi_SetWramBankMaster_B(count, MI_WRAM_ARM7);
count = (count + 1) % HW_FIRM_LOAD_BUFFER_UNIT_NUMS;
size -= unit;
dest += unit;
}
return TRUE;
}
/*---------------------------------------------------------------------------*
Name: MI_LoadHeader
Description: load header
SRLのROMヘッダ部分をARM7から受け取り
ARM7から FIRM_PXI_ID_LOAD_HEADER
ARM7へ FIRM_PXI_ID_AUTH_HEADER
ROMヘッダが格納
seedデータを16バイト送信します
makerom.TWLまたはIPLの仕様に依存します
Arguments: pool pointer to the pool info for SVCSignHeapContext
rsa_key key address
Returns: TRUE if success
*---------------------------------------------------------------------------*/
BOOL MI_LoadHeader( SVCSignHeapContext* pool, const void* rsa_key )
{
SVCSHA1Context ctx;
u8 md[SVC_SHA1_DIGEST_SIZE];
SignatureData sd;
int i;
BOOL result = TRUE;
SVC_SHA1Init(&ctx);
#ifdef PROFILE_ENABLE
pf_cnt = 0x10;
#endif
// load header (hash target)
if ( PXI_RecvID() != FIRM_PXI_ID_LOAD_HEADER ||
#ifdef PROFILE_ENABLE
// 10: after PXI
((profile[pf_cnt++] = PROFILE_PXI_RECV | FIRM_PXI_ID_LOAD_HEADER), FALSE) ||
((profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick())), FALSE) ||
#endif
!MI_LoadBuffer( (u8*)rh, AUTH_SIZE, &ctx ) )
{
return FALSE;
}
SVC_SHA1GetHash(&ctx, md);
#ifdef PROFILE_ENABLE
// 1x: after HMAC
profile[pf_cnt++] = PROFILE_SHA1; // checkpoint
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
// load header (remain)
if ( !MI_LoadBuffer( (u8*)rh + AUTH_SIZE, HEADER_SIZE - AUTH_SIZE, NULL ) )
{
return FALSE;
}
// コンテンツ証明書
if ( CheckRomCertificate( pool, &rh->certificate, rsa_key, *(u32*)rh->s.game_code ) )
{
rsa_key = rh->certificate.pubKeyMod; // ヘッダ用の鍵の取り出し
}
else
{
// とりあえずコンテンツ証明書用の鍵がそのまま使えると仮定
}
// ヘッダ署名チェック
SVC_DecryptSign( pool, &sd, rh->signature, rsa_key );
for (i = 0; i < SVC_SHA1_DIGEST_SIZE; i++)
{
if ( md[i] != sd.digest[i] )
{
result = FALSE;
}
}
#ifdef PROFILE_ENABLE
// 1x: after RSA, before PXI
profile[pf_cnt++] = PROFILE_RSA; // checkpoint
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
profile[pf_cnt++] = (u32)PROFILE_PXI_SEND | FIRM_PXI_ID_AUTH_HEADER; // checkpoint
#endif
if ( result )
{
DC_StoreRange( rh, HW_TWL_ROM_HEADER_BUF_SIZE );
PXI_NotifyID( FIRM_PXI_ID_AUTH_HEADER );
AESi_SendSeed( (AESKey*)sd.aes_key_seed );
// DS互換ヘッダコピー
MI_CpuCopyFast( rh, (void*)HW_ROM_HEADER_BUF, HW_ROM_HEADER_BUF_END-HW_ROM_HEADER_BUF );
}
MI_CpuClear8(&sd, sizeof(sd));
MI_CpuClear8(&md, sizeof(md));
return result;
}
/*---------------------------------------------------------------------------*
Name: MIi_GetTransferSize
Description: get size to transfer once
AES領域をまたぐ場合は (
)
makerom.TWLまたはIPLの使用に依存します
Arguments: offset offset of region from head of ROM_Header
size size of region
Returns: size to transfer once
*---------------------------------------------------------------------------*/
static u32 MIi_GetTransferSize( u32 offset, u32 size )
{
u32 aes_offset = rh->s.aes_target_rom_offset;
u32 aes_end = aes_offset + rh->s.aes_target_size;
u32 end = offset + size;
if ( rh->s.enable_aes )
{
if ( offset >= aes_offset && offset < aes_end )
{
if ( end > aes_end )
{
size = aes_end - offset;
}
}
else
{
if ( offset < aes_offset && offset + size > aes_offset )
{
size = aes_offset - offset;
}
}
}
return size;
}
/*---------------------------------------------------------------------------*
Name: MIi_LoadModule
Description: receive module from ARM7 and store(move) via WRAM[B]
MI_LoadBufferの上位APIです
AES境界をまたぐ場合は2LoadBufferに分割します
SHA1の計算範囲全体を
便
Arguments: dest destination address for received data
offset offset from head of ROM_Header
size size to load
digest digest to compare
Returns: TRUE if success
*---------------------------------------------------------------------------*/
static /*inline*/ BOOL MIi_LoadModule(void* dest, u32 offset, u32 size, const u8 digest[SVC_SHA1_DIGEST_SIZE])
{
SVCHMACSHA1Context ctx;
u8 md[SVC_SHA1_DIGEST_SIZE];
int i;
BOOL result = TRUE;
SVC_HMACSHA1Init(&ctx, s_digestDefaultKey, SVC_SHA1_BLOCK_SIZE );
while ( size > 0 )
{
u32 unit = MIi_GetTransferSize( offset, size );
if ( !MI_LoadBuffer( dest, unit, &ctx.sha1_ctx ) ) // UpdateはSHA1と同じ処理
{
return FALSE;
}
dest = (u8*)dest + unit;
offset += unit;
size -= unit;
}
SVC_HMACSHA1GetHash(&ctx, md);
#ifdef PROFILE_ENABLE
// 3x: after SHA1
profile[pf_cnt++] = PROFILE_SHA1; // checkpoint
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
for (i = 0; i < SVC_SHA1_DIGEST_SIZE; i++)
{
if (md[i] != digest[i])
{
result = FALSE;
}
}
MI_CpuClear8(md, SVC_SHA1_DIGEST_SIZE);
return result;
}
/*---------------------------------------------------------------------------*
Name: MI_LoadStatic
Description: load static binary
ARM9/ARM7のStaticおよびLTD Staticを受信します
ARM7からFIRM_PXI_ID_LOAD_*_STATICを受信します
ARM7へFIRM_PXI_ID_AUTH_*_STATICを送信
0PXI通信すら行いません
APIを呼び出す前にROMヘッダが
Arguments: None
Returns: TRUE if success
*---------------------------------------------------------------------------*/
BOOL MI_LoadStatic( void )
{
// load static
if ( PXI_RecvID() != FIRM_PXI_ID_LOAD_STATIC )
{
return FALSE;
}
#ifdef PROFILE_ENABLE
// 30: after PXI
pf_cnt = 0x30;
profile[pf_cnt++] = PROFILE_PXI_RECV | FIRM_PXI_ID_LOAD_STATIC;
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
// load ARM9 static region
if ( rh->s.main_size > 0 )
{
#ifdef PROFILE_ENABLE
// 31: before PXI
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
if ( !MIi_LoadModule(rh->s.main_ram_address, rh->s.main_rom_offset, rh->s.main_size, rh->s.main_static_digest) )
{
return FALSE;
}
}
// load ARM7 static region
if ( rh->s.sub_size > 0 )
{
#ifdef PROFILE_ENABLE
// 50: before PXI
pf_cnt = 0x50;
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
if ( !MIi_LoadModule( rh->s.sub_ram_address, rh->s.sub_rom_offset, rh->s.sub_size, rh->s.sub_static_digest ) )
{
return FALSE;
}
}
// load ARM9 extended static region
if ( rh->s.main_ltd_size > 0 )
{
#ifdef PROFILE_ENABLE
// 70: before PXI
pf_cnt = 0x70;
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
if ( !MIi_LoadModule( rh->s.main_ltd_ram_address, rh->s.main_ltd_rom_offset, rh->s.main_ltd_size, rh->s.main_ltd_static_digest ) )
{
return FALSE;
}
}
// load ARM7 extended static region
if ( rh->s.sub_ltd_size > 0 )
{
#ifdef PROFILE_ENABLE
// 90: before PXI
pf_cnt = 0x90;
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
if ( !MIi_LoadModule( rh->s.sub_ltd_ram_address, rh->s.sub_ltd_rom_offset, rh->s.sub_ltd_size, rh->s.sub_ltd_static_digest ) )
{
return FALSE;
}
}
#ifdef PROFILE_ENABLE
// 9x: before PXI
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
profile[pf_cnt++] = (u32)PROFILE_PXI_SEND | FIRM_PXI_ID_AUTH_STATIC; // checkpoint
#endif
PXI_NotifyID( FIRM_PXI_ID_AUTH_STATIC );
return TRUE;
}
/*---------------------------------------------------------------------------*
Name: MI_Boot
Description: boot
ROMヘッダの情報を引数にOSi_Bootを呼び出すだけです
APIを呼び出す前にROMヘッダが
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
void MI_Boot( void )
{
OS_BootWithRomHeaderFromFIRM( rh );
}

View File

@ -1,286 +0,0 @@
/*---------------------------------------------------------------------------*
Project: TwlIPL - libraries - mi
File: mi_init_mainMemory.c
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Date:: $
$Rev$
$Author$
*---------------------------------------------------------------------------*/
#include <firm/mi.h>
static u16 intervalTable[] =
{
1, 1, 1, 1,
};
static u32 prescaleTable[] =
{
MI_NDMA_INTERVAL_PS_1,
MI_NDMA_INTERVAL_PS_1,
MI_NDMA_INTERVAL_PS_1,
MI_NDMA_INTERVAL_PS_1,
};
//================================================================================
// memory oparation using DMA (sync)
//================================================================================
/*---------------------------------------------------------------------------*
Name: MIi_ExDmaSendAsync
Description: send data with DMA
async version
Arguments: dmaNo : DMA channel No.
dest : destination address
src : source address
size : size (byte)
Returns: None
*---------------------------------------------------------------------------*/
void MIi_ExDmaSendAsync( u32 dmaNo, const void *src, void *dest, u32 size )
{
u32 idx = dmaNo - MI_EXDMA_CH_MIN;
{
u32 blockSize = MI_NDMA_BWORD_8;
u32 interval = intervalTable[idx];
u32 prescale = prescaleTable[idx];
MIi_ExDmaSendAsyncCore( dmaNo, src, dest, size, size,
blockSize, interval, prescale,
MI_NDMA_CONTINUOUS_OFF, MI_NDMA_SRC_RELOAD_DISABLE, MI_NDMA_DEST_RELOAD_DISABLE,
MI_NDMA_IMM_MODE_ON );
}
}
/*---------------------------------------------------------------------------*
Name: MIi_ExDmaRecvAsync
Description: receive data with DMA
async version
Arguments: dmaNo : DMA channel No.
dest : destination address
src : source address
size : size (byte)
Returns: None
*---------------------------------------------------------------------------*/
void MIi_ExDmaRecvAsync( u32 dmaNo, const void *src, void *dest, u32 size )
{
u32 idx = dmaNo - MI_EXDMA_CH_MIN;
{
u32 blockSize = MI_NDMA_BWORD_8;
u32 interval = intervalTable[idx];
u32 prescale = prescaleTable[idx];
MIi_ExDmaRecvAsyncCore( dmaNo, src, dest, size, size,
blockSize, interval, prescale,
MI_NDMA_CONTINUOUS_OFF, MI_NDMA_SRC_RELOAD_DISABLE, MI_NDMA_DEST_RELOAD_DISABLE,
MI_NDMA_IMM_MODE_ON );
}
}
//----------------- internel functions -------------------
/*---------------------------------------------------------------------------*
Name: MIi_ExDmaSendAsyncCore
Description: send data with DMA
async version
Arguments: dmaNo : DMA channel No.
dest : destination address
src : source address
size : size (byte)
blockSize : block size
Returns: None
*---------------------------------------------------------------------------*/
void MIi_ExDmaSendAsyncCore( u32 dmaNo, const void *src, void *dest, u32 size, u32 oneShotSize,
u32 blockSize, u32 interval, u32 prescale,
u32 continuous, u32 srcRld, u32 destRld,
u32 timing )
{
MIi_WaitExDma( dmaNo );
MIi_SetExDmaParams( dmaNo, src, dest, size, oneShotSize,
blockSize, interval, prescale,
continuous, srcRld, destRld,
timing,
0, MI_NDMA_SRC_INC, MI_NDMA_DEST_FIX );
}
/*---------------------------------------------------------------------------*
Name: MIi_ExDmaRecvAsyncCore
Description: receive data with DMA
async version
Arguments: dmaNo : DMA channel No.
dest : destination address
src : source address
size : size (byte)
blockSize : block size
Returns: None
*---------------------------------------------------------------------------*/
void MIi_ExDmaRecvAsyncCore( u32 dmaNo, const void *src, void *dest, u32 size, u32 oneShotSize,
u32 blockSize, u32 interval, u32 prescale,
u32 continuous, u32 srcRld, u32 destRld,
u32 timing )
{
MIi_WaitExDma( dmaNo );
MIi_SetExDmaParams( dmaNo, src, dest, size, oneShotSize,
blockSize, interval, prescale,
continuous, srcRld, destRld,
timing,
0, MI_NDMA_SRC_FIX, MI_NDMA_DEST_INC );
}
/*---------------------------------------------------------------------------*
Name: MIi_SetExDmaParams
Description: set DMA
Arguments: dmaNo : DMA channel No.
dest : destination address
src : source address
size : size (byte)
blockSize : block size
Returns: None
*---------------------------------------------------------------------------*/
void MIi_SetExDmaParams( u32 dmaNo, const void *src, void *dest, u32 size, u32 oneShotSize,
u32 blockSize, u32 interval, u32 prescale,
u32 continuous, u32 srcRld, u32 destRld,
u32 timing,
u32 fillData, u32 srcDir, u32 destDir )
{
u32 idx = dmaNo - MI_EXDMA_CH_MIN;
if ( idx < MI_EXDMA_CH_NUM )
{
OSIntrMode enabled = OS_DisableInterrupts();
MIExDmaChanRegs *reg = &((MIExDmaChanRegs*)REG_NDMA0SAD_ADDR)[idx];
reg->src = src;
reg->dest = dest;
reg->fillData = fillData;
reg->totalCount = size / 4;
reg->wordCount = oneShotSize / 4;
reg->blockInterval = (interval << REG_MI_NDMA0BCNT_ICNT_SHIFT) | prescale;
reg->ctrl = blockSize
| srcDir | destDir
| srcRld | destRld
| continuous
| timing
| MI_NDMA_ENABLE | MI_NDMA_IF_ENABLE;
(void)OS_RestoreInterrupts(enabled);
}
}
//================================================================================
// DMA WAIT/STOP
//================================================================================
/*---------------------------------------------------------------------------*
Name: MIi_IsExDmaBusy
Description: check whether extended DMA is busy or not
Arguments: dmaNo : DMA channel No.
Returns: TRUE if extended DMA is busy, FALSE if not
*---------------------------------------------------------------------------*/
BOOL MIi_IsExDmaBusy( u32 dmaNo )
{
u32 idx = dmaNo - MI_EXDMA_CH_MIN;
if ( idx < MI_EXDMA_CH_NUM )
{
MIExDmaChanRegs *reg = &((MIExDmaChanRegs*)REG_NDMA0SAD_ADDR)[idx];
return (BOOL)((reg->ctrl & REG_MI_NDMA0CNT_E_MASK) >> REG_MI_NDMA0CNT_E_SHIFT);
}
return FALSE;
}
/*---------------------------------------------------------------------------*
Name: MIi_WaitExDma
Description: wait while extended DMA is busy
Arguments: dmaNo : DMA channel No.
Returns: None
*---------------------------------------------------------------------------*/
void MIi_WaitExDma( u32 dmaNo )
{
u32 idx = dmaNo - MI_EXDMA_CH_MIN;
if ( idx < MI_EXDMA_CH_NUM )
{
MIExDmaChanRegs *reg = &((MIExDmaChanRegs*)REG_NDMA0SAD_ADDR)[idx];
while (reg->ctrl & REG_MI_NDMA0CNT_E_MASK)
{
}
}
}
/*---------------------------------------------------------------------------*
Name: MIi_StopDma
Description: stop extended DMA
Arguments: dmaNo : DMA channel No.
Returns: None
*---------------------------------------------------------------------------*/
void MIi_StopExDma( u32 dmaNo )
{
MIi_StopExDmaAsync( dmaNo );
MIi_WaitExDma( dmaNo );
}
/*---------------------------------------------------------------------------*
Name: MIi_StopDmaAsync
Description: stop extended DMA
async version
Arguments: dmaNo : DMA channel No.
Returns: None
*---------------------------------------------------------------------------*/
void MIi_StopExDmaAsync( u32 dmaNo )
{
OSIntrMode enabled = OS_DisableInterrupts();
u32 idx = dmaNo - MI_EXDMA_CH_MIN;
if ( idx < MI_EXDMA_CH_NUM )
{
MIExDmaChanRegs *reg = &((MIExDmaChanRegs*)REG_NDMA0SAD_ADDR)[idx];
reg->ctrl &= ~MI_NDMA_ENABLE;
}
(void)OS_RestoreInterrupts(enabled);
}

View File

@ -22,15 +22,15 @@
#define RSA_KEY_ADDR rsa_key
static const u8 rsa_key[128] =
{
0xdf, 0x56, 0x30,
0xc9, 0xae, 0x05, 0x55, 0xe8, 0xdf, 0xbe, 0xe6, 0xb9, 0x30, 0xb9, 0x76, 0x93, 0xb4, 0xc2, 0x20,
0xe7, 0xae, 0x4c, 0x3e, 0xc3, 0xed, 0x27, 0xcf, 0x5d, 0x4f, 0xb5, 0x7d, 0xde, 0x38, 0xbc, 0xfe,
0x25, 0x32, 0xd8, 0x23, 0x98, 0x52, 0xb5, 0xda, 0xf7, 0x39, 0xdc, 0xb3, 0x0a, 0x94, 0x7a, 0x2b,
0x79, 0xe6, 0xe0, 0x4c, 0xbc, 0x21, 0xbd, 0x59, 0xb2, 0xc7, 0xf1, 0xc0, 0xf1, 0xfb, 0x29, 0x75,
0xa1, 0x21, 0x93, 0x01, 0x29, 0x1c, 0x9a, 0xe1, 0x2d, 0x55, 0xfc, 0x7b, 0xb8, 0xcb, 0x07, 0x33,
0xc5, 0x91, 0x0d, 0xc8, 0x45, 0x59, 0xef, 0xbe, 0x58, 0xc7, 0xc1, 0x1d, 0xd5, 0xf2, 0xcf, 0x1f,
0xe0, 0x6d, 0x21, 0x00, 0xcd, 0x42, 0xd8, 0x84, 0x85, 0xe3, 0xb2, 0x02, 0x1a, 0xa5, 0x89, 0x02,
0xa1, 0x96, 0xc6, 0xf7, 0x61, 0x68, 0x66, 0xe6, 0x65, 0x12, 0xb7, 0xf1, 0x49
0xAC, 0x93, 0xBB,
0x3C, 0x15, 0x5C, 0x5F, 0x25, 0xB0, 0x4C, 0x37, 0xA4, 0x2D, 0x85, 0x29, 0x1D, 0x7A, 0x9D, 0x2D,
0xD5, 0x79, 0xB5, 0x5D, 0xB1, 0x08, 0x20, 0x9C, 0xF0, 0x4C, 0x56, 0x27, 0x97, 0xF8, 0x7E, 0x3E,
0xCB, 0x94, 0x06, 0x05, 0x94, 0x00, 0x92, 0x9B, 0xB0, 0x5B, 0x06, 0xF6, 0xAF, 0xAA, 0x9C, 0xA5,
0xF0, 0x11, 0xA7, 0x8A, 0xCB, 0x0C, 0x11, 0xD6, 0x0C, 0x3D, 0x30, 0xAC, 0x51, 0x79, 0x5A, 0xB5,
0x7F, 0x11, 0x92, 0x74, 0x48, 0x82, 0x81, 0xBF, 0x3B, 0xFA, 0x93, 0xBF, 0x6B, 0x5B, 0x3F, 0x86,
0x96, 0x4F, 0xCC, 0x90, 0x12, 0xB2, 0x39, 0x8D, 0x68, 0x16, 0x7B, 0xC6, 0x87, 0xF1, 0xF5, 0x60,
0x62, 0x39, 0xFB, 0x10, 0x7E, 0x48, 0x7F, 0xDD, 0x82, 0x38, 0x38, 0x76, 0xB5, 0xCE, 0x21, 0x4B,
0xC9, 0x6F, 0x31, 0x8D, 0x23, 0x57, 0x3D, 0xB6, 0x6C, 0xEE, 0xC2, 0x0D, 0x11
};
#endif

View File

@ -23,15 +23,15 @@
#define RSA_KEY_ADDR rsa_key
static const u8 rsa_key[128] =
{
0xdf, 0x56, 0x30,
0xc9, 0xae, 0x05, 0x55, 0xe8, 0xdf, 0xbe, 0xe6, 0xb9, 0x30, 0xb9, 0x76, 0x93, 0xb4, 0xc2, 0x20,
0xe7, 0xae, 0x4c, 0x3e, 0xc3, 0xed, 0x27, 0xcf, 0x5d, 0x4f, 0xb5, 0x7d, 0xde, 0x38, 0xbc, 0xfe,
0x25, 0x32, 0xd8, 0x23, 0x98, 0x52, 0xb5, 0xda, 0xf7, 0x39, 0xdc, 0xb3, 0x0a, 0x94, 0x7a, 0x2b,
0x79, 0xe6, 0xe0, 0x4c, 0xbc, 0x21, 0xbd, 0x59, 0xb2, 0xc7, 0xf1, 0xc0, 0xf1, 0xfb, 0x29, 0x75,
0xa1, 0x21, 0x93, 0x01, 0x29, 0x1c, 0x9a, 0xe1, 0x2d, 0x55, 0xfc, 0x7b, 0xb8, 0xcb, 0x07, 0x33,
0xc5, 0x91, 0x0d, 0xc8, 0x45, 0x59, 0xef, 0xbe, 0x58, 0xc7, 0xc1, 0x1d, 0xd5, 0xf2, 0xcf, 0x1f,
0xe0, 0x6d, 0x21, 0x00, 0xcd, 0x42, 0xd8, 0x84, 0x85, 0xe3, 0xb2, 0x02, 0x1a, 0xa5, 0x89, 0x02,
0xa1, 0x96, 0xc6, 0xf7, 0x61, 0x68, 0x66, 0xe6, 0x65, 0x12, 0xb7, 0xf1, 0x49
0xAC, 0x93, 0xBB,
0x3C, 0x15, 0x5C, 0x5F, 0x25, 0xB0, 0x4C, 0x37, 0xA4, 0x2D, 0x85, 0x29, 0x1D, 0x7A, 0x9D, 0x2D,
0xD5, 0x79, 0xB5, 0x5D, 0xB1, 0x08, 0x20, 0x9C, 0xF0, 0x4C, 0x56, 0x27, 0x97, 0xF8, 0x7E, 0x3E,
0xCB, 0x94, 0x06, 0x05, 0x94, 0x00, 0x92, 0x9B, 0xB0, 0x5B, 0x06, 0xF6, 0xAF, 0xAA, 0x9C, 0xA5,
0xF0, 0x11, 0xA7, 0x8A, 0xCB, 0x0C, 0x11, 0xD6, 0x0C, 0x3D, 0x30, 0xAC, 0x51, 0x79, 0x5A, 0xB5,
0x7F, 0x11, 0x92, 0x74, 0x48, 0x82, 0x81, 0xBF, 0x3B, 0xFA, 0x93, 0xBF, 0x6B, 0x5B, 0x3F, 0x86,
0x96, 0x4F, 0xCC, 0x90, 0x12, 0xB2, 0x39, 0x8D, 0x68, 0x16, 0x7B, 0xC6, 0x87, 0xF1, 0xF5, 0x60,
0x62, 0x39, 0xFB, 0x10, 0x7E, 0x48, 0x7F, 0xDD, 0x82, 0x38, 0x38, 0x76, 0xB5, 0xCE, 0x21, 0x4B,
0xC9, 0x6F, 0x31, 0x8D, 0x23, 0x57, 0x3D, 0xB6, 0x6C, 0xEE, 0xC2, 0x0D, 0x11
};
#endif

View File

@ -16,41 +16,57 @@
*---------------------------------------------------------------------------*/
#include <firm.h>
#include <twl/mcu.h>
#include <twl/os/ARM7/debugLED.h>
#define FATFS_HEAP_SIZE (64*1024) // FATFS用ヒープ (サイズ調整必要)
#define BOOT_DEVICE FATFS_MEDIA_TYPE_SD
#define PARTITION_NO 0 // 0固定
#define MENU_FILE (char*)L"A:\\menu.srl" // 対象ファイル(DRIVE_LETTERと合わせること)
#define MENU_FILE_A (char*)L"A:\\menu_a.srl" // 対象ファイル(DRIVE_LETTERと合わせること)
#define MENU_FILE_B (char*)L"A:\\menu_b.srl" // 対象ファイル(DRIVE_LETTERと合わせること)
#define MENU_FILE_L (char*)L"A:\\menu_l.srl" // 対象ファイル(DRIVE_LETTERと合わせること)
#define MENU_FILE_R (char*)L"A:\\menu_r.srl" // 対象ファイル(DRIVE_LETTERと合わせること)
#define DRIVE_LETTER 'A' // マウント先ドライブ名
#define DRIVE_NO (DRIVE_LETTER - 'A') // マウント先ドライブ番号
static u8 fatfsHeap[FATFS_HEAP_SIZE] __attribute__ ((aligned (32)));
#ifndef SDK_FINALROM
static u8 step = 0x80;
#endif
/*
Profile
PROFILE_ENABLE
main.cかどこかにu32 profile[256]; u32 pf_cnt = 0;
*/
#ifndef SDK_FINALROM
#define PROFILE_MAX 0x100
#define PROFILE_ENABLE
/*
LEDをFINALROMとは別にOn/Offできます
*/
#define USE_DEBUG_LED
/*
PRINT_MEMORY_ADDR SPrintfを行います()
FINALROM版でもコードが残るので注意してください
*/
#define PRINT_MEMORY_ADDR 0x02000600
#ifdef PROFILE_ENABLE
#define PROFILE_MAX 16
u32 profile[PROFILE_MAX];
u32 pf_cnt = 0;
#define PUSH_PROFILE() (profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()))
#else
#define PUSH_PROFILE() ((void)0)
#endif
/*
Production check
*/
//#define PRODUCTION_CHECK() do { if (reg_SCFG_OP == 0) goto end; } while (0)
#define PRODUCTION_CHECK() ((void)0)
#ifdef USE_DEBUG_LED
static u8 step = 0x80;
#define InitDebugLED() I2Ci_WriteRegister(I2C_SLAVE_DEBUG_LED, 0x03, 0x00)
#define SetDebugLED(pattern) I2Ci_WriteRegister(I2C_SLAVE_DEBUG_LED, 0x01, (pattern));
#else
#define InitDebugLED() ((void)0)
#define SetDebugLED(pattern) ((void)0)
#endif
#ifdef PRINT_MEMORY_ADDR
static char* debugPtr = (char*)PRINT_MEMORY_ADDR;
#undef OS_TPrintf
//#define OS_TPrintf(...) (debugPtr = (char*)((u32)(debugPtr + STD_TSPrintf(debugPtr, __VA_ARGS__) + 0xf) & ~0xf))
#define OS_TPrintf(...) (debugPtr += STD_TSPrintf(debugPtr, __VA_ARGS__))
#endif
#define THREAD_PRIO_FATFS 8
#define DMA_NO_FATFS 3
extern void* SDNandContext; /* NAND初期化パラメータ */
static ROM_Header* const rh= (ROM_Header*)HW_TWL_ROM_HEADER_BUF;
/***************************************************************
PreInit
@ -72,6 +88,18 @@ static void PreInit(void)
*/
#define FIRM_AVAILABLE_BIT 0x80000000UL
*(u32*)HW_RESET_PARAMETER_BUF = (u32)MCUi_ReadRegister( MCU_REG_TEMP_ADDR ) | FIRM_AVAILABLE_BIT;
/*
*/
//if ( MCUi_ReadRegister( MCU_REG_BATTELY ) < 0x02 )
//if ( MCUi_ReadRegister( MCU_REG_IRQ ) & MCU_IRQ_NO_BATTELY )
/*
TWLと識別できているかチェック
#ifdef USE_DEBUG_LED
SetDebugLED(OS_IsRunOnTwl() ? 0xC3 : 0xff);
OS_SpinWaitCpuCycles(0x1000000);
#endif
*/
}
/***************************************************************
@ -90,168 +118,172 @@ static void EraseAll(void)
#endif
}
/***************************************************************
Fatfs4sdmcInit
FATFS周りの初期化 for SDカード
***************************************************************/
static BOOL Fatfs4sdmcInit(void)
{
BOOL result;
/* FATFSライブラリ用にカレントヒープを設定 */
/* WRAM上のfatfsHeapをメインメモリヒープとして登録している */
OSHeapHandle hh;
u8 *lo = (u8*)fatfsHeap;
u8 *hi = (u8*)fatfsHeap + FATFS_HEAP_SIZE;
lo = OS_InitAlloc(OS_ARENA_MAIN_SUBPRIV, lo, hi, 1);
OS_SetArenaLo(OS_ARENA_MAIN_SUBPRIV, lo);
hh = OS_CreateHeap(OS_ARENA_MAIN_SUBPRIV, OS_GetSubPrivArenaLo(), hi);
OS_SetCurrentHeap(OS_ARENA_MAIN_SUBPRIV, hh);
OS_SetDebugLED(++step);
if ( !FATFS_InitFIRM( NULL ) )
{
return FALSE;
}
#ifndef SDK_FINALROM
// 3: after FATFS
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
OS_SetDebugLED(++step);
PM_BackLightOn( FALSE );
if ( !FATFS_MountDriveFIRM( DRIVE_NO, BOOT_DEVICE, PARTITION_NO ) )
{
return FALSE;
}
#ifndef SDK_FINALROM
// 4: after Mount
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
OS_SetDebugLED(++step);
PM_BackLightOn( FALSE );
switch ( PAD_Read() & PAD_KEYPORT_MASK )
{
case 0:
result = FATFS_OpenSpecifiedSrl( MENU_FILE ) && FATFS_SaveSrlFilename( BOOT_DEVICE, MENU_FILE );
break;
case PAD_BUTTON_A:
result = FATFS_OpenSpecifiedSrl( MENU_FILE_A ) && FATFS_SaveSrlFilename( BOOT_DEVICE, MENU_FILE_A );
break;
case PAD_BUTTON_B:
result = FATFS_OpenSpecifiedSrl( MENU_FILE_B ) && FATFS_SaveSrlFilename( BOOT_DEVICE, MENU_FILE_B );
break;
case PAD_BUTTON_L:
result = FATFS_OpenSpecifiedSrl( MENU_FILE_L ) && FATFS_SaveSrlFilename( BOOT_DEVICE, MENU_FILE_L );
break;
case PAD_BUTTON_R:
result = FATFS_OpenSpecifiedSrl( MENU_FILE_R ) && FATFS_SaveSrlFilename( BOOT_DEVICE, MENU_FILE_R );
break;
default:
OS_SetDebugLED( (u8)(PAD_Read() & PAD_KEYPORT_MASK) );
result = FALSE;
break;
}
return result;
}
void TwlSpMain( void )
{
// OS_InitDebugLED and OS_SetDebugLED are able to call after OS_Init
#ifndef SDK_FINALROM
I2Ci_WriteRegister(I2C_SLAVE_DEBUG_LED, 0x03, 0x00);
I2Ci_WriteRegister(I2C_SLAVE_DEBUG_LED, 0x01, ++step);
#endif
int fd; // menu file descriptor
InitDebugLED();
SetDebugLED(++step); // 0x81
PreInit();
#ifndef SDK_FINALROM
I2Ci_WriteRegister(I2C_SLAVE_DEBUG_LED, 0x01, ++step);
// 0: before PXI
profile[pf_cnt++] = (u32)OS_TicksToMicroSecondsBROM(OS_GetTick());
#endif
PUSH_PROFILE();
SetDebugLED(++step); // 0x82
OS_InitFIRM();
PRODUCTION_CHECK();
OS_EnableIrq();
OS_EnableInterrupts();
#ifndef SDK_FINALROM
//OS_EnableIrq();
// 1: after PXI
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
OS_SetDebugLED(++step);
PUSH_PROFILE();
SetDebugLED(++step); // 0x83
PM_InitFIRM();
PM_BackLightOn( FALSE );
#ifndef SDK_FINALROM
// 2: after PM
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
OS_SetDebugLED(++step);
PRODUCTION_CHECK();
if ( !Fatfs4sdmcInit() )
{
goto end;
}
#ifndef SDK_FINALROM
// 5: after Open
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
OS_SetDebugLED(++step);
// 2: after PM_InitFIRM
PUSH_PROFILE();
SetDebugLED(++step); // 0x84
PM_BackLightOn( FALSE );
if ( !FATFS_LoadHeader() || !FATFS_LoadStatic() )
SDNandContext = &OSi_GetFromFirmAddr()->SDNandContext;
if ( !FATFS_Init( DMA_NO_FATFS, THREAD_PRIO_FATFS ) )
{
OS_TPrintf("Failed to call FATFS_Init().\n");
goto end;
}
#ifndef SDK_FINALROM
// 127: before Boot
pf_cnt = PROFILE_MAX-1;
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
// 3: after FS_Init
PUSH_PROFILE();
SetDebugLED(++step); // 0x85
PM_BackLightOn( FALSE );
PXI_RecvID();
SetDebugLED(0x01);
PXI_RecvID();
SetDebugLED(0x02);
if ( PXI_RecvID() != FIRM_PXI_ID_SET_PATH )
{
OS_TPrintf("PXI_RecvID() was received invalid value (!=FIRM_PXI_ID_SET_PATH).\n");
goto end;
}
#ifdef USE_IDLE_THREAD
CreateIdleThread();
#endif
// 4: after PXI
PUSH_PROFILE();
SetDebugLED(++step); // 0x86
PM_BackLightOn( FALSE );
if ( (fd = FS_OpenSrl()) < 0 )
{
OS_TPrintf("Failed to call FS_OpenSrl().\n");
goto end;
}
// 5: after FS_OpenSrl
PUSH_PROFILE();
SetDebugLED(++step); // 0x87
PM_BackLightOn( FALSE );
if ( !FS_LoadHeader( fd ) )
{
OS_TPrintf("Failed to call FS_LoadHeader().\n");
goto end;
}
// 6: after FS_LoadHeader
PUSH_PROFILE();
SetDebugLED(++step); // 0x88
PM_BackLightOn( FALSE );
if ( PXI_RecvID() != FIRM_PXI_ID_DONE_HEADER )
{
OS_TPrintf("PXI_RecvID() was received invalid value (!=FIRM_PXI_ID_DONE_HEADER).\n");
goto end;
}
// 7: after PXI
PUSH_PROFILE();
SetDebugLED(++step); // 0x89
PM_BackLightOn( FALSE );
AESi_InitKeysFIRM();
AESi_RecvSeed( rh->s.developer_encrypt );
// 8: after AESi_RecvSeed
PUSH_PROFILE();
SetDebugLED(++step); // 0x8a
PM_BackLightOn( FALSE );
if ( !FS_LoadStatic( fd ) )
{
OS_TPrintf("Failed to call FS_LoadStatic().\n");
goto end;
}
// 9: after FS_LoadStatic
PUSH_PROFILE();
SetDebugLED(++step); // 0x8b
PM_BackLightOn( FALSE );
if ( PXI_RecvID() != FIRM_PXI_ID_DONE_STATIC )
{
OS_TPrintf("PXI_RecvID() was received invalid value (!=FIRM_PXI_ID_DONE_STATIC).\n");
goto end;
}
// 10: after PXI
PUSH_PROFILE();
#ifdef PROFILE_ENABLE
{
int i;
PXI_RecvID();
OS_TPrintf("\n[ARM7] Begin\n");
for (i = 0; i < PROFILE_MAX; i++)
{
OS_TPrintf("0x%08X\n", profile[i]);
// OS_TPrintf("0x%08X\n", profile[i]);
if ( !profile[i] ) break;
OS_TPrintf("%2d: %7d usec", i, profile[i]);
if (i)
{
OS_TPrintf(" ( %7d usec )\n", profile[i]-profile[i-1]);
}
else
{
OS_TPrintf("\n");
}
}
OS_TPrintf("\n[ARM7] End\n");
}
#endif
OS_SetDebugLED(0);
PRODUCTION_CHECK();
SetDebugLED( 0 );
PM_BackLightOn( TRUE ); // last chance
PMi_SetParams( REG_PMIC_BL_BRT_A_ADDR, 22, PMIC_BL_BRT_A_MASK ); // brighter
PMi_SetParams( REG_PMIC_BL_BRT_B_ADDR, 22, PMIC_BL_BRT_B_MASK ); // brighter
OS_BootFromFIRM();
end:
OS_SetDebugLED( (u8)(0xF0 | step));
SetDebugLED( (u8)(0xF0 | step));
EraseAll();
// failed
while (1)
{
PXI_NotifyID( FIRM_PXI_ID_NULL );
}
PXI_NotifyID( FIRM_PXI_ID_ERR );
PXI_NotifyID( FIRM_PXI_ID_ERR );
PXI_NotifyID( FIRM_PXI_ID_ERR );
PXI_NotifyID( FIRM_PXI_ID_ERR );
OS_Terminate();
}

View File

@ -22,15 +22,15 @@
#define RSA_KEY_ADDR rsa_key
static const u8 rsa_key[128] =
{
0xdf, 0x56, 0x30,
0xc9, 0xae, 0x05, 0x55, 0xe8, 0xdf, 0xbe, 0xe6, 0xb9, 0x30, 0xb9, 0x76, 0x93, 0xb4, 0xc2, 0x20,
0xe7, 0xae, 0x4c, 0x3e, 0xc3, 0xed, 0x27, 0xcf, 0x5d, 0x4f, 0xb5, 0x7d, 0xde, 0x38, 0xbc, 0xfe,
0x25, 0x32, 0xd8, 0x23, 0x98, 0x52, 0xb5, 0xda, 0xf7, 0x39, 0xdc, 0xb3, 0x0a, 0x94, 0x7a, 0x2b,
0x79, 0xe6, 0xe0, 0x4c, 0xbc, 0x21, 0xbd, 0x59, 0xb2, 0xc7, 0xf1, 0xc0, 0xf1, 0xfb, 0x29, 0x75,
0xa1, 0x21, 0x93, 0x01, 0x29, 0x1c, 0x9a, 0xe1, 0x2d, 0x55, 0xfc, 0x7b, 0xb8, 0xcb, 0x07, 0x33,
0xc5, 0x91, 0x0d, 0xc8, 0x45, 0x59, 0xef, 0xbe, 0x58, 0xc7, 0xc1, 0x1d, 0xd5, 0xf2, 0xcf, 0x1f,
0xe0, 0x6d, 0x21, 0x00, 0xcd, 0x42, 0xd8, 0x84, 0x85, 0xe3, 0xb2, 0x02, 0x1a, 0xa5, 0x89, 0x02,
0xa1, 0x96, 0xc6, 0xf7, 0x61, 0x68, 0x66, 0xe6, 0x65, 0x12, 0xb7, 0xf1, 0x49
0xAC, 0x93, 0xBB,
0x3C, 0x15, 0x5C, 0x5F, 0x25, 0xB0, 0x4C, 0x37, 0xA4, 0x2D, 0x85, 0x29, 0x1D, 0x7A, 0x9D, 0x2D,
0xD5, 0x79, 0xB5, 0x5D, 0xB1, 0x08, 0x20, 0x9C, 0xF0, 0x4C, 0x56, 0x27, 0x97, 0xF8, 0x7E, 0x3E,
0xCB, 0x94, 0x06, 0x05, 0x94, 0x00, 0x92, 0x9B, 0xB0, 0x5B, 0x06, 0xF6, 0xAF, 0xAA, 0x9C, 0xA5,
0xF0, 0x11, 0xA7, 0x8A, 0xCB, 0x0C, 0x11, 0xD6, 0x0C, 0x3D, 0x30, 0xAC, 0x51, 0x79, 0x5A, 0xB5,
0x7F, 0x11, 0x92, 0x74, 0x48, 0x82, 0x81, 0xBF, 0x3B, 0xFA, 0x93, 0xBF, 0x6B, 0x5B, 0x3F, 0x86,
0x96, 0x4F, 0xCC, 0x90, 0x12, 0xB2, 0x39, 0x8D, 0x68, 0x16, 0x7B, 0xC6, 0x87, 0xF1, 0xF5, 0x60,
0x62, 0x39, 0xFB, 0x10, 0x7E, 0x48, 0x7F, 0xDD, 0x82, 0x38, 0x38, 0x76, 0xB5, 0xCE, 0x21, 0x4B,
0xC9, 0x6F, 0x31, 0x8D, 0x23, 0x57, 0x3D, 0xB6, 0x6C, 0xEE, 0xC2, 0x0D, 0x11
};
#endif
@ -39,13 +39,43 @@ static const u8 rsa_key[128] =
static u8 acHeap[RSA_HEAP_SIZE] __attribute__ ((aligned (32)));
static SVCSignHeapContext acPool;
#define MENU_FILE "sdmc:/menu.srl"
#define MENU_FILE_A "sdmc:/menu_a.srl"
#define MENU_FILE_B "sdmc:/menu_b.srl"
#define MENU_FILE_L "sdmc:/menu_l.srl"
#define MENU_FILE_R "sdmc:/menu_r.srl"
/*
Profile
PROFILE_ENABLE
main.cかどこかにu32 profile[256]; u32 pf_cnt = 0;
*/
#ifndef SDK_FINALROM
#define PROFILE_MAX 0x100
#define PROFILE_ENABLE
/*
PRINT_MEMORY_ADDR SPrintfを行います()
FINALROM版でもコードが残るので注意してください
*/
#define PRINT_MEMORY_ADDR 0x02000200
//#ifdef SDK_FINALROM // FINALROMで無効化
//#undef PROFILE_ENABLE
//#endif
#ifdef PROFILE_ENABLE
#define PROFILE_MAX 16
u32 profile[PROFILE_MAX];
u32 pf_cnt = 0;
#define PUSH_PROFILE() (profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()))
#else
#define PUSH_PROFILE() ((void)0)
#endif
#ifdef PRINT_MEMORY_ADDR
static char* debugPtr = (char*)PRINT_MEMORY_ADDR;
#undef OS_TPrintf
//#define OS_TPrintf(...) (debugPtr = (char*)((u32)(debugPtr + STD_TSPrintf(debugPtr, __VA_ARGS__) + 0xf) & ~0xf))
#define OS_TPrintf(...) (debugPtr += STD_TSPrintf(debugPtr, __VA_ARGS__))
#endif
/***************************************************************
@ -57,7 +87,7 @@ static void PreInit(void)
{
static const OSMountInfo firmSettings[] =
{
{ 'A', OS_MOUNT_DEVICE_SD, OS_MOUNT_TGT_ROOT, 0, OS_MOUNT_RSC_MMEM, (OS_MOUNT_USR_R|OS_MOUNT_USR_W), 0, 0, "sdmc", "/" },
{ 'A', OS_MOUNT_DEVICE_SD, OS_MOUNT_TGT_ROOT, 0, OS_MOUNT_RSC_WRAM, (OS_MOUNT_USR_R|OS_MOUNT_USR_W), 0, 0, "sdmc", "/" },
{ 0 }
};
/*
@ -84,26 +114,16 @@ static void PreInit(void)
/***************************************************************
PostInit
MI_LoadHeader前にかなり(100msec)
OS_Init後にいろいろ処理したい
***************************************************************/
static void PostInit(void)
{
/*
*/
// ARM9領域を全クリア
if ( OS_GetResetParameter() )
{
MI_CpuClearFast( (void*)HW_FIRM_RESET_BUF_END, HW_TWL_MAIN_MEM_MAIN_END-HW_FIRM_RESET_BUF_END );
}
else
{
MI_CpuClearFast( (void*)HW_MAIN_MEM_MAIN, HW_MAIN_MEM_MAIN_SIZE );
}
DC_FlushAll();
// RSA用ヒープ設定
SVC_InitSignHeap( &acPool, acHeap, sizeof(acHeap) );
// HMAC用鍵準備
FS_SetDigestKey( NULL );
// FS/FATFS初期化
FS_InitFIRM();
}
/***************************************************************
@ -143,11 +163,11 @@ static BOOL CheckHeader(void)
// <20><EFBFBD>˜ÙÚ<E2809A>Å“K‰»<E280B0>ÏÝ
#ifndef FIRM_USE_TWLSDK_KEYS
if ( rhs->platform_code != PLATFORM_CODE_TWL_LIMITED || // TWL Limited only
!rhs->codec_mode || // TWL mode only
!rhs->enable_signature || // Should be use ROM header signature
#else
if ( // no check
if ( // no check
#endif
!rhs->codec_mode || // TWL mode only
// should be in main memory
HW_TWL_MAIN_MEM > (u32)rhs->main_ram_address ||
HW_TWL_MAIN_MEM > (u32)rhs->sub_ram_address ||
@ -166,7 +186,7 @@ static BOOL CheckHeader(void)
(u32)rhs->sub_ram_address + rhs->sub_size <= (u32)rhs->sub_entry_address ||
0 )
{
OS_TPrintf("Invalid ROM header for MENU Launcher!\n");
OS_TPrintf("Invalid ROM header for SDMC Launcher!\n");
return FALSE;
}
return TRUE;
@ -193,50 +213,115 @@ void TwlMain( void )
{
PreInit();
#ifndef SDK_FINALROM
// 0: before PXI
profile[pf_cnt++] = (u32)OS_TicksToMicroSecondsBROM(OS_GetTick());
#endif
PUSH_PROFILE();
OS_InitFIRM();
OS_EnableIrq();
#ifndef SDK_FINALROM
OS_InitTick();
// 1: after PXI
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
OS_EnableInterrupts();
SVC_InitSignHeap( &acPool, acHeap, sizeof(acHeap) );
#ifdef PROFILE_ENABLE
OS_InitTick();
#endif
// 1: after PXI
PUSH_PROFILE();
PXI_NotifyID( FIRM_PXI_ID_NULL );
PostInit();
#ifndef SDK_FINALROM
// 2: after PostInit
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
#endif
// 2: after PostInit
PUSH_PROFILE();
PXI_NotifyID( FIRM_PXI_ID_NULL );
// load menu
if ( MI_LoadHeader( &acPool, RSA_KEY_ADDR ) && CheckHeader() && MI_LoadStatic() )
switch ( PAD_Read() & PAD_KEYPORT_MASK )
{
#ifndef SDK_FINALROM
// 127: before Boot
pf_cnt = PROFILE_MAX-1;
profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick());
{
int i;
OS_TPrintf("\n[ARM9] Begin\n");
for (i = 0; i < PROFILE_MAX; i++)
{
OS_TPrintf("0x%08X\n", profile[i]);
}
OS_TPrintf("\n[ARM9] End\n");
PXI_NotifyID( FIRM_PXI_ID_NULL );
}
#endif
OS_BootFromFIRM();
case 0:
STD_CopyString((char*)HW_TWL_FS_BOOT_SRL_PATH_BUF, MENU_FILE);
break;
case PAD_BUTTON_A:
STD_CopyString((char*)HW_TWL_FS_BOOT_SRL_PATH_BUF, MENU_FILE_A);
break;
case PAD_BUTTON_B:
STD_CopyString((char*)HW_TWL_FS_BOOT_SRL_PATH_BUF, MENU_FILE_B);
break;
case PAD_BUTTON_L:
STD_CopyString((char*)HW_TWL_FS_BOOT_SRL_PATH_BUF, MENU_FILE_L);
break;
case PAD_BUTTON_R:
STD_CopyString((char*)HW_TWL_FS_BOOT_SRL_PATH_BUF, MENU_FILE_R);
break;
default:
OS_TPrintf("Unknown pad pattern (%X).\n", PAD_Read() & PAD_KEYPORT_MASK);
goto end;
}
// 3: after FS_ResolveSrl
PUSH_PROFILE();
PXI_NotifyID( FIRM_PXI_ID_SET_PATH );
// 4: after PXI
PUSH_PROFILE();
if ( !FS_LoadHeader(&acPool, RSA_KEY_ADDR ) || !CheckHeader() )
{
OS_TPrintf("Failed to call FS_LoadHeader() and/or CheckHeader().\n");
goto end;
}
// 5: after FS_LoadHeader
PUSH_PROFILE();
PXI_NotifyID( FIRM_PXI_ID_DONE_HEADER );
// 6: after PXI
PUSH_PROFILE();
AESi_SendSeed( FS_GetAesKeySeed() );
FS_DeleteAesKeySeed();
// 7: after AESi_SendSeed
PUSH_PROFILE();
if ( !FS_LoadStatic() )
{
OS_TPrintf("Failed to call FS_LoadStatic().\n");
goto end;
}
// 8: after FS_LoadStatic
PUSH_PROFILE();
PXI_NotifyID( FIRM_PXI_ID_DONE_STATIC );
// 9: after PXI
PUSH_PROFILE();
#ifdef PROFILE_ENABLE
{
int i;
OS_TPrintf("\n[ARM9] Begin\n");
for (i = 0; i < PROFILE_MAX; i++)
{
// OS_TPrintf("0x%08X\n", profile[i]);
if ( !profile[i] ) break;
OS_TPrintf("%2d: %7d usec", i, profile[i]);
if (i)
{
OS_TPrintf(" ( %7d usec )\n", profile[i]-profile[i-1]);
}
else
{
OS_TPrintf("\n");
}
}
OS_TPrintf("\n[ARM9] End\n");
PXI_NotifyID( FIRM_PXI_ID_NULL );
}
#endif
OS_BootFromFIRM();
end:
EraseAll();
// failed