WRAM経由ファイル操作関数の組み込み(ハッシュ計算およびAES領域復号のCallbackは未実装)

git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlIPL/trunk@1158 b08762b0-b915-fc4b-9d8c-17b2551a87ff
This commit is contained in:
yoshida_teruhisa 2008-04-16 06:45:32 +00:00
parent 6bcf86e427
commit 8b5f5ecd76
4 changed files with 546 additions and 7 deletions

View File

@ -36,6 +36,7 @@ SRCS = sysmenu_lib.c \
keys.c \
title.c \
banner.c \
fs_wram.c \
../common/src/status.c \
../common/src/pxi.c \
../common/src/mountInfo.c \

View File

@ -0,0 +1,78 @@
/*---------------------------------------------------------------------------*
Project: TwlSDK - include - fs
File: fs_wram.h
Copyright 2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Date:: $
$Rev$
$Author$
*---------------------------------------------------------------------------*/
#ifndef TWL_FS_WRAM_H_
#define TWL_FS_WRAM_H_
#ifdef SDK_TWL
#include <twl.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
FSWramCallback
Read/Write中のWRAMにデータがある状態で呼び出されるAPI
addr
len
arg APIに渡した引数
*/
typedef void (*FSWramCallback)(const void* addr, u32 len, void* arg);
/*
FS_InitWramTransfer
priority
*/
BOOL FS_InitWramTransfer( u32 priority );
/*
FS_ReadFileViaWram
FS/FATFSに対して同期Readを行う
p_file FSでオープンしたファイル ()
dst
len
wram WRAM (B or C)
slot (ARM7/ARM9両方で確保可能であること)
size
callback Read中にWRAMにデータがある段階で随時呼び出されるコールバック
arg
*/
BOOL FS_ReadFileViaWram( FSFile *p_file, void *dst, s32 len, MIWramPos wram, s32 slot, MIWramSize size, FSWramCallback callback, void* arg );
/*
FS_WriteFileViaWram
FS/FATFSに対して同期Writeを行う
p_file FSでオープンしたファイル ()
src
len
wram WRAM (B or C)
slot (ARM7/ARM9両方で確保可能であること)
size
callback Write中にWRAMにデータがある段階で随時呼び出されるコールバック
arg
*/
BOOL FS_WriteFileViaWram( FSFile *p_file, const void *src, s32 len, MIWramPos wram, s32 slot, MIWramSize size, FSWramCallback callback, void* arg );
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* TWL_FS_WRAM_H_ */

View File

