summaryrefslogtreecommitdiffstats
path: root/src/core/loader
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/loader')
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp11
-rw-r--r--src/core/loader/deconstructed_rom_directory.h6
-rw-r--r--src/core/loader/elf.cpp6
-rw-r--r--src/core/loader/loader.cpp9
-rw-r--r--src/core/loader/loader.h6
-rw-r--r--src/core/loader/nca.cpp63
-rw-r--r--src/core/loader/nca.h6
-rw-r--r--src/core/loader/nro.cpp2
-rw-r--r--src/core/loader/nro.h2
-rw-r--r--src/core/loader/nso.cpp2
-rw-r--r--src/core/loader/nso.h2
-rw-r--r--src/core/loader/xci.cpp74
-rw-r--r--src/core/loader/xci.h44
13 files changed, 179 insertions, 54 deletions
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index b0277a875..9a8cdd0ff 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -20,6 +20,10 @@ namespace Loader {
AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file)
: AppLoader(std::move(file)) {}
+AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(
+ FileSys::VirtualDir directory)
+ : AppLoader(directory->GetFile("main")), dir(std::move(directory)) {}
+
FileType AppLoader_DeconstructedRomDirectory::IdentifyType(const FileSys::VirtualFile& file) {
if (FileSys::IsDirectoryExeFS(file->GetContainingDirectory())) {
return FileType::DeconstructedRomDirectory;
@@ -34,7 +38,12 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
return ResultStatus::ErrorAlreadyLoaded;
}
- const FileSys::VirtualDir dir = file->GetContainingDirectory();
+ if (dir == nullptr) {
+ if (file == nullptr)
+ return ResultStatus::ErrorInvalidFormat;
+ dir = file->GetContainingDirectory();
+ }
+
const FileSys::VirtualFile npdm = dir->GetFile("main.npdm");
if (npdm == nullptr)
return ResultStatus::ErrorInvalidFormat;
diff --git a/src/core/loader/deconstructed_rom_directory.h b/src/core/loader/deconstructed_rom_directory.h
index 982a037f7..7d5433563 100644
--- a/src/core/loader/deconstructed_rom_directory.h
+++ b/src/core/loader/deconstructed_rom_directory.h
@@ -7,7 +7,7 @@
#include <string>
#include "common/common_types.h"
#include "core/file_sys/program_metadata.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
#include "core/loader/loader.h"
namespace Loader {
@@ -22,6 +22,9 @@ class AppLoader_DeconstructedRomDirectory final : public AppLoader {
public:
explicit AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile main_file);
+ // Overload to accept exefs directory. Must contain 'main' and 'main.npdm'
+ explicit AppLoader_DeconstructedRomDirectory(FileSys::VirtualDir directory);
+
/**
* Returns the type of the file
* @param file std::shared_ptr<VfsFile> open file
@@ -40,6 +43,7 @@ public:
private:
FileSys::ProgramMetadata metadata;
FileSys::VirtualFile romfs;
+ FileSys::VirtualDir dir;
};
} // namespace Loader
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp
index 352938dcb..a7133f5a6 100644
--- a/src/core/loader/elf.cpp
+++ b/src/core/loader/elf.cpp
@@ -311,11 +311,11 @@ SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) {
CodeSet::Segment* codeset_segment;
u32 permission_flags = p->p_flags & (PF_R | PF_W | PF_X);
if (permission_flags == (PF_R | PF_X)) {
- codeset_segment = &codeset->code;
+ codeset_segment = &codeset->CodeSegment();
} else if (permission_flags == (PF_R)) {
- codeset_segment = &codeset->rodata;
+ codeset_segment = &codeset->RODataSegment();
} else if (permission_flags == (PF_R | PF_W)) {
- codeset_segment = &codeset->data;
+ codeset_segment = &codeset->DataSegment();
} else {
LOG_ERROR(Loader, "Unexpected ELF PT_LOAD segment id {} with flags {:X}", i,
p->p_flags);
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index cbc4177c6..57e6c0365 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -13,6 +13,7 @@
#include "core/loader/nca.h"
#include "core/loader/nro.h"
#include "core/loader/nso.h"
+#include "core/loader/xci.h"
namespace Loader {
@@ -35,6 +36,7 @@ FileType IdentifyFile(FileSys::VirtualFile file) {
CHECK_TYPE(NSO)
CHECK_TYPE(NRO)
CHECK_TYPE(NCA)
+ CHECK_TYPE(XCI)
#undef CHECK_TYPE
@@ -60,6 +62,8 @@ FileType GuessFromFilename(const std::string& name) {
return FileType::NSO;
if (extension == "nca")
return FileType::NCA;
+ if (extension == "xci")
+ return FileType::XCI;
return FileType::Unknown;
}
@@ -74,6 +78,8 @@ const char* GetFileTypeString(FileType type) {
return "NSO";
case FileType::NCA:
return "NCA";
+ case FileType::XCI:
+ return "XCI";
case FileType::DeconstructedRomDirectory:
return "Directory";
case FileType::Error:
@@ -111,6 +117,9 @@ static std::unique_ptr<AppLoader> GetFileLoader(FileSys::VirtualFile file, FileT
case FileType::NCA:
return std::make_unique<AppLoader_NCA>(std::move(file));
+ case FileType::XCI:
+ return std::make_unique<AppLoader_XCI>(std::move(file));
+
// NX deconstructed ROM directory.
case FileType::DeconstructedRomDirectory:
return std::make_unique<AppLoader_DeconstructedRomDirectory>(std::move(file));
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index fbf11e5d0..e69ab85ef 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -14,7 +14,7 @@
#include "common/common_types.h"
#include "common/file_util.h"
#include "core/file_sys/vfs.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
namespace Kernel {
struct AddressMapping;
@@ -31,6 +31,7 @@ enum class FileType {
NSO,
NRO,
NCA,
+ XCI,
DeconstructedRomDirectory,
};
@@ -72,7 +73,8 @@ enum class ResultStatus {
ErrorNotUsed,
ErrorAlreadyLoaded,
ErrorMemoryAllocationFailed,
- ErrorEncrypted,
+ ErrorMissingKeys,
+ ErrorDecrypting,
ErrorUnsupportedArch,
};
diff --git a/src/core/loader/nca.cpp b/src/core/loader/nca.cpp
index c80df23be..dbc67c0b5 100644
--- a/src/core/loader/nca.cpp
+++ b/src/core/loader/nca.cpp
@@ -22,15 +22,14 @@
namespace Loader {
-AppLoader_NCA::AppLoader_NCA(FileSys::VirtualFile file) : AppLoader(std::move(file)) {}
+AppLoader_NCA::AppLoader_NCA(FileSys::VirtualFile file_)
+ : AppLoader(std::move(file_)), nca(std::make_unique<FileSys::NCA>(file)) {}
FileType AppLoader_NCA::IdentifyType(const FileSys::VirtualFile& file) {
- // TODO(DarkLordZach): Assuming everything is decrypted. Add crypto support.
- FileSys::NCAHeader header{};
- if (sizeof(FileSys::NCAHeader) != file->ReadObject(&header))
- return FileType::Error;
+ FileSys::NCA nca(file);
- if (IsValidNCA(header) && header.content_type == FileSys::NCAContentType::Program)
+ if (nca.GetStatus() == ResultStatus::Success &&
+ nca.GetType() == FileSys::NCAContentType::Program)
return FileType::NCA;
return FileType::Error;
@@ -41,8 +40,7 @@ ResultStatus AppLoader_NCA::Load(Kernel::SharedPtr<Kernel::Process>& process) {
return ResultStatus::ErrorAlreadyLoaded;
}
- nca = std::make_unique<FileSys::NCA>(file);
- ResultStatus result = nca->GetStatus();
+ const auto result = nca->GetStatus();
if (result != ResultStatus::Success) {
return result;
}
@@ -50,44 +48,16 @@ ResultStatus AppLoader_NCA::Load(Kernel::SharedPtr<Kernel::Process>& process) {
if (nca->GetType() != FileSys::NCAContentType::Program)
return ResultStatus::ErrorInvalidFormat;
- auto exefs = nca->GetExeFS();
+ const auto exefs = nca->GetExeFS();
if (exefs == nullptr)
return ResultStatus::ErrorInvalidFormat;
- result = metadata.Load(exefs->GetFile("main.npdm"));
- if (result != ResultStatus::Success) {
- return result;
- }
- metadata.Print();
-
- const FileSys::ProgramAddressSpaceType arch_bits{metadata.GetAddressSpaceType()};
- if (arch_bits == FileSys::ProgramAddressSpaceType::Is32Bit) {
- return ResultStatus::ErrorUnsupportedArch;
- }
+ directory_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(exefs);
- VAddr next_load_addr{Memory::PROCESS_IMAGE_VADDR};
- for (const auto& module : {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3",
- "subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"}) {
- const VAddr load_addr = next_load_addr;
-
- next_load_addr = AppLoader_NSO::LoadModule(exefs->GetFile(module), load_addr);
- if (next_load_addr) {
- LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", module, load_addr);
- // Register module with GDBStub
- GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false);
- } else {
- next_load_addr = load_addr;
- }
- }
-
- process->program_id = metadata.GetTitleID();
- process->svc_access_mask.set();
- process->address_mappings = default_address_mappings;
- process->resource_limit =
- Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
- process->Run(Memory::PROCESS_IMAGE_VADDR, metadata.GetMainThreadPriority(),
- metadata.GetMainThreadStackSize());
+ const auto load_result = directory_loader->Load(process);
+ if (load_result != ResultStatus::Success)
+ return load_result;
if (nca->GetRomFS() != nullptr && nca->GetRomFS()->GetSize() > 0)
Service::FileSystem::RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(*this));
@@ -98,12 +68,21 @@ ResultStatus AppLoader_NCA::Load(Kernel::SharedPtr<Kernel::Process>& process) {
}
ResultStatus AppLoader_NCA::ReadRomFS(FileSys::VirtualFile& dir) {
- if (nca == nullptr || nca->GetRomFS() == nullptr || nca->GetRomFS()->GetSize() == 0)
+ if (nca == nullptr)
+ return ResultStatus::ErrorNotLoaded;
+ if (nca->GetRomFS() == nullptr || nca->GetRomFS()->GetSize() == 0)
return ResultStatus::ErrorNotUsed;
dir = nca->GetRomFS();
return ResultStatus::Success;
}
+ResultStatus AppLoader_NCA::ReadProgramId(u64& out_program_id) {
+ if (nca == nullptr)
+ return ResultStatus::ErrorNotLoaded;
+ out_program_id = nca->GetTitleId();
+ return ResultStatus::Success;
+}
+
AppLoader_NCA::~AppLoader_NCA() = default;
} // namespace Loader
diff --git a/src/core/loader/nca.h b/src/core/loader/nca.h
index 52c95953a..0fd2d0417 100644
--- a/src/core/loader/nca.h
+++ b/src/core/loader/nca.h
@@ -8,8 +8,9 @@
#include "common/common_types.h"
#include "core/file_sys/content_archive.h"
#include "core/file_sys/program_metadata.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
#include "core/loader/loader.h"
+#include "deconstructed_rom_directory.h"
namespace Loader {
@@ -33,12 +34,15 @@ public:
ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
+ ResultStatus ReadProgramId(u64& out_program_id) override;
+
~AppLoader_NCA();
private:
FileSys::ProgramMetadata metadata;
std::unique_ptr<FileSys::NCA> nca;
+ std::unique_ptr<AppLoader_DeconstructedRomDirectory> directory_loader;
};
} // namespace Loader
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp
index 7d3ec2a76..dc053cdad 100644
--- a/src/core/loader/nro.cpp
+++ b/src/core/loader/nro.cpp
@@ -159,7 +159,7 @@ bool AppLoader_NRO::LoadNro(FileSys::VirtualFile file, VAddr load_base) {
// Resize program image to include .bss section and page align each section
bss_size = PageAlignSize(mod_header.bss_end_offset - mod_header.bss_start_offset);
}
- codeset->data.size += bss_size;
+ codeset->DataSegment().size += bss_size;
program_image.resize(static_cast<u32>(program_image.size()) + bss_size);
// Load codeset for current process
diff --git a/src/core/loader/nro.h b/src/core/loader/nro.h
index 04a0f497e..bb01c9e25 100644
--- a/src/core/loader/nro.h
+++ b/src/core/loader/nro.h
@@ -6,7 +6,7 @@
#include <string>
#include "common/common_types.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
#include "core/loader/linker.h"
#include "core/loader/loader.h"
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index 06b1b33f4..fee7d58c6 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -127,7 +127,7 @@ VAddr AppLoader_NSO::LoadModule(FileSys::VirtualFile file, VAddr load_base) {
// Resize program image to include .bss section and page align each section
bss_size = PageAlignSize(mod_header.bss_end_offset - mod_header.bss_start_offset);
}
- codeset->data.size += bss_size;
+ codeset->DataSegment().size += bss_size;
const u32 image_size{PageAlignSize(static_cast<u32>(program_image.size()) + bss_size)};
program_image.resize(image_size);
diff --git a/src/core/loader/nso.h b/src/core/loader/nso.h
index 3f7567500..aaeb1f2a9 100644
--- a/src/core/loader/nso.h
+++ b/src/core/loader/nso.h
@@ -6,7 +6,7 @@
#include <string>
#include "common/common_types.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
#include "core/loader/linker.h"
#include "core/loader/loader.h"
diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp
new file mode 100644
index 000000000..eb4dee2c2
--- /dev/null
+++ b/src/core/loader/xci.cpp
@@ -0,0 +1,74 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <vector>
+
+#include "common/file_util.h"
+#include "common/logging/log.h"
+#include "common/string_util.h"
+#include "common/swap.h"
+#include "core/core.h"
+#include "core/file_sys/content_archive.h"
+#include "core/file_sys/control_metadata.h"
+#include "core/file_sys/program_metadata.h"
+#include "core/file_sys/romfs.h"
+#include "core/gdbstub/gdbstub.h"
+#include "core/hle/kernel/process.h"
+#include "core/hle/kernel/resource_limit.h"
+#include "core/hle/service/filesystem/filesystem.h"
+#include "core/loader/nso.h"
+#include "core/loader/xci.h"
+#include "core/memory.h"
+
+namespace Loader {
+
+AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file)
+ : AppLoader(file), xci(std::make_unique<FileSys::XCI>(file)),
+ nca_loader(std::make_unique<AppLoader_NCA>(
+ xci->GetNCAFileByType(FileSys::NCAContentType::Program))) {}
+
+AppLoader_XCI::~AppLoader_XCI() = default;
+
+FileType AppLoader_XCI::IdentifyType(const FileSys::VirtualFile& file) {
+ FileSys::XCI xci(file);
+
+ if (xci.GetStatus() == ResultStatus::Success &&
+ xci.GetNCAByType(FileSys::NCAContentType::Program) != nullptr &&
+ AppLoader_NCA::IdentifyType(xci.GetNCAFileByType(FileSys::NCAContentType::Program)) ==
+ FileType::NCA) {
+ return FileType::XCI;
+ }
+
+ return FileType::Error;
+}
+
+ResultStatus AppLoader_XCI::Load(Kernel::SharedPtr<Kernel::Process>& process) {
+ if (is_loaded) {
+ return ResultStatus::ErrorAlreadyLoaded;
+ }
+
+ if (xci->GetNCAFileByType(FileSys::NCAContentType::Program) == nullptr) {
+ if (!Core::Crypto::KeyManager::KeyFileExists(false))
+ return ResultStatus::ErrorMissingKeys;
+ return ResultStatus::ErrorDecrypting;
+ }
+
+ auto result = nca_loader->Load(process);
+ if (result != ResultStatus::Success)
+ return result;
+
+ is_loaded = true;
+
+ return ResultStatus::Success;
+}
+
+ResultStatus AppLoader_XCI::ReadRomFS(FileSys::VirtualFile& dir) {
+ return nca_loader->ReadRomFS(dir);
+}
+
+ResultStatus AppLoader_XCI::ReadProgramId(u64& out_program_id) {
+ return nca_loader->ReadProgramId(out_program_id);
+}
+
+} // namespace Loader
diff --git a/src/core/loader/xci.h b/src/core/loader/xci.h
new file mode 100644
index 000000000..0dbcfbdf8
--- /dev/null
+++ b/src/core/loader/xci.h
@@ -0,0 +1,44 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <memory>
+#include "common/common_types.h"
+#include "core/file_sys/card_image.h"
+#include "core/loader/loader.h"
+#include "core/loader/nca.h"
+
+namespace Loader {
+
+/// Loads an XCI file
+class AppLoader_XCI final : public AppLoader {
+public:
+ explicit AppLoader_XCI(FileSys::VirtualFile file);
+ ~AppLoader_XCI();
+
+ /**
+ * 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() override {
+ return IdentifyType(file);
+ }
+
+ ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override;
+
+ ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
+ ResultStatus ReadProgramId(u64& out_program_id) override;
+
+private:
+ FileSys::ProgramMetadata metadata;
+
+ std::unique_ptr<FileSys::XCI> xci;
+ std::unique_ptr<AppLoader_NCA> nca_loader;
+};
+
+} // namespace Loader