summaryrefslogtreecommitdiffstats
path: root/src/core/loader
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/loader')
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp11
-rw-r--r--src/core/loader/deconstructed_rom_directory.h4
-rw-r--r--src/core/loader/kip.cpp102
-rw-r--r--src/core/loader/kip.h35
-rw-r--r--src/core/loader/loader.cpp16
-rw-r--r--src/core/loader/loader.h11
-rw-r--r--src/core/loader/nax.cpp4
-rw-r--r--src/core/loader/nax.h2
-rw-r--r--src/core/loader/nca.cpp9
-rw-r--r--src/core/loader/nca.h2
-rw-r--r--src/core/loader/nso.cpp13
-rw-r--r--src/core/loader/nso.h5
-rw-r--r--src/core/loader/nsp.cpp4
-rw-r--r--src/core/loader/nsp.h2
-rw-r--r--src/core/loader/xci.cpp4
-rw-r--r--src/core/loader/xci.h2
16 files changed, 223 insertions, 3 deletions
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index 10b13fb1d..f9e88be2b 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -141,6 +141,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
const FileSys::PatchManager pm(metadata.GetTitleID());
// Load NSO modules
+ modules.clear();
const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress();
VAddr next_load_addr = base_address;
for (const auto& module : {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3",
@@ -159,6 +160,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
}
next_load_addr = *tentative_next_load_addr;
+ modules.insert_or_assign(load_addr, module);
LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", module, load_addr);
// Register module with GDBStub
GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false);
@@ -212,4 +214,13 @@ bool AppLoader_DeconstructedRomDirectory::IsRomFSUpdatable() const {
return false;
}
+ResultStatus AppLoader_DeconstructedRomDirectory::ReadNSOModules(Modules& modules) {
+ if (!is_loaded) {
+ return ResultStatus::ErrorNotInitialized;
+ }
+
+ modules = this->modules;
+ return ResultStatus::Success;
+}
+
} // namespace Loader
diff --git a/src/core/loader/deconstructed_rom_directory.h b/src/core/loader/deconstructed_rom_directory.h
index 1a65c16a4..1c0a354a4 100644
--- a/src/core/loader/deconstructed_rom_directory.h
+++ b/src/core/loader/deconstructed_rom_directory.h
@@ -45,6 +45,8 @@ public:
ResultStatus ReadTitle(std::string& title) override;
bool IsRomFSUpdatable() const override;
+ ResultStatus ReadNSOModules(Modules& modules) override;
+
private:
FileSys::ProgramMetadata metadata;
FileSys::VirtualFile romfs;
@@ -54,6 +56,8 @@ private:
std::string name;
u64 title_id{};
bool override_update;
+
+ Modules modules;
};
} // namespace Loader
diff --git a/src/core/loader/kip.cpp b/src/core/loader/kip.cpp
new file mode 100644
index 000000000..70051c13a
--- /dev/null
+++ b/src/core/loader/kip.cpp
@@ -0,0 +1,102 @@
+// Copyright 2019 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/file_sys/kernel_executable.h"
+#include "core/file_sys/program_metadata.h"
+#include "core/gdbstub/gdbstub.h"
+#include "core/hle/kernel/code_set.h"
+#include "core/hle/kernel/process.h"
+#include "core/loader/kip.h"
+
+namespace Loader {
+
+namespace {
+constexpr u32 PageAlignSize(u32 size) {
+ return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK;
+}
+} // Anonymous namespace
+
+AppLoader_KIP::AppLoader_KIP(FileSys::VirtualFile file_)
+ : AppLoader(std::move(file_)), kip(std::make_unique<FileSys::KIP>(file)) {}
+
+AppLoader_KIP::~AppLoader_KIP() = default;
+
+FileType AppLoader_KIP::IdentifyType(const FileSys::VirtualFile& file) {
+ u32_le magic{};
+ if (file->GetSize() < sizeof(u32) || file->ReadObject(&magic) != sizeof(u32)) {
+ return FileType::Error;
+ }
+
+ if (magic == Common::MakeMagic('K', 'I', 'P', '1')) {
+ return FileType::KIP;
+ }
+
+ return FileType::Error;
+}
+
+FileType AppLoader_KIP::GetFileType() const {
+ return (kip != nullptr && kip->GetStatus() == ResultStatus::Success) ? FileType::KIP
+ : FileType::Error;
+}
+
+AppLoader::LoadResult AppLoader_KIP::Load(Kernel::Process& process) {
+ if (is_loaded) {
+ return {ResultStatus::ErrorAlreadyLoaded, {}};
+ }
+
+ if (kip == nullptr) {
+ return {ResultStatus::ErrorNullFile, {}};
+ }
+
+ if (kip->GetStatus() != ResultStatus::Success) {
+ return {kip->GetStatus(), {}};
+ }
+
+ const auto get_kip_address_space_type = [](const auto& kip) {
+ return kip.Is64Bit()
+ ? (kip.Is39BitAddressSpace() ? FileSys::ProgramAddressSpaceType::Is39Bit
+ : FileSys::ProgramAddressSpaceType::Is36Bit)
+ : FileSys::ProgramAddressSpaceType::Is32Bit;
+ };
+
+ const auto address_space = get_kip_address_space_type(*kip);
+
+ FileSys::ProgramMetadata metadata;
+ metadata.LoadManual(kip->Is64Bit(), address_space, kip->GetMainThreadPriority(),
+ kip->GetMainThreadCpuCore(), kip->GetMainThreadStackSize(),
+ kip->GetTitleID(), 0xFFFFFFFFFFFFFFFF, kip->GetKernelCapabilities());
+
+ const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress();
+ Kernel::CodeSet codeset;
+ std::vector<u8> program_image;
+
+ const auto load_segment = [&program_image](Kernel::CodeSet::Segment& segment,
+ const std::vector<u8>& data, u32 offset) {
+ segment.addr = offset;
+ segment.offset = offset;
+ segment.size = PageAlignSize(static_cast<u32>(data.size()));
+ program_image.resize(offset);
+ program_image.insert(program_image.end(), data.begin(), data.end());
+ };
+
+ load_segment(codeset.CodeSegment(), kip->GetTextSection(), kip->GetTextOffset());
+ load_segment(codeset.RODataSegment(), kip->GetRODataSection(), kip->GetRODataOffset());
+ load_segment(codeset.DataSegment(), kip->GetDataSection(), kip->GetDataOffset());
+
+ program_image.resize(PageAlignSize(kip->GetBSSOffset()) + kip->GetBSSSize());
+ codeset.DataSegment().size += kip->GetBSSSize();
+
+ GDBStub::RegisterModule(kip->GetName(), base_address, base_address + program_image.size());
+
+ codeset.memory = std::move(program_image);
+ process.LoadModule(std::move(codeset), base_address);
+
+ LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", kip->GetName(), base_address);
+
+ is_loaded = true;
+ return {ResultStatus::Success,
+ LoadParameters{kip->GetMainThreadPriority(), kip->GetMainThreadStackSize()}};
+}
+
+} // namespace Loader
diff --git a/src/core/loader/kip.h b/src/core/loader/kip.h
new file mode 100644
index 000000000..12ca40269
--- /dev/null
+++ b/src/core/loader/kip.h
@@ -0,0 +1,35 @@
+// Copyright 2019 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/loader/loader.h"
+
+namespace FileSys {
+class KIP;
+}
+
+namespace Loader {
+
+class AppLoader_KIP final : public AppLoader {
+public:
+ explicit AppLoader_KIP(FileSys::VirtualFile file);
+ ~AppLoader_KIP() override;
+
+ /**
+ * Returns the type of the file
+ * @param file std::shared_ptr<VfsFile> open file
+ * @return FileType found, or FileType::Error if this loader doesn't know it
+ */
+ static FileType IdentifyType(const FileSys::VirtualFile& file);
+
+ FileType GetFileType() const override;
+
+ LoadResult Load(Kernel::Process& process) override;
+
+private:
+ std::unique_ptr<FileSys::KIP> kip;
+};
+
+} // namespace Loader
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index d8cc30959..59ca7091a 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -11,6 +11,7 @@
#include "core/hle/kernel/process.h"
#include "core/loader/deconstructed_rom_directory.h"
#include "core/loader/elf.h"
+#include "core/loader/kip.h"
#include "core/loader/nax.h"
#include "core/loader/nca.h"
#include "core/loader/nro.h"
@@ -36,6 +37,7 @@ FileType IdentifyFile(FileSys::VirtualFile file) {
CHECK_TYPE(XCI)
CHECK_TYPE(NAX)
CHECK_TYPE(NSP)
+ CHECK_TYPE(KIP)
#undef CHECK_TYPE
@@ -63,6 +65,8 @@ FileType GuessFromFilename(const std::string& name) {
return FileType::XCI;
if (extension == "nsp")
return FileType::NSP;
+ if (extension == "kip")
+ return FileType::KIP;
return FileType::Unknown;
}
@@ -83,6 +87,8 @@ std::string GetFileTypeString(FileType type) {
return "NAX";
case FileType::NSP:
return "NSP";
+ case FileType::KIP:
+ return "KIP";
case FileType::DeconstructedRomDirectory:
return "Directory";
case FileType::Error:
@@ -93,7 +99,7 @@ std::string GetFileTypeString(FileType type) {
return "unknown";
}
-constexpr std::array<const char*, 62> RESULT_MESSAGES{
+constexpr std::array<const char*, 66> RESULT_MESSAGES{
"The operation completed successfully.",
"The loader requested to load is already loaded.",
"The operation is not implemented.",
@@ -156,6 +162,10 @@ constexpr std::array<const char*, 62> RESULT_MESSAGES{
"The BKTR-type NCA has a bad Subsection bucket.",
"The BKTR-type NCA is missing the base RomFS.",
"The NSP or XCI does not contain an update in addition to the base game.",
+ "The KIP file has a bad header.",
+ "The KIP BLZ decompression of the section failed unexpectedly.",
+ "The INI file has a bad header.",
+ "The INI file contains more than the maximum allowable number of KIP files.",
};
std::ostream& operator<<(std::ostream& os, ResultStatus status) {
@@ -205,6 +215,10 @@ static std::unique_ptr<AppLoader> GetFileLoader(FileSys::VirtualFile file, FileT
case FileType::NSP:
return std::make_unique<AppLoader_NSP>(std::move(file));
+ // NX KIP (Kernel Internal Process) file format
+ case FileType::KIP:
+ return std::make_unique<AppLoader_KIP>(std::move(file));
+
// NX deconstructed ROM directory.
case FileType::DeconstructedRomDirectory:
return std::make_unique<AppLoader_DeconstructedRomDirectory>(std::move(file));
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index 869406b75..227ecc704 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -37,6 +37,7 @@ enum class FileType {
NSP,
XCI,
NAX,
+ KIP,
DeconstructedRomDirectory,
};
@@ -124,6 +125,10 @@ enum class ResultStatus : u16 {
ErrorBadSubsectionBuckets,
ErrorMissingBKTRBaseRomFS,
ErrorNoPackedUpdate,
+ ErrorBadKIPHeader,
+ ErrorBLZDecompressionFailed,
+ ErrorBadINIHeader,
+ ErrorINITooManyKIPs,
};
std::ostream& operator<<(std::ostream& os, ResultStatus status);
@@ -267,6 +272,12 @@ public:
return ResultStatus::ErrorNotImplemented;
}
+ using Modules = std::map<VAddr, std::string>;
+
+ virtual ResultStatus ReadNSOModules(Modules& modules) {
+ return ResultStatus::ErrorNotImplemented;
+ }
+
protected:
FileSys::VirtualFile file;
bool is_loaded = false;
diff --git a/src/core/loader/nax.cpp b/src/core/loader/nax.cpp
index 34efef09a..a152981a0 100644
--- a/src/core/loader/nax.cpp
+++ b/src/core/loader/nax.cpp
@@ -94,4 +94,8 @@ ResultStatus AppLoader_NAX::ReadLogo(std::vector<u8>& buffer) {
return nca_loader->ReadLogo(buffer);
}
+ResultStatus AppLoader_NAX::ReadNSOModules(Modules& modules) {
+ return nca_loader->ReadNSOModules(modules);
+}
+
} // namespace Loader
diff --git a/src/core/loader/nax.h b/src/core/loader/nax.h
index 00f1659c1..eaec9bf58 100644
--- a/src/core/loader/nax.h
+++ b/src/core/loader/nax.h
@@ -42,6 +42,8 @@ public:
ResultStatus ReadBanner(std::vector<u8>& buffer) override;
ResultStatus ReadLogo(std::vector<u8>& buffer) override;
+ ResultStatus ReadNSOModules(Modules& modules) override;
+
private:
std::unique_ptr<FileSys::NAX> nax;
std::unique_ptr<AppLoader_NCA> nca_loader;
diff --git a/src/core/loader/nca.cpp b/src/core/loader/nca.cpp
index b3f8f1083..0f65fb637 100644
--- a/src/core/loader/nca.cpp
+++ b/src/core/loader/nca.cpp
@@ -105,4 +105,13 @@ ResultStatus AppLoader_NCA::ReadLogo(std::vector<u8>& buffer) {
buffer = logo->GetFile("NintendoLogo.png")->ReadAllBytes();
return ResultStatus::Success;
}
+
+ResultStatus AppLoader_NCA::ReadNSOModules(Modules& modules) {
+ if (directory_loader == nullptr) {
+ return ResultStatus::ErrorNotInitialized;
+ }
+
+ return directory_loader->ReadNSOModules(modules);
+}
+
} // namespace Loader
diff --git a/src/core/loader/nca.h b/src/core/loader/nca.h
index 94f0ed677..e47dc0e47 100644
--- a/src/core/loader/nca.h
+++ b/src/core/loader/nca.h
@@ -42,6 +42,8 @@ public:
ResultStatus ReadBanner(std::vector<u8>& buffer) override;
ResultStatus ReadLogo(std::vector<u8>& buffer) override;
+ ResultStatus ReadNSOModules(Modules& modules) override;
+
private:
std::unique_ptr<FileSys::NCA> nca;
std::unique_ptr<AppLoader_DeconstructedRomDirectory> directory_loader;
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index 62c090353..29311404a 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -152,8 +152,8 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
auto& system = Core::System::GetInstance();
const auto cheats = pm->CreateCheatList(system, nso_header.build_id);
if (!cheats.empty()) {
- system.RegisterCheatList(cheats, Common::HexArrayToString(nso_header.build_id),
- load_base, load_base + program_image.size());
+ system.RegisterCheatList(cheats, Common::HexToString(nso_header.build_id), load_base,
+ load_base + program_image.size());
}
}
@@ -172,11 +172,15 @@ AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::Process& process) {
return {ResultStatus::ErrorAlreadyLoaded, {}};
}
+ modules.clear();
+
// Load module
const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress();
if (!LoadModule(process, *file, base_address, true)) {
return {ResultStatus::ErrorLoadingNSO, {}};
}
+
+ modules.insert_or_assign(base_address, file->GetName());
LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), base_address);
is_loaded = true;
@@ -184,4 +188,9 @@ AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::Process& process) {
LoadParameters{Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE}};
}
+ResultStatus AppLoader_NSO::ReadNSOModules(Modules& modules) {
+ modules = this->modules;
+ return ResultStatus::Success;
+}
+
} // namespace Loader
diff --git a/src/core/loader/nso.h b/src/core/loader/nso.h
index fdce9191c..58cbe162d 100644
--- a/src/core/loader/nso.h
+++ b/src/core/loader/nso.h
@@ -85,6 +85,11 @@ public:
std::optional<FileSys::PatchManager> pm = {});
LoadResult Load(Kernel::Process& process) override;
+
+ ResultStatus ReadNSOModules(Modules& modules) override;
+
+private:
+ Modules modules;
};
} // namespace Loader
diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp
index ad56bbb38..3a22ec2c6 100644
--- a/src/core/loader/nsp.cpp
+++ b/src/core/loader/nsp.cpp
@@ -183,4 +183,8 @@ ResultStatus AppLoader_NSP::ReadLogo(std::vector<u8>& buffer) {
return secondary_loader->ReadLogo(buffer);
}
+ResultStatus AppLoader_NSP::ReadNSOModules(Modules& modules) {
+ return secondary_loader->ReadNSOModules(modules);
+}
+
} // namespace Loader
diff --git a/src/core/loader/nsp.h b/src/core/loader/nsp.h
index 85e870bdf..868b028d3 100644
--- a/src/core/loader/nsp.h
+++ b/src/core/loader/nsp.h
@@ -49,6 +49,8 @@ public:
ResultStatus ReadBanner(std::vector<u8>& buffer) override;
ResultStatus ReadLogo(std::vector<u8>& buffer) override;
+ ResultStatus ReadNSOModules(Modules& modules) override;
+
private:
std::unique_ptr<FileSys::NSP> nsp;
std::unique_ptr<AppLoader> secondary_loader;
diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp
index 1e285a053..a5c4d3688 100644
--- a/src/core/loader/xci.cpp
+++ b/src/core/loader/xci.cpp
@@ -149,4 +149,8 @@ ResultStatus AppLoader_XCI::ReadLogo(std::vector<u8>& buffer) {
return nca_loader->ReadLogo(buffer);
}
+ResultStatus AppLoader_XCI::ReadNSOModules(Modules& modules) {
+ return nca_loader->ReadNSOModules(modules);
+}
+
} // namespace Loader
diff --git a/src/core/loader/xci.h b/src/core/loader/xci.h
index ae7145b14..618ae2f47 100644
--- a/src/core/loader/xci.h
+++ b/src/core/loader/xci.h
@@ -49,6 +49,8 @@ public:
ResultStatus ReadBanner(std::vector<u8>& buffer) override;
ResultStatus ReadLogo(std::vector<u8>& buffer) override;
+ ResultStatus ReadNSOModules(Modules& modules) override;
+
private:
std::unique_ptr<FileSys::XCI> xci;
std::unique_ptr<AppLoader_NCA> nca_loader;