mirror of
https://github.com/rvtr/ctr_Repair.git
synced 2025-10-31 13:51:08 -04:00
SDに出力するResult用マクロの整理 git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_Repair@3 385bec56-5757-e545-9c3a-d8741f4650f1
391 lines
12 KiB
C++
391 lines
12 KiB
C++
/*---------------------------------------------------------------------------*
|
|
Project: Horizon
|
|
File: Exporter.cpp
|
|
|
|
Copyright 2009 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 <vector>
|
|
#include <cstdlib>
|
|
#include <cwchar>
|
|
#include <string>
|
|
#include <cstdlib>
|
|
#include <nn/fs/CTR/fs_ArchiveTypesForSystem.h>
|
|
#include <nn/fs/CTR/MPCore/fs_FileSystemBasePrivate.h>
|
|
#include <nn/cfg/CTR/cfg_ApiNor.h> // cfg:norの初期化に必要
|
|
#include <nn/cfg/CTR/cfg_NtrSettings.h>
|
|
#include <nn/ps/CTR/ps_API.h>
|
|
#include <nn/drivers/aes/CTR/ARM946ES/driverAes_Types.h>
|
|
#include <nn/crypto/crypto_SwAesCtrContext.h>
|
|
|
|
#include "Exporter.h"
|
|
#include "CommonLogger.h"
|
|
#include "SDMountManager.h"
|
|
#include "ConsoleBackup.h"
|
|
#include "HeapManager.h"
|
|
#include "SdReaderWriter.h"
|
|
#include "FileName.h"
|
|
#include "FileTransfer.h"
|
|
#include "common_Types.h"
|
|
#include "Aes_define.h"
|
|
|
|
namespace ConsoleBackup
|
|
{
|
|
|
|
namespace
|
|
{
|
|
|
|
common::SdReaderWriter s_SdWriter;
|
|
common::NtrNorData s_NtrNorData;
|
|
|
|
::std::string s_SysSaveRoot;
|
|
|
|
const size_t EXPORT_THREAD_STACK_SIZE = 0x4000;
|
|
nn::os::Thread s_ExportThread;
|
|
nn::os::StackBuffer<EXPORT_THREAD_STACK_SIZE> s_ExportThreadStack;
|
|
|
|
wchar_t s_RootName[256];
|
|
|
|
bool s_IsExportThreadFinished = false;
|
|
|
|
}
|
|
|
|
void DeleteTrash()
|
|
{
|
|
// TODO: リードオンリーのファイルが消去できない
|
|
|
|
COMMON_LOGGER("Delete Trash.\n");
|
|
|
|
std::wstring currentDirectory = common::SDMC_ROOT_DIRECTORY_PATH;
|
|
nn::fs::FileInputStream fis;
|
|
nn::fs::Directory dir;
|
|
nn::Result result;
|
|
std::vector<nn::fs::DirectoryEntry> entryList; //カレントディレクトリのエントリ一覧を格納
|
|
std::vector<nn::fs::DirectoryEntry>::iterator entryIndex;
|
|
|
|
common::SdMountManager::Mount();
|
|
|
|
result = dir.TryInitialize(currentDirectory.c_str());
|
|
|
|
if (result.IsSuccess())
|
|
{
|
|
nn::fs::DirectoryEntry entry;
|
|
s32 numEntry;
|
|
for (;;)
|
|
{
|
|
result = dir.TryRead(&numEntry, &entry, 1);
|
|
if (result.IsFailure())
|
|
{
|
|
dir.Finalize();
|
|
}
|
|
if (numEntry == 0)
|
|
{
|
|
// ルートディレクトリを閉じる
|
|
dir.Finalize();
|
|
|
|
// ルートディレクトリの子を開く
|
|
for (entryIndex = entryList.begin(); entryIndex != entryList.end(); entryIndex++)
|
|
{
|
|
// ディレクトリなら削除する
|
|
if (entryIndex->attributes.isDirectory)
|
|
{
|
|
NN_LOG("Try Delete %ls%ls/\n", currentDirectory.c_str(), entryIndex->entryName);
|
|
result = nn::fs::TryDeleteDirectoryRecursively((currentDirectory + ::std::wstring(
|
|
entryIndex->entryName)).c_str());
|
|
if(result.IsFailure())
|
|
{
|
|
COMMON_LOGGER_RESULT_WITH_LINE(result , __LINE__);
|
|
}
|
|
|
|
}
|
|
// ファイルならログとAP設定以外は削除する
|
|
else
|
|
{
|
|
if (std::wcscmp(entryIndex->entryName, common::AP_SETTING_FILENAME) != 0 && std::wcscmp(
|
|
entryIndex->entryName, common::Logger::LOG_FILENAME) != 0)
|
|
{
|
|
NN_LOG("Try Delete %ls%ls\n", currentDirectory.c_str(), entryIndex->entryName);
|
|
result = nn::fs::TryDeleteFile(
|
|
(currentDirectory + ::std::wstring(entryIndex->entryName)).c_str());
|
|
if(result.IsFailure())
|
|
{
|
|
COMMON_LOGGER_RESULT_WITH_LINE(result , __LINE__);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 削除完了
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
// vectorに保存する
|
|
entryList.push_back(entry);
|
|
if (entry.attributes.isDirectory)
|
|
{
|
|
NN_LOG("%ls%ls/\n", currentDirectory.c_str(), entry.entryName);
|
|
}
|
|
else
|
|
{
|
|
NN_LOG("%ls%ls\n", currentDirectory.c_str(), entry.entryName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NN_LOG("failed initialize directory\n");
|
|
COMMON_LOGGER_RESULT_WITH_LINE(result , __LINE__);
|
|
dir.Finalize();
|
|
}
|
|
|
|
common::SdMountManager::Unmount();
|
|
}
|
|
|
|
void WriteNorData()
|
|
{
|
|
COMMON_LOGGER("Export NOR Data.\n");
|
|
|
|
nn::Result result;
|
|
|
|
nn::cfg::nor::CTR::Initialize();
|
|
|
|
NN_LOG("Get NTR User Setting\n");
|
|
|
|
// NTR設定
|
|
result = nn::cfg::nor::CTR::GetNtrSetting(&s_NtrNorData.ntrConfig.ncd, &s_NtrNorData.ntrConfig.ncd_ex);
|
|
COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result);
|
|
|
|
// TWL WiFi設定
|
|
result = nn::cfg::nor::CTR::ReadTwlWifiSetting(0, s_NtrNorData.TwlWiFiSetting, common::TWL_WIFI_SETTING_SIZE);
|
|
COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result);
|
|
|
|
// NTR WiFi設定
|
|
result = nn::cfg::nor::CTR::ReadNtrWifiSetting(0, s_NtrNorData.NtrWiFiSetting, common::NTR_WIFI_SETTING_SIZE);
|
|
COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result);
|
|
|
|
s_SdWriter.WriteBuf(common::NOR_PATHNAME, &s_NtrNorData, sizeof(common::NtrNorData));
|
|
}
|
|
|
|
void WriteSerialNumber()
|
|
{
|
|
COMMON_LOGGER("Export Serial Number.\n");
|
|
|
|
u8* serial;
|
|
size_t size;
|
|
GetSerialNumber(&serial, &size);
|
|
|
|
s_SdWriter.WriteBuf(common::SERIAL_PATHNAME, serial, size);
|
|
}
|
|
|
|
void WriteIvs()
|
|
{
|
|
COMMON_LOGGER("Export IVS.\n");
|
|
|
|
bit8 iv[AES_BLOCK_SIZE] =
|
|
{
|
|
0xdf, 0x0f, 0xf9, 0x1b, 0x34, 0x47, 0x70, 0x7f,
|
|
0x7d, 0x06, 0x85, 0xe6, 0xe7, 0xb6, 0x4e, 0xe9
|
|
};
|
|
|
|
void* ivs;
|
|
size_t size;
|
|
GetIvs(&ivs, &size);
|
|
|
|
void* enc;
|
|
nn::Result result;
|
|
enc = common::HeapManager::GetHeap()->Allocate(size);
|
|
if(enc != NULL)
|
|
{
|
|
// AES暗号化する
|
|
nn::crypto::Initialize();
|
|
|
|
nn::crypto::SwAesCtrContext swAesCtrContest;
|
|
|
|
swAesCtrContest.Initialize(iv, common::key, sizeof(common::key));
|
|
swAesCtrContest.Encrypt(enc, ivs, size);
|
|
|
|
s_SdWriter.WriteBuf(common::IVS_PATHNAME, enc, size);
|
|
|
|
common::HeapManager::GetHeap()->Free(enc);
|
|
}
|
|
}
|
|
|
|
// IVSからセーブデータディレクトリ名を生成する
|
|
void GetSaveDataDirectoryRoot()
|
|
{
|
|
nn::Result result;
|
|
using namespace nn::dbg;
|
|
|
|
const size_t SEED_SIZE = 16;
|
|
bit8 hash[nn::crypto::Sha256Context::HASH_SIZE];
|
|
const size_t SYS_SAVE_ROOT_LENGTH = 16;
|
|
char rootHash[SYS_SAVE_ROOT_LENGTH];
|
|
char rootStr[SYS_SAVE_ROOT_LENGTH * 2 + 1];
|
|
|
|
void* addr;
|
|
size_t size;
|
|
GetIvs(&addr, &size);
|
|
|
|
// 最後の16バイトのハッシュを使う
|
|
nn::crypto::CalculateSha256(hash, &reinterpret_cast<bit8*> (addr)[size - SEED_SIZE], SEED_SIZE);
|
|
|
|
for (u8 i = 0; i < SEED_SIZE / 4; i++)
|
|
{
|
|
for (u8 j = 0; j < SEED_SIZE / 4; j++)
|
|
{
|
|
rootHash[i * 4 + j] = hash[i * 4 + 3 - j];
|
|
}
|
|
}
|
|
|
|
// 得られたハッシュから文字列を生成
|
|
for (s32 k = 0; k < SEED_SIZE; k++)
|
|
{
|
|
for (s32 i = 6; i < 8; ++i)
|
|
{
|
|
bit32 n = (rootHash[k] >> ((7 - i) * 4)) & 0xf;
|
|
NN_TASSERT_(0 <= n && n < 16);
|
|
rootStr[i - 6 + k * 2] = static_cast<char> (n < 10 ? '0' + n : 'a' + (n - 10));
|
|
}
|
|
}
|
|
rootStr[SYS_SAVE_ROOT_LENGTH * 2] = '\0';
|
|
|
|
// セーブデータディレクトリ名を保存する
|
|
s_SysSaveRoot = ::std::string(rootStr);
|
|
|
|
NN_LOG("%s\n", s_SysSaveRoot.c_str());
|
|
}
|
|
|
|
|
|
void ExportThreadFunc()
|
|
{
|
|
nn::Result result;
|
|
|
|
s_IsExportThreadFinished = false;
|
|
result = nn::fs::MountSpecialArchive(common::NAND_ARCHIVE_NAME, nn::fs::CTR::ARCHIVE_TYPE_CTR_NAND);
|
|
if(result.IsFailure())
|
|
{
|
|
COMMON_LOGGER_RESULT_WITH_LINE(result , __LINE__);
|
|
}
|
|
|
|
result = common::SdMountManager::Mount();
|
|
|
|
size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize();
|
|
NN_LOG("AllocatableSize = %d\n", bufSize);
|
|
|
|
void* buf = common::HeapManager::GetHeap()->Allocate(bufSize);
|
|
if (buf != NULL)
|
|
{
|
|
|
|
common::CopyDirectory(
|
|
(::std::wstring(common::NAND_DATA_ROOT_PATHNAME_WITH_SLASH) + ::std::wstring(s_RootName) + ::std::wstring(L"/")).c_str(),
|
|
(common::SDMC_ROOT_DIRECTORY_PATH + ::std::wstring(common::SD_SAVEDATA_ROOT_NAME) + ::std::wstring(s_RootName) + ::std::wstring(L"/")).c_str(),
|
|
buf, bufSize);
|
|
|
|
common::HeapManager::GetHeap()->Free(buf);
|
|
}
|
|
|
|
common::SdMountManager::Unmount();
|
|
nn::fs::Unmount(common::NAND_ARCHIVE_NAME);
|
|
|
|
NN_LOG("Export Thread Finalize\n");
|
|
s_IsExportThreadFinished = true;
|
|
}
|
|
|
|
nn::Result WriteSaveData()
|
|
{
|
|
// NANDからSDカードに書き出し
|
|
nn::Result result;
|
|
|
|
result = nn::fs::MountSpecialArchive(common::NAND_ARCHIVE_NAME, nn::fs::CTR::ARCHIVE_TYPE_CTR_NAND);
|
|
if(result.IsFailure())
|
|
{
|
|
COMMON_LOGGER_RESULT_WITH_LINE(result , __LINE__);
|
|
return result;
|
|
}
|
|
|
|
u32 fileNum = 0;
|
|
u32 fileSize = 0;
|
|
common::CalculateFileNum(::std::wstring(common::NAND_DATA_ROOT_PATHNAME_WITH_SLASH), fileNum, fileSize);
|
|
|
|
nn::fs::Unmount(common::NAND_ARCHIVE_NAME);
|
|
|
|
NN_LOG("File Number = %d\n", fileNum);
|
|
NN_LOG("File Size = %d\n", fileSize);
|
|
// 進捗表示用
|
|
common::SetTotalSize(fileSize);
|
|
|
|
::std::mbstowcs(s_RootName, s_SysSaveRoot.c_str(), s_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());
|
|
|
|
// セーブデータディレクトリ以下のデータをSDカードにコピー
|
|
// コピー用ディレクトリ作成
|
|
COMMON_LOGGER("Create Backup Directory.\n");
|
|
s_SdWriter.CreateDirectory((::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring(
|
|
common::SD_SAVEDATA_ROOT_NAME)).c_str());
|
|
s_SdWriter.CreateDirectory((::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring(
|
|
common::SD_SAVEDATA_ROOT_NAME) + ::std::wstring(s_RootName) + ::std::wstring(L"/")).c_str());
|
|
|
|
COMMON_LOGGER("Export NAND Data Start...\n");
|
|
|
|
// SDにコピーするためのスレッドの作成
|
|
s_ExportThread.Start(ExportThreadFunc, s_ExportThreadStack);
|
|
|
|
return result;
|
|
}
|
|
|
|
void FinalizeExportThread()
|
|
{
|
|
s_ExportThread.Join();
|
|
}
|
|
|
|
void ExportData()
|
|
{
|
|
static bool init = true;
|
|
|
|
if (init)
|
|
{
|
|
// 不要なデータを削除する
|
|
DeleteTrash();
|
|
|
|
// NORデータをSDカードに書き込む
|
|
WriteNorData();
|
|
|
|
// シリアルナンバーをSDカードに書き込む
|
|
WriteSerialNumber();
|
|
|
|
// 完全性検証SEEDをSDカードに書き込む
|
|
WriteIvs();
|
|
|
|
// IVSからセーブデータディレクトリ名を計算
|
|
GetSaveDataDirectoryRoot();
|
|
|
|
// NANDのセーブデータをSDに書き出す
|
|
WriteSaveData();
|
|
|
|
init = false;
|
|
}
|
|
}
|
|
|
|
u32 GetProgress()
|
|
{
|
|
return common::GetProgress();
|
|
}
|
|
|
|
bool IsExportFinished()
|
|
{
|
|
return s_IsExportThreadFinished;
|
|
}
|
|
|
|
}
|