mirror of
https://github.com/rvtr/TwlIPL.git
synced 2025-10-31 06:01:12 -04:00
git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlIPL/trunk@2562 b08762b0-b915-fc4b-9d8c-17b2551a87ff
333 lines
11 KiB
C
333 lines
11 KiB
C
/*---------------------------------------------------------------------------*
|
||
Project: TwlSDK - NandInitializer
|
||
File: kami_write_nandfirm.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 <twl/fatfs.h>
|
||
#include <nitro/card.h>
|
||
#include <twl/nam.h>
|
||
#include <nitro/nvram.h>
|
||
#include "kami_font.h"
|
||
#include "kami_pxi.h"
|
||
|
||
#include <firm/format/firm_common.h>
|
||
#include "kami_write_nandfirm.h"
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
マクロ定義
|
||
*---------------------------------------------------------------------------*/
|
||
|
||
// NANDファーム書き込みの際にNVRAMの未割り当て領域+予約領域を0クリアする場合は定義します(開発用)
|
||
//#define CLEAR_NON_ASIGNED_AREA_AND_RESERVED_AREA_ALL
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
定数定義
|
||
*---------------------------------------------------------------------------*/
|
||
|
||
#define NAND_BLOCK_BYTE 0x200
|
||
#define NAND_FIRM_START_OFFSET 0x200
|
||
#define NAND_FIRM_START_OFFSET_IN_FILE 0x200
|
||
|
||
#define NVRAM_PAGE_SIZE 0x100
|
||
#define NVRAM_NORFIRM_RESERVED_ADDRESS 0x200
|
||
#define NVRAM_NORFIRM_NANDBOOT_FLAG_OFFSET 0xff
|
||
#define NVRAM_NORFIRM_NANDBOOT_FLAG 0x80
|
||
|
||
#define NVRAM_NON_ASIGNED_AREA_ADDRESS 0x300
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
内部変数定義
|
||
*---------------------------------------------------------------------------*/
|
||
|
||
static u8 sNvramPageSizeBuffer[NVRAM_PAGE_SIZE] ATTRIBUTE_ALIGN(32); // ARM7からアクセスするためスタックでは駄目
|
||
static u32 sReservedAreaEndAddress;
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
内部関数定義
|
||
*---------------------------------------------------------------------------*/
|
||
|
||
void kamiEraseNandfirmVersion( u32 nandfirmsize );
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: kamiWriteNandfirm
|
||
|
||
Description:
|
||
|
||
Arguments: no
|
||
|
||
Returns: None.
|
||
*---------------------------------------------------------------------------*/
|
||
BOOL kamiWriteNandfirm(const char* pFullPath, NAMAlloc allocFunc, NAMFree freeFunc)
|
||
{
|
||
FSFile file;
|
||
|
||
BOOL open_is_ok;
|
||
BOOL read_is_ok;
|
||
u8* pTempBuf;
|
||
u32 file_size;
|
||
u32 nandfirm_size;
|
||
u32 alloc_size;
|
||
u32 write_block;
|
||
BOOL result = TRUE;
|
||
u16 crc_w1, crc_w2;
|
||
u16 crc_r1, crc_r2;
|
||
u16 crc_norfirm_reserved_area_w, crc_norfirm_reserved_area_r;
|
||
#ifdef CLEAR_NON_ASIGNED_AREA_AND_RESERVED_AREA_ALL
|
||
u32 write_offset;
|
||
#endif // CLEAR_NON_ASIGNED_AREA_AND_RESERVED_AREA_ALL
|
||
|
||
// .nandファイルオープン
|
||
FS_InitFile(&file);
|
||
open_is_ok = FS_OpenFile(&file, pFullPath);
|
||
if (!open_is_ok)
|
||
{
|
||
OS_Warning("Failure! FS_OpenFile");
|
||
return FALSE;
|
||
}
|
||
|
||
// サイズチェック
|
||
file_size = FS_GetFileLength(&file) ;
|
||
if (file_size > (800*1024))
|
||
{
|
||
kamiFontPrintfConsoleEx(1, "too big file size!\n");
|
||
FS_CloseFile(&file);
|
||
return FALSE;
|
||
}
|
||
|
||
nandfirm_size = file_size - NAND_FIRM_START_OFFSET_IN_FILE;
|
||
|
||
// バッファ確保
|
||
// 書き込みがブロック単位(512byte)であることを考慮し512アライメントを確保
|
||
alloc_size = MATH_ROUNDUP(file_size, 512);
|
||
pTempBuf = allocFunc( alloc_size );
|
||
if (pTempBuf == NULL)
|
||
{
|
||
kamiFontPrintfConsoleEx(1, "Fail Alloc()!\n");
|
||
FS_CloseFile(&file);
|
||
return FALSE;
|
||
}
|
||
|
||
MI_CpuClear8( pTempBuf, alloc_size );
|
||
|
||
// .nandファイルリード
|
||
DC_FlushRange(pTempBuf, alloc_size);
|
||
read_is_ok = FS_ReadFile( &file, pTempBuf, (s32)file_size );
|
||
DC_FlushRange(pTempBuf, file_size);
|
||
if (!read_is_ok)
|
||
{
|
||
kamiFontPrintfConsoleEx(1, "Fail FS_ReadFile!\n");
|
||
FS_CloseFile(&file);
|
||
freeFunc(pTempBuf);
|
||
return FALSE;
|
||
}
|
||
|
||
// ファイルクローズ
|
||
FS_CloseFile(&file);
|
||
|
||
// 書き込み前のCRCを計算
|
||
crc_w1 = SVC_GetCRC16( 0xffff, pTempBuf, sizeof(NORHeaderDS) );
|
||
crc_w2 = SVC_GetCRC16( 0xffff, pTempBuf+NAND_FIRM_START_OFFSET_IN_FILE, nandfirm_size );
|
||
|
||
// まずNORHeaderDS領域を書き込む(40byte?)
|
||
if (NVRAMi_Write(0, sizeof(NORHeaderDS), (void*)pTempBuf) != NVRAM_RESULT_SUCCESS)
|
||
{
|
||
kamiFontPrintfConsoleEx(1, "Fail NVRAMi_Write()\n");
|
||
result = FALSE;
|
||
}
|
||
|
||
// CRCを計算するので念のためにクリアしてからリードする
|
||
MI_CpuClear8( pTempBuf, sizeof(NORHeaderDS) );
|
||
DC_FlushRange(pTempBuf, sizeof(NORHeaderDS));
|
||
|
||
// CRCチェックのためNvramからリード
|
||
if (NVRAMi_Read(0, sizeof(NORHeaderDS), pTempBuf) != NVRAM_RESULT_SUCCESS)
|
||
{
|
||
kamiFontPrintfConsoleEx(1, "Fail NVRAMi_Read()!\n");
|
||
}
|
||
DC_FlushRange(pTempBuf, sizeof(NORHeaderDS));
|
||
|
||
// 書き込み後のCRCを計算
|
||
crc_r1 = SVC_GetCRC16( 0xffff, pTempBuf, sizeof(NORHeaderDS) );
|
||
|
||
// NVRAM先頭部分のCRC比較
|
||
if ( crc_w1 != crc_r1 )
|
||
{
|
||
freeFunc(pTempBuf);
|
||
kamiFontPrintfConsoleEx(1, "Fail! CRC check %x!=%x\n", crc_w1, crc_r1);
|
||
return FALSE;
|
||
}
|
||
|
||
// nandfirm 起動フラグを立てる
|
||
MI_CpuClear8( sNvramPageSizeBuffer, NVRAM_PAGE_SIZE );
|
||
sNvramPageSizeBuffer[NVRAM_NORFIRM_NANDBOOT_FLAG_OFFSET] = NVRAM_NORFIRM_NANDBOOT_FLAG;
|
||
DC_FlushRange( sNvramPageSizeBuffer, NVRAM_PAGE_SIZE);
|
||
|
||
// NORファームリザーブ領域の書き込みデータのCRCを計算
|
||
crc_norfirm_reserved_area_w = SVC_GetCRC16( 0xffff, sNvramPageSizeBuffer, NVRAM_PAGE_SIZE );
|
||
|
||
if (NVRAMi_Write(NVRAM_NORFIRM_RESERVED_ADDRESS, NVRAM_PAGE_SIZE, sNvramPageSizeBuffer) != NVRAM_RESULT_SUCCESS)
|
||
{
|
||
kamiFontPrintfConsoleEx(1, "Fail NVRAMi_Write()\n");
|
||
result = FALSE;
|
||
}
|
||
|
||
// CRCを計算するので念のためにクリアしてからリードする
|
||
MI_CpuClear8( sNvramPageSizeBuffer, NVRAM_PAGE_SIZE );
|
||
|
||
// 読み込みはARM7が直接メモリに書き出すため
|
||
DC_FlushRange(sNvramPageSizeBuffer, NVRAM_PAGE_SIZE);
|
||
|
||
if (NVRAMi_Read(NVRAM_NORFIRM_RESERVED_ADDRESS, NVRAM_PAGE_SIZE, sNvramPageSizeBuffer) != NVRAM_RESULT_SUCCESS)
|
||
{
|
||
kamiFontPrintfConsoleEx(1, "Fail NVRAMi_Read()\n");
|
||
result = FALSE;
|
||
}
|
||
|
||
// 書き込み後のCRCを計算
|
||
DC_FlushRange(sNvramPageSizeBuffer, NVRAM_PAGE_SIZE);
|
||
crc_norfirm_reserved_area_r = SVC_GetCRC16( 0xffff, sNvramPageSizeBuffer, NVRAM_PAGE_SIZE );
|
||
|
||
// NORファームリザーブ領域のCRC比較
|
||
if ( crc_norfirm_reserved_area_w != crc_norfirm_reserved_area_r )
|
||
{
|
||
kamiFontPrintfConsoleEx(1, "Fail! Norfirm Reserved Area CRC check %x!=%x\n", crc_norfirm_reserved_area_w, crc_norfirm_reserved_area_r);
|
||
result = FALSE;
|
||
}
|
||
|
||
#ifdef CLEAR_NON_ASIGNED_AREA_AND_RESERVED_AREA_ALL
|
||
DC_InvalidateRange( sNvramPageSizeBuffer, NVRAM_PAGE_SIZE );
|
||
// 未割り当て領域+予約領域を0クリアします(開発用)
|
||
if (NVRAMi_Read(NVRAM_CONFIG_DATA_OFFSET_ADDRESS, NVRAM_PAGE_SIZE, &sNvramPageSizeBuffer) != NVRAM_RESULT_SUCCESS)
|
||
{
|
||
kamiFontPrintfConsoleEx(1, "Fail NVRAMi_Read()\n");
|
||
result = FALSE;
|
||
}
|
||
sReservedAreaEndAddress = (u32)(*(u16 *)sNvramPageSizeBuffer << NVRAM_CONFIG_DATA_OFFSET_SHIFT) - 0xA00;// TWL WiFi設定 + NTR WiFi設定 を差し引く
|
||
//OS_Printf("end = %x\n", sReservedAreaEndAddress);
|
||
|
||
MI_CpuFill8( sNvramPageSizeBuffer, 0x00, NVRAM_PAGE_SIZE );
|
||
DC_FlushRange( sNvramPageSizeBuffer, NVRAM_PAGE_SIZE );
|
||
|
||
for (write_offset=NVRAM_NON_ASIGNED_AREA_ADDRESS; write_offset < sReservedAreaEndAddress; write_offset += NVRAM_PAGE_SIZE)
|
||
{
|
||
if (NVRAMi_Write(write_offset, NVRAM_PAGE_SIZE, sNvramPageSizeBuffer) != NVRAM_RESULT_SUCCESS)
|
||
{
|
||
kamiFontPrintfConsoleEx(1, "Fail NVRAMi_Write()\n");
|
||
result = FALSE;
|
||
}
|
||
}
|
||
//OS_Printf("write_offset = %x\n", write_offset);
|
||
#else
|
||
// 未割り当て領域先頭256byte+予約領域を0クリアします
|
||
|
||
MI_CpuFill8( sNvramPageSizeBuffer, 0x00, NVRAM_PAGE_SIZE );
|
||
DC_FlushRange( sNvramPageSizeBuffer, NVRAM_PAGE_SIZE );
|
||
|
||
if (NVRAMi_Write(NVRAM_NON_ASIGNED_AREA_ADDRESS, NVRAM_PAGE_SIZE, sNvramPageSizeBuffer) != NVRAM_RESULT_SUCCESS)
|
||
{
|
||
kamiFontPrintfConsoleEx(1, "Fail NVRAMi_Write()\n");
|
||
result = FALSE;
|
||
}
|
||
|
||
DC_InvalidateRange( sNvramPageSizeBuffer, NVRAM_PAGE_SIZE );
|
||
if (NVRAMi_Read(NVRAM_CONFIG_DATA_OFFSET_ADDRESS, NVRAM_PAGE_SIZE, &sNvramPageSizeBuffer) != NVRAM_RESULT_SUCCESS)
|
||
{
|
||
kamiFontPrintfConsoleEx(1, "Fail NVRAMi_Read()\n");
|
||
result = FALSE;
|
||
}
|
||
sReservedAreaEndAddress = (u32)(*(u16 *)sNvramPageSizeBuffer << NVRAM_CONFIG_DATA_OFFSET_SHIFT) - 0xA00;// TWL WiFi設定 + NTR WiFi設定 を差し引く
|
||
|
||
MI_CpuFill8( sNvramPageSizeBuffer, 0x00, NVRAM_PAGE_SIZE );
|
||
DC_FlushRange( sNvramPageSizeBuffer, NVRAM_PAGE_SIZE );
|
||
|
||
if (NVRAMi_Write(sReservedAreaEndAddress - 0x100, NVRAM_PAGE_SIZE, sNvramPageSizeBuffer) != NVRAM_RESULT_SUCCESS)
|
||
{
|
||
kamiFontPrintfConsoleEx(1, "Fail NVRAMi_Write()\n");
|
||
result = FALSE;
|
||
}
|
||
#endif
|
||
|
||
// NANDログ情報のクリア
|
||
if (kamiClearNandErrorLog() != KAMI_RESULT_SUCCESS)
|
||
{
|
||
kamiFontPrintfConsoleEx(1, "Fail kamiClearNandErrorLog()\n");
|
||
result = FALSE;
|
||
}
|
||
|
||
// nandfirmバージョンの消去(デバッグ用)
|
||
kamiEraseNandfirmVersion(nandfirm_size);
|
||
|
||
// kamiFontPrintfConsoleEx(0, "NAND Firm Import Start!\n");
|
||
|
||
// NAND書き込み
|
||
write_block = nandfirm_size/NAND_BLOCK_BYTE + (nandfirm_size % NAND_BLOCK_BYTE != 0);
|
||
kamiNandWrite( NAND_FIRM_START_OFFSET/NAND_BLOCK_BYTE, pTempBuf+NAND_FIRM_START_OFFSET, write_block ); // ブロック単位、バイト単位、ブロック単位
|
||
kamiFontLoadScreenData();
|
||
|
||
// CRCを計算するので念のためにクリアしてからリードする
|
||
MI_CpuClear8( pTempBuf, nandfirm_size );
|
||
DC_FlushRange(pTempBuf, nandfirm_size);
|
||
|
||
// CRCチェックのためNandからリード
|
||
if (kamiNandRead(NAND_FIRM_START_OFFSET/NAND_BLOCK_BYTE, pTempBuf, write_block ) == KAMI_RESULT_SEND_ERROR)
|
||
{
|
||
kamiFontPrintfConsoleEx(1, "kamiNandRead ... %s!\n", "ERROR");
|
||
}
|
||
DC_FlushRange(pTempBuf, nandfirm_size);
|
||
|
||
// 書き込み後のCRCを計算
|
||
crc_r2 = SVC_GetCRC16( 0xffff, pTempBuf, nandfirm_size );
|
||
|
||
// NAND部分についてのCRCチェック
|
||
if (crc_w2 == crc_r2)
|
||
{
|
||
// kamiFontPrintfConsoleEx(0, "Success! CRC check %x==%x\n", crc_w2, crc_r2);
|
||
}
|
||
else
|
||
{
|
||
result = FALSE;
|
||
kamiFontPrintfConsoleEx(1, "Fail! CRC check %x!=%x\n", crc_w2, crc_r2);
|
||
}
|
||
|
||
// メモリ解放
|
||
freeFunc(pTempBuf);
|
||
|
||
return result;
|
||
}
|
||
|
||
/*---------------------------------------------------------------------------*
|
||
Name: kamiEraseNandfirmVersion
|
||
|
||
Description: nandfirmのバージョン情報を消去します。(デバッグ用)
|
||
|
||
Arguments: no
|
||
|
||
Returns: None.
|
||
*---------------------------------------------------------------------------*/
|
||
void kamiEraseNandfirmVersion( u32 nandfirmsize )
|
||
{
|
||
u8 buffer[NAND_BLOCK_BYTE];
|
||
u32 blockNo;
|
||
|
||
if ((nandfirmsize % NAND_BLOCK_BYTE)==0)
|
||
{
|
||
blockNo = NAND_FIRM_START_OFFSET/NAND_BLOCK_BYTE + nandfirmsize/NAND_BLOCK_BYTE;
|
||
MI_CpuClear8( buffer, NAND_BLOCK_BYTE );
|
||
DC_FlushRange(buffer, NAND_BLOCK_BYTE);
|
||
kamiNandWrite( blockNo, buffer, 1 ); // ブロック単位、バイト単位、ブロック単位
|
||
}
|
||
}
|