From c3548967b1fbc818a495dda72ef135b71b44e002 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Wed, 5 Jun 2019 00:21:17 -0400 Subject: loader: Add AppLoader_KIP for KIP files --- src/core/loader/kip.cpp | 98 +++++++++++++++++++++++++++++++++++++++++++++++++ src/core/loader/kip.h | 35 ++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 src/core/loader/kip.cpp create mode 100644 src/core/loader/kip.h (limited to 'src/core/loader') 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(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 program_image; + + const auto load_segment = [&program_image](Kernel::CodeSet::Segment& segment, + const std::vector& data, u32 offset) { + segment.addr = offset; + segment.offset = offset; + segment.size = PageAlignSize(static_cast(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 diff --git a/src/core/loader/kip.h b/src/core/loader/kip.h new file mode 100644 index 000000000..12ca40269 --- /dev/null +++ b/src/core/loader/kip.h @@ -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 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 kip; +}; + +} // namespace Loader -- cgit v1.2.3 From a76bd4926883e0b0d5649b04779525582708331d Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Wed, 5 Jun 2019 00:21:44 -0400 Subject: loader: Add KIP and INI file parser-specific errors --- src/core/loader/loader.cpp | 6 +++++- src/core/loader/loader.h | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src/core/loader') diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index d8cc30959..8a783ae2f 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -93,7 +93,7 @@ std::string GetFileTypeString(FileType type) { return "unknown"; } -constexpr std::array RESULT_MESSAGES{ +constexpr std::array RESULT_MESSAGES{ "The operation completed successfully.", "The loader requested to load is already loaded.", "The operation is not implemented.", @@ -156,6 +156,10 @@ constexpr std::array RESULT_MESSAGES{ "The BKTR-type NCA has a bad Subsection bucket.", "The BKTR-type NCA is missing the base RomFS.", "The NSP or XCI does not contain an update in addition to the base game.", + "The KIP file has a bad header.", + "The KIP BLZ decompression of the section failed unexpectedly.", + "The INI file has a bad header.", + "The INI file contains more than the maximum allowable number of KIP files.", }; std::ostream& operator<<(std::ostream& os, ResultStatus status) { diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index f7846db52..fbca730a2 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h @@ -124,6 +124,10 @@ enum class ResultStatus : u16 { ErrorBadSubsectionBuckets, ErrorMissingBKTRBaseRomFS, ErrorNoPackedUpdate, + ErrorBadKIPHeader, + ErrorBLZDecompressionFailed, + ErrorBadINIHeader, + ErrorINITooManyKIPs, }; std::ostream& operator<<(std::ostream& os, ResultStatus status); -- cgit v1.2.3 From ce9f7ac4f2023b81e5d97a06c0fb17d252002697 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Wed, 5 Jun 2019 00:22:07 -0400 Subject: loader: Add recognition for KIP file type --- src/core/loader/loader.cpp | 10 ++++++++++ src/core/loader/loader.h | 1 + 2 files changed, 11 insertions(+) (limited to 'src/core/loader') diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 8a783ae2f..59ca7091a 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -11,6 +11,7 @@ #include "core/hle/kernel/process.h" #include "core/loader/deconstructed_rom_directory.h" #include "core/loader/elf.h" +#include "core/loader/kip.h" #include "core/loader/nax.h" #include "core/loader/nca.h" #include "core/loader/nro.h" @@ -36,6 +37,7 @@ FileType IdentifyFile(FileSys::VirtualFile file) { CHECK_TYPE(XCI) CHECK_TYPE(NAX) CHECK_TYPE(NSP) + CHECK_TYPE(KIP) #undef CHECK_TYPE @@ -63,6 +65,8 @@ FileType GuessFromFilename(const std::string& name) { return FileType::XCI; if (extension == "nsp") return FileType::NSP; + if (extension == "kip") + return FileType::KIP; return FileType::Unknown; } @@ -83,6 +87,8 @@ std::string GetFileTypeString(FileType type) { return "NAX"; case FileType::NSP: return "NSP"; + case FileType::KIP: + return "KIP"; case FileType::DeconstructedRomDirectory: return "Directory"; case FileType::Error: @@ -209,6 +215,10 @@ static std::unique_ptr GetFileLoader(FileSys::VirtualFile file, FileT case FileType::NSP: return std::make_unique(std::move(file)); + // NX KIP (Kernel Internal Process) file format + case FileType::KIP: + return std::make_unique(std::move(file)); + // NX deconstructed ROM directory. case FileType::DeconstructedRomDirectory: return std::make_unique(std::move(file)); diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index fbca730a2..4068a60f8 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h @@ -37,6 +37,7 @@ enum class FileType { NSP, XCI, NAX, + KIP, DeconstructedRomDirectory, }; -- cgit v1.2.3 From 9db119f8a2e5a4d877f00b9efb40e4a109c95ef7 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 6 Jun 2019 19:20:15 -0400 Subject: kernel_executable: Optimize BLZ decompression --- src/core/loader/kip.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src/core/loader') diff --git a/src/core/loader/kip.cpp b/src/core/loader/kip.cpp index 2efd14f04..70051c13a 100644 --- a/src/core/loader/kip.cpp +++ b/src/core/loader/kip.cpp @@ -53,10 +53,14 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::Process& process) { return {kip->GetStatus(), {}}; } - const auto address_space = - kip->Is64Bit() ? (kip->Is39BitAddressSpace() ? FileSys::ProgramAddressSpaceType::Is39Bit - : FileSys::ProgramAddressSpaceType::Is36Bit) - : FileSys::ProgramAddressSpaceType::Is32Bit; + 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(), -- cgit v1.2.3