diff --git a/trunk/ConsoleDataMigration/sources/ConsoleRestore/Controller.cpp b/trunk/ConsoleDataMigration/sources/ConsoleRestore/Controller.cpp index 81f8b84..93617d2 100644 --- a/trunk/ConsoleDataMigration/sources/ConsoleRestore/Controller.cpp +++ b/trunk/ConsoleDataMigration/sources/ConsoleRestore/Controller.cpp @@ -1124,7 +1124,7 @@ void ControlState(common::HardwareStateManager& manager, ::std::vector #include @@ -99,11 +100,15 @@ common::VerDef s_SDVersionData; // SDカードから読み込んだファイル一覧 common::ImportDataList s_FileLists; +u64 s_ImportProgress = 0; + } // SDからファイル一覧を読み込む nn::Result ReadFileList(SdFileSize* sdFileSize, common::ImportDataList* fileList); +bool RequiresImportApi(); + CheckedNetworkSetting s_CurrentNetowrkSetting1; void ConvertTimeZoneString(const char* str) @@ -659,7 +664,15 @@ nn::Result ImportIvs() { if (result.IsSuccess()) { - if (s_SDVersionData.cup.majorVersion < common::CUP_MAJOR_VER_2ND_NUP) + // 2ndNUPからはAPI経由で書き込む + if (RequiresImportApi()) + { + result = nn::fs::CTR::ImportIntegrityVerificationSeed( + *reinterpret_cast(dec)); + NN_UTIL_RETURN_IF_FAILED(result); + COMMON_LOGGER("Import SDCI.\n"); + } + else { s32 writeSize; result = fos.TryWrite(&writeSize, dec, readSize, true); @@ -668,14 +681,6 @@ nn::Result ImportIvs() COMMON_LOGGER("Import SDCI.\n"); } } - // 2ndNUPからはAPI経由で書き込む - else - { - result = nn::fs::CTR::ImportIntegrityVerificationSeed( - *reinterpret_cast(dec)); - NN_UTIL_RETURN_IF_FAILED(result); - COMMON_LOGGER("Import SDCI.\n"); - } } } } @@ -706,6 +711,11 @@ bool ImportIvsData() return ImportIvs().IsSuccess(); } +bool RequiresImportApi() +{ + return common::CUP_MAJOR_VER_2ND_NUP <= s_SDVersionData.cup.majorVersion; +} + void ImportThreadFunc() { nn::Result result; @@ -728,14 +738,27 @@ void ImportThreadFunc() void* buf = heap.GetAddr(); if (buf != NULL) { - if(!common::CopyDirectory( - &s_FileLists, - (::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring(common::SD_SAVEDATA_ROOT_NAME)).c_str(), - common::NAND_DATA_ROOT_PATHNAME_WITH_SLASH, - buf, bufSize, false, NULL, NULL)) + // 吸い出したバージョンによって書き込み関数を変える + if(RequiresImportApi()) { - s_IsImportSucceeded = false; - return; + common::SaveDataMover saveDataMover; + saveDataMover.StartImport(buf, bufSize, &s_ImportProgress); + if(saveDataMover.GetLastResult().IsFailure()) + { + s_IsImportSucceeded = false; + return; + } + } + else + { + if (!common::CopyDirectory( + &s_FileLists, + (::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring(common::SD_SAVEDATA_ROOT_NAME)).c_str(), + common::NAND_DATA_ROOT_PATHNAME_WITH_SLASH, buf, bufSize, false, NULL, NULL)) + { + s_IsImportSucceeded = false; + return; + } } } @@ -1036,7 +1059,14 @@ void CreateTransferAccountFinishedFile() u32 GetImportProgress() { - return common::GetProgress(); + if(RequiresImportApi()) + { + return s_ImportProgress; + } + else + { + return common::GetProgress(); + } } bool UpdateNetworkSetting(nn::ac::NetworkSetting& networkSetting) @@ -1769,7 +1799,7 @@ nn::Result InitializeHardwareDependentSetting() return result; } -nn::Result SetupFileList() +nn::Result SetupVersionAndFileList() { std::memset(&s_SdFileSize, 0, sizeof(s_SdFileSize)); @@ -1777,6 +1807,10 @@ nn::Result SetupFileList() nn::Result result = ReadFileList(&s_SdFileSize, &s_FileLists); NN_UTIL_RETURN_IF_FAILED(result); + // バージョンデータを読み込む + result = ReadVersionData(); + NN_UTIL_RETURN_IF_FAILED(result); + return result; } diff --git a/trunk/ConsoleDataMigration/sources/ConsoleRestore/Importer.h b/trunk/ConsoleDataMigration/sources/ConsoleRestore/Importer.h index e2c49b1..d17382a 100644 --- a/trunk/ConsoleDataMigration/sources/ConsoleRestore/Importer.h +++ b/trunk/ConsoleDataMigration/sources/ConsoleRestore/Importer.h @@ -35,7 +35,7 @@ nn::Result EqualsRegionDataandRegion(); nn::Result ReadSerialNumber(u8* serial); // 出力ファイル一覧を読み込む -nn::Result SetupFileList(); +nn::Result SetupVersionAndFileList(); // インポート用のスレッドを終了する void FinalizeImportThread(); diff --git a/trunk/ConsoleDataMigration/sources/ConsoleRestore/OMakefile b/trunk/ConsoleDataMigration/sources/ConsoleRestore/OMakefile index a806df9..9eec3b1 100644 --- a/trunk/ConsoleDataMigration/sources/ConsoleRestore/OMakefile +++ b/trunk/ConsoleDataMigration/sources/ConsoleRestore/OMakefile @@ -46,6 +46,7 @@ SOURCES[] = ../common/VersionDetect.cpp ../common/ResFont.cpp ../common/HardwareStateManager.cpp + ../common/SaveDataMover.cpp CTR_BANNER_SPEC = $(TARGET_PROGRAM).bsf diff --git a/trunk/ConsoleDataMigration/sources/common/FileTransfer.cpp b/trunk/ConsoleDataMigration/sources/common/FileTransfer.cpp index daf8d15..5f33263 100644 --- a/trunk/ConsoleDataMigration/sources/common/FileTransfer.cpp +++ b/trunk/ConsoleDataMigration/sources/common/FileTransfer.cpp @@ -803,7 +803,8 @@ nn::Result CalculateFileSizeRecursively(std::wstring currentDirectory, s64& file // ディレクトリの場合 if (entry.attributes.isDirectory) { - return CalculateFileSizeRecursively(currentDirectory + std::wstring(entry.entryName) + std::wstring(L"/"), fileSize); + result = CalculateFileSizeRecursively(currentDirectory + std::wstring(entry.entryName) + std::wstring(L"/"), fileSize); + NN_UTIL_RETURN_IF_FAILED(result); } // ファイルの場合 else diff --git a/trunk/ConsoleDataMigration/sources/common/SaveDataMover.cpp b/trunk/ConsoleDataMigration/sources/common/SaveDataMover.cpp index b62af03..dc28294 100644 --- a/trunk/ConsoleDataMigration/sources/common/SaveDataMover.cpp +++ b/trunk/ConsoleDataMigration/sources/common/SaveDataMover.cpp @@ -1,4 +1,4 @@ -/*---------------------------------------------------------------------------* +/*---------------------------------------------------------------------------* Project: Horizon File: SaveDataMover.cpp @@ -49,6 +49,31 @@ namespace return id == 0x0001002c; // nim } + bit32 HexStringToBit32(const char* hex, int maxLen) + { + bit32 val = 0; + for(int i = 0; i < maxLen; ++i) + { + val *= 16; + if(hex[i] >= '0' && hex[i] <= '9') + { + val += (hex[i] - '0'); + } + else if(hex[i] >= 'a' && hex[i] <= 'f') + { + val += (hex[i] - 'a' + 10); + } + else if(hex[i] >= 'A' && hex[i] <= 'F') + { + val += (hex[i] - 'A' + 10); + } + else + { + break; + } + } + return val; + } } @@ -65,13 +90,25 @@ void SaveDataMover::StartExport(void* buf, size_t bufSize, u64* progress) { SetupExport(); COMMON_LOGGER_RETURN_VOID_IF_FAILED(GetLastResult()); - CalculateFileSize(); + CalculateExportFileSize(); COMMON_LOGGER_RETURN_VOID_IF_FAILED(GetLastResult()); ExportSystemSaveData(buf, bufSize, progress); COMMON_LOGGER_RETURN_VOID_IF_FAILED(GetLastResult()); ExportSharedExtSaveData(buf, bufSize, progress); } +void SaveDataMover::StartImport(void* buf, size_t bufSize, u64* progress) +{ + SetupImport(buf, bufSize); + COMMON_LOGGER_RETURN_VOID_IF_FAILED(GetLastResult()); + CalculateImportFileSize(); + COMMON_LOGGER_RETURN_VOID_IF_FAILED(GetLastResult()); + ImportSystemSaveData(buf, bufSize, progress); + COMMON_LOGGER_RETURN_VOID_IF_FAILED(GetLastResult()); + ImportSharedExtSaveData(buf, bufSize, progress); + COMMON_LOGGER_RETURN_VOID_IF_FAILED(GetLastResult()); +} + nn::Result SaveDataMover::GetLastResult() { return m_Result; @@ -120,13 +157,13 @@ void SaveDataMover::SetupExport() } -void SaveDataMover::CalculateFileSize() +void SaveDataMover::CalculateExportFileSize() { - CalculateSystemSaveDataSize(); - CalculateSharedExtSaveDataSize(); + CalculateExportSystemSaveDataSize(); + CalculateExportSharedExtSaveDataSize(); } -void SaveDataMover::CalculateSystemSaveDataSize() +void SaveDataMover::CalculateExportSystemSaveDataSize() { s32 systemSaveDataIdNum; m_Result = nn::fs::EnumerateSystemSaveData(&systemSaveDataIdNum, s_SystemSaveDataIdList, MAX_SYSTEM_SAVE_DATA_ID_NUM); @@ -154,7 +191,7 @@ void SaveDataMover::CalculateSystemSaveDataSize() } } -void SaveDataMover::CalculateSharedExtSaveDataSize() +void SaveDataMover::CalculateExportSharedExtSaveDataSize() { // 共有拡張セーブデータのサイズを確認する // 0. ID の列挙を行う。 @@ -171,10 +208,9 @@ void SaveDataMover::CalculateSharedExtSaveDataSize() m_Result = nn::fs::MountSharedExtSaveDataRawStorage(ARC_NAME, id); COMMON_LOGGER_RETURN_VOID_IF_FAILED(m_Result); - // 2. アーカイブ内を走査して、含まれるファイルと - // ディレクトリを、その構造を保ったまま - // エクスポートする。 - COMMON_LOGGER_RETURN_VOID_IF_FAILED(common::CalculateFileSizeRecursively(L"sext:/", m_TotalSize)); + // 2. アーカイブ内を走査して、含まれるファイルサイズを計算する + m_Result = common::CalculateFileSizeRecursively(L"sext:/", m_TotalSize); + COMMON_LOGGER_RETURN_VOID_IF_FAILED(m_Result); // 3. アンマウントする m_Result = nn::fs::Unmount(ARC_NAME); @@ -290,6 +326,152 @@ nn::Result SaveDataMover::Export(void* buf, size_t bufSize, bit32 id, u64* progr return nn::ResultSuccess(); } +void SaveDataMover::SetupImport(void* buf, size_t bufSize) +{ + // 引っ越しコンテクストを取得 + nn::fs::DeviceMoveContext moveContext; + + // コンテキストのSDからの入力 + size_t readSize; + common::SdReaderWriter sdReader; + m_Result = sdReader.ReadBufWithCmac(common::MOVE_CONTEXT_PATHNAME, buf, bufSize, &readSize); + COMMON_LOGGER_RETURN_VOID_IF_FAILED(m_Result); + + // AES復号化する + nn::crypto::SwAesCtrContext swAesCtrContest; + + swAesCtrContest.Initialize(common::iv, common::key, sizeof(common::key)); + m_Result = swAesCtrContest.Decrypt(&moveContext, buf, readSize); + COMMON_LOGGER_RETURN_VOID_IF_FAILED(m_Result); + + // 1. StartDeviceMoveAsDestination + m_Result = StartDeviceMoveAsDestination(moveContext); + COMMON_LOGGER_RETURN_VOID_IF_FAILED(m_Result); +} + +void SaveDataMover::ImportSystemSaveData(void* buf, size_t bufSize, u64* progress) +{ + // セーブデータが格納されているディレクトリを開く + nn::fs::Directory root; + m_Result = root.TryInitialize(SD_SAVEDATA_SYS_ROOT_PATH); + COMMON_LOGGER_RETURN_VOID_IF_FAILED(m_Result); + nn::fs::DirectoryEntry entry; + s32 numOut = 0; + + // ディレクトリ内を見てセーブデータをインポートする。 + while(1) + { + root.TryRead(&numOut, &entry, 1); + if(numOut == 0) + { + break; + } + + bit32 id = HexStringToBit32(entry.shortName.body, 8); + if(id == 0) + { + break; + } + + NN_LOG("id: %08x\n", id); + + nn::fs::FileInputStream input; + char name[64]; + nn::nstd::TSNPrintf(name, 64, "%s/%s", SD_SAVEDATA_SYS_ROOT_PATH, entry.shortName.body); + m_Result = input.TryInitialize(name); + if(m_Result.IsFailure()) + { + NN_LOG("Failed to open save data file, r = %08x\n", m_Result.GetPrintableBits()); + continue; + } + + // 1. fs::CreateAndOpenNewSystemSaveDataRawStorageFile を呼び + // ID に対する FileOutputStream を得る。 + nn::fs::FileOutputStream output; + m_Result = nn::fs::CreateAndOpenNewSystemSaveDataRawStorageFile(&output, id, input.GetSize()); + if(m_Result.IsFailure()) + { + NN_LOG("Failed to open storage on nand, r = %08x\n", m_Result.GetPrintableBits()); + continue; + } + + + // 2. 1 で得たストリームに対して書き込みを行う。 + // 本来は引っ越し元からデータを受け取り、書き込むが + // ここでは SD から読み込んだデータを書き込む。 + m_Result = CopyFile(input, output, buf, bufSize, progress); + if(m_Result.IsFailure()) + { + NN_LOG("Failed to copy, r = %08x\n", m_Result.GetPrintableBits()); + continue; + } + } + NN_LOG("\n"); +} + +void SaveDataMover::ImportSharedExtSaveData(void* buf, size_t bufSize, u64* progress) +{ + nn::fs::Directory srcRoot; + m_Result = srcRoot.TryInitialize(SD_SAVEDATA_EXT_ROOT_PATH); + COMMON_LOGGER_RETURN_VOID_IF_FAILED(m_Result); + + nn::fs::DirectoryEntry entry; + s32 numEntry; + while(1) + { + srcRoot.TryRead(&numEntry, &entry, 1); + if(numEntry == 0) + { + break; + } + bit32 id = HexStringToBit32(entry.shortName.body, 8); + NN_LOG("Import: %08x\n", id); + + m_Result = Import(buf, bufSize, id, progress); + if(m_Result.IsFailure()) + { + NN_LOG("Failed to import. result = %08x\n", m_Result.GetPrintableBits()); + } + + } + NN_LOG("\n"); +} + +nn::Result SaveDataMover::Import(void* buf, size_t bufSize, bit32 id, u64* progress) +{ + const char* ARC_NAME = "sext:"; + + const int MAX_PATH_LEN = 127; + char srcRoot[MAX_PATH_LEN + 1]; + + NN_UTIL_RETURN_IF_FAILED(nn::fs::CreateNewSharedExtSaveDataRawStorage(id)); + + // 2. fs::CreateNewSharedExtSaveDataRawStorage を呼び + // 書き込み用の領域を作成します。 + nn::nstd::TSNPrintf(srcRoot, MAX_PATH_LEN, "%s/%08x", SD_SAVEDATA_EXT_ROOT_PATH, id); + + m_Result = nn::fs::MountNewSharedExtSaveDataRawStorage(ARC_NAME, id); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(m_Result); + + // 4. 3 でマウントした領域に、引っ越し元のアーカイブと + // 同じ構造でファイルとディレクトリを置く。 + m_Result = CopyRecursivly(buf, bufSize, srcRoot, ARC_NAME, progress); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(m_Result); + + m_Result = nn::fs::Unmount(ARC_NAME); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(m_Result); + + return nn::ResultSuccess(); +} + +void SaveDataMover::CalculateImportFileSize() +{ + m_Result = common::CalculateFileSizeRecursively( + (::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring(common::SD_SAVEDATA_ROOT_NAME)).c_str(), + m_TotalSize); + COMMON_LOGGER_RETURN_VOID_IF_FAILED(m_Result); +} + // ファイルの読み書き nn::Result SaveDataMover::CopyFile(nn::fs::FileInputStream& is, nn::fs::FileOutputStream& os, void* pBuffer, const s32 bufferSize, u64* progress) diff --git a/trunk/ConsoleDataMigration/sources/common/SaveDataMover.h b/trunk/ConsoleDataMigration/sources/common/SaveDataMover.h index 20e4b69..7e5bebc 100644 --- a/trunk/ConsoleDataMigration/sources/common/SaveDataMover.h +++ b/trunk/ConsoleDataMigration/sources/common/SaveDataMover.h @@ -1,4 +1,4 @@ -/*---------------------------------------------------------------------------* +/*---------------------------------------------------------------------------* Project: Horizon File: SaveDataMover.h @@ -37,14 +37,15 @@ public: nn::Result GetLastResult(); private: + //******************** 出力用API群 ******************** //! @brief 出力を準備します void SetupExport(); //! @brief 出力するファイルサイズを計算します - void CalculateFileSize(); + void CalculateExportFileSize(); - void CalculateSystemSaveDataSize(); - void CalculateSharedExtSaveDataSize(); + void CalculateExportSystemSaveDataSize(); + void CalculateExportSharedExtSaveDataSize(); //! @brief システムセーブデータを出力します void ExportSystemSaveData(void* buf, size_t bufSize, u64* progress); @@ -55,6 +56,24 @@ private: //! @breif 共有拡張セーブデータを出力します nn::Result Export(void* buf, size_t bufSize, bit32 id, u64* progress); + + //******************** 入力用API群 ******************** + //!@ brief 入力を準備します + void SetupImport(void* buf, size_t bufSize); + + //! @brief システムセーブデータを入力します + void ImportSystemSaveData(void* buf, size_t bufSize, u64* progress); + + //! @brief 共有拡張セーブデータを入力します + void ImportSharedExtSaveData(void* buf, size_t bufSize, u64* progress); + + //! @brief 共有拡張セーブデータを出力します + nn::Result Import(void* buf, size_t bufSize, bit32 id, u64* progress); + + //! @brief 入力するファイルサイズを計算します + void CalculateImportFileSize(); + + nn::Result CopyFile(nn::fs::FileInputStream& is, nn::fs::FileOutputStream& os, void* pBuffer, const s32 bufferSize, u64* progress); @@ -65,6 +84,7 @@ private: s64 m_FinishedSize; s64 m_TotalSize; + NN_PADDING4; nn::Result m_Result; };