diff options
| author | 2019-06-05 00:21:17 -0400 | |
|---|---|---|
| committer | 2019-06-05 00:21:17 -0400 | |
| commit | c3548967b1fbc818a495dda72ef135b71b44e002 (patch) | |
| tree | 15f7acb1e34d77bfd99e07156c053055eb0be75b /src/core/loader/kip.cpp | |
| parent | program_metadata: Add function to load meta from raw parameters (diff) | |
| download | yuzu-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.cpp | 98 |
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 | |||
| 12 | namespace Loader { | ||
| 13 | |||
| 14 | namespace { | ||
| 15 | constexpr u32 PageAlignSize(u32 size) { | ||
| 16 | return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK; | ||
| 17 | } | ||
| 18 | } // Anonymous namespace | ||
| 19 | |||
| 20 | AppLoader_KIP::AppLoader_KIP(FileSys::VirtualFile file_) | ||
| 21 | : AppLoader(std::move(file_)), kip(std::make_unique<FileSys::KIP>(file)) {} | ||
| 22 | |||
| 23 | AppLoader_KIP::~AppLoader_KIP() = default; | ||
| 24 | |||
| 25 | FileType 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 | |||
| 38 | FileType AppLoader_KIP::GetFileType() const { | ||
| 39 | return (kip != nullptr && kip->GetStatus() == ResultStatus::Success) ? FileType::KIP | ||
| 40 | : FileType::Error; | ||
| 41 | } | ||
| 42 | |||
| 43 | AppLoader::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 | ||