2018-02-25 04:34:19 -06:00
|
|
|
// Copyright 2018 yuzu emulator team
|
|
|
|
// Licensed under GPLv2 or any later version
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
2018-09-03 20:58:19 -05:00
|
|
|
#include <cstddef>
|
|
|
|
#include <vector>
|
|
|
|
|
2018-02-25 04:34:19 -06:00
|
|
|
#include "common/logging/log.h"
|
|
|
|
#include "core/file_sys/program_metadata.h"
|
|
|
|
#include "core/loader/loader.h"
|
|
|
|
|
|
|
|
namespace FileSys {
|
|
|
|
|
2018-09-19 18:19:05 -05:00
|
|
|
ProgramMetadata::ProgramMetadata() = default;
|
|
|
|
|
|
|
|
ProgramMetadata::~ProgramMetadata() = default;
|
|
|
|
|
2018-07-18 20:07:11 -05:00
|
|
|
Loader::ResultStatus ProgramMetadata::Load(VirtualFile file) {
|
2019-04-05 14:52:13 -05:00
|
|
|
const std::size_t total_size = file->GetSize();
|
|
|
|
if (total_size < sizeof(Header)) {
|
2018-08-09 20:06:44 -05:00
|
|
|
return Loader::ResultStatus::ErrorBadNPDMHeader;
|
2019-04-05 14:52:13 -05:00
|
|
|
}
|
2018-02-25 04:34:19 -06:00
|
|
|
|
2019-04-05 14:52:13 -05:00
|
|
|
if (sizeof(Header) != file->ReadObject(&npdm_header)) {
|
2018-08-09 20:06:44 -05:00
|
|
|
return Loader::ResultStatus::ErrorBadNPDMHeader;
|
2019-04-05 14:52:13 -05:00
|
|
|
}
|
2018-02-25 04:34:19 -06:00
|
|
|
|
2019-04-05 14:52:13 -05:00
|
|
|
if (sizeof(AcidHeader) != file->ReadObject(&acid_header, npdm_header.acid_offset)) {
|
2018-08-09 20:06:44 -05:00
|
|
|
return Loader::ResultStatus::ErrorBadACIDHeader;
|
2019-04-05 14:52:13 -05:00
|
|
|
}
|
2018-02-25 04:34:19 -06:00
|
|
|
|
2019-04-05 14:52:13 -05:00
|
|
|
if (sizeof(AciHeader) != file->ReadObject(&aci_header, npdm_header.aci_offset)) {
|
2018-08-09 20:06:44 -05:00
|
|
|
return Loader::ResultStatus::ErrorBadACIHeader;
|
2019-04-05 14:52:13 -05:00
|
|
|
}
|
2018-07-07 22:24:51 -05:00
|
|
|
|
2019-04-05 14:52:13 -05:00
|
|
|
if (sizeof(FileAccessControl) != file->ReadObject(&acid_file_access, acid_header.fac_offset)) {
|
2018-08-09 20:06:44 -05:00
|
|
|
return Loader::ResultStatus::ErrorBadFileAccessControl;
|
2019-04-05 14:52:13 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if (sizeof(FileAccessHeader) != file->ReadObject(&aci_file_access, aci_header.fah_offset)) {
|
2018-08-09 20:06:44 -05:00
|
|
|
return Loader::ResultStatus::ErrorBadFileAccessHeader;
|
2019-04-05 14:52:13 -05:00
|
|
|
}
|
2018-07-07 22:24:51 -05:00
|
|
|
|
2018-12-19 22:50:20 -06:00
|
|
|
aci_kernel_capabilities.resize(aci_header.kac_size / sizeof(u32));
|
|
|
|
const u64 read_size = aci_header.kac_size;
|
|
|
|
const u64 read_offset = npdm_header.aci_offset + aci_header.kac_offset;
|
|
|
|
if (file->ReadBytes(aci_kernel_capabilities.data(), read_size, read_offset) != read_size) {
|
|
|
|
return Loader::ResultStatus::ErrorBadKernelCapabilityDescriptors;
|
|
|
|
}
|
|
|
|
|
2018-02-25 04:34:19 -06:00
|
|
|
return Loader::ResultStatus::Success;
|
|
|
|
}
|
|
|
|
|
2019-06-04 23:20:26 -05:00
|
|
|
void ProgramMetadata::LoadManual(bool is_64_bit, ProgramAddressSpaceType address_space,
|
|
|
|
u8 main_thread_prio, u8 main_thread_core,
|
|
|
|
u32 main_thread_stack_size, u64 title_id,
|
|
|
|
u64 filesystem_permissions,
|
|
|
|
KernelCapabilityDescriptors capabilities) {
|
|
|
|
npdm_header.has_64_bit_instructions.Assign(is_64_bit);
|
|
|
|
npdm_header.address_space_type.Assign(address_space);
|
|
|
|
npdm_header.main_thread_priority = main_thread_prio;
|
|
|
|
npdm_header.main_thread_cpu = main_thread_core;
|
|
|
|
npdm_header.main_stack_size = main_thread_stack_size;
|
|
|
|
aci_header.title_id = title_id;
|
|
|
|
aci_file_access.permissions = filesystem_permissions;
|
|
|
|
aci_kernel_capabilities = std ::move(capabilities);
|
|
|
|
}
|
|
|
|
|
2018-02-25 04:34:19 -06:00
|
|
|
bool ProgramMetadata::Is64BitProgram() const {
|
|
|
|
return npdm_header.has_64_bit_instructions;
|
|
|
|
}
|
|
|
|
|
|
|
|
ProgramAddressSpaceType ProgramMetadata::GetAddressSpaceType() const {
|
|
|
|
return npdm_header.address_space_type;
|
|
|
|
}
|
|
|
|
|
|
|
|
u8 ProgramMetadata::GetMainThreadPriority() const {
|
|
|
|
return npdm_header.main_thread_priority;
|
|
|
|
}
|
|
|
|
|
|
|
|
u8 ProgramMetadata::GetMainThreadCore() const {
|
|
|
|
return npdm_header.main_thread_cpu;
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 ProgramMetadata::GetMainThreadStackSize() const {
|
|
|
|
return npdm_header.main_stack_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
u64 ProgramMetadata::GetTitleID() const {
|
|
|
|
return aci_header.title_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
u64 ProgramMetadata::GetFilesystemPermissions() const {
|
|
|
|
return aci_file_access.permissions;
|
|
|
|
}
|
|
|
|
|
2019-07-07 11:42:54 -05:00
|
|
|
u32 ProgramMetadata::GetSystemResourceSize() const {
|
|
|
|
return npdm_header.system_resource_size;
|
|
|
|
}
|
|
|
|
|
2018-12-19 22:50:20 -06:00
|
|
|
const ProgramMetadata::KernelCapabilityDescriptors& ProgramMetadata::GetKernelCapabilities() const {
|
|
|
|
return aci_kernel_capabilities;
|
|
|
|
}
|
|
|
|
|
2018-02-25 04:34:19 -06:00
|
|
|
void ProgramMetadata::Print() const {
|
2018-07-02 11:13:26 -05:00
|
|
|
LOG_DEBUG(Service_FS, "Magic: {:.4}", npdm_header.magic.data());
|
|
|
|
LOG_DEBUG(Service_FS, "Main thread priority: 0x{:02X}", npdm_header.main_thread_priority);
|
|
|
|
LOG_DEBUG(Service_FS, "Main thread core: {}", npdm_header.main_thread_cpu);
|
|
|
|
LOG_DEBUG(Service_FS, "Main thread stack size: 0x{:X} bytes", npdm_header.main_stack_size);
|
|
|
|
LOG_DEBUG(Service_FS, "Process category: {}", npdm_header.process_category);
|
|
|
|
LOG_DEBUG(Service_FS, "Flags: 0x{:02X}", npdm_header.flags);
|
|
|
|
LOG_DEBUG(Service_FS, " > 64-bit instructions: {}",
|
2018-07-02 11:20:50 -05:00
|
|
|
npdm_header.has_64_bit_instructions ? "YES" : "NO");
|
2018-02-25 04:34:19 -06:00
|
|
|
|
2018-12-27 18:16:43 -06:00
|
|
|
const char* address_space = "Unknown";
|
2018-02-25 04:34:19 -06:00
|
|
|
switch (npdm_header.address_space_type) {
|
2018-09-22 19:09:32 -05:00
|
|
|
case ProgramAddressSpaceType::Is36Bit:
|
2018-12-27 18:16:43 -06:00
|
|
|
address_space = "64-bit (36-bit address space)";
|
|
|
|
break;
|
2018-09-22 19:09:32 -05:00
|
|
|
case ProgramAddressSpaceType::Is39Bit:
|
2018-12-27 18:16:43 -06:00
|
|
|
address_space = "64-bit (39-bit address space)";
|
2018-02-25 04:34:19 -06:00
|
|
|
break;
|
|
|
|
case ProgramAddressSpaceType::Is32Bit:
|
|
|
|
address_space = "32-bit";
|
|
|
|
break;
|
2018-12-27 18:16:43 -06:00
|
|
|
case ProgramAddressSpaceType::Is32BitNoMap:
|
|
|
|
address_space = "32-bit (no map region)";
|
|
|
|
break;
|
2018-02-25 04:34:19 -06:00
|
|
|
}
|
|
|
|
|
2018-07-02 11:13:26 -05:00
|
|
|
LOG_DEBUG(Service_FS, " > Address space: {}\n", address_space);
|
2018-02-25 04:34:19 -06:00
|
|
|
|
|
|
|
// Begin ACID printing (potential perms, signed)
|
2018-07-02 11:13:26 -05:00
|
|
|
LOG_DEBUG(Service_FS, "Magic: {:.4}", acid_header.magic.data());
|
|
|
|
LOG_DEBUG(Service_FS, "Flags: 0x{:02X}", acid_header.flags);
|
|
|
|
LOG_DEBUG(Service_FS, " > Is Retail: {}", acid_header.is_retail ? "YES" : "NO");
|
|
|
|
LOG_DEBUG(Service_FS, "Title ID Min: 0x{:016X}", acid_header.title_id_min);
|
|
|
|
LOG_DEBUG(Service_FS, "Title ID Max: 0x{:016X}", acid_header.title_id_max);
|
|
|
|
LOG_DEBUG(Service_FS, "Filesystem Access: 0x{:016X}\n", acid_file_access.permissions);
|
2018-02-25 04:34:19 -06:00
|
|
|
|
|
|
|
// Begin ACI0 printing (actual perms, unsigned)
|
2018-07-02 11:13:26 -05:00
|
|
|
LOG_DEBUG(Service_FS, "Magic: {:.4}", aci_header.magic.data());
|
|
|
|
LOG_DEBUG(Service_FS, "Title ID: 0x{:016X}", aci_header.title_id);
|
|
|
|
LOG_DEBUG(Service_FS, "Filesystem Access: 0x{:016X}\n", aci_file_access.permissions);
|
2018-02-25 04:34:19 -06:00
|
|
|
}
|
|
|
|
} // namespace FileSys
|