mikage-dev/source/platform/pxi.hpp
2024-03-08 10:54:13 +01:00

308 lines
9.1 KiB
C++

#pragma once
#include "ipc.hpp"
#include <functional>
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<uint8_t>(media_type) };
}
static auto IPCSerialize(const ProgramInfo& data) {
return std::make_tuple(data.program_id, static_cast<uint32_t>(data.media_type), uint32_t{});
}
using ipc_data_size = std::integral_constant<size_t, 4>;
};
/**
* 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<size_t, 2>;
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<ProgramHandle>::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<ProgramInfo>::add_serialized<ProgramInfo>
::response::add_serialized<ProgramHandle>;
using UnregisterProgram = IPC::IPCCommand<0x3>::add_serialized<ProgramHandle>
::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<Platform::PXI::PM::ProgramHandle> {
auto operator()(const Platform::PXI::PM::ProgramHandle& handle) const {
return std::hash<decltype(handle.value)>{}(handle.value);
}
};
} // namespace std