5bc4eabe36
Removes all remaining usages of the global system instance. After this, migration can begin to migrate to being constructed and managed entirely by the various frontends.
104 lines
3.8 KiB
C++
104 lines
3.8 KiB
C++
// Copyright 2019 yuzu emulator team
|
|
// Licensed under GPLv2 or any later version
|
|
// Refer to the license.txt file included.
|
|
|
|
#include <cstring>
|
|
#include "core/file_sys/kernel_executable.h"
|
|
#include "core/file_sys/program_metadata.h"
|
|
#include "core/hle/kernel/code_set.h"
|
|
#include "core/hle/kernel/memory/page_table.h"
|
|
#include "core/hle/kernel/process.h"
|
|
#include "core/loader/kip.h"
|
|
#include "core/memory.h"
|
|
|
|
namespace Loader {
|
|
|
|
namespace {
|
|
constexpr u32 PageAlignSize(u32 size) {
|
|
return static_cast<u32>((size + Core::Memory::PAGE_MASK) & ~Core::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,
|
|
[[maybe_unused]] Core::System& system) {
|
|
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.PageTable().GetCodeRegionStart();
|
|
Kernel::CodeSet codeset;
|
|
Kernel::PhysicalMemory 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 + data.size());
|
|
std::memcpy(program_image.data() + offset, data.data(), data.size());
|
|
};
|
|
|
|
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();
|
|
|
|
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
|