@ -0,0 +1,457 @@
/*---------------------------------------------------------------------------*
Project: TwlSDK - libraries - fs
File: fs_wram.c
Copyright 2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Date:: $
$Rev$
$Author$
*---------------------------------------------------------------------------*/
#include <twl.h>
#include "fs_wram.h"
/*
ARM9側スレッドありとなしでは構造が全く変わるがCARDもやっているのでスレッド前提はありかと
(PXIが非同期で発生する点に注意)
Read時の流れ
ARM9 (API) ARM7 (TASK)
WRAMをすべてARM7側にする
()
WRAMに1ブロックコピー
WRAMに1ブロックコピー
ARM9側にする
()
WRAMからdstにコピー
ARM7側にする
ARM7に通知 WRAMに1ブロックコピー
ARM9側にする WRAMが足りなくなったらストール
()
WRAMからdstにコピー
ARM7側にする
ARM7に通知 WRAMに1ブロックコピー
ARM9側にする
()
WRAMからdstにコピー
ARM7側にする
ARM7に通知
Write時の流れ
ARM9 (API) ARM7 (TASK)
()
ARM9側にする
srcからWRAMに1ブロックコピー
()
ARM7側にする
ARM9側にする
srcからWRAMに1ブロックコピー
()
ARM7側にする
ARM9側にする
srcからWRAMに1ブロックコピー
()
ARM7側にする
WRAMが足りなくなったらストール
ARM9側にする
srcからWRAMに1ブロックコピー
()
ARM7側にする
CARD FSがARM7側で処理するAPIを用意するか次第
AESもFSi_IsValidAddressForARM7のようなものでアクセス可能にできれば
ARM7に渡して暗号処理を施して返してもらうと
(AESはdest==srcが可能かと)
*/
/*
READ: WRAMサイズ128KB512Bで十分 ()
WRITE: WRAMサイズ256KB1KBは欲しい()
*/
#define FS_WRAM_CALLBACK_UNIT 1024
#define FS_WRAM_THREAD_STACK_SIZE 512
// 以下、固定値
#define FS_WRAM_MESSAGE_ARRAY_MAX 8
#define FS_WRAM_SLOT_SIZE (32*1024)
typedef enum FSWramCommand
{
FS_WRAM_COMMAND_READ,
FS_WRAM_COMMAND_WRITE
}
FSWramCommand;
typedef struct FSWramCommandParam
{
void* addr;
int length;
}
FSWramCommandParam;
typedef struct FSWramWork
{
u64 stack[FS_WRAM_THREAD_STACK_SIZE/sizeof(u64)];
OSThread thread;
OSMessageQueue msgQ4task;
OSMessage msgArray4task[FS_WRAM_MESSAGE_ARRAY_MAX];
OSMessageQueue msgQ4api;
OSMessage msgArray4api[FS_WRAM_MESSAGE_ARRAY_MAX];
FSWramCommandParam param[FS_WRAM_MESSAGE_ARRAY_MAX];
BOOL busy;
FSWramCommand command;
FSFile *p_file;
int nums; // WRAMスロット数
u32 base; // WRAMの先頭アドレス
}
FSWramWork;
static FSWramWork FSiWramWork;
/*
// override
BOOL FSi_IsValidAddressForARM7(const void *buffer, u32 length);
BOOL FSi_IsValidAddressForARM7(const void *buffer, u32 length)
{
u32 addr = (u32)buffer;
u32 dtcm = OS_GetDTCMAddress();
if ((addr + length > dtcm) && (addr < dtcm + HW_DTCM_SIZE))
{
return FALSE;
}
if ((addr >= HW_TWL_MAIN_MEM) && (addr + length <= HW_TWL_MAIN_MEM_END))
{
return TRUE;
}
if ((addr >= HW_EXT_WRAM_ARM7) && (addr + length <= GX_GetSizeOfARM7()))
{
return TRUE;
}
if (FSiWramWork.busy)
{
if ((addr >= FSiWramWork.base) && (addr + length <= FSiWramWork.base + FSiWramWork.nums * FS_WRAM_SLOT_SIZE))
{
return TRUE;
}
}
return FALSE;
}
*/
static void FSi_WramThread(void* arg)
{
#pragma unused(arg)
while (1)
{
FSWramCommandParam *cmd;
int result;
OS_ReceiveMessage(&FSiWramWork.msgQ4task, (OSMessage*)&cmd, OS_MESSAGE_BLOCK);
switch (FSiWramWork.command)
{
case FS_WRAM_COMMAND_READ:
result = FS_ReadFile( FSiWramWork.p_file, cmd->addr, cmd->length );
//OS_TPrintf("%s: (0x%08X) %d msec\n", __func__, cmd->addr, (int)OS_TicksToMilliSeconds(OS_GetTick()));
break;
case FS_WRAM_COMMAND_WRITE:
result = FS_WriteFile( FSiWramWork.p_file, cmd->addr, cmd->length );
//OS_TPrintf("%s: (0x%08X) %d msec\n", __func__, cmd->addr, (int)OS_TicksToMilliSeconds(OS_GetTick()));
break;
default:
result = -1;
}
if ( cmd->length != result )
{
OS_TWarning("%s: Failed to %s file (%d <=> %d).\n", __func__, FSiWramWork.command==FS_WRAM_COMMAND_READ?"read":"write", cmd->length, result);
}
OS_SendMessage(&FSiWramWork.msgQ4api, (OSMessage)(result==cmd->length?TRUE:FALSE), OS_MESSAGE_BLOCK);
}
}
BOOL FS_InitWramTransfer( u32 priority )
{
static BOOL initialized = FALSE;
if (initialized)
{
return FALSE;
}
OS_InitMessageQueue(&FSiWramWork.msgQ4task, FSiWramWork.msgArray4task, FS_WRAM_MESSAGE_ARRAY_MAX);
OS_InitMessageQueue(&FSiWramWork.msgQ4api, FSiWramWork.msgArray4api, FS_WRAM_MESSAGE_ARRAY_MAX);
OS_CreateThread(&FSiWramWork.thread, FSi_WramThread, 0,
(void*)(FSiWramWork.stack + (FS_WRAM_THREAD_STACK_SIZE/sizeof(u64))),
FS_WRAM_THREAD_STACK_SIZE, priority);
OS_WakeupThreadDirect(&FSiWramWork.thread);
return TRUE;
}
static int FSi_Increment( int p )
{
return (p + 1) % FSiWramWork.nums;
}
static int FSi_GetStackCount( int call, int ret )
{
return (call - ret + FSiWramWork.nums) % FSiWramWork.nums;
}
static BOOL FSi_ReadWram(u8* dest, u32 len, MIWramPos wram, s32 slot, FSWramCallback callback, void* arg)
{
u32 size4api = len;
u32 size4task = len;
int call = 0;
int ret = 0;
while ( size4api > 0 )
{
const u8* src = (u8*)(FSiWramWork.base + ret * FS_WRAM_SLOT_SIZE);
u32 unit = size4api < FS_WRAM_SLOT_SIZE ? size4api : FS_WRAM_SLOT_SIZE;
BOOL result;
// できるだけ起動する
for ( ; FSi_GetStackCount(call, ret) < FSiWramWork.nums - 1 && size4task > 0; call = FSi_Increment(call) )
{
FSiWramWork.param[call].addr = (void*)(FSiWramWork.base + call * FS_WRAM_SLOT_SIZE);
FSiWramWork.param[call].length = (int)(size4task < FS_WRAM_SLOT_SIZE ? size4task : FS_WRAM_SLOT_SIZE);
OS_SendMessage(&FSiWramWork.msgQ4task, (OSMessage)&FSiWramWork.param[call], OS_MESSAGE_BLOCK);
size4task -= FSiWramWork.param[call].length;
}
// task待ち
OS_ReceiveMessage(&FSiWramWork.msgQ4api, (OSMessage*)&result, OS_MESSAGE_BLOCK);
if (!result)
{
OS_TPrintf("%s: Failed to read file.\n", __func__);
return FALSE;
}
MI_SwitchWramSlot( wram, slot + ret, MI_WRAM_SIZE_32KB, MI_WRAM_ARM7, MI_WRAM_ARM9 );
//OS_TPrintf("%s: %d,%d (0x%08X->0x%08X) %d msec\n", __func__, call, ret, src, dest, (int)OS_TicksToMilliSeconds(OS_GetTick()));
if ( callback )
{
int done;
for ( done = 0; done < unit; done += FS_WRAM_CALLBACK_UNIT )
{
const u8* s = src + done;
u8* d = dest + done;
u32 u = unit - done < FS_WRAM_CALLBACK_UNIT ? unit - done : FS_WRAM_CALLBACK_UNIT;
callback(s, u, arg);
MI_CpuCopyFast( s, d, u );
}
}
else
{
MI_CpuCopyFast( src, dest, unit );
}
DC_InvalidateRange( (void*)src, unit );
//MI_SwitchWramSlot( wram, slot + ret, MI_WRAM_SIZE_32KB, MI_WRAM_ARM9, MI_WRAM_ARM7 );
size4api -= unit;
dest += unit;
ret = FSi_Increment(ret);
}
return TRUE;
}
static BOOL FSi_WriteWram(const u8* src, u32 len, MIWramPos wram, s32 slot, FSWramCallback callback, void* arg)
{
u32 size = len;
int call = 0;
int ret = 0;
while ( size > 0 )
{
u8* dest = (u8*)(FSiWramWork.base + call * FS_WRAM_SLOT_SIZE);
u32 unit = size < FS_WRAM_SLOT_SIZE ? size : FS_WRAM_SLOT_SIZE;
BOOL result;
// task済み回収
while ( OS_ReceiveMessage(&FSiWramWork.msgQ4api, (OSMessage*)&result, OS_MESSAGE_NOBLOCK) )
{
if (!result)
{
OS_TPrintf("%s: Failed to read file.\n", __func__);
return FALSE;
}
ret = FSi_Increment(ret);
}
// task回収ゼロだったら待つ
if ( FSi_GetStackCount( call, ret ) == FSiWramWork.nums - 1 )
{
OS_ReceiveMessage(&FSiWramWork.msgQ4api, (OSMessage*)&result, OS_MESSAGE_BLOCK);
if (!result)
{
OS_TPrintf("%s: Failed to read file.\n", __func__);
return FALSE;
}
ret = FSi_Increment(ret);
}
MI_SwitchWramSlot( wram, slot + call, MI_WRAM_SIZE_32KB, MI_WRAM_ARM7, MI_WRAM_ARM9 );
//OS_TPrintf("%s: %d,%d (0x%08X->0x%08X) %d msec\n", __func__, call, ret, src, dest, (int)OS_TicksToMilliSeconds(OS_GetTick()));
if ( callback )
{
int done;
for ( done = 0; done < unit; done += FS_WRAM_CALLBACK_UNIT )
{
const u8* s = src + done;
u8* d = dest + done;
u32 u = unit - done < FS_WRAM_CALLBACK_UNIT ? unit - done : FS_WRAM_CALLBACK_UNIT;
MI_CpuCopyFast( s, d, u );
callback(d, u, arg);
}
}
else
{
MI_CpuCopyFast( src, dest, unit );
}
DC_FlushRange( dest, unit );
//MI_SwitchWramSlot( wram, slot + call, MI_WRAM_SIZE_32KB, MI_WRAM_ARM9, MI_WRAM_ARM7 );
// 1つ用意できたので起動する
FSiWramWork.param[call].addr = (void*)(FSiWramWork.base + call * FS_WRAM_SLOT_SIZE);
FSiWramWork.param[call].length = (int)unit;
OS_SendMessage(&FSiWramWork.msgQ4task, (OSMessage)&FSiWramWork.param[call], OS_MESSAGE_BLOCK);
size -= unit;
src += unit;
dest += unit;
call = FSi_Increment(call);
}
// 残りtask回収
while ( FSi_GetStackCount(call, ret) )
{
BOOL result;
OS_ReceiveMessage(&FSiWramWork.msgQ4api, (OSMessage*)&result, OS_MESSAGE_BLOCK);
if (!result)
{
OS_TPrintf("%s: Failed to read file.\n", __func__);
return FALSE;
}
ret = FSi_Increment(ret);
}
return TRUE;
}
BOOL FS_ReadFileViaWram( FSFile *p_file, void *dst, s32 len, MIWramPos wram, s32 slot, MIWramSize size, FSWramCallback callback, void* arg )
{
OSIntrMode enabled = OS_DisableInterrupts();
BOOL result;
int l,n;
SDK_ASSERT( wram != MI_WRAM_A );
if ( FSiWramWork.busy ) // 転送中
{
OS_RestoreInterrupts(enabled);
return FALSE;
}
FSiWramWork.busy = TRUE;
OS_RestoreInterrupts(enabled);
// WRAMの確保
FSiWramWork.base = MI_AllocWramSlot( wram, slot, size, MI_WRAM_ARM9 );
if ( FSiWramWork.base == 0 )
{
FSiWramWork.busy = FALSE;
OS_TPrintf("Cannot allocate WRAM %d, %d, %d\n", wram, slot, size);
return FALSE;
}
// パラメータ設定
FSiWramWork.command = FS_WRAM_COMMAND_READ;
FSiWramWork.p_file = p_file;
FSiWramWork.nums = MI_WRAM_ENUM_TO_SIZE( size ) * 1024 / FS_WRAM_SLOT_SIZE;
// 必要に応じて7側にスイッチ可能なWRAMとして指定
n = 1 << slot;
for(l=0;l<FSiWramWork.nums-1;l++)
{
n = n << 1;
n += 1;
}
FSi_SetSwitchableWramSlots(n,0);
// WRAM->ARM9起動
result = FSi_ReadWram(dst, (u32)len, wram, slot, callback, arg);
MI_FreeWramSlot( wram, slot, size, MI_WRAM_ARM9 );
FSi_SetSwitchableWramSlots(0,0); // スイッチ可能WRAMの指定を元に戻す
FSiWramWork.busy = FALSE;
return result;
}
BOOL FS_WriteFileViaWram( FSFile *p_file, const void *src, s32 len, MIWramPos wram, s32 slot, MIWramSize size, FSWramCallback callback, void* arg )
{
OSIntrMode enabled = OS_DisableInterrupts();
BOOL result;
int l,n;
SDK_ASSERT( wram != MI_WRAM_A );
if ( FSiWramWork.busy ) // 転送中
{
OS_RestoreInterrupts(enabled);
return FALSE;
}
FSiWramWork.busy = TRUE;
OS_RestoreInterrupts(enabled);
// WRAMの確保
FSiWramWork.base = MI_AllocWramSlot( wram, slot, size, MI_WRAM_ARM7 );
if ( FSiWramWork.base == 0 )
{
FSiWramWork.busy = FALSE;
OS_TPrintf("Cannot allocate WRAM %d, %d, %d\n", wram, slot, size);
return FALSE;
}
// パラメータ設定
FSiWramWork.command = FS_WRAM_COMMAND_WRITE;
FSiWramWork.p_file = p_file;
FSiWramWork.nums = MI_WRAM_ENUM_TO_SIZE( size ) * 1024 / FS_WRAM_SLOT_SIZE;
// 必要に応じて7側にスイッチ可能なWRAMとして指定
n = 1 << slot;
for(l=0;l<FSiWramWork.nums-1;l++)
{
n = n << 1;
n += 1;
}
FSi_SetSwitchableWramSlots(n,0);
// ARM9->WRAM起動
result = FSi_WriteWram(src, (u32)len, wram, slot, callback, arg);
MI_FreeWramSlot( wram, slot, size, MI_WRAM_ARM7 );
FSi_SetSwitchableWramSlots(0,0); // スイッチ可能WRAMの指定を元に戻す
FSiWramWork.busy = FALSE;
return result;
}

