summaryrefslogtreecommitdiff
path: root/src/core/loader/kip.cpp
diff options
context:
space:
mode:
authorGravatar Zach Hilman2019-06-05 00:21:17 -0400
committerGravatar Zach Hilman2019-06-05 00:21:17 -0400
commitc3548967b1fbc818a495dda72ef135b71b44e002 (patch)
tree15f7acb1e34d77bfd99e07156c053055eb0be75b /src/core/loader/kip.cpp
parentprogram_metadata: Add function to load meta from raw parameters (diff)
downloadyuzu-c3548967b1fbc818a495dda72ef135b71b44e002.tar.gz
yuzu-c3548967b1fbc818a495dda72ef135b71b44e002.tar.xz
yuzu-c3548967b1fbc818a495dda72ef135b71b44e002.zip
loader: Add AppLoader_KIP for KIP files
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 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/file_sys/kernel_executable.h"
6#include "core/file_sys/program_metadata.h"
7#include "core/gdbstub/gdbstub.h"
8#include "core/hle/kernel/code_set.h"
9#include "core/hle/kernel/process.h"
10#include "core/loader/kip.h"
11
12namespace Loader {
13
14namespace {
15constexpr u32 PageAlignSize(u32 size) {
16 return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK;
17}
18} // Anonymous namespace
19
20AppLoader_KIP::AppLoader_KIP(FileSys::VirtualFile file_)
21 : AppLoader(std::move(file_)), kip(std::make_unique<FileSys::KIP>(file)) {}
22
23AppLoader_KIP::~AppLoader_KIP() = default;
24
25FileType AppLoader_KIP::IdentifyType(const FileSys::VirtualFile& file) {
26 u32_le magic{};
27 if (file->GetSize() < sizeof(u32) || file->ReadObject(&magic) != sizeof(u32)) {
28 return FileType::Error;
29 }
30
31 if (magic == Common::MakeMagic('K', 'I', 'P', '1')) {
32 return FileType::KIP;
33 }
34
35 return FileType::Error;
36}
37
38FileType AppLoader_KIP::GetFileType() const {
39 return (kip != nullptr && kip->GetStatus() == ResultStatus::Success) ? FileType::KIP
40 : FileType::Error;
41}
42
43AppLoader::LoadResult AppLoader_KIP::Load(Kernel::Process& process) {
44 if (is_loaded) {
45 return {ResultStatus::ErrorAlreadyLoaded, {}};
46 }
47
48 if (kip == nullptr) {
49 return {ResultStatus::ErrorNullFile, {}};
50 }
51
52 if (kip->GetStatus() != ResultStatus::Success) {
53 return {kip->GetStatus(), {}};
54 }
55
56 const auto address_space =
57 kip->Is64Bit() ? (kip->Is39BitAddressSpace() ? FileSys::ProgramAddressSpaceType::Is39Bit
58 : FileSys::ProgramAddressSpaceType::Is36Bit)
59 : FileSys::ProgramAddressSpaceType::Is32Bit;
60
61 FileSys::ProgramMetadata metadata;
62 metadata.LoadManual(kip->Is64Bit(), address_space, kip->GetMainThreadPriority(),
63 kip->GetMainThreadCpuCore(), kip->GetMainThreadStackSize(),
64 kip->GetTitleID(), 0xFFFFFFFFFFFFFFFF, kip->GetKernelCapabilities());
65
66 const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress();
67 Kernel::CodeSet codeset;
68 std::vector<u8> program_image;
69
70 const auto load_segment = [&program_image](Kernel::CodeSet::Segment& segment,
71 const std::vector<u8>& data, u32 offset) {
72 segment.addr = offset;
73 segment.offset = offset;
74 segment.size = PageAlignSize(static_cast<u32>(data.size()));
75 program_image.resize(offset);
76 program_image.insert(program_image.end(), data.begin(), data.end());
77 };
78
79 load_segment(codeset.CodeSegment(), kip->GetTextSection(), kip->GetTextOffset());
80 load_segment(codeset.RODataSegment(), kip->GetRODataSection(), kip->GetRODataOffset());
81 load_segment(codeset.DataSegment(), kip->GetDataSection(), kip->GetDataOffset());
82
83 program_image.resize(PageAlignSize(kip->GetBSSOffset()) + kip->GetBSSSize());
84 codeset.DataSegment().size += kip->GetBSSSize();
85
86 GDBStub::RegisterModule(kip->GetName(), base_address, base_address + program_image.size());
87
88 codeset.memory = std::move(program_image);
89 process.LoadModule(std::move(codeset), base_address);
90
91 LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", kip->GetName(), base_address);
92
93 is_loaded = true;
94 return {ResultStatus::Success,
95 LoadParameters{kip->GetMainThreadPriority(), kip->GetMainThreadStackSize()}};
96}
97
98} // namespace Loader