From 6008e8a3563de777f7a2c651e016f50692b311af Mon Sep 17 00:00:00 2001 From: TuxSH Date: Sun, 10 Mar 2019 22:18:58 +0100 Subject: [PATCH] Implement PxiPM --- libctru/include/3ds.h | 1 + libctru/include/3ds/services/pxipm.h | 42 +++++++++++++++ libctru/source/services/pxipm.c | 79 ++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 libctru/include/3ds/services/pxipm.h create mode 100644 libctru/source/services/pxipm.c diff --git a/libctru/include/3ds.h b/libctru/include/3ds.h index 571e3e4..5691d81 100644 --- a/libctru/include/3ds.h +++ b/libctru/include/3ds.h @@ -59,6 +59,7 @@ extern "C" { #include <3ds/services/ptmu.h> #include <3ds/services/ptmsysm.h> #include <3ds/services/pxidev.h> +#include <3ds/services/pxipm.h> #include <3ds/services/soc.h> #include <3ds/services/mic.h> #include <3ds/services/mvd.h> diff --git a/libctru/include/3ds/services/pxipm.h b/libctru/include/3ds/services/pxipm.h new file mode 100644 index 0000000..8b877c6 --- /dev/null +++ b/libctru/include/3ds/services/pxipm.h @@ -0,0 +1,42 @@ +/** + * @file pxipm.h + * @brief Process Manager PXI service + */ + +#pragma once + +#include <3ds/exheader.h> +#include <3ds/services/fs.h> + +/// Initializes PxiPM. +Result pxiPmInit(void); + +/// Exits PxiPM. +void pxiPmExit(void); + +/** + * @brief Gets the current PxiPM session handle. + * @return The current PxiPM session handle. + */ +Handle *pxiPmGetSessionHandle(void); + +/** + * @brief Retrives the exheader information set(s) (SCI+ACI) about a program. + * @param exheaderInfos[out] Pointer to the output exheader information set. + * @param programHandle The program handle. + */ +Result PXIPM_GetProgramInfo(ExHeader_Info *exheaderInfo, u64 programHandle); + +/** + * @brief Loads a program and registers it to Process9. + * @param programHandle[out] Pointer to the output the program handle to. + * @param programInfo Information about the program to load. + * @param updateInfo Information about the program update to load. + */ +Result PXIPM_RegisterProgram(u64 *programHandle, const FS_ProgramInfo *programInfo, const FS_ProgramInfo *updateInfo); + +/** + * @brief Unloads a program and unregisters it from Process9. + * @param programHandle The program handle. + */ +Result PXIPM_UnregisterProgram(u64 programHandle); diff --git a/libctru/source/services/pxipm.c b/libctru/source/services/pxipm.c new file mode 100644 index 0000000..86ba765 --- /dev/null +++ b/libctru/source/services/pxipm.c @@ -0,0 +1,79 @@ +#include +#include <3ds/result.h> +#include <3ds/synchronization.h> +#include <3ds/result.h> +#include <3ds/services/pxipm.h> +#include <3ds/svc.h> +#include <3ds/srv.h> +#include <3ds/ipc.h> + +static Handle pxiPmHandle; +static int pxiPmRefCount; + +Result pxiPmInit(void) +{ + Result ret = 0; + + if (AtomicPostIncrement(&pxiPmRefCount)) return 0; + + ret = srvGetServiceHandle(&pxiPmHandle, "PxiPM"); + + if (R_FAILED(ret)) AtomicDecrement(&pxiPmRefCount); + return ret; +} + +void pxiPmExit(void) +{ + if (AtomicDecrement(&pxiPmRefCount)) return; + svcCloseHandle(pxiPmHandle); +} + +Handle *pxiPmGetSessionHandle(void) +{ + return &pxiPmHandle; +} + +Result PXIPM_GetProgramInfo(ExHeader_Info *exheaderInfo, u64 programHandle) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x1, 2, 2); // 0x10082 + cmdbuf[1] = (u32)programHandle; + cmdbuf[2] = (u32)(programHandle >> 32); + cmdbuf[3] = IPC_Desc_PXIBuffer(sizeof(ExHeader_Info), 0, false); + cmdbuf[4] = (u32)exheaderInfo; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(pxiPmHandle))) return ret; + + return cmdbuf[1]; +} + +Result PXIPM_RegisterProgram(u64 *programHandle, const FS_ProgramInfo *programInfo, const FS_ProgramInfo *updateInfo) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x2, 8, 0); // 0x20200 + memcpy(&cmdbuf[1], programInfo, sizeof(FS_ProgramInfo)); + memcpy(&cmdbuf[5], updateInfo, sizeof(FS_ProgramInfo)); + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(pxiPmHandle))) return ret; + *programHandle = ((u64)cmdbuf[3] << 32) | cmdbuf[2]; + + return cmdbuf[1]; +} + +Result PXIPM_UnregisterProgram(u64 programHandle) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x3, 2, 0); // 0x30080 + cmdbuf[1] = (u32)programHandle; + cmdbuf[2] = (u32)(programHandle >> 32); + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(pxiPmHandle))) return ret; + + return cmdbuf[1]; +}