mirror of
https://github.com/rvtr/ctr_Repair.git
synced 2025-10-31 13:51:08 -04:00
リビジョン 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:
parent
2b184df183
commit
e5d5e566aa
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -54,6 +54,9 @@ void FinalizeExportThread();
|
||||
// 出力が成功したかどうか
|
||||
bool IsExportSucceeded();
|
||||
|
||||
// 新たにスレッドを起動して、メモリチェックを行う
|
||||
void CheckFcram();
|
||||
|
||||
}
|
||||
|
||||
#endif /* EXPORTER_H_ */
|
||||
|
||||
@ -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 */
|
||||
@ -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_ */
|
||||
@ -28,6 +28,7 @@ SOURCES[] =
|
||||
Exporter.cpp
|
||||
Checker.cpp
|
||||
SavedataChecker.cpp
|
||||
HeapChecker.cpp
|
||||
../common/Util.cpp
|
||||
../common/DrawSystemState.cpp
|
||||
../common/FileTransfer.cpp
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user