diff options
Diffstat (limited to 'src/core/file_sys')
| -rw-r--r-- | src/core/file_sys/card_image.cpp | 2 | ||||
| -rw-r--r-- | src/core/file_sys/card_image.h | 16 | ||||
| -rw-r--r-- | src/core/file_sys/content_archive.cpp | 5 | ||||
| -rw-r--r-- | src/core/file_sys/content_archive.h | 3 | ||||
| -rw-r--r-- | src/core/file_sys/errors.h | 25 | ||||
| -rw-r--r-- | src/core/file_sys/patch_manager.cpp | 49 | ||||
| -rw-r--r-- | src/core/file_sys/registered_cache.cpp | 13 | ||||
| -rw-r--r-- | src/core/file_sys/registered_cache.h | 3 | ||||
| -rw-r--r-- | src/core/file_sys/submission_package.cpp | 2 | ||||
| -rw-r--r-- | src/core/file_sys/submission_package.h | 2 |
10 files changed, 87 insertions, 33 deletions
diff --git a/src/core/file_sys/card_image.cpp b/src/core/file_sys/card_image.cpp index 1ece55731..2c145bd09 100644 --- a/src/core/file_sys/card_image.cpp +++ b/src/core/file_sys/card_image.cpp @@ -176,7 +176,7 @@ Loader::ResultStatus XCI::AddNCAFromPartition(XCIPartition part) { for (const VirtualFile& file : partitions[static_cast<std::size_t>(part)]->GetFiles()) { if (file->GetExtension() != "nca") continue; - auto nca = std::make_shared<NCA>(file); + auto nca = std::make_shared<NCA>(file, nullptr, 0, keys); // TODO(DarkLordZach): Add proper Rev1+ Support if (nca->IsUpdate()) continue; diff --git a/src/core/file_sys/card_image.h b/src/core/file_sys/card_image.h index 8f62571cf..a350496f7 100644 --- a/src/core/file_sys/card_image.h +++ b/src/core/file_sys/card_image.h @@ -9,6 +9,7 @@ #include <vector> #include "common/common_types.h" #include "common/swap.h" +#include "core/crypto/key_manager.h" #include "core/file_sys/vfs.h" namespace Loader { @@ -31,7 +32,18 @@ enum class GamecardSize : u8 { }; struct GamecardInfo { - std::array<u8, 0x70> data; + u64_le firmware_version; + u32_le access_control_flags; + u32_le read_wait_time1; + u32_le read_wait_time2; + u32_le write_wait_time1; + u32_le write_wait_time2; + u32_le firmware_mode; + u32_le cup_version; + std::array<u8, 4> reserved1; + u64_le update_partition_hash; + u64_le cup_id; + std::array<u8, 0x38> reserved2; }; static_assert(sizeof(GamecardInfo) == 0x70, "GamecardInfo has incorrect size."); @@ -107,5 +119,7 @@ private: std::shared_ptr<NSP> secure_partition; std::shared_ptr<NCA> program; std::vector<std::shared_ptr<NCA>> ncas; + + Core::Crypto::KeyManager keys; }; } // namespace FileSys diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp index b46fe893c..19b6f8600 100644 --- a/src/core/file_sys/content_archive.cpp +++ b/src/core/file_sys/content_archive.cpp @@ -101,8 +101,9 @@ static bool IsValidNCA(const NCAHeader& header) { return header.magic == Common::MakeMagic('N', 'C', 'A', '3'); } -NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_, u64 bktr_base_ivfc_offset) - : file(std::move(file_)), bktr_base_romfs(std::move(bktr_base_romfs_)) { +NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_, u64 bktr_base_ivfc_offset, + Core::Crypto::KeyManager keys_) + : file(std::move(file_)), bktr_base_romfs(std::move(bktr_base_romfs_)), keys(std::move(keys_)) { if (file == nullptr) { status = Loader::ResultStatus::ErrorNullFile; return; diff --git a/src/core/file_sys/content_archive.h b/src/core/file_sys/content_archive.h index 4bba55607..99294cbb4 100644 --- a/src/core/file_sys/content_archive.h +++ b/src/core/file_sys/content_archive.h @@ -79,7 +79,8 @@ inline bool IsDirectoryExeFS(const std::shared_ptr<VfsDirectory>& pfs) { class NCA : public ReadOnlyVfsDirectory { public: explicit NCA(VirtualFile file, VirtualFile bktr_base_romfs = nullptr, - u64 bktr_base_ivfc_offset = 0); + u64 bktr_base_ivfc_offset = 0, + Core::Crypto::KeyManager keys = Core::Crypto::KeyManager()); ~NCA() override; Loader::ResultStatus GetStatus() const; diff --git a/src/core/file_sys/errors.h b/src/core/file_sys/errors.h index fea0593c7..e4a4ee4ab 100644 --- a/src/core/file_sys/errors.h +++ b/src/core/file_sys/errors.h @@ -8,25 +8,10 @@ namespace FileSys { -namespace ErrCodes { -enum { - NotFound = 1, - TitleNotFound = 1002, - SdCardNotFound = 2001, - RomFSNotFound = 2520, -}; -} - -constexpr ResultCode ERROR_PATH_NOT_FOUND(ErrorModule::FS, ErrCodes::NotFound); - -// TODO(bunnei): Replace these with correct errors for Switch OS -constexpr ResultCode ERROR_INVALID_PATH(-1); -constexpr ResultCode ERROR_UNSUPPORTED_OPEN_FLAGS(-1); -constexpr ResultCode ERROR_INVALID_OPEN_FLAGS(-1); -constexpr ResultCode ERROR_FILE_NOT_FOUND(-1); -constexpr ResultCode ERROR_UNEXPECTED_FILE_OR_DIRECTORY(-1); -constexpr ResultCode ERROR_DIRECTORY_ALREADY_EXISTS(-1); -constexpr ResultCode ERROR_FILE_ALREADY_EXISTS(-1); -constexpr ResultCode ERROR_DIRECTORY_NOT_EMPTY(-1); +constexpr ResultCode ERROR_PATH_NOT_FOUND{ErrorModule::FS, 1}; +constexpr ResultCode ERROR_ENTITY_NOT_FOUND{ErrorModule::FS, 1002}; +constexpr ResultCode ERROR_SD_CARD_NOT_FOUND{ErrorModule::FS, 2001}; +constexpr ResultCode ERROR_INVALID_OFFSET{ErrorModule::FS, 6061}; +constexpr ResultCode ERROR_INVALID_SIZE{ErrorModule::FS, 6062}; } // namespace FileSys diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index 8d062eb3e..e8df08724 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp @@ -26,6 +26,11 @@ namespace FileSys { constexpr u64 SINGLE_BYTE_MODULUS = 0x100; constexpr u64 DLC_BASE_TITLE_ID_MASK = 0xFFFFFFFFFFFFE000; +constexpr std::array<const char*, 14> EXEFS_FILE_NAMES{ + "main", "main.npdm", "rtld", "sdk", "subsdk0", "subsdk1", "subsdk2", + "subsdk3", "subsdk4", "subsdk5", "subsdk6", "subsdk7", "subsdk8", "subsdk9", +}; + struct NSOBuildHeader { u32_le magic; INSERT_PADDING_BYTES(0x3C); @@ -57,6 +62,15 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const { if (exefs == nullptr) return exefs; + if (Settings::values.dump_exefs) { + LOG_INFO(Loader, "Dumping ExeFS for title_id={:016X}", title_id); + const auto dump_dir = Service::FileSystem::GetModificationDumpRoot(title_id); + if (dump_dir != nullptr) { + const auto exefs_dir = GetOrCreateDirectoryRelative(dump_dir, "/exefs"); + VfsRawCopyD(exefs, exefs_dir); + } + } + const auto installed = Service::FileSystem::GetUnionContents(); // Game Updates @@ -70,6 +84,30 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const { exefs = update->GetExeFS(); } + // LayeredExeFS + const auto load_dir = Service::FileSystem::GetModificationLoadRoot(title_id); + if (load_dir != nullptr && load_dir->GetSize() > 0) { + auto patch_dirs = load_dir->GetSubdirectories(); + std::sort( + patch_dirs.begin(), patch_dirs.end(), + [](const VirtualDir& l, const VirtualDir& r) { return l->GetName() < r->GetName(); }); + + std::vector<VirtualDir> layers; + layers.reserve(patch_dirs.size() + 1); + for (const auto& subdir : patch_dirs) { + auto exefs_dir = subdir->GetSubdirectory("exefs"); + if (exefs_dir != nullptr) + layers.push_back(std::move(exefs_dir)); + } + layers.push_back(exefs); + + auto layered = LayeredVfsDirectory::MakeLayeredDirectory(std::move(layers)); + if (layered != nullptr) { + LOG_INFO(Loader, " ExeFS: LayeredExeFS patches applied successfully"); + exefs = std::move(layered); + } + } + return exefs; } @@ -314,18 +352,25 @@ std::map<std::string, std::string, std::less<>> PatchManager::GetPatchVersionNam if (IsDirValidAndNonEmpty(exefs_dir)) { bool ips = false; bool ipswitch = false; + bool layeredfs = false; for (const auto& file : exefs_dir->GetFiles()) { - if (file->GetExtension() == "ips") + if (file->GetExtension() == "ips") { ips = true; - else if (file->GetExtension() == "pchtxt") + } else if (file->GetExtension() == "pchtxt") { ipswitch = true; + } else if (std::find(EXEFS_FILE_NAMES.begin(), EXEFS_FILE_NAMES.end(), + file->GetName()) != EXEFS_FILE_NAMES.end()) { + layeredfs = true; + } } if (ips) AppendCommaIfNotEmpty(types, "IPS"); if (ipswitch) AppendCommaIfNotEmpty(types, "IPSwitch"); + if (layeredfs) + AppendCommaIfNotEmpty(types, "LayeredExeFS"); } if (IsDirValidAndNonEmpty(mod->GetSubdirectory("romfs"))) AppendCommaIfNotEmpty(types, "LayeredFS"); diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp index 96302a241..a3f8f2f73 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp @@ -106,9 +106,12 @@ static ContentRecordType GetCRTypeFromNCAType(NCAContentType type) { VirtualFile RegisteredCache::OpenFileOrDirectoryConcat(const VirtualDir& dir, std::string_view path) const { - if (dir->GetFileRelative(path) != nullptr) - return dir->GetFileRelative(path); - if (dir->GetDirectoryRelative(path) != nullptr) { + const auto file = dir->GetFileRelative(path); + if (file != nullptr) + return file; + + const auto nca_dir = dir->GetDirectoryRelative(path); + if (nca_dir != nullptr) { const auto nca_dir = dir->GetDirectoryRelative(path); VirtualFile file = nullptr; @@ -225,7 +228,7 @@ void RegisteredCache::ProcessFiles(const std::vector<NcaID>& ids) { if (file == nullptr) continue; - const auto nca = std::make_shared<NCA>(parser(file, id)); + const auto nca = std::make_shared<NCA>(parser(file, id), nullptr, 0, keys); if (nca->GetStatus() != Loader::ResultStatus::Success || nca->GetType() != NCAContentType::Meta) { continue; @@ -315,7 +318,7 @@ std::unique_ptr<NCA> RegisteredCache::GetEntry(u64 title_id, ContentRecordType t const auto raw = GetEntryRaw(title_id, type); if (raw == nullptr) return nullptr; - return std::make_unique<NCA>(raw); + return std::make_unique<NCA>(raw, nullptr, 0, keys); } std::unique_ptr<NCA> RegisteredCache::GetEntry(RegisteredCacheEntry entry) const { diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h index 6cfb16017..6b89db8de 100644 --- a/src/core/file_sys/registered_cache.h +++ b/src/core/file_sys/registered_cache.h @@ -12,6 +12,7 @@ #include <vector> #include <boost/container/flat_map.hpp> #include "common/common_types.h" +#include "core/crypto/key_manager.h" #include "core/file_sys/vfs.h" namespace FileSys { @@ -133,6 +134,8 @@ private: VirtualDir dir; RegisteredCacheParsingFunction parser; + Core::Crypto::KeyManager keys; + // maps tid -> NcaID of meta boost::container::flat_map<u64, NcaID> meta_id; // maps tid -> meta diff --git a/src/core/file_sys/submission_package.cpp b/src/core/file_sys/submission_package.cpp index 2aaba4179..e1a4210db 100644 --- a/src/core/file_sys/submission_package.cpp +++ b/src/core/file_sys/submission_package.cpp @@ -252,7 +252,7 @@ void NSP::ReadNCAs(const std::vector<VirtualFile>& files) { continue; } - auto next_nca = std::make_shared<NCA>(next_file); + auto next_nca = std::make_shared<NCA>(next_file, nullptr, 0, keys); if (next_nca->GetType() == NCAContentType::Program) program_status[cnmt.GetTitleID()] = next_nca->GetStatus(); if (next_nca->GetStatus() == Loader::ResultStatus::Success || diff --git a/src/core/file_sys/submission_package.h b/src/core/file_sys/submission_package.h index 338080b7e..9a28ed5bb 100644 --- a/src/core/file_sys/submission_package.h +++ b/src/core/file_sys/submission_package.h @@ -70,6 +70,8 @@ private: std::map<u64, std::map<ContentRecordType, std::shared_ptr<NCA>>> ncas; std::vector<VirtualFile> ticket_files; + Core::Crypto::KeyManager keys; + VirtualFile romfs; VirtualDir exefs; }; |
