TwlIPL/build/libraries/mi/ARM9/mi_loader.c
yutaka 3a9b3c9023 デバッガでは動作しましたが、NANDに書いても動かない状態です。
TwlSDK/include/nitro/pxi/common/regname.h のした4行のバグを修正しないと動きません。

git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlIPL/trunk@26 b08762b0-b915-fc4b-9d8c-17b2551a87ff
2007-09-21 13:14:53 +00:00

273 lines
7.2 KiB
C

/*---------------------------------------------------------------------------*
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 <firm/format/format_rom.h>
#define PXI_FIFO_TAG_DATA PXI_FIFO_TAG_USER_0
static ROM_Header* const rh = (ROM_Header*)(HW_MAIN_MEM_SYSTEM_END - 0x2000);
#define HEADER_SIZE 0x1000
#define AUTH_SIZE 0xe00
#define RSA_BLOCK_SIZE 128
#define SLOT_SIZE 0x8000
#define HASH_UNIT 0x800 // TODO: optimizing to maximize cache efficiency
typedef struct SHA1_CTX // 実際には、サイズが同じなら中身は何でも良い
{
u32 h0,h1,h2,h3,h4;
u32 Nl,Nh;
u32 data[16];
int num;
void (*sha_block)(struct SHA1_CTX *c, const u8 *W, int num);
}
SHA1_CTX;
static inline void SHA1_Init(SHA1_CTX *ctx)
{
if (ctx == NULL)
return;
MI_CpuClear8(ctx, sizeof(SHA1_CTX));
SVC_SHA1Init(ctx);
}
static inline void SHA1_Update(SHA1_CTX *ctx, const void* data, u32 len)
{
if (ctx == NULL)
return;
if (len > 0 && data == NULL)
return;
SVC_SHA1Update(ctx, data, len);
}
static inline void SHA1_GetHash(SHA1_CTX *ctx, u8* md)
{
if (ctx == NULL)
return;
if (md == NULL)
return;
SVC_SHA1GetHash(md, ctx);
}
static inline void SHA1_Calc(u8* md, const void* data, u32 len)
{
SVC_CalcSHA1(md, data, len);
}
static BOOL MI_LoadBuffer(u8* dest, u32 size, SHA1_CTX *ctx)
{
u8* base = (void*)MI_GetWramMapStart_B();
static int count = 0;
while (size > 0)
{
u8* src = base + count * SLOT_SIZE;
u32 unit = size < SLOT_SIZE ? size : SLOT_SIZE;
if ( PXI_RecvID() != FIRM_PXI_ID_LOAD_PIRIOD )
{
return FALSE;
}
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;
SHA1_Update( ctx, s, u );
MI_CpuCopyFast( s, d, u );
}
}
else
{
MI_CpuCopyFast( src, dest, unit );
}
MI_CpuClearFast( src, unit );
DC_FlushRange( src, unit );
MIi_SetWramBankMaster_B(count, MI_WRAM_ARM7);
count = (count + 1) & 0x07;
size -= unit;
dest += unit;
}
return TRUE;
}
/*---------------------------------------------------------------------------*
Name: MI_LoadHeader
Description: load header
Arguments: pool pointer to the pool info for SVC_DecryptoSign
rsa_key key address
Returns: TRUE if success
*---------------------------------------------------------------------------*/
BOOL MI_LoadHeader( int* pool, const void* rsa_key )
{
SHA1_CTX ctx;
u8 md[DIGEST_SIZE_SHA1];
SHA1_Init(&ctx);
// load header (hash target)
if ( PXI_RecvID() != FIRM_PXI_ID_LOAD_HEADER ||
!MI_LoadBuffer( (u8*)rh, AUTH_SIZE, &ctx ) )
{
return FALSE;
}
SHA1_GetHash(&ctx, md);
// load header (remain)
if ( !MI_LoadBuffer( (u8*)rh + AUTH_SIZE, HEADER_SIZE - AUTH_SIZE, NULL ) )
{
return FALSE;
}
// RSA
#if 0
makerom.TWLのset_signature.cのCheckRomCertificateを元に書き換える
#endif
{
SignatureData sd;
#if 0
int i;
BOOL result = TRUE;
SVC_DecryptoSign(pool, &sd, rh->signature, rsa_key);
for (i = 0; i < DIGEST_SIZE_SHA1; i++)
{
if ( md[i] != sd.digest[i] )
{
result = FALSE;
}
}
#endif
#if 0
if ( !result )
{
return FALSE;
}
#endif
PXI_NotifyID( FIRM_PXI_ID_AUTH_HEADER );
// PXI_SendDataByFifo( PXI_FIFO_TAG_DATA, sd.aes_key_seed, AES_BLOCK_SIZE );
MI_CpuClear8(&sd, sizeof(sd));
MI_CpuClear8(&md, sizeof(md));
}
return TRUE;
}
static inline BOOL MIi_LoadModule(void* dest, u32 size, const u8 digest[DIGEST_SIZE_SHA1])
{
SHA1_CTX ctx;
u8 md[DIGEST_SIZE_SHA1];
int i;
BOOL result = TRUE;
SHA1_Init(&ctx);
if ( !MI_LoadBuffer( dest, size, &ctx ) )
{
return FALSE;
}
#if 0
SHA1_GetHash(&ctx, md);
for ( i = 0; i < DIGEST_SIZE_SHA1; i++ )
{
if ( md[i] != digest[i] )
{
result = FALSE;
}
}
#endif
return result;
}
/*---------------------------------------------------------------------------*
Name: MI_LoadMenu
Description: load menu program
Arguments: None
Returns: TRUE if success
*---------------------------------------------------------------------------*/
BOOL MI_LoadMenu( void )
{
// load ARM9 static region
if ( rh->s.main_size > 0 )
{
if ( PXI_RecvID() != FIRM_PXI_ID_LOAD_ARM9_STATIC ||
!MIi_LoadModule( rh->s.main_ram_address, rh->s.main_size, rh->s.main_static_digest ) )
{
return FALSE;
}
PXI_NotifyID( FIRM_PXI_ID_AUTH_ARM9_STATIC );
}
// load ARM7 static region
if ( rh->s.sub_size > 0 )
{
if ( PXI_RecvID() != FIRM_PXI_ID_LOAD_ARM7_STATIC ||
!MIi_LoadModule( rh->s.sub_ram_address, rh->s.sub_size, rh->s.sub_static_digest ) )
{
return FALSE;
}
PXI_NotifyID( FIRM_PXI_ID_AUTH_ARM7_STATIC );
}
// load ARM9 extended static region
if ( rh->s.main_ex_size > 0 )
{
if ( PXI_RecvID() != FIRM_PXI_ID_LOAD_ARM9_STATIC_EX ||
!MIi_LoadModule( rh->s.main_ex_ram_address, rh->s.main_ex_size, rh->s.main_static_ex_digest ) )
{
return FALSE;
}
PXI_NotifyID( FIRM_PXI_ID_AUTH_ARM9_STATIC_EX );
}
// load ARM7 extended static region
if ( rh->s.sub_ex_size > 0 )
{
if ( PXI_RecvID() != FIRM_PXI_ID_LOAD_ARM7_STATIC_EX ||
!MIi_LoadModule( rh->s.sub_ex_ram_address, rh->s.sub_ex_size, rh->s.sub_static_ex_digest ) )
{
return FALSE;
}
PXI_NotifyID( FIRM_PXI_ID_AUTH_ARM7_STATIC_EX );
}
return TRUE;
}
/*---------------------------------------------------------------------------*
Name: MI_BootMenu
Description: boot menu
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
void MI_BootMenu( void )
{
OSi_Boot( rh->s.main_entry_address, (MIHeader_WramRegs*)rh->s.main_wram_config_data );
}