// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include #include #include "common/bit_field.h" #include "common/common_funcs.h" #include "common/common_types.h" #include "common/swap.h" #include "core/file_sys/vfs/vfs_types.h" namespace Loader { enum class ResultStatus : u16; } namespace FileSys { enum class ProgramAddressSpaceType : u8 { Is32Bit = 0, Is36Bit = 1, Is32BitNoMap = 2, Is39Bit = 3, }; enum class ProgramFilePermission : u64 { MountContent = 1ULL << 0, SaveDataBackup = 1ULL << 5, SdCard = 1ULL << 21, Calibration = 1ULL << 34, Bit62 = 1ULL << 62, Everything = 1ULL << 63, }; enum class PoolPartition : u32 { Application = 0, Applet = 1, System = 2, SystemNonSecure = 3, }; /** * Helper which implements an interface to parse Program Description Metadata (NPDM) * Data can either be loaded from a file path or with data and an offset into it. */ class ProgramMetadata { public: using KernelCapabilityDescriptors = std::vector; ProgramMetadata(); ~ProgramMetadata(); ProgramMetadata(const ProgramMetadata&) = default; ProgramMetadata& operator=(const ProgramMetadata&) = default; ProgramMetadata(ProgramMetadata&&) = default; ProgramMetadata& operator=(ProgramMetadata&&) = default; /// Gets a default ProgramMetadata configuration, should only be used for homebrew formats where /// we do not have an NPDM file static ProgramMetadata GetDefault(); Loader::ResultStatus Load(VirtualFile file); Loader::ResultStatus Reload(VirtualFile file); /// Load from parameters instead of NPDM file, used for KIP void LoadManual(bool is_64_bit, ProgramAddressSpaceType address_space, s32 main_thread_prio, u32 main_thread_core, u32 main_thread_stack_size, u64 title_id, u64 filesystem_permissions, u32 system_resource_size, KernelCapabilityDescriptors capabilities); bool Is64BitProgram() const; ProgramAddressSpaceType GetAddressSpaceType() const; u8 GetMainThreadPriority() const; u8 GetMainThreadCore() const; u32 GetMainThreadStackSize() const; u64 GetTitleID() const; u64 GetFilesystemPermissions() const; u32 GetSystemResourceSize() const; PoolPartition GetPoolPartition() const; const KernelCapabilityDescriptors& GetKernelCapabilities() const; const std::array& GetName() const { return npdm_header.application_name; } void Print() const; private: struct Header { std::array magic; std::array reserved; union { u8 flags; BitField<0, 1, u8> has_64_bit_instructions; BitField<1, 3, ProgramAddressSpaceType> address_space_type; BitField<4, 4, u8> reserved_2; }; u8 reserved_3; u8 main_thread_priority; u8 main_thread_cpu; std::array reserved_4; u32_le system_resource_size; u32_le process_category; u32_le main_stack_size; std::array application_name; std::array reserved_5; u32_le aci_offset; u32_le aci_size; u32_le acid_offset; u32_le acid_size; }; static_assert(sizeof(Header) == 0x80, "NPDM header structure size is wrong"); struct AcidHeader { std::array signature; std::array nca_modulus; std::array magic; u32_le nca_size; std::array reserved; union { u32 flags; BitField<0, 1, u32> production_flag; BitField<1, 1, u32> unqualified_approval; BitField<2, 4, PoolPartition> pool_partition; }; u64_le title_id_min; u64_le title_id_max; u32_le fac_offset; u32_le fac_size; u32_le sac_offset; u32_le sac_size; u32_le kac_offset; u32_le kac_size; INSERT_PADDING_BYTES(0x8); }; static_assert(sizeof(AcidHeader) == 0x240, "ACID header structure size is wrong"); struct AciHeader { std::array magic; std::array reserved; u64_le title_id; INSERT_PADDING_BYTES(0x8); u32_le fah_offset; u32_le fah_size; u32_le sac_offset; u32_le sac_size; u32_le kac_offset; u32_le kac_size; INSERT_PADDING_BYTES(0x8); }; static_assert(sizeof(AciHeader) == 0x40, "ACI0 header structure size is wrong"); // FileAccessControl and FileAccessHeader need loaded per-component: this layout does not // reflect the real layout to avoid reference binding to misaligned addresses struct FileAccessControl { u8 version; // 3 padding bytes u64_le permissions; std::array unknown; }; struct FileAccessHeader { u8 version; // 3 padding bytes u64_le permissions; u32_le unk_offset; u32_le unk_size; u32_le unk_offset_2; u32_le unk_size_2; }; Header npdm_header{}; AciHeader aci_header{}; AcidHeader acid_header{}; FileAccessControl acid_file_access{}; FileAccessHeader aci_file_access{}; KernelCapabilityDescriptors aci_kernel_capabilities{}; }; } // namespace FileSys