View File

@ -20,6 +20,7 @@
#include <firm/format/from_firm.h>
#include <firm/hw/ARM9/mmap_firm.h>
#include "internal_api.h"
#include "fs_wram.h"
// define data-----------------------------------------------------------------
#define CARD_BANNER_INDEX ( LAUNCHER_TITLE_LIST_NUM - 1 )
@ -503,7 +504,7 @@ OS_TPrintf("RebootSystem failed: cant read file(%p, %d, %d, %d)\n", &s_authcode,
return;
}
}
/*
// [TODO:]新規Read関数の準備、とりあえずWRAMBをガメるつもりで実装
FS_InitWramTransfer(3);
MI_FreeWram_B( MI_WRAM_ARM7 );
@ -512,7 +513,7 @@ OS_TPrintf("RebootSystem failed: cant read file(%p, %d, %d, %d)\n", &s_authcode,
MI_CancelWram_B( MI_WRAM_ARM7 );
MI_CancelWram_B( MI_WRAM_ARM9 );
MI_CancelWram_B( MI_WRAM_DSP );
*/
for (i = region_header; i < region_max; ++i)
{
u32 len = MATH_ROUNDUP( length[i], SYSM_ALIGNMENT_LOAD_MODULE );// AES暗号化領域の関係で、ロードサイズは32バイトアライメントに補正
@ -528,16 +529,15 @@ OS_TPrintf("RebootSystem failed: cant seek file(%d)\n", source[i]);
return;
}
/*
// [TODO:]ここで新規関数を使って同時にハッシュ計算やAES処理もやってしまう予定
// 別スレッドで同じWRAM使おうとすると多分コケるのでしっかりWRAMガメないとダメ
if ( !FS_ReadFileViaWram(file, (void *)destaddr[i], len, MI_WRAM_B, 0, MI_WRAM_SIZE_256KB, , ) )
// [TODO:]ここで同時にハッシュ計算やAES処理もやってしまう予定
// 別スレッドで同じWRAM使おうとすると多分コケるので注意
if ( !FS_ReadFileViaWram(file, (void *)destaddr[i], (s32)len, MI_WRAM_B, 0, MI_WRAM_SIZE_128KB, NULL, NULL ) )
{
OS_TPrintf("RebootSystem failed: cant read file(%d, %d)\n", source[i], len);
FS_CloseFile(file);
return;
}
*/
/*
readLen = FS_ReadFile(file, (void *)destaddr[i], (s32)len);
if( readLen < 0 )
@ -546,12 +546,14 @@ OS_TPrintf("RebootSystem failed: cant read file(%d, %d)\n", source[i], len);
FS_CloseFile(file);
return;
}
*/
}
(void)FS_CloseFile(file);
}
OS_TPrintf("RebootSystem : Load Succeed.\n");
SYSMi_GetWork()->flags.common.isLoadSucceeded = TRUE;
}
@ -942,6 +944,7 @@ static AuthResult SYSMi_AuthenticateHeader( TitleProperty *pBootTitle)
{
ROM_Header_Short *hs = ( ROM_Header_Short *)SYSM_CARD_ROM_HEADER_BUF;
// [TODO:]認証結果はどこかワークに保存しておく
// [TODO:]ヘッダに署名ビットがあるはずなので、それを確認して署名チェックを行う
if( hs->platform_code & PLATFORM_CODE_FLAG_TWL )
{
// TWLアプリ