リビジョン 516-528 を branches/work/VerificationFailed からマージ:

git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_Repair@685 385bec56-5757-e545-9c3a-d8741f4650f1
This commit is contained in:
N2614 2012-04-09 07:13:33 +00:00
parent 2b184df183
commit e5d5e566aa
8 changed files with 377 additions and 4 deletions

View File

@ -19,6 +19,7 @@
#include "HeapManager.h"
#include "SaveDataChecker.h"
#include <nn/drivers/aes/CTR/ARM946ES/driverAes_Types.h>
#include "HeapChecker.h"
namespace ConsoleBackup
{
@ -58,6 +59,7 @@ void CheckSaveDataThreadFunc(bool erase)
common::HeapManager heap(bufSize);
if (heap.GetAddr() != NULL)
{
bufSize = GetCheckedHeapSize();
s_pChecker = new NandSavedataChecker(heap.GetAddr(), bufSize);
s_CheckerResult = s_pChecker->CleanUp(erase);
}

View File

@ -32,6 +32,7 @@ namespace
typedef enum BackupState
{
STARTUP, // 初期値
CHECK_FCRAM, // FCRAMの確認
CHECK_SAVEDATA, // セーブデータの確認
EXPORT_TWL_NAND, // TWLセーブデータ領域の吸出し中
EXPORT_TWL_SOUND, // TWLサウンド領域の吸出し中
@ -177,18 +178,48 @@ void ControlState(common::HardwareStateManager& manager, common::OperationMessag
if (nextStep && !error)
{
COMMON_LOGGER("Checking SaveData\n");
COMMON_LOGGER("Checking Memory\n");
if(forceDelete)
{
s_BackupMode = BACKUP_MODE_DELETE_IF_FAILED;
}
s_BackupState = CHECK_SAVEDATA;
s_BackupState = CHECK_FCRAM;
}
}
break;
case CHECK_FCRAM:
{
static bool init = true;
if (init)
{
// ヒープをチェックする
CheckFcram();
init = false;
}
PutAliveMessage(operationMessage, "Checking Memory");
// 処理が完了した
if (IsExportThreadFinished())
{
FinalizeExportThread();
if (IsExportSucceeded())
{
COMMON_LOGGER("Checking SaveData\n");
s_BackupState = CHECK_SAVEDATA;
}
else
{
s_BackupState = FAIL;
}
}
}
break;
case CHECK_SAVEDATA:
{
static bool init = true;

View File

@ -1,4 +1,4 @@
/*---------------------------------------------------------------------------*
/*---------------------------------------------------------------------------*
Project: Horizon
File: Exporter.cpp
@ -48,6 +48,7 @@
#include "VersionDetect.h"
#include "Util.h"
#include "SaveDataMover.h"
#include "HeapChecker.h"
namespace ConsoleBackup
{
@ -165,6 +166,9 @@ nn::Result WriteTwlTitleList(std::vector<std::wstring>& programIdList)
}
common::HeapManager manager(heapSize);
if (manager.GetAddr() != NULL)
{
heapSize = GetCheckedHeapSize();
char* titleListBuf = reinterpret_cast<char*> (manager.GetAddr());
size_t writeSize = 0;
@ -172,7 +176,8 @@ nn::Result WriteTwlTitleList(std::vector<std::wstring>& programIdList)
{
for (std::vector<std::wstring>::iterator it = programIdList.begin(); it != programIdList.end(); it++)
{
nn::nstd::TSNPrintf(titleListBuf + writeSize, heapSize - writeSize, "%s\n", common::GetCharStr(it->c_str()));
nn::nstd::TSNPrintf(titleListBuf + writeSize, heapSize - writeSize, "%s\n",
common::GetCharStr(it->c_str()));
NN_LOG("%ls\n", it->c_str());
writeSize += it->size() + sizeof('\n');
}
@ -186,6 +191,12 @@ nn::Result WriteTwlTitleList(std::vector<std::wstring>& programIdList)
nn::Result::DESCRIPTION_OUT_OF_MEMORY);
}
}
else
{
return nn::Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_OUT_OF_RESOURCE, nn::Result::MODULE_APPLICATION,
nn::Result::DESCRIPTION_OUT_OF_MEMORY);
}
}
nn::Result WriteRegionData()
@ -502,6 +513,7 @@ void WriteTwlData(enum common::TWL_PATH_INDEX path)
void* buf = writeHeap.GetAddr();
if (buf != NULL)
{
bufSize = GetCheckedHeapSize();
nn::fs::FileOutputStream list;
result = list.TryInitialize(common::FILE_LIST_PATHNAME, true);
COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded);
@ -623,6 +635,7 @@ void WriteTwlSaveData()
void* buf = writeHeap.GetAddr();
if (buf != NULL)
{
bufSize = GetCheckedHeapSize();
nn::fs::FileOutputStream list;
result = list.TryInitialize(common::FILE_LIST_PATHNAME, true);
COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded);
@ -786,6 +799,7 @@ void ExportThreadFunc()
void* buf = writeHeap.GetAddr();
if (buf != NULL)
{
bufSize = GetCheckedHeapSize();
common::SaveDataMover saveDataMover;
saveDataMover.StartExport(buf, bufSize, &s_ExportProgress);
COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(
@ -872,6 +886,52 @@ void AddShutDownPtmEvent()
nn::fnd::DateTime::GetNow());
}
void HeapCheckerFunc()
{
s_IsExportSucceeded = true;
size_t heapSize = common::GetAllocatableSize();
if(heapSize > common::FILE_COPY_HEAP_SIZE)
{
heapSize = common::FILE_COPY_HEAP_SIZE;
}
common::HeapManager heap(heapSize);
nn::Result result;
result = nn::fs::MountSpecialArchive(common::NAND_ARCHIVE_NAME, nn::fs::CTR::ARCHIVE_TYPE_CTR_NAND);
COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded);
result = common::SdMountManager::Mount();
COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded);
result = CheckHeap(
(::std::wstring(common::NAND_DATA_ROOT_PATHNAME_WITH_SLASH) + ::std::wstring(s_RootName)
+ ::std::wstring(L"/")).c_str(), heap.GetAddr(), heapSize);
if(result.IsFailure())
{
s_IsExportSucceeded = false;
}
result = common::SdMountManager::Unmount();
COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded);
result = nn::fs::Unmount(common::NAND_ARCHIVE_NAME);
COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded);
}
void CheckFcram()
{
::std::string sysSaveRoot;
// IVSからセーブデータディレクトリ名を計算
common::Util::GetSaveDataDirectoryRoot(sysSaveRoot);
::std::mbstowcs(s_RootName, sysSaveRoot.c_str(), sysSaveRoot.size() + 1);
NN_LOG("%ls\n", (::std::wstring(common::NAND_DATA_ROOT_PATHNAME_WITH_SLASH) + ::std::wstring(s_RootName) + ::std::wstring(L"/")).c_str());
s_ExportThread.Start(HeapCheckerFunc, s_ExportThreadStack);
}
bool ExportData(common::HardwareStateManager& manager)
{
static bool init = true;

View File

@ -54,6 +54,9 @@ void FinalizeExportThread();
// 出力が成功したかどうか
bool IsExportSucceeded();
// 新たにスレッドを起動して、メモリチェックを行う
void CheckFcram();
}
#endif /* EXPORTER_H_ */

View File

@ -0,0 +1,180 @@
/*---------------------------------------------------------------------------*
Project: Horizon
File: HeapChecker.cpp
Copyright 2009-2011 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.
$Rev$
*---------------------------------------------------------------------------*/
#include <nn/crypto/crypto_SwAesCtrContext.h>
#include "Aes_define.h"
#include "HeapChecker.h"
#include "SdReaderWriter.h"
#include "CommonLogger.h"
namespace ConsoleBackup
{
namespace
{
HeapChecker s_HeapChecker;
}
nn::Result CheckHeap(std::wstring saveRoot, void* buf, size_t& bufSize)
{
return s_HeapChecker.Check(saveRoot, buf, bufSize);
}
size_t GetCheckedHeapSize()
{
return s_HeapChecker.GetCheckedSize();
}
HeapChecker::HeapChecker() :
m_CheckedSize(0), m_IsAlreadyChecked(false)
{
}
HeapChecker::~HeapChecker()
{
// TODO Auto-generated destructor stub
}
nn::Result HeapChecker::Check(std::wstring saveRoot, void* buf, size_t& bufSize)
{
// 2回目のチェックは行わない
if(m_IsAlreadyChecked)
{
NN_PANIC("HeapChecker Already checked");
}
nn::Result result;
common::SdReaderWriter sdReaderWriter;
// cecdセーブデータが存在しない場合は値を変更せずreturnする
{
nn::fs::FileInputStream nandFile;
result = nandFile.TryInitialize(std::wstring(saveRoot + std::wstring(L"sysdata/00010026/00000000")).c_str());
if (result <= nn::fs::ResultNotFound())
{
COMMON_LOGGER("No Reference Data. Use Default Memory Size.\n");
m_CheckedSize = bufSize;
m_IsAlreadyChecked = true;
return nn::ResultSuccess();
}
}
for(; HEAP_SIZE_MIN < bufSize; bufSize /= 2)
{
result = nn::fs::TryDeleteFile(HEAP_CHECKER_FILE);
if(!(result <= nn::fs::ResultNotFound()))
{
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
}
// NANDから読み込む
nn::fs::FileInputStream nandFile;
result = nandFile.TryInitialize(std::wstring(saveRoot + std::wstring(L"sysdata/00010026/00000000")).c_str());
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
nn::fs::FileStream sdFile;
result = sdFile.TryInitialize(HEAP_CHECKER_FILE,
nn::fs::OPEN_MODE_READ | nn::fs::OPEN_MODE_WRITE | nn::fs::OPEN_MODE_CREATE);
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
s32 readSize = 0;
nn::crypto::Sha256Context writeContext;
writeContext.Initialize();
nn::crypto::SwAesCtrContext aes;
aes.Initialize(common::checkiv, common::checkkey, sizeof(common::checkkey));
for(;;)
{
result = nandFile.TryRead(&readSize, buf, bufSize);
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
if(readSize == 0)
{
break;
}
aes.Encrypt(buf, buf, readSize);
writeContext.Update(buf, readSize);
s32 writeSize;
result = sdFile.TryWrite(&writeSize, buf, readSize, false);
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
result = sdFile.TryFlush();
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
}
bit8 sha256WriteContext[nn::crypto::Sha256Context::HASH_SIZE];
writeContext.GetHash(sha256WriteContext);
nn::crypto::Sha256Context readContext;
readContext.Initialize();
sdFile.SetPosition(0);
for(;;)
{
result = sdFile.TryRead(&readSize, buf, bufSize);
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
if(readSize == 0)
{
break;
}
readContext.Update(buf, readSize);
}
bit8 sha256ReadContext[nn::crypto::Sha256Context::HASH_SIZE];
readContext.GetHash(sha256ReadContext);
if(std::memcmp(sha256WriteContext, sha256ReadContext, sizeof(sha256ReadContext)) != 0)
{
COMMON_LOGGER("MemoryCheck Failure!! Size: %d\n", bufSize);
}
else
{
// チェックOK
break;
}
}
nn::fs::TryDeleteFile(HEAP_CHECKER_FILE);
if(bufSize == HEAP_SIZE_MIN)
{
return nn::Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_OUT_OF_RESOURCE, nn::Result::MODULE_APPLICATION,
nn::Result::DESCRIPTION_OUT_OF_MEMORY);
}
else
{
m_CheckedSize = bufSize;
m_IsAlreadyChecked = true;
return nn::ResultSuccess();
}
}
size_t HeapChecker::GetCheckedSize()
{
if(m_IsAlreadyChecked)
{
return m_CheckedSize;
}
else
{
return 0;
}
}
} /* namespace ConsoleBackup */

View File

@ -0,0 +1,71 @@
/*---------------------------------------------------------------------------*
Project: Horizon
File: HeapChecker.h
Copyright 2009-2011 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.
$Rev$
*---------------------------------------------------------------------------*/
#ifndef HEAPCHECKER_H_
#define HEAPCHECKER_H_
#include <string>
#include <nn.h>
namespace ConsoleBackup
{
nn::Result CheckHeap(std::wstring saveRoot, void* buf, size_t& bufSize);
size_t GetCheckedHeapSize();
//! @brief チェックするヒープサイズの下限です。
const size_t HEAP_SIZE_MIN = 512 * 1024;
//! @brief チェックに使うファイルへのパスです。
const wchar_t* const HEAP_CHECKER_FILE = L"sdmc:/CTR_Console_Repair/Check";
class HeapChecker
{
public:
HeapChecker();
virtual ~HeapChecker();
/*!
@brief 使NANDから読み出したデータをSDカードに書き出し
bufSizeが設定されます
@param[in] saveRoot NANDセーブデータのルートディレクトリのパス
@param[in] buf
@param[inout] buSize
@return ResultOutofMemory
@return ResultSuccess
*/
nn::Result Check(std::wstring saveRoot, void* buf, size_t& bufSize);
/*!
@brief
@return Check関数 Check関数が呼び出されていない場合は0
*/
size_t GetCheckedSize();
private:
size_t m_CheckedSize;
NN_PADDING3;
bool m_IsAlreadyChecked;
};
} /* namespace ConsoleBackup */
#endif /* HEAPCHECKER_H_ */

View File

@ -28,6 +28,7 @@ SOURCES[] =
Exporter.cpp
Checker.cpp
SavedataChecker.cpp
HeapChecker.cpp
../common/Util.cpp
../common/DrawSystemState.cpp
../common/FileTransfer.cpp

View File

@ -50,6 +50,18 @@ namespace common
0x7d, 0x06, 0x85, 0xe6, 0xe7, 0xb6, 0x4e, 0xe9
};
const bit8 checkkey[AES_KEY_SIZE] NN_ATTRIBUTE_ALIGN(4) =
{
0x5c, 0x5d, 0x56, 0x79, 0x20, 0x75, 0xfc, 0x56,
0x82, 0x6e, 0xd7, 0x55, 0xf5, 0xec, 0x0c, 0xc4
};
const bit8 checkiv[AES_BLOCK_SIZE] NN_ATTRIBUTE_ALIGN(4) =
{
0xb8, 0x84, 0x87, 0xce, 0xd5, 0xfd, 0x0a, 0xd4,
0x5b, 0x3f, 0x3b, 0xc8, 0xc9, 0x85, 0xdf, 0x8a
};
#else
const bit8 key[AES_KEY_SIZE] NN_ATTRIBUTE_ALIGN(4) =
{
@ -68,6 +80,19 @@ namespace common
0xe4, 0xcf, 0x58, 0xe5, 0xc9, 0xd6, 0xac, 0x7d,
0xf1, 0xb9, 0x82, 0xf9, 0xa2, 0xd8, 0xda, 0x7b
};
const bit8 checkkey[AES_KEY_SIZE] NN_ATTRIBUTE_ALIGN(4) =
{
0xaf, 0xce, 0x0a, 0x87, 0xae, 0x24, 0x64, 0xad,
0x1d, 0xfd, 0x11, 0x7a, 0xd5, 0xf3, 0xe8, 0x5b
};
const bit8 checkiv[AES_BLOCK_SIZE] NN_ATTRIBUTE_ALIGN(4) =
{
0x17, 0x32, 0x7c, 0xf3, 0x00, 0xae, 0x58, 0x67,
0x78, 0x5e, 0x56, 0xcd, 0x85, 0x70, 0xd7, 0x59
};
#endif