summaryrefslogtreecommitdiffstats
path: root/src/core/loader/kip.cpp
diff options
context:
space:
mode:
authorZach Hilman <zachhilman@gmail.com>2019-06-05 06:21:17 +0200
committerZach Hilman <zachhilman@gmail.com>2019-06-05 06:21:17 +0200
commitc3548967b1fbc818a495dda72ef135b71b44e002 (patch)
tree15f7acb1e34d77bfd99e07156c053055eb0be75b /src/core/loader/kip.cpp
parentprogram_metadata: Add function to load meta from raw parameters (diff)
downloadyuzu-c3548967b1fbc818a495dda72ef135b71b44e002.tar
yuzu-c3548967b1fbc818a495dda72ef135b71b44e002.tar.gz
yuzu-c3548967b1fbc818a495dda72ef135b71b44e002.tar.bz2
yuzu-c3548967b1fbc818a495dda72ef135b71b44e002.tar.lz
yuzu-c3548967b1fbc818a495dda72ef135b71b44e002.tar.xz
yuzu-c3548967b1fbc818a495dda72ef135b71b44e002.tar.zst
yuzu-c3548967b1fbc818a495dda72ef135b71b44e002.zip
Diffstat (limited to 'src/core/loader/kip.cpp')
-rw-r--r--src/core/loader/kip.cpp98
1 files changed, 98 insertions, 0 deletions
diff --git a/src/core/loader/kip.cpp b/src/core/loader/kip.cpp
new file mode 100644
index 000000000..2efd14f04
--- /dev/null
+++ b/src/core/loader/kip.cpp
@@ -0,0 +1,98 @@
+// 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 address_space =
+ kip->Is64Bit() ? (kip->Is39BitAddressSpace() ? FileSys::ProgramAddressSpaceType::Is39Bit
+ : FileSys::ProgramAddressSpaceType::Is36Bit)
+ : FileSys::ProgramAddressSpaceType::Is32Bit;
+
+ 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