aboutsummaryrefslogtreecommitdiff
path: root/src/core/file_sys
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/file_sys')
-rw-r--r--src/core/file_sys/bis_factory.cpp9
-rw-r--r--src/core/file_sys/bis_factory.h4
-rw-r--r--src/core/file_sys/card_image.cpp2
-rw-r--r--src/core/file_sys/card_image.h3
-rw-r--r--src/core/file_sys/content_archive.cpp38
-rw-r--r--src/core/file_sys/content_archive.h10
-rw-r--r--src/core/file_sys/control_metadata.cpp6
-rw-r--r--src/core/file_sys/control_metadata.h1
-rw-r--r--src/core/file_sys/errors.h25
-rw-r--r--src/core/file_sys/fsmitm_romfsbuild.h1
-rw-r--r--src/core/file_sys/ips_layer.cpp4
-rw-r--r--src/core/file_sys/patch_manager.cpp22
-rw-r--r--src/core/file_sys/registered_cache.cpp75
-rw-r--r--src/core/file_sys/registered_cache.h26
-rw-r--r--src/core/file_sys/savedata_factory.cpp32
-rw-r--r--src/core/file_sys/savedata_factory.h3
-rw-r--r--src/core/file_sys/submission_package.cpp2
-rw-r--r--src/core/file_sys/submission_package.h2
-rw-r--r--src/core/file_sys/vfs.cpp4
-rw-r--r--src/core/file_sys/vfs.h8
-rw-r--r--src/core/file_sys/vfs_offset.cpp4
-rw-r--r--src/core/file_sys/vfs_offset.h2
-rw-r--r--src/core/file_sys/vfs_static.h4
23 files changed, 156 insertions, 131 deletions
diff --git a/src/core/file_sys/bis_factory.cpp b/src/core/file_sys/bis_factory.cpp
index 76a2b7e86..e29f70b3a 100644
--- a/src/core/file_sys/bis_factory.cpp
+++ b/src/core/file_sys/bis_factory.cpp
@@ -8,8 +8,9 @@
namespace FileSys {
-BISFactory::BISFactory(VirtualDir nand_root_, VirtualDir load_root_)
+BISFactory::BISFactory(VirtualDir nand_root_, VirtualDir load_root_, VirtualDir dump_root_)
: nand_root(std::move(nand_root_)), load_root(std::move(load_root_)),
+ dump_root(std::move(dump_root_)),
sysnand_cache(std::make_unique<RegisteredCache>(
GetOrCreateDirectoryRelative(nand_root, "/system/Contents/registered"))),
usrnand_cache(std::make_unique<RegisteredCache>(
@@ -32,4 +33,10 @@ VirtualDir BISFactory::GetModificationLoadRoot(u64 title_id) const {
return GetOrCreateDirectoryRelative(load_root, fmt::format("/{:016X}", title_id));
}
+VirtualDir BISFactory::GetModificationDumpRoot(u64 title_id) const {
+ if (title_id == 0)
+ return nullptr;
+ return GetOrCreateDirectoryRelative(dump_root, fmt::format("/{:016X}", title_id));
+}
+
} // namespace FileSys
diff --git a/src/core/file_sys/bis_factory.h b/src/core/file_sys/bis_factory.h
index 364d309bd..453c11ad2 100644
--- a/src/core/file_sys/bis_factory.h
+++ b/src/core/file_sys/bis_factory.h
@@ -17,17 +17,19 @@ class RegisteredCache;
/// registered caches.
class BISFactory {
public:
- explicit BISFactory(VirtualDir nand_root, VirtualDir load_root);
+ explicit BISFactory(VirtualDir nand_root, VirtualDir load_root, VirtualDir dump_root);
~BISFactory();
RegisteredCache* GetSystemNANDContents() const;
RegisteredCache* GetUserNANDContents() const;
VirtualDir GetModificationLoadRoot(u64 title_id) const;
+ VirtualDir GetModificationDumpRoot(u64 title_id) const;
private:
VirtualDir nand_root;
VirtualDir load_root;
+ VirtualDir dump_root;
std::unique_ptr<RegisteredCache> sysnand_cache;
std::unique_ptr<RegisteredCache> usrnand_cache;
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..25f5914b6 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 {
@@ -107,5 +108,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 77e04704e..19b6f8600 100644
--- a/src/core/file_sys/content_archive.cpp
+++ b/src/core/file_sys/content_archive.cpp
@@ -4,10 +4,9 @@
#include <algorithm>
#include <cstring>
+#include <optional>
#include <utility>
-#include <boost/optional.hpp>
-
#include "common/logging/log.h"
#include "core/crypto/aes_util.h"
#include "core/crypto/ctr_encryption_layer.h"
@@ -102,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;
@@ -306,18 +306,18 @@ bool NCA::ReadRomFSSection(const NCASectionHeader& section, const NCASectionTabl
subsection_buckets.back().entries.push_back({section.bktr.relocation.offset, {0}, ctr_low});
subsection_buckets.back().entries.push_back({size, {0}, 0});
- boost::optional<Core::Crypto::Key128> key = boost::none;
+ std::optional<Core::Crypto::Key128> key = {};
if (encrypted) {
if (has_rights_id) {
status = Loader::ResultStatus::Success;
key = GetTitlekey();
- if (key == boost::none) {
+ if (!key) {
status = Loader::ResultStatus::ErrorMissingTitlekey;
return false;
}
} else {
key = GetKeyAreaKey(NCASectionCryptoType::BKTR);
- if (key == boost::none) {
+ if (!key) {
status = Loader::ResultStatus::ErrorMissingKeyAreaKey;
return false;
}
@@ -332,7 +332,7 @@ bool NCA::ReadRomFSSection(const NCASectionHeader& section, const NCASectionTabl
auto bktr = std::make_shared<BKTR>(
bktr_base_romfs, std::make_shared<OffsetVfsFile>(file, romfs_size, base_offset),
relocation_block, relocation_buckets, subsection_block, subsection_buckets, encrypted,
- encrypted ? key.get() : Core::Crypto::Key128{}, base_offset, bktr_base_ivfc_offset,
+ encrypted ? *key : Core::Crypto::Key128{}, base_offset, bktr_base_ivfc_offset,
section.raw.section_ctr);
// BKTR applies to entire IVFC, so make an offset version to level 6
@@ -388,11 +388,11 @@ u8 NCA::GetCryptoRevision() const {
return master_key_id;
}
-boost::optional<Core::Crypto::Key128> NCA::GetKeyAreaKey(NCASectionCryptoType type) const {
+std::optional<Core::Crypto::Key128> NCA::GetKeyAreaKey(NCASectionCryptoType type) const {
const auto master_key_id = GetCryptoRevision();
if (!keys.HasKey(Core::Crypto::S128KeyType::KeyArea, master_key_id, header.key_index))
- return boost::none;
+ return {};
std::vector<u8> key_area(header.key_area.begin(), header.key_area.end());
Core::Crypto::AESCipher<Core::Crypto::Key128> cipher(
@@ -416,25 +416,25 @@ boost::optional<Core::Crypto::Key128> NCA::GetKeyAreaKey(NCASectionCryptoType ty
return out;
}
-boost::optional<Core::Crypto::Key128> NCA::GetTitlekey() {
+std::optional<Core::Crypto::Key128> NCA::GetTitlekey() {
const auto master_key_id = GetCryptoRevision();
u128 rights_id{};
memcpy(rights_id.data(), header.rights_id.data(), 16);
if (rights_id == u128{}) {
status = Loader::ResultStatus::ErrorInvalidRightsID;
- return boost::none;
+ return {};
}
auto titlekey = keys.GetKey(Core::Crypto::S128KeyType::Titlekey, rights_id[1], rights_id[0]);
if (titlekey == Core::Crypto::Key128{}) {
status = Loader::ResultStatus::ErrorMissingTitlekey;
- return boost::none;
+ return {};
}
if (!keys.HasKey(Core::Crypto::S128KeyType::Titlekek, master_key_id)) {
status = Loader::ResultStatus::ErrorMissingTitlekek;
- return boost::none;
+ return {};
}
Core::Crypto::AESCipher<Core::Crypto::Key128> cipher(
@@ -458,25 +458,25 @@ VirtualFile NCA::Decrypt(const NCASectionHeader& s_header, VirtualFile in, u64 s
case NCASectionCryptoType::BKTR:
LOG_DEBUG(Crypto, "called with mode=CTR, starting_offset={:016X}", starting_offset);
{
- boost::optional<Core::Crypto::Key128> key = boost::none;
+ std::optional<Core::Crypto::Key128> key = {};
if (has_rights_id) {
status = Loader::ResultStatus::Success;
key = GetTitlekey();
- if (key == boost::none) {
+ if (!key) {
if (status == Loader::ResultStatus::Success)
status = Loader::ResultStatus::ErrorMissingTitlekey;
return nullptr;
}
} else {
key = GetKeyAreaKey(NCASectionCryptoType::CTR);
- if (key == boost::none) {
+ if (!key) {
status = Loader::ResultStatus::ErrorMissingKeyAreaKey;
return nullptr;
}
}
- auto out = std::make_shared<Core::Crypto::CTREncryptionLayer>(
- std::move(in), key.value(), starting_offset);
+ auto out = std::make_shared<Core::Crypto::CTREncryptionLayer>(std::move(in), *key,
+ starting_offset);
std::vector<u8> iv(16);
for (u8 i = 0; i < 8; ++i)
iv[i] = s_header.raw.section_ctr[0x8 - i - 1];
diff --git a/src/core/file_sys/content_archive.h b/src/core/file_sys/content_archive.h
index 211946686..99294cbb4 100644
--- a/src/core/file_sys/content_archive.h
+++ b/src/core/file_sys/content_archive.h
@@ -6,9 +6,10 @@
#include <array>
#include <memory>
+#include <optional>
#include <string>
#include <vector>
-#include <boost/optional.hpp>
+
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/swap.h"
@@ -78,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;
@@ -111,8 +113,8 @@ private:
bool ReadPFS0Section(const NCASectionHeader& section, const NCASectionTableEntry& entry);
u8 GetCryptoRevision() const;
- boost::optional<Core::Crypto::Key128> GetKeyAreaKey(NCASectionCryptoType type) const;
- boost::optional<Core::Crypto::Key128> GetTitlekey();
+ std::optional<Core::Crypto::Key128> GetKeyAreaKey(NCASectionCryptoType type) const;
+ std::optional<Core::Crypto::Key128> GetTitlekey();
VirtualFile Decrypt(const NCASectionHeader& header, VirtualFile in, u64 starting_offset);
std::vector<VirtualDir> dirs;
diff --git a/src/core/file_sys/control_metadata.cpp b/src/core/file_sys/control_metadata.cpp
index a012c2be9..c8fa912bf 100644
--- a/src/core/file_sys/control_metadata.cpp
+++ b/src/core/file_sys/control_metadata.cpp
@@ -66,4 +66,10 @@ std::string NACP::GetVersionString() const {
return Common::StringFromFixedZeroTerminatedBuffer(raw->version_string.data(),
raw->version_string.size());
}
+
+std::vector<u8> NACP::GetRawBytes() const {
+ std::vector<u8> out(sizeof(RawNACP));
+ std::memcpy(out.data(), raw.get(), sizeof(RawNACP));
+ return out;
+}
} // namespace FileSys
diff --git a/src/core/file_sys/control_metadata.h b/src/core/file_sys/control_metadata.h
index 141f7e056..bfaad46b4 100644
--- a/src/core/file_sys/control_metadata.h
+++ b/src/core/file_sys/control_metadata.h
@@ -81,6 +81,7 @@ public:
u64 GetTitleId() const;
u64 GetDLCBaseTitleId() const;
std::string GetVersionString() const;
+ std::vector<u8> GetRawBytes() const;
private:
std::unique_ptr<RawNACP> raw;
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/fsmitm_romfsbuild.h b/src/core/file_sys/fsmitm_romfsbuild.h
index 3d377b0af..a62502193 100644
--- a/src/core/file_sys/fsmitm_romfsbuild.h
+++ b/src/core/file_sys/fsmitm_romfsbuild.h
@@ -27,7 +27,6 @@
#include <map>
#include <memory>
#include <string>
-#include <boost/detail/container_fwd.hpp>
#include "common/common_types.h"
#include "core/file_sys/vfs.h"
diff --git a/src/core/file_sys/ips_layer.cpp b/src/core/file_sys/ips_layer.cpp
index 999939d5a..485c4913a 100644
--- a/src/core/file_sys/ips_layer.cpp
+++ b/src/core/file_sys/ips_layer.cpp
@@ -103,12 +103,12 @@ VirtualFile PatchIPS(const VirtualFile& in, const VirtualFile& ips) {
offset += sizeof(u16);
const auto data = ips->ReadByte(offset++);
- if (data == boost::none)
+ if (!data)
return nullptr;
if (real_offset + rle_size > in_data.size())
rle_size = static_cast<u16>(in_data.size() - real_offset);
- std::memset(in_data.data() + real_offset, data.get(), rle_size);
+ std::memset(in_data.data() + real_offset, *data, rle_size);
} else { // Standard Patch
auto read = data_size;
if (real_offset + read > in_data.size())
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp
index cb457b987..8d062eb3e 100644
--- a/src/core/file_sys/patch_manager.cpp
+++ b/src/core/file_sys/patch_manager.cpp
@@ -19,6 +19,7 @@
#include "core/file_sys/vfs_vector.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/loader/loader.h"
+#include "core/settings.h"
namespace FileSys {
@@ -65,7 +66,7 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const {
if (update != nullptr && update->GetExeFS() != nullptr &&
update->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) {
LOG_INFO(Loader, " ExeFS: Update ({}) applied successfully",
- FormatTitleVersion(installed->GetEntryVersion(update_tid).get_value_or(0)));
+ FormatTitleVersion(installed->GetEntryVersion(update_tid).value_or(0)));
exefs = update->GetExeFS();
}
@@ -119,6 +120,18 @@ std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso) const {
const auto build_id_raw = Common::HexArrayToString(header.build_id);
const auto build_id = build_id_raw.substr(0, build_id_raw.find_last_not_of('0') + 1);
+ if (Settings::values.dump_nso) {
+ LOG_INFO(Loader, "Dumping NSO for build_id={}, title_id={:016X}", build_id, title_id);
+ const auto dump_dir = Service::FileSystem::GetModificationDumpRoot(title_id);
+ if (dump_dir != nullptr) {
+ const auto nso_dir = GetOrCreateDirectoryRelative(dump_dir, "/nso");
+ const auto file = nso_dir->CreateFile(fmt::format("{}.nso", build_id));
+
+ file->Resize(nso.size());
+ file->WriteBytes(nso);
+ }
+ }
+
LOG_INFO(Loader, "Patching NSO for build_id={}", build_id);
const auto load_dir = Service::FileSystem::GetModificationLoadRoot(title_id);
@@ -236,7 +249,7 @@ VirtualFile PatchManager::PatchRomFS(VirtualFile romfs, u64 ivfc_offset, Content
if (new_nca->GetStatus() == Loader::ResultStatus::Success &&
new_nca->GetRomFS() != nullptr) {
LOG_INFO(Loader, " RomFS: Update ({}) applied successfully",
- FormatTitleVersion(installed->GetEntryVersion(update_tid).get_value_or(0)));
+ FormatTitleVersion(installed->GetEntryVersion(update_tid).value_or(0)));
romfs = new_nca->GetRomFS();
}
} else if (update_raw != nullptr) {
@@ -280,12 +293,11 @@ std::map<std::string, std::string, std::less<>> PatchManager::GetPatchVersionNam
} else {
if (installed->HasEntry(update_tid, ContentRecordType::Program)) {
const auto meta_ver = installed->GetEntryVersion(update_tid);
- if (meta_ver == boost::none || meta_ver.get() == 0) {
+ if (meta_ver.value_or(0) == 0) {
out.insert_or_assign("Update", "");
} else {
out.insert_or_assign(
- "Update",
- FormatTitleVersion(meta_ver.get(), TitleVersionFormat::ThreeElements));
+ "Update", FormatTitleVersion(*meta_ver, TitleVersionFormat::ThreeElements));
}
} else if (update_raw != nullptr) {
out.insert_or_assign("Update", "PACKED");
diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp
index 29b100414..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;
@@ -159,28 +162,28 @@ VirtualFile RegisteredCache::GetFileAtID(NcaID id) const {
return file;
}
-static boost::optional<NcaID> CheckMapForContentRecord(
+static std::optional<NcaID> CheckMapForContentRecord(
const boost::container::flat_map<u64, CNMT>& map, u64 title_id, ContentRecordType type) {
if (map.find(title_id) == map.end())
- return boost::none;
+ return {};
const auto& cnmt = map.at(title_id);
const auto iter = std::find_if(cnmt.GetContentRecords().begin(), cnmt.GetContentRecords().end(),
[type](const ContentRecord& rec) { return rec.type == type; });
if (iter == cnmt.GetContentRecords().end())
- return boost::none;
+ return {};
- return boost::make_optional(iter->nca_id);
+ return std::make_optional(iter->nca_id);
}
-boost::optional<NcaID> RegisteredCache::GetNcaIDFromMetadata(u64 title_id,
- ContentRecordType type) const {
+std::optional<NcaID> RegisteredCache::GetNcaIDFromMetadata(u64 title_id,
+ ContentRecordType type) const {
if (type == ContentRecordType::Meta && meta_id.find(title_id) != meta_id.end())
return meta_id.at(title_id);
const auto res1 = CheckMapForContentRecord(yuzu_meta, title_id, type);
- if (res1 != boost::none)
+ if (res1)
return res1;
return CheckMapForContentRecord(meta, title_id, type);
}
@@ -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;
@@ -283,17 +286,14 @@ bool RegisteredCache::HasEntry(RegisteredCacheEntry entry) const {
VirtualFile RegisteredCache::GetEntryUnparsed(u64 title_id, ContentRecordType type) const {
const auto id = GetNcaIDFromMetadata(title_id, type);
- if (id == boost::none)
- return nullptr;
-
- return GetFileAtID(id.get());
+ return id ? GetFileAtID(*id) : nullptr;
}
VirtualFile RegisteredCache::GetEntryUnparsed(RegisteredCacheEntry entry) const {
return GetEntryUnparsed(entry.title_id, entry.type);
}
-boost::optional<u32> RegisteredCache::GetEntryVersion(u64 title_id) const {
+std::optional<u32> RegisteredCache::GetEntryVersion(u64 title_id) const {
const auto meta_iter = meta.find(title_id);
if (meta_iter != meta.end())
return meta_iter->second.GetTitleVersion();
@@ -302,15 +302,12 @@ boost::optional<u32> RegisteredCache::GetEntryVersion(u64 title_id) const {
if (yuzu_meta_iter != yuzu_meta.end())
return yuzu_meta_iter->second.GetTitleVersion();
- return boost::none;
+ return {};
}
VirtualFile RegisteredCache::GetEntryRaw(u64 title_id, ContentRecordType type) const {
const auto id = GetNcaIDFromMetadata(title_id, type);
- if (id == boost::none)
- return nullptr;
-
- return parser(GetFileAtID(id.get()), id.get());
+ return id ? parser(GetFileAtID(*id), *id) : nullptr;
}
VirtualFile RegisteredCache::GetEntryRaw(RegisteredCacheEntry entry) const {
@@ -321,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 {
@@ -364,8 +361,8 @@ std::vector<RegisteredCacheEntry> RegisteredCache::ListEntries() const {
}
std::vector<RegisteredCacheEntry> RegisteredCache::ListEntriesFilter(
- boost::optional<TitleType> title_type, boost::optional<ContentRecordType> record_type,
- boost::optional<u64> title_id) const {
+ std::optional<TitleType> title_type, std::optional<ContentRecordType> record_type,
+ std::optional<u64> title_id) const {
std::vector<RegisteredCacheEntry> out;
IterateAllMetadata<RegisteredCacheEntry>(
out,
@@ -373,11 +370,11 @@ std::vector<RegisteredCacheEntry> RegisteredCache::ListEntriesFilter(
return RegisteredCacheEntry{c.GetTitleID(), r.type};
},
[&title_type, &record_type, &title_id](const CNMT& c, const ContentRecord& r) {
- if (title_type != boost::none && title_type.get() != c.GetType())
+ if (title_type && *title_type != c.GetType())
return false;
- if (record_type != boost::none && record_type.get() != r.type)
+ if (record_type && *record_type != r.type)
return false;
- if (title_id != boost::none && title_id.get() != c.GetTitleID())
+ if (title_id && *title_id != c.GetTitleID())
return false;
return true;
});
@@ -459,7 +456,7 @@ InstallResult RegisteredCache::InstallEntry(std::shared_ptr<NCA> nca, TitleType
InstallResult RegisteredCache::RawInstallNCA(std::shared_ptr<NCA> nca, const VfsCopyFunction& copy,
bool overwrite_if_exists,
- boost::optional<NcaID> override_id) {
+ std::optional<NcaID> override_id) {
const auto in = nca->GetBaseFile();
Core::Crypto::SHA256Hash hash{};
@@ -468,12 +465,12 @@ InstallResult RegisteredCache::RawInstallNCA(std::shared_ptr<NCA> nca, const Vfs
// game is massive), we're going to cheat and only hash the first MB of the NCA.
// Also, for XCIs the NcaID matters, so if the override id isn't none, use that.
NcaID id{};
- if (override_id == boost::none) {
+ if (override_id) {
+ id = *override_id;
+ } else {
const auto& data = in->ReadBytes(0x100000);
mbedtls_sha256(data.data(), data.size(), hash.data(), 0);
memcpy(id.data(), hash.data(), 16);
- } else {
- id = override_id.get();
}
std::string path = GetRelativePathFromNcaID(id, false, true);
@@ -543,14 +540,14 @@ bool RegisteredCacheUnion::HasEntry(RegisteredCacheEntry entry) const {
return HasEntry(entry.title_id, entry.type);
}
-boost::optional<u32> RegisteredCacheUnion::GetEntryVersion(u64 title_id) const {
+std::optional<u32> RegisteredCacheUnion::GetEntryVersion(u64 title_id) const {
for (const auto& c : caches) {
const auto res = c->GetEntryVersion(title_id);
- if (res != boost::none)
+ if (res)
return res;
}
- return boost::none;
+ return {};
}
VirtualFile RegisteredCacheUnion::GetEntryUnparsed(u64 title_id, ContentRecordType type) const {
@@ -609,8 +606,8 @@ std::vector<RegisteredCacheEntry> RegisteredCacheUnion::ListEntries() const {
}
std::vector<RegisteredCacheEntry> RegisteredCacheUnion::ListEntriesFilter(
- boost::optional<TitleType> title_type, boost::optional<ContentRecordType> record_type,
- boost::optional<u64> title_id) const {
+ std::optional<TitleType> title_type, std::optional<ContentRecordType> record_type,
+ std::optional<u64> title_id) const {
std::vector<RegisteredCacheEntry> out;
for (const auto& c : caches) {
c->IterateAllMetadata<RegisteredCacheEntry>(
@@ -619,11 +616,11 @@ std::vector<RegisteredCacheEntry> RegisteredCacheUnion::ListEntriesFilter(
return RegisteredCacheEntry{c.GetTitleID(), r.type};
},
[&title_type, &record_type, &title_id](const CNMT& c, const ContentRecord& r) {
- if (title_type != boost::none && title_type.get() != c.GetType())
+ if (title_type && *title_type != c.GetType())
return false;
- if (record_type != boost::none && record_type.get() != r.type)
+ if (record_type && *record_type != r.type)
return false;
- if (title_id != boost::none && title_id.get() != c.GetTitleID())
+ if (title_id && *title_id != c.GetTitleID())
return false;
return true;
});
diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h
index 5beceffb3..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 {
@@ -84,7 +85,7 @@ public:
bool HasEntry(u64 title_id, ContentRecordType type) const;
bool HasEntry(RegisteredCacheEntry entry) const;
- boost::optional<u32> GetEntryVersion(u64 title_id) const;
+ std::optional<u32> GetEntryVersion(u64 title_id) const;
VirtualFile GetEntryUnparsed(u64 title_id, ContentRecordType type) const;
VirtualFile GetEntryUnparsed(RegisteredCacheEntry entry) const;
@@ -96,11 +97,10 @@ public:
std::unique_ptr<NCA> GetEntry(RegisteredCacheEntry entry) const;
std::vector<RegisteredCacheEntry> ListEntries() const;
- // If a parameter is not boost::none, it will be filtered for from all entries.
+ // If a parameter is not std::nullopt, it will be filtered for from all entries.
std::vector<RegisteredCacheEntry> ListEntriesFilter(
- boost::optional<TitleType> title_type = boost::none,
- boost::optional<ContentRecordType> record_type = boost::none,
- boost::optional<u64> title_id = boost::none) const;
+ std::optional<TitleType> title_type = {}, std::optional<ContentRecordType> record_type = {},
+ std::optional<u64> title_id = {}) const;
// Raw copies all the ncas from the xci/nsp to the csache. Does some quick checks to make sure
// there is a meta NCA and all of them are accessible.
@@ -125,16 +125,17 @@ private:
std::vector<NcaID> AccumulateFiles() const;
void ProcessFiles(const std::vector<NcaID>& ids);
void AccumulateYuzuMeta();
- boost::optional<NcaID> GetNcaIDFromMetadata(u64 title_id, ContentRecordType type) const;
+ std::optional<NcaID> GetNcaIDFromMetadata(u64 title_id, ContentRecordType type) const;
VirtualFile GetFileAtID(NcaID id) const;
VirtualFile OpenFileOrDirectoryConcat(const VirtualDir& dir, std::string_view path) const;
InstallResult RawInstallNCA(std::shared_ptr<NCA> nca, const VfsCopyFunction& copy,
- bool overwrite_if_exists,
- boost::optional<NcaID> override_id = boost::none);
+ bool overwrite_if_exists, std::optional<NcaID> override_id = {});
bool RawInstallYuzuMeta(const CNMT& cnmt);
VirtualDir dir;
RegisteredCacheParsingFunction parser;
+ Core::Crypto::KeyManager keys;
+
// maps tid -> NcaID of meta
boost::container::flat_map<u64, NcaID> meta_id;
// maps tid -> meta
@@ -153,7 +154,7 @@ public:
bool HasEntry(u64 title_id, ContentRecordType type) const;
bool HasEntry(RegisteredCacheEntry entry) const;
- boost::optional<u32> GetEntryVersion(u64 title_id) const;
+ std::optional<u32> GetEntryVersion(u64 title_id) const;
VirtualFile GetEntryUnparsed(u64 title_id, ContentRecordType type) const;
VirtualFile GetEntryUnparsed(RegisteredCacheEntry entry) const;
@@ -165,11 +166,10 @@ public:
std::unique_ptr<NCA> GetEntry(RegisteredCacheEntry entry) const;
std::vector<RegisteredCacheEntry> ListEntries() const;
- // If a parameter is not boost::none, it will be filtered for from all entries.
+ // If a parameter is not std::nullopt, it will be filtered for from all entries.
std::vector<RegisteredCacheEntry> ListEntriesFilter(
- boost::optional<TitleType> title_type = boost::none,
- boost::optional<ContentRecordType> record_type = boost::none,
- boost::optional<u64> title_id = boost::none) const;
+ std::optional<TitleType> title_type = {}, std::optional<ContentRecordType> record_type = {},
+ std::optional<u64> title_id = {}) const;
private:
std::vector<RegisteredCache*> caches;
diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp
index ef1aaebbb..5434f2149 100644
--- a/src/core/file_sys/savedata_factory.cpp
+++ b/src/core/file_sys/savedata_factory.cpp
@@ -83,28 +83,32 @@ ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space, SaveDataDescr
return MakeResult<VirtualDir>(std::move(out));
}
-std::string SaveDataFactory::GetFullPath(SaveDataSpaceId space, SaveDataType type, u64 title_id,
- u128 user_id, u64 save_id) {
- // According to switchbrew, if a save is of type SaveData and the title id field is 0, it should
- // be interpreted as the title id of the current process.
- if (type == SaveDataType::SaveData && title_id == 0)
- title_id = Core::CurrentProcess()->GetTitleID();
-
- std::string out;
+VirtualDir SaveDataFactory::GetSaveDataSpaceDirectory(SaveDataSpaceId space) const {
+ return dir->GetDirectoryRelative(GetSaveDataSpaceIdPath(space));
+}
+std::string SaveDataFactory::GetSaveDataSpaceIdPath(SaveDataSpaceId space) {
switch (space) {
case SaveDataSpaceId::NandSystem:
- out = "/system/";
- break;
+ return "/system/";
case SaveDataSpaceId::NandUser:
- out = "/user/";
- break;
+ return "/user/";
case SaveDataSpaceId::TemporaryStorage:
- out = "/temp/";
- break;
+ return "/temp/";
default:
ASSERT_MSG(false, "Unrecognized SaveDataSpaceId: {:02X}", static_cast<u8>(space));
+ return "/unrecognized/"; ///< To prevent corruption when ignoring asserts.
}
+}
+
+std::string SaveDataFactory::GetFullPath(SaveDataSpaceId space, SaveDataType type, u64 title_id,
+ u128 user_id, u64 save_id) {
+ // According to switchbrew, if a save is of type SaveData and the title id field is 0, it should
+ // be interpreted as the title id of the current process.
+ if (type == SaveDataType::SaveData && title_id == 0)
+ title_id = Core::CurrentProcess()->GetTitleID();
+
+ std::string out = GetSaveDataSpaceIdPath(space);
switch (type) {
case SaveDataType::SystemSaveData:
diff --git a/src/core/file_sys/savedata_factory.h b/src/core/file_sys/savedata_factory.h
index d69ef6741..2a0088040 100644
--- a/src/core/file_sys/savedata_factory.h
+++ b/src/core/file_sys/savedata_factory.h
@@ -52,6 +52,9 @@ public:
ResultVal<VirtualDir> Open(SaveDataSpaceId space, SaveDataDescriptor meta);
+ VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const;
+
+ static std::string GetSaveDataSpaceIdPath(SaveDataSpaceId space);
static std::string GetFullPath(SaveDataSpaceId space, SaveDataType type, u64 title_id,
u128 user_id, u64 save_id);
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;
};
diff --git a/src/core/file_sys/vfs.cpp b/src/core/file_sys/vfs.cpp
index 3824c74e0..7b584de7f 100644
--- a/src/core/file_sys/vfs.cpp
+++ b/src/core/file_sys/vfs.cpp
@@ -167,13 +167,13 @@ std::string VfsFile::GetExtension() const {
VfsDirectory::~VfsDirectory() = default;
-boost::optional<u8> VfsFile::ReadByte(std::size_t offset) const {
+std::optional<u8> VfsFile::ReadByte(std::size_t offset) const {
u8 out{};
std::size_t size = Read(&out, 1, offset);
if (size == 1)
return out;
- return boost::none;
+ return {};
}
std::vector<u8> VfsFile::ReadBytes(std::size_t size, std::size_t offset) const {
diff --git a/src/core/file_sys/vfs.h b/src/core/file_sys/vfs.h
index 09dc9f288..002f99d4e 100644
--- a/src/core/file_sys/vfs.h
+++ b/src/core/file_sys/vfs.h
@@ -4,13 +4,15 @@
#pragma once
+#include <functional>
#include <map>
#include <memory>
+#include <optional>
#include <string>
#include <string_view>
#include <type_traits>
#include <vector>
-#include <boost/optional.hpp>
+
#include "common/common_types.h"
#include "core/file_sys/vfs_types.h"
@@ -103,8 +105,8 @@ public:
// into file. Returns number of bytes successfully written.
virtual std::size_t Write(const u8* data, std::size_t length, std::size_t offset = 0) = 0;
- // Reads exactly one byte at the offset provided, returning boost::none on error.
- virtual boost::optional<u8> ReadByte(std::size_t offset = 0) const;
+ // Reads exactly one byte at the offset provided, returning std::nullopt on error.
+ virtual std::optional<u8> ReadByte(std::size_t offset = 0) const;
// Reads size bytes starting at offset in file into a vector.
virtual std::vector<u8> ReadBytes(std::size_t size, std::size_t offset = 0) const;
// Reads all the bytes from the file into a vector. Equivalent to 'file->Read(file->GetSize(),
diff --git a/src/core/file_sys/vfs_offset.cpp b/src/core/file_sys/vfs_offset.cpp
index a4c6719a0..c96f88488 100644
--- a/src/core/file_sys/vfs_offset.cpp
+++ b/src/core/file_sys/vfs_offset.cpp
@@ -57,11 +57,11 @@ std::size_t OffsetVfsFile::Write(const u8* data, std::size_t length, std::size_t
return file->Write(data, TrimToFit(length, r_offset), offset + r_offset);
}
-boost::optional<u8> OffsetVfsFile::ReadByte(std::size_t r_offset) const {
+std::optional<u8> OffsetVfsFile::ReadByte(std::size_t r_offset) const {
if (r_offset < size)
return file->ReadByte(offset + r_offset);
- return boost::none;
+ return {};
}
std::vector<u8> OffsetVfsFile::ReadBytes(std::size_t r_size, std::size_t r_offset) const {
diff --git a/src/core/file_sys/vfs_offset.h b/src/core/file_sys/vfs_offset.h
index 8062702a7..f7b7a3256 100644
--- a/src/core/file_sys/vfs_offset.h
+++ b/src/core/file_sys/vfs_offset.h
@@ -29,7 +29,7 @@ public:
bool IsReadable() const override;
std::size_t Read(u8* data, std::size_t length, std::size_t offset) const override;
std::size_t Write(const u8* data, std::size_t length, std::size_t offset) override;
- boost::optional<u8> ReadByte(std::size_t offset) const override;
+ std::optional<u8> ReadByte(std::size_t offset) const override;
std::vector<u8> ReadBytes(std::size_t size, std::size_t offset) const override;
std::vector<u8> ReadAllBytes() const override;
bool WriteByte(u8 data, std::size_t offset) override;
diff --git a/src/core/file_sys/vfs_static.h b/src/core/file_sys/vfs_static.h
index 44fab51d1..9f5a90b1b 100644
--- a/src/core/file_sys/vfs_static.h
+++ b/src/core/file_sys/vfs_static.h
@@ -53,10 +53,10 @@ public:
return 0;
}
- boost::optional<u8> ReadByte(std::size_t offset) const override {
+ std::optional<u8> ReadByte(std::size_t offset) const override {
if (offset < size)
return value;
- return boost::none;
+ return {};
}
std::vector<u8> ReadBytes(std::size_t length, std::size_t offset) const override {