// Copyright 2017 Citra Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. #pragma once #include #include #include #include "common/common_types.h" #include "common/swap.h" namespace Loader { enum class ResultStatus; } //////////////////////////////////////////////////////////////////////////////////////////////////// // FileSys namespace namespace FileSys { enum TMDSignatureType : u32 { Rsa4096Sha1 = 0x10000, Rsa2048Sha1 = 0x10001, EllipticSha1 = 0x10002, Rsa4096Sha256 = 0x10003, Rsa2048Sha256 = 0x10004, EcdsaSha256 = 0x10005 }; enum TMDContentTypeFlag : u16 { Encrypted = 1 << 0, Disc = 1 << 2, CFM = 1 << 3, Optional = 1 << 14, Shared = 1 << 15 }; enum TMDContentIndex { Main = 0, Manual = 1, DLP = 2 }; /** * Helper which implements an interface to read and write Title Metadata (TMD) files. * If a file path is provided and the file exists, it can be parsed and used, otherwise * it must be created. The TMD file can then be interpreted, modified and/or saved. */ class TitleMetadata { public: struct ContentChunk { u32_be id; u16_be index; u16_be type; u64_be size; std::array hash; }; static_assert(sizeof(ContentChunk) == 0x30, "TMD ContentChunk structure size is wrong"); struct ContentInfo { u16_be index; u16_be command_count; std::array hash; }; static_assert(sizeof(ContentInfo) == 0x24, "TMD ContentInfo structure size is wrong"); #pragma pack(push, 1) struct Body { std::array issuer; u8 version; u8 ca_crl_version; u8 signer_crl_version; u8 reserved; u64_be system_version; u64_be title_id; u32_be title_type; u16_be group_id; u32_be savedata_size; u32_be srl_private_savedata_size; std::array reserved_2; u8 srl_flag; std::array reserved_3; u32_be access_rights; u16_be title_version; u16_be content_count; u16_be boot_content; std::array reserved_4; std::array contentinfo_hash; std::array contentinfo; }; static_assert(sizeof(Body) == 0x9C4, "TMD body structure size is wrong"); #pragma pack(pop) Loader::ResultStatus Load(const std::string& file_path); Loader::ResultStatus Load(const std::vector file_data, size_t offset = 0); Loader::ResultStatus Save(const std::string& file_path); u64 GetTitleID() const; u32 GetTitleType() const; u16 GetTitleVersion() const; u64 GetSystemVersion() const; size_t GetContentCount() const; u32 GetBootContentID() const; u32 GetManualContentID() const; u32 GetDLPContentID() const; u32 GetContentIDByIndex(u16 index) const; u16 GetContentTypeByIndex(u16 index) const; u64 GetContentSizeByIndex(u16 index) const; void SetTitleID(u64 title_id); void SetTitleType(u32 type); void SetTitleVersion(u16 version); void SetSystemVersion(u64 version); void AddContentChunk(const ContentChunk& chunk); void Print() const; private: Body tmd_body; u32_be signature_type; std::vector tmd_signature; std::vector tmd_chunks; }; } // namespace FileSys