#pragma once #include "ipc.hpp" #include namespace Platform { /** * PXI: Interprocessor communication. * This ARM11 system module implements the services used to interface the * ARM9 processor. */ namespace PXI { /** * Low-level interface for filesystem access. In contrast to the * userland-facing FS module, archives and files are identified with * module-specific uint64_t handles here. */ namespace FS { // TODO: Consider introducing a separate add_pxi_buffer tag! /** * Inputs: * - transaction * - archive handle * - path type * - path size * - open flags * - attributes * - path buffer */ using OpenFile = IPC::IPCCommand<0x1>::add_uint32::add_uint64::add_uint32::add_uint32::add_uint32::add_uint32::add_pxi_buffer ::response::add_uint64; // Response not verified /** * Inputs: * - transaction * - archive handle * - path type * - path size * - path buffer */ using DeleteFile = IPC::IPCCommand<0x2>::add_uint32::add_uint64::add_uint32::add_uint32::add_pxi_buffer_r ::response; // Response not verified /** * Inputs: * - file handle * - file offset at which to start reading * - number of bytes to read * - destination buffer * * Outputs: * - number of bytes that were successfully read */ //using ReadFile = IPC::IPCCommand<0x9>::add_uint64::add_uint64::add_uint32::add_pxi_buffer // ::response::add_uint32; // Response not verified using ReadFile = IPC::IPCCommand<0x9>::add_uint64::add_uint64::add_uint32::add_pxi_buffer ::response::add_uint32; // Response not verified /** * Fills the given buffer with the SHA256 of the given file. The implementation * need not compute this from the actual file contents but may instead load * a precomputed hash from a location that is not normally accessible through * the given file object. * * For instance, the SHA256 hashes of each section of an application's ExeFS * are included in the header, so archive 0x2345678e need not compute the * hash manually but can instead just return the hash from that header. * * Inputs: * - file handle * - size of the given PXI buffer (usually 0x20) */ using GetFileSHA256 = IPC::IPCCommand<0xa>::add_uint64::add_uint32::add_pxi_buffer ::response; // Response not verified; missing a "4" in the end /** * Inputs: * - file handle * - file offset at which to start reading * - number of bytes to read * - flush flags * - destination buffer * * Outputs: * - number of bytes that were successfully read * * Notes: * - 3dbrew has the parameter order of "number of bytes to read" and "flush flags" mixed up, it seems. */ using WriteFile = IPC::IPCCommand<0xb>::add_uint64::add_uint64::add_uint32::add_uint32::add_pxi_buffer ::response::add_uint32; // Response not verified /** * Inputs: * - file handle * - output buffer size * - input buffer size * - input buffer * - output buffer * * Outputs: * - number of bytes that were successfully read * * @todo Why does this take a file handle? It seems the MAC is solely computed from the input buffer... */ using CalcSavegameMAC = IPC::IPCCommand<0xc>::add_uint64::add_uint32::add_uint32::add_pxi_buffer::add_pxi_buffer ::response; // Response not verified /** * Inputs: * - file handle */ using GetFileSize = IPC::IPCCommand<0xd>::add_uint64 ::response::add_uint64; // Response not verified /** * Inputs: * - new size * - file handle * * @note At least for archive 0x1234567c, this leaves any appended data uninitialized */ using SetFileSize = IPC::IPCCommand<0xe>::add_uint64::add_uint64 ::response; // Response not verified /** * Inputs: * - file handle */ using CloseFile = IPC::IPCCommand<0xf>::add_uint64 ::response; // Response not verified //using OpenArchive = IPC::IPCCommand<0x12>::add_uint32::add_uint32::add_uint32::add_pxi_buffer // ::response::add_uint64; // Response not verified using OpenArchive = IPC::IPCCommand<0x12>::add_uint32::add_uint32::add_uint32::add_pxi_buffer_r ::response::add_uint64; // Response not verified using CloseArchive = IPC::IPCCommand<0x16>::add_uint64 ::response; using Unknown0x4f = IPC::IPCCommand<0x4f>::add_uint32::add_uint32 ::response; using SetPriority = IPC::IPCCommand<0x50>::add_uint32 ::response; } // namespace FS namespace PM { struct ProgramInfo { uint64_t program_id; uint8_t media_type; static auto IPCDeserialize(uint64_t program_id, uint32_t media_type, uint32_t unknown) { return ProgramInfo { program_id, static_cast(media_type) }; } static auto IPCSerialize(const ProgramInfo& data) { return std::make_tuple(data.program_id, static_cast(data.media_type), uint32_t{}); } using ipc_data_size = std::integral_constant; }; /** * Opaque handle used by PM to identify programs registered through RegisterProgram * * If the upper 32 bits of this are 0xffff0000, the raw value of this handle is * also used as the title id for Host IO (which is a feature available on dev-units). */ struct ProgramHandle { uint64_t value; static auto IPCDeserialize(uint64_t value) { return ProgramHandle { value }; } static auto IPCSerialize(const ProgramHandle& data) { return std::make_tuple(data.value); } using ipc_data_size = std::integral_constant; bool operator==(const ProgramHandle& other) const { return value == other.value; } }; /** * Retrieves the "public" part of the extended header, i.e. the SCI and the primary ACI * * Inputs: * - Program handle (returned from RegisterProgram) for the program of interest * - Target buffer for the SCI and ACI stored in the extended header */ using GetExtendedHeader = IPC::IPCCommand<0x1>::add_serialized::add_pxi_buffer ::response; /** * Inputs: * - ProgramInfo for the title to be registered * - ProgramInfo for an update title to be registered * * Outputs: * - program handle */ using RegisterProgram = IPC::IPCCommand<0x2>::add_serialized::add_serialized ::response::add_serialized; using UnregisterProgram = IPC::IPCCommand<0x3>::add_serialized ::response; } // namespace PM namespace PS { /** * Inputs: * - SHA256 hash (?) * - Size of first buffer * - Size of second buffer * - Unknown PXI buffer * - Unknown PXI buffer * * Outputs: * - Result code (0 if signature verification successfull) * - Unknown if any other outputs follow */ using VerifyRsaSha256 = IPC::IPCCommand<0x3>::add_uint32::add_uint32::add_uint32::add_uint32::add_uint32::add_uint32::add_uint32::add_uint32 ::add_uint32::add_uint32::add_pxi_buffer::add_pxi_buffer::response; } // namespace PS namespace MC { /// TODO: Remove the commented out ones. They were actually AM commands! // 3dbrew erratum: Takes one input word // using Unknown0x1 = IPC::IPCCommand<0x1>::add_uint32 // ::response; // // using Unknown0x2 = IPC::IPCCommand<0x2>::add_uint32::add_uint32::add_pxi_buffer_r // ::response; // // using Unknown0xa = IPC::IPCCommand<0xa>::add_uint32::add_uint32::add_uint32 // ::response; } // namespace MC namespace AM { /** * Returns the number of titles for the given media type * * Inputs: * - Media type * * Outputs: * - Title count */ using GetTitleCount = IPC::IPCCommand<0x1>::add_uint32 ::response::add_uint32; /** * Retrieves the list of all title IDs for the given media type * * Inputs: * - Number of titles to get information from (usually to be queried via * GetTitleCount first) * - Media type * - Output buffer that is large enough to hold 8 * the requested number of titles * * Outputs: * - Number of titles for which information was stored in the output buffer */ using GetTitleList = IPC::IPCCommand<0x2>::add_uint32::add_uint32::add_pxi_buffer_r ::response::add_uint32; /** * Retrieves the list of all title IDs for the given media type * * Inputs: * - Media type * - Number of titles to get information from (usually to be queried via * GetTitleCount first) * - Input buffer that holds title IDs for the titles to get information of * - Output buffer that is large enough to hold 0x18 * the requested number of titles */ using GetTitleInfos = IPC::IPCCommand<0x3>::add_uint32::add_uint32::add_pxi_buffer_r::add_pxi_buffer ::response; } // namespace AM } // namespace PXI } // namespace Platform // Implement std::hash for use in unordered containers namespace std { template<> struct hash { auto operator()(const Platform::PXI::PM::ProgramHandle& handle) const { return std::hash{}(handle.value); } }; } // namespace std