diff options
Diffstat (limited to 'src/core')
41 files changed, 337 insertions, 219 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 4fddaafd1..78986deb5 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -400,8 +400,8 @@ create_target_directory_groups(core) target_link_libraries(core PUBLIC common PRIVATE audio_core video_core) target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt lz4_static mbedtls opus unicorn open_source_archives) if (ENABLE_WEB_SERVICE) - add_definitions(-DENABLE_WEB_SERVICE) - target_link_libraries(core PUBLIC json-headers web_service) + target_compile_definitions(core PRIVATE -DENABLE_WEB_SERVICE) + target_link_libraries(core PRIVATE web_service) endif() if (ARCHITECTURE_x86_64) diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index 0762321a9..4d2491870 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp @@ -144,7 +144,7 @@ std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit() const { // Multi-process state config.processor_id = core_index; - config.global_monitor = &exclusive_monitor->monitor; + config.global_monitor = &exclusive_monitor.monitor; // System registers config.tpidrro_el0 = &cb->tpidrro_el0; @@ -171,10 +171,9 @@ void ARM_Dynarmic::Step() { cb->InterpreterFallback(jit->GetPC(), 1); } -ARM_Dynarmic::ARM_Dynarmic(std::shared_ptr<ExclusiveMonitor> exclusive_monitor, - std::size_t core_index) +ARM_Dynarmic::ARM_Dynarmic(ExclusiveMonitor& exclusive_monitor, std::size_t core_index) : cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), core_index{core_index}, - exclusive_monitor{std::dynamic_pointer_cast<DynarmicExclusiveMonitor>(exclusive_monitor)} { + exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} { ThreadContext ctx{}; inner_unicorn.SaveContext(ctx); PageTableChanged(); diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h index 4ee92ee27..512bf8ce9 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.h +++ b/src/core/arm/dynarmic/arm_dynarmic.h @@ -23,7 +23,7 @@ class DynarmicExclusiveMonitor; class ARM_Dynarmic final : public ARM_Interface { public: - ARM_Dynarmic(std::shared_ptr<ExclusiveMonitor> exclusive_monitor, std::size_t core_index); + ARM_Dynarmic(ExclusiveMonitor& exclusive_monitor, std::size_t core_index); ~ARM_Dynarmic(); void MapBackingMemory(VAddr address, std::size_t size, u8* memory, @@ -62,7 +62,7 @@ private: ARM_Unicorn inner_unicorn; std::size_t core_index; - std::shared_ptr<DynarmicExclusiveMonitor> exclusive_monitor; + DynarmicExclusiveMonitor& exclusive_monitor; Memory::PageTable* current_page_table = nullptr; }; diff --git a/src/core/core.cpp b/src/core/core.cpp index e2fb9e038..3c57a62ec 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -71,9 +71,9 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, } /// Runs a CPU core while the system is powered on -void RunCpuCore(std::shared_ptr<Cpu> cpu_state) { +void RunCpuCore(Cpu& cpu_state) { while (Core::System::GetInstance().IsPoweredOn()) { - cpu_state->RunLoop(true); + cpu_state.RunLoop(true); } } } // Anonymous namespace @@ -95,7 +95,7 @@ struct System::Impl { status = ResultStatus::Success; // Update thread_to_cpu in case Core 0 is run from a different host thread - thread_to_cpu[std::this_thread::get_id()] = cpu_cores[0]; + thread_to_cpu[std::this_thread::get_id()] = cpu_cores[0].get(); if (GDBStub::IsServerEnabled()) { GDBStub::HandlePacket(); @@ -139,16 +139,16 @@ struct System::Impl { auto main_process = Kernel::Process::Create(kernel, "main"); kernel.MakeCurrentProcess(main_process.get()); - cpu_barrier = std::make_shared<CpuBarrier>(); + cpu_barrier = std::make_unique<CpuBarrier>(); cpu_exclusive_monitor = Cpu::MakeExclusiveMonitor(cpu_cores.size()); for (std::size_t index = 0; index < cpu_cores.size(); ++index) { - cpu_cores[index] = std::make_shared<Cpu>(cpu_exclusive_monitor, cpu_barrier, index); + cpu_cores[index] = std::make_unique<Cpu>(*cpu_exclusive_monitor, *cpu_barrier, index); } telemetry_session = std::make_unique<Core::TelemetrySession>(); service_manager = std::make_shared<Service::SM::ServiceManager>(); - Service::Init(service_manager, virtual_filesystem); + Service::Init(service_manager, *virtual_filesystem); GDBStub::Init(); renderer = VideoCore::CreateRenderer(emu_window); @@ -160,12 +160,12 @@ struct System::Impl { // Create threads for CPU cores 1-3, and build thread_to_cpu map // CPU core 0 is run on the main thread - thread_to_cpu[std::this_thread::get_id()] = cpu_cores[0]; + thread_to_cpu[std::this_thread::get_id()] = cpu_cores[0].get(); if (Settings::values.use_multi_core) { for (std::size_t index = 0; index < cpu_core_threads.size(); ++index) { cpu_core_threads[index] = - std::make_unique<std::thread>(RunCpuCore, cpu_cores[index + 1]); - thread_to_cpu[cpu_core_threads[index]->get_id()] = cpu_cores[index + 1]; + std::make_unique<std::thread>(RunCpuCore, std::ref(*cpu_cores[index + 1])); + thread_to_cpu[cpu_core_threads[index]->get_id()] = cpu_cores[index + 1].get(); } } @@ -245,6 +245,7 @@ struct System::Impl { for (auto& cpu_core : cpu_cores) { cpu_core.reset(); } + cpu_exclusive_monitor.reset(); cpu_barrier.reset(); // Shutdown kernel and core timing @@ -282,9 +283,9 @@ struct System::Impl { std::unique_ptr<VideoCore::RendererBase> renderer; std::unique_ptr<Tegra::GPU> gpu_core; std::shared_ptr<Tegra::DebugContext> debug_context; - std::shared_ptr<ExclusiveMonitor> cpu_exclusive_monitor; - std::shared_ptr<CpuBarrier> cpu_barrier; - std::array<std::shared_ptr<Cpu>, NUM_CPU_CORES> cpu_cores; + std::unique_ptr<ExclusiveMonitor> cpu_exclusive_monitor; + std::unique_ptr<CpuBarrier> cpu_barrier; + std::array<std::unique_ptr<Cpu>, NUM_CPU_CORES> cpu_cores; std::array<std::unique_ptr<std::thread>, NUM_CPU_CORES - 1> cpu_core_threads; std::size_t active_core{}; ///< Active core, only used in single thread mode @@ -298,7 +299,7 @@ struct System::Impl { std::string status_details = ""; /// Map of guest threads to CPU cores - std::map<std::thread::id, std::shared_ptr<Cpu>> thread_to_cpu; + std::map<std::thread::id, Cpu*> thread_to_cpu; Core::PerfStats perf_stats; Core::FrameLimiter frame_limiter; @@ -354,12 +355,15 @@ std::size_t System::CurrentCoreIndex() { } Kernel::Scheduler& System::CurrentScheduler() { - return *CurrentCpuCore().Scheduler(); + return CurrentCpuCore().Scheduler(); } -const std::shared_ptr<Kernel::Scheduler>& System::Scheduler(std::size_t core_index) { - ASSERT(core_index < NUM_CPU_CORES); - return impl->cpu_cores[core_index]->Scheduler(); +Kernel::Scheduler& System::Scheduler(std::size_t core_index) { + return CpuCore(core_index).Scheduler(); +} + +const Kernel::Scheduler& System::Scheduler(std::size_t core_index) const { + return CpuCore(core_index).Scheduler(); } Kernel::Process* System::CurrentProcess() { @@ -380,6 +384,11 @@ Cpu& System::CpuCore(std::size_t core_index) { return *impl->cpu_cores[core_index]; } +const Cpu& System::CpuCore(std::size_t core_index) const { + ASSERT(core_index < NUM_CPU_CORES); + return *impl->cpu_cores[core_index]; +} + ExclusiveMonitor& System::Monitor() { return *impl->cpu_exclusive_monitor; } diff --git a/src/core/core.h b/src/core/core.h index ea4d53914..173be45f8 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -156,6 +156,9 @@ public: /// Gets a CPU interface to the CPU core with the specified index Cpu& CpuCore(std::size_t core_index); + /// Gets a CPU interface to the CPU core with the specified index + const Cpu& CpuCore(std::size_t core_index) const; + /// Gets the exclusive monitor ExclusiveMonitor& Monitor(); @@ -172,7 +175,10 @@ public: const VideoCore::RendererBase& Renderer() const; /// Gets the scheduler for the CPU core with the specified index - const std::shared_ptr<Kernel::Scheduler>& Scheduler(std::size_t core_index); + Kernel::Scheduler& Scheduler(std::size_t core_index); + + /// Gets the scheduler for the CPU core with the specified index + const Kernel::Scheduler& Scheduler(std::size_t core_index) const; /// Provides a pointer to the current process Kernel::Process* CurrentProcess(); diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp index 265f8ed9c..fffda8a99 100644 --- a/src/core/core_cpu.cpp +++ b/src/core/core_cpu.cpp @@ -49,10 +49,8 @@ bool CpuBarrier::Rendezvous() { return false; } -Cpu::Cpu(std::shared_ptr<ExclusiveMonitor> exclusive_monitor, - std::shared_ptr<CpuBarrier> cpu_barrier, std::size_t core_index) - : cpu_barrier{std::move(cpu_barrier)}, core_index{core_index} { - +Cpu::Cpu(ExclusiveMonitor& exclusive_monitor, CpuBarrier& cpu_barrier, std::size_t core_index) + : cpu_barrier{cpu_barrier}, core_index{core_index} { if (Settings::values.use_cpu_jit) { #ifdef ARCHITECTURE_x86_64 arm_interface = std::make_unique<ARM_Dynarmic>(exclusive_monitor, core_index); @@ -64,15 +62,15 @@ Cpu::Cpu(std::shared_ptr<ExclusiveMonitor> exclusive_monitor, arm_interface = std::make_unique<ARM_Unicorn>(); } - scheduler = std::make_shared<Kernel::Scheduler>(*arm_interface); + scheduler = std::make_unique<Kernel::Scheduler>(*arm_interface); } Cpu::~Cpu() = default; -std::shared_ptr<ExclusiveMonitor> Cpu::MakeExclusiveMonitor(std::size_t num_cores) { +std::unique_ptr<ExclusiveMonitor> Cpu::MakeExclusiveMonitor(std::size_t num_cores) { if (Settings::values.use_cpu_jit) { #ifdef ARCHITECTURE_x86_64 - return std::make_shared<DynarmicExclusiveMonitor>(num_cores); + return std::make_unique<DynarmicExclusiveMonitor>(num_cores); #else return nullptr; // TODO(merry): Passthrough exclusive monitor #endif @@ -83,7 +81,7 @@ std::shared_ptr<ExclusiveMonitor> Cpu::MakeExclusiveMonitor(std::size_t num_core void Cpu::RunLoop(bool tight_loop) { // Wait for all other CPU cores to complete the previous slice, such that they run in lock-step - if (!cpu_barrier->Rendezvous()) { + if (!cpu_barrier.Rendezvous()) { // If rendezvous failed, session has been killed return; } diff --git a/src/core/core_cpu.h b/src/core/core_cpu.h index ee7e04abc..1d2bdc6cd 100644 --- a/src/core/core_cpu.h +++ b/src/core/core_cpu.h @@ -41,8 +41,7 @@ private: class Cpu { public: - Cpu(std::shared_ptr<ExclusiveMonitor> exclusive_monitor, - std::shared_ptr<CpuBarrier> cpu_barrier, std::size_t core_index); + Cpu(ExclusiveMonitor& exclusive_monitor, CpuBarrier& cpu_barrier, std::size_t core_index); ~Cpu(); void RunLoop(bool tight_loop = true); @@ -59,8 +58,12 @@ public: return *arm_interface; } - const std::shared_ptr<Kernel::Scheduler>& Scheduler() const { - return scheduler; + Kernel::Scheduler& Scheduler() { + return *scheduler; + } + + const Kernel::Scheduler& Scheduler() const { + return *scheduler; } bool IsMainCore() const { @@ -71,14 +74,14 @@ public: return core_index; } - static std::shared_ptr<ExclusiveMonitor> MakeExclusiveMonitor(std::size_t num_cores); + static std::unique_ptr<ExclusiveMonitor> MakeExclusiveMonitor(std::size_t num_cores); private: void Reschedule(); std::unique_ptr<ARM_Interface> arm_interface; - std::shared_ptr<CpuBarrier> cpu_barrier; - std::shared_ptr<Kernel::Scheduler> scheduler; + CpuBarrier& cpu_barrier; + std::unique_ptr<Kernel::Scheduler> scheduler; std::atomic<bool> reschedule_pending = false; std::size_t core_index; diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp index a59a7e1f5..fd0786068 100644 --- a/src/core/crypto/key_manager.cpp +++ b/src/core/crypto/key_manager.cpp @@ -98,7 +98,7 @@ std::array<u8, 144> DecryptKeyblob(const std::array<u8, 176>& encrypted_keyblob, return keyblob; } -void KeyManager::DeriveGeneralPurposeKeys(u8 crypto_revision) { +void KeyManager::DeriveGeneralPurposeKeys(std::size_t crypto_revision) { const auto kek_generation_source = GetKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKekGeneration)); const auto key_generation_source = @@ -147,31 +147,38 @@ boost::optional<Key128> DeriveSDSeed() { "rb+"); if (!save_43.IsOpen()) return boost::none; + const FileUtil::IOFile sd_private( FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir) + "/Nintendo/Contents/private", "rb+"); if (!sd_private.IsOpen()) return boost::none; - sd_private.Seek(0, SEEK_SET); std::array<u8, 0x10> private_seed{}; - if (sd_private.ReadBytes(private_seed.data(), private_seed.size()) != 0x10) + if (sd_private.ReadBytes(private_seed.data(), private_seed.size()) != private_seed.size()) { return boost::none; + } std::array<u8, 0x10> buffer{}; std::size_t offset = 0; for (; offset + 0x10 < save_43.GetSize(); ++offset) { - save_43.Seek(offset, SEEK_SET); + if (!save_43.Seek(offset, SEEK_SET)) { + return boost::none; + } + save_43.ReadBytes(buffer.data(), buffer.size()); - if (buffer == private_seed) + if (buffer == private_seed) { break; + } } - if (offset + 0x10 >= save_43.GetSize()) + if (!save_43.Seek(offset + 0x10, SEEK_SET)) { return boost::none; + } Key128 seed{}; - save_43.Seek(offset + 0x10, SEEK_SET); - save_43.ReadBytes(seed.data(), seed.size()); + if (save_43.ReadBytes(seed.data(), seed.size()) != seed.size()) { + return boost::none; + } return seed; } @@ -234,7 +241,9 @@ std::vector<TicketRaw> GetTicketblob(const FileUtil::IOFile& ticket_save) { return {}; std::vector<u8> buffer(ticket_save.GetSize()); - ticket_save.ReadBytes(buffer.data(), buffer.size()); + if (ticket_save.ReadBytes(buffer.data(), buffer.size()) != buffer.size()) { + return {}; + } std::vector<TicketRaw> out; u32 magic{}; @@ -261,6 +270,9 @@ static std::array<u8, size> operator^(const std::array<u8, size>& lhs, template <size_t target_size, size_t in_size> static std::array<u8, target_size> MGF1(const std::array<u8, in_size>& seed) { + // Avoids truncation overflow within the loop below. + static_assert(target_size <= 0xFF); + std::array<u8, in_size + 4> seed_exp{}; std::memcpy(seed_exp.data(), seed.data(), in_size); @@ -268,7 +280,7 @@ static std::array<u8, target_size> MGF1(const std::array<u8, in_size>& seed) { size_t i = 0; while (out.size() < target_size) { out.resize(out.size() + 0x20); - seed_exp[in_size + 3] = i; + seed_exp[in_size + 3] = static_cast<u8>(i); mbedtls_sha256(seed_exp.data(), seed_exp.size(), out.data() + out.size() - 0x20, 0); ++i; } @@ -299,10 +311,11 @@ boost::optional<std::pair<Key128, Key128>> ParseTicket(const TicketRaw& ticket, std::memcpy(&cert_authority, ticket.data() + 0x140, sizeof(cert_authority)); if (cert_authority == 0) return boost::none; - if (cert_authority != Common::MakeMagic('R', 'o', 'o', 't')) + if (cert_authority != Common::MakeMagic('R', 'o', 'o', 't')) { LOG_INFO(Crypto, "Attempting to parse ticket with non-standard certificate authority {:08X}.", cert_authority); + } Key128 rights_id; std::memcpy(rights_id.data(), ticket.data() + 0x2A0, sizeof(Key128)); @@ -871,9 +884,9 @@ void KeyManager::DeriveETicket(PartitionDataManager& data) { "/system/save/80000000000000e2", "rb+"); + const auto blob2 = GetTicketblob(save2); auto res = GetTicketblob(save1); - const auto res2 = GetTicketblob(save2); - std::copy(res2.begin(), res2.end(), std::back_inserter(res)); + res.insert(res.end(), blob2.begin(), blob2.end()); for (const auto& raw : res) { const auto pair = ParseTicket(raw, rsa_key); diff --git a/src/core/crypto/key_manager.h b/src/core/crypto/key_manager.h index a41abbdfc..cccb3c0ae 100644 --- a/src/core/crypto/key_manager.h +++ b/src/core/crypto/key_manager.h @@ -175,7 +175,7 @@ private: void WriteKeyToFile(KeyCategory category, std::string_view keyname, const std::array<u8, Size>& key); - void DeriveGeneralPurposeKeys(u8 crypto_revision); + void DeriveGeneralPurposeKeys(std::size_t crypto_revision); void SetKeyWrapped(S128KeyType id, Key128 key, u64 field1 = 0, u64 field2 = 0); void SetKeyWrapped(S256KeyType id, Key256 key, u64 field1 = 0, u64 field2 = 0); diff --git a/src/core/crypto/partition_data_manager.cpp b/src/core/crypto/partition_data_manager.cpp index d1c04e98d..25cee1f3a 100644 --- a/src/core/crypto/partition_data_manager.cpp +++ b/src/core/crypto/partition_data_manager.cpp @@ -11,7 +11,6 @@ #include <array> #include <cctype> #include <cstring> -#include <boost/optional/optional.hpp> #include <mbedtls/sha256.h> #include "common/assert.h" #include "common/common_funcs.h" @@ -19,7 +18,7 @@ #include "common/hex_util.h" #include "common/logging/log.h" #include "common/string_util.h" -#include "core/crypto/ctr_encryption_layer.h" +#include "common/swap.h" #include "core/crypto/key_manager.h" #include "core/crypto/partition_data_manager.h" #include "core/crypto/xts_encryption_layer.h" @@ -302,10 +301,10 @@ FileSys::VirtualFile FindFileInDirWithNames(const FileSys::VirtualDir& dir, return nullptr; } -PartitionDataManager::PartitionDataManager(FileSys::VirtualDir sysdata_dir) +PartitionDataManager::PartitionDataManager(const FileSys::VirtualDir& sysdata_dir) : boot0(FindFileInDirWithNames(sysdata_dir, "BOOT0")), - fuses(FindFileInDirWithNames(sysdata_dir, "fuse")), - kfuses(FindFileInDirWithNames(sysdata_dir, "kfuse")), + fuses(FindFileInDirWithNames(sysdata_dir, "fuses")), + kfuses(FindFileInDirWithNames(sysdata_dir, "kfuses")), package2({ FindFileInDirWithNames(sysdata_dir, "BCPKG2-1-Normal-Main"), FindFileInDirWithNames(sysdata_dir, "BCPKG2-2-Normal-Sub"), @@ -314,13 +313,14 @@ PartitionDataManager::PartitionDataManager(FileSys::VirtualDir sysdata_dir) FindFileInDirWithNames(sysdata_dir, "BCPKG2-5-Repair-Main"), FindFileInDirWithNames(sysdata_dir, "BCPKG2-6-Repair-Sub"), }), + prodinfo(FindFileInDirWithNames(sysdata_dir, "PRODINFO")), secure_monitor(FindFileInDirWithNames(sysdata_dir, "secmon")), package1_decrypted(FindFileInDirWithNames(sysdata_dir, "pkg1_decr")), secure_monitor_bytes(secure_monitor == nullptr ? std::vector<u8>{} : secure_monitor->ReadAllBytes()), package1_decrypted_bytes(package1_decrypted == nullptr ? std::vector<u8>{} - : package1_decrypted->ReadAllBytes()), - prodinfo(FindFileInDirWithNames(sysdata_dir, "PRODINFO")) {} + : package1_decrypted->ReadAllBytes()) { +} PartitionDataManager::~PartitionDataManager() = default; @@ -332,18 +332,19 @@ FileSys::VirtualFile PartitionDataManager::GetBoot0Raw() const { return boot0; } -std::array<u8, 176> PartitionDataManager::GetEncryptedKeyblob(u8 index) const { - if (HasBoot0() && index < 32) +PartitionDataManager::EncryptedKeyBlob PartitionDataManager::GetEncryptedKeyblob( + std::size_t index) const { + if (HasBoot0() && index < NUM_ENCRYPTED_KEYBLOBS) return GetEncryptedKeyblobs()[index]; return {}; } -std::array<std::array<u8, 176>, 32> PartitionDataManager::GetEncryptedKeyblobs() const { +PartitionDataManager::EncryptedKeyBlobs PartitionDataManager::GetEncryptedKeyblobs() const { if (!HasBoot0()) return {}; - std::array<std::array<u8, 176>, 32> out{}; - for (size_t i = 0; i < 0x20; ++i) + EncryptedKeyBlobs out{}; + for (size_t i = 0; i < out.size(); ++i) boot0->Read(out[i].data(), out[i].size(), 0x180000 + i * 0x200); return out; } @@ -389,7 +390,7 @@ std::array<u8, 16> PartitionDataManager::GetKeyblobMACKeySource() const { return FindKeyFromHex(package1_decrypted_bytes, source_hashes[0]); } -std::array<u8, 16> PartitionDataManager::GetKeyblobKeySource(u8 revision) const { +std::array<u8, 16> PartitionDataManager::GetKeyblobKeySource(std::size_t revision) const { if (keyblob_source_hashes[revision] == SHA256Hash{}) { LOG_WARNING(Crypto, "No keyblob source hash for crypto revision {:02X}! Cannot derive keys...", @@ -446,7 +447,7 @@ bool AttemptDecrypt(const std::array<u8, 16>& key, Package2Header& header) { return false; } -void PartitionDataManager::DecryptPackage2(std::array<std::array<u8, 16>, 0x20> package2_keys, +void PartitionDataManager::DecryptPackage2(const std::array<Key128, 0x20>& package2_keys, Package2Type type) { FileSys::VirtualFile file = std::make_shared<FileSys::OffsetVfsFile>( package2[static_cast<size_t>(type)], @@ -456,43 +457,38 @@ void PartitionDataManager::DecryptPackage2(std::array<std::array<u8, 16>, 0x20> if (file->ReadObject(&header) != sizeof(Package2Header)) return; - u8 revision = 0xFF; + std::size_t revision = 0xFF; if (header.magic != Common::MakeMagic('P', 'K', '2', '1')) { - for (size_t i = 0; i < package2_keys.size(); ++i) { - if (AttemptDecrypt(package2_keys[i], header)) + for (std::size_t i = 0; i < package2_keys.size(); ++i) { + if (AttemptDecrypt(package2_keys[i], header)) { revision = i; + } } } if (header.magic != Common::MakeMagic('P', 'K', '2', '1')) return; - const std::vector<u8> s1_iv(header.section_ctr[1].begin(), header.section_ctr[1].end()); - const auto a = std::make_shared<FileSys::OffsetVfsFile>( file, header.section_size[1], header.section_size[0] + sizeof(Package2Header)); auto c = a->ReadAllBytes(); AESCipher<Key128> cipher(package2_keys[revision], Mode::CTR); - cipher.SetIV(s1_iv); + cipher.SetIV({header.section_ctr[1].begin(), header.section_ctr[1].end()}); cipher.Transcode(c.data(), c.size(), c.data(), Op::Decrypt); - // package2_decrypted[static_cast<size_t>(type)] = s1; - INIHeader ini; std::memcpy(&ini, c.data(), sizeof(INIHeader)); if (ini.magic != Common::MakeMagic('I', 'N', 'I', '1')) return; - std::map<u64, KIPHeader> kips{}; u64 offset = sizeof(INIHeader); for (size_t i = 0; i < ini.process_count; ++i) { KIPHeader kip; std::memcpy(&kip, c.data() + offset, sizeof(KIPHeader)); if (kip.magic != Common::MakeMagic('K', 'I', 'P', '1')) return; - kips.emplace(offset, kip); const auto name = Common::StringFromFixedZeroTerminatedBuffer(kip.name.data(), kip.name.size()); @@ -503,33 +499,29 @@ void PartitionDataManager::DecryptPackage2(std::array<std::array<u8, 16>, 0x20> continue; } - std::vector<u8> text(kip.sections[0].size_compressed); - std::vector<u8> rodata(kip.sections[1].size_compressed); - std::vector<u8> data(kip.sections[2].size_compressed); + const u64 initial_offset = sizeof(KIPHeader) + offset; + const auto text_begin = c.cbegin() + initial_offset; + const auto text_end = text_begin + kip.sections[0].size_compressed; + const std::vector<u8> text = DecompressBLZ({text_begin, text_end}); - u64 offset_sec = sizeof(KIPHeader) + offset; - std::memcpy(text.data(), c.data() + offset_sec, text.size()); - offset_sec += text.size(); - std::memcpy(rodata.data(), c.data() + offset_sec, rodata.size()); - offset_sec += rodata.size(); - std::memcpy(data.data(), c.data() + offset_sec, data.size()); + const auto rodata_end = text_end + kip.sections[1].size_compressed; + const std::vector<u8> rodata = DecompressBLZ({text_end, rodata_end}); - offset += sizeof(KIPHeader) + kip.sections[0].size_compressed + - kip.sections[1].size_compressed + kip.sections[2].size_compressed; + const auto data_end = rodata_end + kip.sections[2].size_compressed; + const std::vector<u8> data = DecompressBLZ({rodata_end, data_end}); - text = DecompressBLZ(text); - rodata = DecompressBLZ(rodata); - data = DecompressBLZ(data); + std::vector<u8> out; + out.reserve(text.size() + rodata.size() + data.size()); + out.insert(out.end(), text.begin(), text.end()); + out.insert(out.end(), rodata.begin(), rodata.end()); + out.insert(out.end(), data.begin(), data.end()); - std::vector<u8> out(text.size() + rodata.size() + data.size()); - std::memcpy(out.data(), text.data(), text.size()); - std::memcpy(out.data() + text.size(), rodata.data(), rodata.size()); - std::memcpy(out.data() + text.size() + rodata.size(), data.data(), data.size()); + offset += sizeof(KIPHeader) + out.size(); if (name == "FS") - package2_fs[static_cast<size_t>(type)] = out; + package2_fs[static_cast<size_t>(type)] = std::move(out); else if (name == "spl") - package2_spl[static_cast<size_t>(type)] = out; + package2_spl[static_cast<size_t>(type)] = std::move(out); } } diff --git a/src/core/crypto/partition_data_manager.h b/src/core/crypto/partition_data_manager.h index 45c7fecfa..0ad007c72 100644 --- a/src/core/crypto/partition_data_manager.h +++ b/src/core/crypto/partition_data_manager.h @@ -5,9 +5,7 @@ #pragma once #include <vector> -#include "common/common_funcs.h" #include "common/common_types.h" -#include "common/swap.h" #include "core/file_sys/vfs_types.h" namespace Core::Crypto { @@ -24,15 +22,20 @@ enum class Package2Type { class PartitionDataManager { public: static const u8 MAX_KEYBLOB_SOURCE_HASH; + static constexpr std::size_t NUM_ENCRYPTED_KEYBLOBS = 32; + static constexpr std::size_t ENCRYPTED_KEYBLOB_SIZE = 0xB0; - explicit PartitionDataManager(FileSys::VirtualDir sysdata_dir); + using EncryptedKeyBlob = std::array<u8, ENCRYPTED_KEYBLOB_SIZE>; + using EncryptedKeyBlobs = std::array<EncryptedKeyBlob, NUM_ENCRYPTED_KEYBLOBS>; + + explicit PartitionDataManager(const FileSys::VirtualDir& sysdata_dir); ~PartitionDataManager(); // BOOT0 bool HasBoot0() const; FileSys::VirtualFile GetBoot0Raw() const; - std::array<u8, 0xB0> GetEncryptedKeyblob(u8 index) const; - std::array<std::array<u8, 0xB0>, 0x20> GetEncryptedKeyblobs() const; + EncryptedKeyBlob GetEncryptedKeyblob(std::size_t index) const; + EncryptedKeyBlobs GetEncryptedKeyblobs() const; std::vector<u8> GetSecureMonitor() const; std::array<u8, 0x10> GetPackage2KeySource() const; std::array<u8, 0x10> GetAESKekGenerationSource() const; @@ -43,7 +46,7 @@ public: std::vector<u8> GetPackage1Decrypted() const; std::array<u8, 0x10> GetMasterKeySource() const; std::array<u8, 0x10> GetKeyblobMACKeySource() const; - std::array<u8, 0x10> GetKeyblobKeySource(u8 revision) const; + std::array<u8, 0x10> GetKeyblobKeySource(std::size_t revision) const; // Fuses bool HasFuses() const; @@ -57,7 +60,8 @@ public: // Package2 bool HasPackage2(Package2Type type = Package2Type::NormalMain) const; FileSys::VirtualFile GetPackage2Raw(Package2Type type = Package2Type::NormalMain) const; - void DecryptPackage2(std::array<std::array<u8, 16>, 0x20> package2, Package2Type type); + void DecryptPackage2(const std::array<std::array<u8, 16>, 0x20>& package2_keys, + Package2Type type); const std::vector<u8>& GetPackage2FSDecompressed( Package2Type type = Package2Type::NormalMain) const; std::array<u8, 0x10> GetKeyAreaKeyApplicationSource( diff --git a/src/core/file_sys/bis_factory.cpp b/src/core/file_sys/bis_factory.cpp index 6102ef476..76a2b7e86 100644 --- a/src/core/file_sys/bis_factory.cpp +++ b/src/core/file_sys/bis_factory.cpp @@ -10,19 +10,19 @@ namespace FileSys { BISFactory::BISFactory(VirtualDir nand_root_, VirtualDir load_root_) : nand_root(std::move(nand_root_)), load_root(std::move(load_root_)), - sysnand_cache(std::make_shared<RegisteredCache>( + sysnand_cache(std::make_unique<RegisteredCache>( GetOrCreateDirectoryRelative(nand_root, "/system/Contents/registered"))), - usrnand_cache(std::make_shared<RegisteredCache>( + usrnand_cache(std::make_unique<RegisteredCache>( GetOrCreateDirectoryRelative(nand_root, "/user/Contents/registered"))) {} BISFactory::~BISFactory() = default; -std::shared_ptr<RegisteredCache> BISFactory::GetSystemNANDContents() const { - return sysnand_cache; +RegisteredCache* BISFactory::GetSystemNANDContents() const { + return sysnand_cache.get(); } -std::shared_ptr<RegisteredCache> BISFactory::GetUserNANDContents() const { - return usrnand_cache; +RegisteredCache* BISFactory::GetUserNANDContents() const { + return usrnand_cache.get(); } VirtualDir BISFactory::GetModificationLoadRoot(u64 title_id) const { diff --git a/src/core/file_sys/bis_factory.h b/src/core/file_sys/bis_factory.h index c352e0925..364d309bd 100644 --- a/src/core/file_sys/bis_factory.h +++ b/src/core/file_sys/bis_factory.h @@ -20,8 +20,8 @@ public: explicit BISFactory(VirtualDir nand_root, VirtualDir load_root); ~BISFactory(); - std::shared_ptr<RegisteredCache> GetSystemNANDContents() const; - std::shared_ptr<RegisteredCache> GetUserNANDContents() const; + RegisteredCache* GetSystemNANDContents() const; + RegisteredCache* GetUserNANDContents() const; VirtualDir GetModificationLoadRoot(u64 title_id) const; @@ -29,8 +29,8 @@ private: VirtualDir nand_root; VirtualDir load_root; - std::shared_ptr<RegisteredCache> sysnand_cache; - std::shared_ptr<RegisteredCache> usrnand_cache; + std::unique_ptr<RegisteredCache> sysnand_cache; + std::unique_ptr<RegisteredCache> usrnand_cache; }; } // namespace FileSys diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp index aa1b3c17d..6dcec7816 100644 --- a/src/core/file_sys/content_archive.cpp +++ b/src/core/file_sys/content_archive.cpp @@ -133,7 +133,7 @@ boost::optional<Core::Crypto::Key128> NCA::GetKeyAreaKey(NCASectionCryptoType ty static_cast<u8>(type)); u128 out_128{}; memcpy(out_128.data(), out.data(), 16); - LOG_DEBUG(Crypto, "called with crypto_rev={:02X}, kak_index={:02X}, key={:016X}{:016X}", + LOG_TRACE(Crypto, "called with crypto_rev={:02X}, kak_index={:02X}, key={:016X}{:016X}", master_key_id, header.key_index, out_128[1], out_128[0]); return out; diff --git a/src/core/file_sys/control_metadata.cpp b/src/core/file_sys/control_metadata.cpp index 5b1177a03..a012c2be9 100644 --- a/src/core/file_sys/control_metadata.cpp +++ b/src/core/file_sys/control_metadata.cpp @@ -17,11 +17,13 @@ const std::array<const char*, 15> LANGUAGE_NAMES = { }; std::string LanguageEntry::GetApplicationName() const { - return Common::StringFromFixedZeroTerminatedBuffer(application_name.data(), 0x200); + return Common::StringFromFixedZeroTerminatedBuffer(application_name.data(), + application_name.size()); } std::string LanguageEntry::GetDeveloperName() const { - return Common::StringFromFixedZeroTerminatedBuffer(developer_name.data(), 0x100); + return Common::StringFromFixedZeroTerminatedBuffer(developer_name.data(), + developer_name.size()); } NACP::NACP(VirtualFile file) : raw(std::make_unique<RawNACP>()) { @@ -56,7 +58,12 @@ u64 NACP::GetTitleId() const { return raw->title_id; } +u64 NACP::GetDLCBaseTitleId() const { + return raw->dlc_base_title_id; +} + std::string NACP::GetVersionString() const { - return Common::StringFromFixedZeroTerminatedBuffer(raw->version_string.data(), 0x10); + return Common::StringFromFixedZeroTerminatedBuffer(raw->version_string.data(), + raw->version_string.size()); } } // namespace FileSys diff --git a/src/core/file_sys/control_metadata.h b/src/core/file_sys/control_metadata.h index 43d6f0719..141f7e056 100644 --- a/src/core/file_sys/control_metadata.h +++ b/src/core/file_sys/control_metadata.h @@ -79,6 +79,7 @@ public: std::string GetApplicationName(Language language = Language::Default) const; std::string GetDeveloperName(Language language = Language::Default) const; u64 GetTitleId() const; + u64 GetDLCBaseTitleId() const; std::string GetVersionString() const; private: diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index 019caebe9..0117cb0bf 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp @@ -214,8 +214,14 @@ static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType t VirtualFile PatchManager::PatchRomFS(VirtualFile romfs, u64 ivfc_offset, ContentRecordType type, VirtualFile update_raw) const { - LOG_INFO(Loader, "Patching RomFS for title_id={:016X}, type={:02X}", title_id, - static_cast<u8>(type)); + const auto log_string = fmt::format("Patching RomFS for title_id={:016X}, type={:02X}", + title_id, static_cast<u8>(type)) + .c_str(); + + if (type == ContentRecordType::Program) + LOG_INFO(Loader, log_string); + else + LOG_DEBUG(Loader, log_string); if (romfs == nullptr) return romfs; @@ -346,7 +352,7 @@ std::map<std::string, std::string, std::less<>> PatchManager::GetPatchVersionNam } std::pair<std::unique_ptr<NACP>, VirtualFile> PatchManager::GetControlMetadata() const { - const auto& installed{Service::FileSystem::GetUnionContents()}; + const auto installed{Service::FileSystem::GetUnionContents()}; const auto base_control_nca = installed->GetEntry(title_id, ContentRecordType::Control); if (base_control_nca == nullptr) diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp index e9b040689..1febb398e 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp @@ -308,14 +308,14 @@ VirtualFile RegisteredCache::GetEntryRaw(RegisteredCacheEntry entry) const { return GetEntryRaw(entry.title_id, entry.type); } -std::shared_ptr<NCA> RegisteredCache::GetEntry(u64 title_id, ContentRecordType type) const { +std::unique_ptr<NCA> RegisteredCache::GetEntry(u64 title_id, ContentRecordType type) const { const auto raw = GetEntryRaw(title_id, type); if (raw == nullptr) return nullptr; - return std::make_shared<NCA>(raw); + return std::make_unique<NCA>(raw); } -std::shared_ptr<NCA> RegisteredCache::GetEntry(RegisteredCacheEntry entry) const { +std::unique_ptr<NCA> RegisteredCache::GetEntry(RegisteredCacheEntry entry) const { return GetEntry(entry.title_id, entry.type); } @@ -516,7 +516,7 @@ bool RegisteredCache::RawInstallYuzuMeta(const CNMT& cnmt) { }) != yuzu_meta.end(); } -RegisteredCacheUnion::RegisteredCacheUnion(std::vector<std::shared_ptr<RegisteredCache>> caches) +RegisteredCacheUnion::RegisteredCacheUnion(std::vector<RegisteredCache*> caches) : caches(std::move(caches)) {} void RegisteredCacheUnion::Refresh() { @@ -572,14 +572,14 @@ VirtualFile RegisteredCacheUnion::GetEntryRaw(RegisteredCacheEntry entry) const return GetEntryRaw(entry.title_id, entry.type); } -std::shared_ptr<NCA> RegisteredCacheUnion::GetEntry(u64 title_id, ContentRecordType type) const { +std::unique_ptr<NCA> RegisteredCacheUnion::GetEntry(u64 title_id, ContentRecordType type) const { const auto raw = GetEntryRaw(title_id, type); if (raw == nullptr) return nullptr; - return std::make_shared<NCA>(raw); + return std::make_unique<NCA>(raw); } -std::shared_ptr<NCA> RegisteredCacheUnion::GetEntry(RegisteredCacheEntry entry) const { +std::unique_ptr<NCA> RegisteredCacheUnion::GetEntry(RegisteredCacheEntry entry) const { return GetEntry(entry.title_id, entry.type); } diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h index c0cd59fc5..5ddacba47 100644 --- a/src/core/file_sys/registered_cache.h +++ b/src/core/file_sys/registered_cache.h @@ -88,8 +88,8 @@ public: VirtualFile GetEntryRaw(u64 title_id, ContentRecordType type) const; VirtualFile GetEntryRaw(RegisteredCacheEntry entry) const; - std::shared_ptr<NCA> GetEntry(u64 title_id, ContentRecordType type) const; - std::shared_ptr<NCA> GetEntry(RegisteredCacheEntry entry) const; + std::unique_ptr<NCA> GetEntry(u64 title_id, ContentRecordType type) const; + 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. @@ -142,7 +142,7 @@ private: // Combines multiple RegisteredCaches (i.e. SysNAND, UserNAND, SDMC) into one interface. class RegisteredCacheUnion { public: - explicit RegisteredCacheUnion(std::vector<std::shared_ptr<RegisteredCache>> caches); + explicit RegisteredCacheUnion(std::vector<RegisteredCache*> caches); void Refresh(); @@ -157,8 +157,8 @@ public: VirtualFile GetEntryRaw(u64 title_id, ContentRecordType type) const; VirtualFile GetEntryRaw(RegisteredCacheEntry entry) const; - std::shared_ptr<NCA> GetEntry(u64 title_id, ContentRecordType type) const; - std::shared_ptr<NCA> GetEntry(RegisteredCacheEntry entry) const; + std::unique_ptr<NCA> GetEntry(u64 title_id, ContentRecordType type) const; + 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. @@ -168,7 +168,7 @@ public: boost::optional<u64> title_id = boost::none) const; private: - std::vector<std::shared_ptr<RegisteredCache>> caches; + std::vector<RegisteredCache*> caches; }; } // namespace FileSys diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp index 47f2ab9e0..ef1aaebbb 100644 --- a/src/core/file_sys/savedata_factory.cpp +++ b/src/core/file_sys/savedata_factory.cpp @@ -51,6 +51,13 @@ ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space, SaveDataDescr meta.title_id); } + if (meta.type == SaveDataType::DeviceSaveData && meta.user_id != u128{0, 0}) { + LOG_WARNING(Service_FS, + "Possibly incorrect SaveDataDescriptor, type is DeviceSaveData but user_id is " + "non-zero ({:016X}{:016X})", + meta.user_id[1], meta.user_id[0]); + } + std::string save_directory = GetFullPath(space, meta.type, meta.title_id, meta.user_id, meta.save_id); @@ -92,6 +99,9 @@ std::string SaveDataFactory::GetFullPath(SaveDataSpaceId space, SaveDataType typ case SaveDataSpaceId::NandUser: out = "/user/"; break; + case SaveDataSpaceId::TemporaryStorage: + out = "/temp/"; + break; default: ASSERT_MSG(false, "Unrecognized SaveDataSpaceId: {:02X}", static_cast<u8>(space)); } @@ -100,10 +110,11 @@ std::string SaveDataFactory::GetFullPath(SaveDataSpaceId space, SaveDataType typ case SaveDataType::SystemSaveData: return fmt::format("{}save/{:016X}/{:016X}{:016X}", out, save_id, user_id[1], user_id[0]); case SaveDataType::SaveData: + case SaveDataType::DeviceSaveData: return fmt::format("{}save/{:016X}/{:016X}{:016X}/{:016X}", out, 0, user_id[1], user_id[0], title_id); case SaveDataType::TemporaryStorage: - return fmt::format("{}temp/{:016X}/{:016X}{:016X}/{:016X}", out, 0, user_id[1], user_id[0], + return fmt::format("{}{:016X}/{:016X}{:016X}/{:016X}", out, 0, user_id[1], user_id[0], title_id); default: ASSERT_MSG(false, "Unrecognized SaveDataType: {:02X}", static_cast<u8>(type)); diff --git a/src/core/file_sys/sdmc_factory.cpp b/src/core/file_sys/sdmc_factory.cpp index d66a9c9a4..bd3a57058 100644 --- a/src/core/file_sys/sdmc_factory.cpp +++ b/src/core/file_sys/sdmc_factory.cpp @@ -10,10 +10,10 @@ namespace FileSys { SDMCFactory::SDMCFactory(VirtualDir dir_) - : dir(std::move(dir_)), contents(std::make_shared<RegisteredCache>( + : dir(std::move(dir_)), contents(std::make_unique<RegisteredCache>( GetOrCreateDirectoryRelative(dir, "/Nintendo/Contents/registered"), [](const VirtualFile& file, const NcaID& id) { - return std::make_shared<NAX>(file, id)->GetDecrypted(); + return NAX{file, id}.GetDecrypted(); })) {} SDMCFactory::~SDMCFactory() = default; @@ -22,8 +22,8 @@ ResultVal<VirtualDir> SDMCFactory::Open() { return MakeResult<VirtualDir>(dir); } -std::shared_ptr<RegisteredCache> SDMCFactory::GetSDMCContents() const { - return contents; +RegisteredCache* SDMCFactory::GetSDMCContents() const { + return contents.get(); } } // namespace FileSys diff --git a/src/core/file_sys/sdmc_factory.h b/src/core/file_sys/sdmc_factory.h index ea12149de..42794ba5b 100644 --- a/src/core/file_sys/sdmc_factory.h +++ b/src/core/file_sys/sdmc_factory.h @@ -19,12 +19,12 @@ public: ~SDMCFactory(); ResultVal<VirtualDir> Open(); - std::shared_ptr<RegisteredCache> GetSDMCContents() const; + RegisteredCache* GetSDMCContents() const; private: VirtualDir dir; - std::shared_ptr<RegisteredCache> contents; + std::unique_ptr<RegisteredCache> contents; }; } // namespace FileSys diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index e961ef121..bdcc889e0 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp @@ -207,7 +207,7 @@ void RegisterModule(std::string name, VAddr beg, VAddr end, bool add_elf_ext) { static Kernel::Thread* FindThreadById(int id) { for (u32 core = 0; core < Core::NUM_CPU_CORES; core++) { - const auto& threads = Core::System::GetInstance().Scheduler(core)->GetThreadList(); + const auto& threads = Core::System::GetInstance().Scheduler(core).GetThreadList(); for (auto& thread : threads) { if (thread->GetThreadID() == static_cast<u32>(id)) { current_core = core; @@ -597,7 +597,7 @@ static void HandleQuery() { } else if (strncmp(query, "fThreadInfo", strlen("fThreadInfo")) == 0) { std::string val = "m"; for (u32 core = 0; core < Core::NUM_CPU_CORES; core++) { - const auto& threads = Core::System::GetInstance().Scheduler(core)->GetThreadList(); + const auto& threads = Core::System::GetInstance().Scheduler(core).GetThreadList(); for (const auto& thread : threads) { val += fmt::format("{:x}", thread->GetThreadID()); val += ","; @@ -612,7 +612,7 @@ static void HandleQuery() { buffer += "l<?xml version=\"1.0\"?>"; buffer += "<threads>"; for (u32 core = 0; core < Core::NUM_CPU_CORES; core++) { - const auto& threads = Core::System::GetInstance().Scheduler(core)->GetThreadList(); + const auto& threads = Core::System::GetInstance().Scheduler(core).GetThreadList(); for (const auto& thread : threads) { buffer += fmt::format(R"*(<thread id="{:x}" core="{:d}" name="Thread {:x}"></thread>)*", diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index ebf193930..57157beb4 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -39,7 +39,7 @@ static std::vector<SharedPtr<Thread>> GetThreadsWaitingOnAddress(VAddr address) std::vector<SharedPtr<Thread>>& waiting_threads, VAddr arb_addr) { const auto& scheduler = Core::System::GetInstance().Scheduler(core_index); - const auto& thread_list = scheduler->GetThreadList(); + const auto& thread_list = scheduler.GetThreadList(); for (const auto& thread : thread_list) { if (thread->GetArbiterWaitAddress() == arb_addr) diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index c80b2c507..073dd5a7d 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -153,11 +153,11 @@ void Process::PrepareForTermination() { } }; - auto& system = Core::System::GetInstance(); - stop_threads(system.Scheduler(0)->GetThreadList()); - stop_threads(system.Scheduler(1)->GetThreadList()); - stop_threads(system.Scheduler(2)->GetThreadList()); - stop_threads(system.Scheduler(3)->GetThreadList()); + const auto& system = Core::System::GetInstance(); + stop_threads(system.Scheduler(0).GetThreadList()); + stop_threads(system.Scheduler(1).GetThreadList()); + stop_threads(system.Scheduler(2).GetThreadList()); + stop_threads(system.Scheduler(3).GetThreadList()); } /** diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 3fd082550..d08b84bde 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -796,7 +796,7 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target std::vector<SharedPtr<Thread>>& waiting_threads, VAddr condvar_addr) { const auto& scheduler = Core::System::GetInstance().Scheduler(core_index); - const auto& thread_list = scheduler->GetThreadList(); + const auto& thread_list = scheduler.GetThreadList(); for (const auto& thread : thread_list) { if (thread->GetCondVarWaitAddress() == condvar_addr) diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 352ce1725..35ec98c1a 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -97,7 +97,7 @@ void Thread::CancelWakeupTimer() { static boost::optional<s32> GetNextProcessorId(u64 mask) { for (s32 index = 0; index < Core::NUM_CPU_CORES; ++index) { if (mask & (1ULL << index)) { - if (!Core::System::GetInstance().Scheduler(index)->GetCurrentThread()) { + if (!Core::System::GetInstance().Scheduler(index).GetCurrentThread()) { // Core is enabled and not running any threads, use this one return index; } @@ -147,14 +147,14 @@ void Thread::ResumeFromWait() { new_processor_id = processor_id; } if (ideal_core != -1 && - Core::System::GetInstance().Scheduler(ideal_core)->GetCurrentThread() == nullptr) { + Core::System::GetInstance().Scheduler(ideal_core).GetCurrentThread() == nullptr) { new_processor_id = ideal_core; } ASSERT(*new_processor_id < 4); // Add thread to new core's scheduler - auto& next_scheduler = Core::System::GetInstance().Scheduler(*new_processor_id); + auto* next_scheduler = &Core::System::GetInstance().Scheduler(*new_processor_id); if (*new_processor_id != processor_id) { // Remove thread from previous core's scheduler @@ -169,7 +169,7 @@ void Thread::ResumeFromWait() { next_scheduler->ScheduleThread(this, current_priority); // Change thread's scheduler - scheduler = next_scheduler.get(); + scheduler = next_scheduler; Core::System::GetInstance().CpuCore(processor_id).PrepareReschedule(); } @@ -230,7 +230,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(KernelCore& kernel, std::string name thread->name = std::move(name); thread->callback_handle = kernel.ThreadWakeupCallbackHandleTable().Create(thread).Unwrap(); thread->owner_process = &owner_process; - thread->scheduler = Core::System::GetInstance().Scheduler(processor_id).get(); + thread->scheduler = &Core::System::GetInstance().Scheduler(processor_id); thread->scheduler->AddThread(thread, priority); thread->tls_address = thread->owner_process->MarkNextAvailableTLSSlotAsUsed(*thread); @@ -375,14 +375,14 @@ void Thread::ChangeCore(u32 core, u64 mask) { new_processor_id = processor_id; } if (ideal_core != -1 && - Core::System::GetInstance().Scheduler(ideal_core)->GetCurrentThread() == nullptr) { + Core::System::GetInstance().Scheduler(ideal_core).GetCurrentThread() == nullptr) { new_processor_id = ideal_core; } ASSERT(*new_processor_id < 4); // Add thread to new core's scheduler - auto& next_scheduler = Core::System::GetInstance().Scheduler(*new_processor_id); + auto* next_scheduler = &Core::System::GetInstance().Scheduler(*new_processor_id); if (*new_processor_id != processor_id) { // Remove thread from previous core's scheduler @@ -397,7 +397,7 @@ void Thread::ChangeCore(u32 core, u64 mask) { next_scheduler->ScheduleThread(this, current_priority); // Change thread's scheduler - scheduler = next_scheduler.get(); + scheduler = next_scheduler; Core::System::GetInstance().CpuCore(processor_id).PrepareReschedule(); } diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp index 0ecfb5af1..518161bf7 100644 --- a/src/core/hle/service/aoc/aoc_u.cpp +++ b/src/core/hle/service/aoc/aoc_u.cpp @@ -7,8 +7,10 @@ #include <vector> #include "common/logging/log.h" #include "core/file_sys/content_archive.h" +#include "core/file_sys/control_metadata.h" #include "core/file_sys/nca_metadata.h" #include "core/file_sys/partition_filesystem.h" +#include "core/file_sys/patch_manager.h" #include "core/file_sys/registered_cache.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/process.h" @@ -19,7 +21,7 @@ namespace Service::AOC { constexpr u64 DLC_BASE_TITLE_ID_MASK = 0xFFFFFFFFFFFFE000; -constexpr u64 DLC_BASE_TO_AOC_ID_MASK = 0x1000; +constexpr u64 DLC_BASE_TO_AOC_ID = 0x1000; static bool CheckAOCTitleIDMatchesBase(u64 base, u64 aoc) { return (aoc & DLC_BASE_TITLE_ID_MASK) == base; @@ -97,14 +99,24 @@ void AOC_U::ListAddOnContent(Kernel::HLERequestContext& ctx) { ctx.WriteBuffer(out); - IPC::ResponseBuilder rb{ctx, 2}; + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); + rb.Push(count); } void AOC_U::GetAddOnContentBaseId(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); - rb.Push(Core::System::GetInstance().CurrentProcess()->GetTitleID() | DLC_BASE_TO_AOC_ID_MASK); + const auto title_id = Core::System::GetInstance().CurrentProcess()->GetTitleID(); + FileSys::PatchManager pm{title_id}; + + const auto res = pm.GetControlMetadata(); + if (res.first == nullptr) { + rb.Push(title_id + DLC_BASE_TO_AOC_ID); + return; + } + + rb.Push(res.first->GetDLCBaseTitleId()); } void AOC_U::PrepareAddOnContent(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 439e62d27..e32a7c48e 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -319,13 +319,12 @@ ResultVal<FileSys::VirtualDir> OpenSDMC() { return sdmc_factory->Open(); } -std::shared_ptr<FileSys::RegisteredCacheUnion> GetUnionContents() { - return std::make_shared<FileSys::RegisteredCacheUnion>( - std::vector<std::shared_ptr<FileSys::RegisteredCache>>{ - GetSystemNANDContents(), GetUserNANDContents(), GetSDMCContents()}); +std::unique_ptr<FileSys::RegisteredCacheUnion> GetUnionContents() { + return std::make_unique<FileSys::RegisteredCacheUnion>(std::vector<FileSys::RegisteredCache*>{ + GetSystemNANDContents(), GetUserNANDContents(), GetSDMCContents()}); } -std::shared_ptr<FileSys::RegisteredCache> GetSystemNANDContents() { +FileSys::RegisteredCache* GetSystemNANDContents() { LOG_TRACE(Service_FS, "Opening System NAND Contents"); if (bis_factory == nullptr) @@ -334,7 +333,7 @@ std::shared_ptr<FileSys::RegisteredCache> GetSystemNANDContents() { return bis_factory->GetSystemNANDContents(); } -std::shared_ptr<FileSys::RegisteredCache> GetUserNANDContents() { +FileSys::RegisteredCache* GetUserNANDContents() { LOG_TRACE(Service_FS, "Opening User NAND Contents"); if (bis_factory == nullptr) @@ -343,7 +342,7 @@ std::shared_ptr<FileSys::RegisteredCache> GetUserNANDContents() { return bis_factory->GetUserNANDContents(); } -std::shared_ptr<FileSys::RegisteredCache> GetSDMCContents() { +FileSys::RegisteredCache* GetSDMCContents() { LOG_TRACE(Service_FS, "Opening SDMC Contents"); if (sdmc_factory == nullptr) @@ -361,19 +360,19 @@ FileSys::VirtualDir GetModificationLoadRoot(u64 title_id) { return bis_factory->GetModificationLoadRoot(title_id); } -void CreateFactories(const FileSys::VirtualFilesystem& vfs, bool overwrite) { +void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite) { if (overwrite) { bis_factory = nullptr; save_data_factory = nullptr; sdmc_factory = nullptr; } - auto nand_directory = vfs->OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir), - FileSys::Mode::ReadWrite); - auto sd_directory = vfs->OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir), - FileSys::Mode::ReadWrite); - auto load_directory = vfs->OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::LoadDir), - FileSys::Mode::ReadWrite); + auto nand_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir), + FileSys::Mode::ReadWrite); + auto sd_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir), + FileSys::Mode::ReadWrite); + auto load_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::LoadDir), + FileSys::Mode::ReadWrite); if (bis_factory == nullptr) bis_factory = std::make_unique<FileSys::BISFactory>(nand_directory, load_directory); @@ -383,7 +382,7 @@ void CreateFactories(const FileSys::VirtualFilesystem& vfs, bool overwrite) { sdmc_factory = std::make_unique<FileSys::SDMCFactory>(std::move(sd_directory)); } -void InstallInterfaces(SM::ServiceManager& service_manager, const FileSys::VirtualFilesystem& vfs) { +void InstallInterfaces(SM::ServiceManager& service_manager, FileSys::VfsFilesystem& vfs) { romfs_factory = nullptr; CreateFactories(vfs, false); std::make_shared<FSP_LDR>()->InstallAsService(service_manager); diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index 53b01bb01..6ca5c5636 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h @@ -47,19 +47,19 @@ ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space, FileSys::SaveDataDescriptor save_struct); ResultVal<FileSys::VirtualDir> OpenSDMC(); -std::shared_ptr<FileSys::RegisteredCacheUnion> GetUnionContents(); +std::unique_ptr<FileSys::RegisteredCacheUnion> GetUnionContents(); -std::shared_ptr<FileSys::RegisteredCache> GetSystemNANDContents(); -std::shared_ptr<FileSys::RegisteredCache> GetUserNANDContents(); -std::shared_ptr<FileSys::RegisteredCache> GetSDMCContents(); +FileSys::RegisteredCache* GetSystemNANDContents(); +FileSys::RegisteredCache* GetUserNANDContents(); +FileSys::RegisteredCache* GetSDMCContents(); FileSys::VirtualDir GetModificationLoadRoot(u64 title_id); // Creates the SaveData, SDMC, and BIS Factories. Should be called once and before any function // above is called. -void CreateFactories(const FileSys::VirtualFilesystem& vfs, bool overwrite = true); +void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite = true); -void InstallInterfaces(SM::ServiceManager& service_manager, const FileSys::VirtualFilesystem& vfs); +void InstallInterfaces(SM::ServiceManager& service_manager, FileSys::VfsFilesystem& vfs); // A class that wraps a VfsDirectory with methods that return ResultVal and ResultCode instead of // pointers and booleans. This makes using a VfsDirectory with switch services much easier and diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/pl_u.cpp index 4b2f758a8..44accecb7 100644 --- a/src/core/hle/service/ns/pl_u.cpp +++ b/src/core/hle/service/ns/pl_u.cpp @@ -161,7 +161,7 @@ PL_U::PL_U() : ServiceFramework("pl:u"), impl{std::make_unique<Impl>()} { }; RegisterHandlers(functions); // Attempt to load shared font data from disk - const auto nand = FileSystem::GetSystemNANDContents(); + const auto* nand = FileSystem::GetSystemNANDContents(); std::size_t offset = 0; // Rebuild shared fonts from data ncas if (nand->HasEntry(static_cast<u64>(FontArchives::Standard), diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 62f049660..a225cb4cb 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -197,7 +197,7 @@ ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& co // Module interface /// Initialize ServiceManager -void Init(std::shared_ptr<SM::ServiceManager>& sm, const FileSys::VirtualFilesystem& rfs) { +void Init(std::shared_ptr<SM::ServiceManager>& sm, FileSys::VfsFilesystem& vfs) { // NVFlinger needs to be accessed by several services like Vi and AppletOE so we instantiate it // here and pass it into the respective InstallInterfaces functions. auto nv_flinger = std::make_shared<NVFlinger::NVFlinger>(); @@ -220,7 +220,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm, const FileSys::VirtualFilesys EUPLD::InstallInterfaces(*sm); Fatal::InstallInterfaces(*sm); FGM::InstallInterfaces(*sm); - FileSystem::InstallInterfaces(*sm, rfs); + FileSystem::InstallInterfaces(*sm, vfs); Friend::InstallInterfaces(*sm); GRC::InstallInterfaces(*sm); HID::InstallInterfaces(*sm); diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 2fc57a82e..98483ecf1 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -180,8 +180,7 @@ private: }; /// Initialize ServiceManager -void Init(std::shared_ptr<SM::ServiceManager>& sm, - const std::shared_ptr<FileSys::VfsFilesystem>& vfs); +void Init(std::shared_ptr<SM::ServiceManager>& sm, FileSys::VfsFilesystem& vfs); /// Shutdown ServiceManager void Shutdown(); diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index bbc02abcc..184537daa 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -968,6 +968,54 @@ private: rb.PushCopyObjects(vsync_event); } + enum class ConvertedScaleMode : u64 { + None = 0, // VI seems to name this as "Unknown" but lots of games pass it, assume it's no + // scaling/default + Freeze = 1, + ScaleToWindow = 2, + Crop = 3, + NoCrop = 4, + }; + + // This struct is different, currently it's 1:1 but this might change in the future. + enum class NintendoScaleMode : u32 { + None = 0, + Freeze = 1, + ScaleToWindow = 2, + Crop = 3, + NoCrop = 4, + }; + + void ConvertScalingMode(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + auto mode = rp.PopEnum<NintendoScaleMode>(); + LOG_DEBUG(Service_VI, "called mode={}", static_cast<u32>(mode)); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + switch (mode) { + case NintendoScaleMode::None: + rb.PushEnum(ConvertedScaleMode::None); + break; + case NintendoScaleMode::Freeze: + rb.PushEnum(ConvertedScaleMode::Freeze); + break; + case NintendoScaleMode::ScaleToWindow: + rb.PushEnum(ConvertedScaleMode::ScaleToWindow); + break; + case NintendoScaleMode::Crop: + rb.PushEnum(ConvertedScaleMode::Crop); + break; + case NintendoScaleMode::NoCrop: + rb.PushEnum(ConvertedScaleMode::NoCrop); + break; + default: + UNIMPLEMENTED_MSG("Unknown scaling mode {}", static_cast<u32>(mode)); + rb.PushEnum(ConvertedScaleMode::None); + break; + } + } + std::shared_ptr<NVFlinger::NVFlinger> nv_flinger; }; @@ -991,7 +1039,7 @@ IApplicationDisplayService::IApplicationDisplayService( {2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"}, {2031, &IApplicationDisplayService::DestroyStrayLayer, "DestroyStrayLayer"}, {2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"}, - {2102, nullptr, "ConvertScalingMode"}, + {2102, &IApplicationDisplayService::ConvertScalingMode, "ConvertScalingMode"}, {2450, nullptr, "GetIndirectLayerImageMap"}, {2451, nullptr, "GetIndirectLayerImageCropMap"}, {2460, nullptr, "GetIndirectLayerImageRequiredMemoryInfo"}, diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 951fd8257..8518dddcb 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp @@ -139,14 +139,22 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process) for (const auto& module : {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3", "subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"}) { const FileSys::VirtualFile module_file = dir->GetFile(module); - if (module_file != nullptr) { - const VAddr load_addr = next_load_addr; - next_load_addr = AppLoader_NSO::LoadModule(module_file, load_addr, - std::strcmp(module, "rtld") == 0, pm); - LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", module, load_addr); - // Register module with GDBStub - GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false); + if (module_file == nullptr) { + continue; } + + const VAddr load_addr = next_load_addr; + const bool should_pass_arguments = std::strcmp(module, "rtld") == 0; + const auto tentative_next_load_addr = + AppLoader_NSO::LoadModule(*module_file, load_addr, should_pass_arguments, pm); + if (!tentative_next_load_addr) { + return ResultStatus::ErrorLoadingNSO; + } + + next_load_addr = *tentative_next_load_addr; + LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", module, load_addr); + // Register module with GDBStub + GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false); } process.Run(base_address, metadata.GetMainThreadPriority(), metadata.GetMainThreadStackSize()); diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 91659ec17..9cd0b0ccd 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -93,7 +93,7 @@ std::string GetFileTypeString(FileType type) { return "unknown"; } -constexpr std::array<const char*, 59> RESULT_MESSAGES{ +constexpr std::array<const char*, 60> RESULT_MESSAGES{ "The operation completed successfully.", "The loader requested to load is already loaded.", "The operation is not implemented.", @@ -128,6 +128,7 @@ constexpr std::array<const char*, 59> RESULT_MESSAGES{ "The RomFS could not be found.", "The ELF file has incorrect size as determined by the header.", "There was a general error loading the NRO into emulated memory.", + "There was a general error loading the NSO into emulated memory.", "There is no icon available.", "There is no control data available.", "The NAX file has a bad header.", diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index 0e0333db5..e562b3a04 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h @@ -90,6 +90,7 @@ enum class ResultStatus : u16 { ErrorNoRomFS, ErrorIncorrectELFFileSize, ErrorLoadingNRO, + ErrorLoadingNSO, ErrorNoIcon, ErrorNoControl, ErrorBadNAXHeader, diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index 576fe692a..243b499f2 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp @@ -127,10 +127,10 @@ static constexpr u32 PageAlignSize(u32 size) { return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK; } -bool AppLoader_NRO::LoadNro(FileSys::VirtualFile file, VAddr load_base) { +bool AppLoader_NRO::LoadNro(const FileSys::VfsFile& file, VAddr load_base) { // Read NSO header NroHeader nro_header{}; - if (sizeof(NroHeader) != file->ReadObject(&nro_header)) { + if (sizeof(NroHeader) != file.ReadObject(&nro_header)) { return {}; } if (nro_header.magic != Common::MakeMagic('N', 'R', 'O', '0')) { @@ -138,7 +138,7 @@ bool AppLoader_NRO::LoadNro(FileSys::VirtualFile file, VAddr load_base) { } // Build program image - std::vector<u8> program_image = file->ReadBytes(PageAlignSize(nro_header.file_size)); + std::vector<u8> program_image = file.ReadBytes(PageAlignSize(nro_header.file_size)); if (program_image.size() != PageAlignSize(nro_header.file_size)) { return {}; } @@ -182,7 +182,7 @@ bool AppLoader_NRO::LoadNro(FileSys::VirtualFile file, VAddr load_base) { Core::CurrentProcess()->LoadModule(std::move(codeset), load_base); // Register module with GDBStub - GDBStub::RegisterModule(file->GetName(), load_base, load_base); + GDBStub::RegisterModule(file.GetName(), load_base, load_base); return true; } @@ -195,7 +195,7 @@ ResultStatus AppLoader_NRO::Load(Kernel::Process& process) { // Load NRO const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); - if (!LoadNro(file, base_address)) { + if (!LoadNro(*file, base_address)) { return ResultStatus::ErrorLoadingNRO; } diff --git a/src/core/loader/nro.h b/src/core/loader/nro.h index 04b46119a..50ee5a78a 100644 --- a/src/core/loader/nro.h +++ b/src/core/loader/nro.h @@ -41,7 +41,7 @@ public: bool IsRomFSUpdatable() const override; private: - bool LoadNro(FileSys::VirtualFile file, VAddr load_base); + bool LoadNro(const FileSys::VfsFile& file, VAddr load_base); std::vector<u8> icon_data; std::unique_ptr<FileSys::NACP> nacp; diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index ba57db9bf..68efca5c0 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp @@ -93,17 +93,14 @@ static constexpr u32 PageAlignSize(u32 size) { return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK; } -VAddr AppLoader_NSO::LoadModule(FileSys::VirtualFile file, VAddr load_base, - bool should_pass_arguments, - boost::optional<FileSys::PatchManager> pm) { - if (file == nullptr) - return {}; - - if (file->GetSize() < sizeof(NsoHeader)) +std::optional<VAddr> AppLoader_NSO::LoadModule(const FileSys::VfsFile& file, VAddr load_base, + bool should_pass_arguments, + std::optional<FileSys::PatchManager> pm) { + if (file.GetSize() < sizeof(NsoHeader)) return {}; NsoHeader nso_header{}; - if (sizeof(NsoHeader) != file->ReadObject(&nso_header)) + if (sizeof(NsoHeader) != file.ReadObject(&nso_header)) return {}; if (nso_header.magic != Common::MakeMagic('N', 'S', 'O', '0')) @@ -114,7 +111,7 @@ VAddr AppLoader_NSO::LoadModule(FileSys::VirtualFile file, VAddr load_base, std::vector<u8> program_image; for (std::size_t i = 0; i < nso_header.segments.size(); ++i) { std::vector<u8> data = - file->ReadBytes(nso_header.segments_compressed_size[i], nso_header.segments[i].offset); + file.ReadBytes(nso_header.segments_compressed_size[i], nso_header.segments[i].offset); if (nso_header.IsSegmentCompressed(i)) { data = DecompressSegment(data, nso_header.segments[i]); } @@ -157,7 +154,7 @@ VAddr AppLoader_NSO::LoadModule(FileSys::VirtualFile file, VAddr load_base, program_image.resize(image_size); // Apply patches if necessary - if (pm != boost::none && pm->HasNSOPatch(nso_header.build_id)) { + if (pm && pm->HasNSOPatch(nso_header.build_id)) { std::vector<u8> pi_header(program_image.size() + 0x100); std::memcpy(pi_header.data(), &nso_header, sizeof(NsoHeader)); std::memcpy(pi_header.data() + 0x100, program_image.data(), program_image.size()); @@ -172,7 +169,7 @@ VAddr AppLoader_NSO::LoadModule(FileSys::VirtualFile file, VAddr load_base, Core::CurrentProcess()->LoadModule(std::move(codeset), load_base); // Register module with GDBStub - GDBStub::RegisterModule(file->GetName(), load_base, load_base); + GDBStub::RegisterModule(file.GetName(), load_base, load_base); return load_base + image_size; } @@ -184,7 +181,9 @@ ResultStatus AppLoader_NSO::Load(Kernel::Process& process) { // Load module const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); - LoadModule(file, base_address, true); + if (!LoadModule(*file, base_address, true)) { + return ResultStatus::ErrorLoadingNSO; + } LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), base_address); process.Run(base_address, Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE); diff --git a/src/core/loader/nso.h b/src/core/loader/nso.h index 70ab3b718..433306139 100644 --- a/src/core/loader/nso.h +++ b/src/core/loader/nso.h @@ -4,6 +4,7 @@ #pragma once +#include <optional> #include "common/common_types.h" #include "core/file_sys/patch_manager.h" #include "core/loader/linker.h" @@ -36,8 +37,9 @@ public: return IdentifyType(file); } - static VAddr LoadModule(FileSys::VirtualFile file, VAddr load_base, bool should_pass_arguments, - boost::optional<FileSys::PatchManager> pm = boost::none); + static std::optional<VAddr> LoadModule(const FileSys::VfsFile& file, VAddr load_base, + bool should_pass_arguments, + std::optional<FileSys::PatchManager> pm = {}); ResultStatus Load(Kernel::Process& process) override; }; |