loader: Add AppLoader_KIP for KIP files
This commit is contained in:
parent
b550a01f74
commit
c3548967b1
3 changed files with 135 additions and 0 deletions
|
@ -437,6 +437,8 @@ add_library(core STATIC
|
|||
loader/deconstructed_rom_directory.h
|
||||
loader/elf.cpp
|
||||
loader/elf.h
|
||||
loader/kip.cpp
|
||||
loader/kip.h
|
||||
loader/loader.cpp
|
||||
loader/loader.h
|
||||
loader/nax.cpp
|
||||
|
|
98
src/core/loader/kip.cpp
Normal file
98
src/core/loader/kip.cpp
Normal file
|
@ -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
|
35
src/core/loader/kip.h
Normal file
35
src/core/loader/kip.h
Normal file
|
@ -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
|
Loading…
Reference in a new issue