--- /dev/null
+#pragma once
+
+#include <3ds/types.h>
+#include <3ds/exheader.h>
+
+
+/// Initialize PxiPM. Note that you must be able to access this, and few modules can.
+Result pxipmInit(void);
+
+/// Deinitialize PxiPM.
+void pxipmExit(void);
+
+/**
+ * @brief Register a program (or reregister) a program with PxiPM.
+ * @param prog_handle The program's handle
+ * @param title The program's current info
+ * @param update Information to update if re-registering
+ */
+Result PXIPM_RegisterProgram(u64 *prog_handle, FS_ProgramInfo *title, FS_ProgramInfo *update);
+
+/**
+ * @brief Get a program's information from PxiPM
+ * @param exheader Exheader to place infomation retrieved in
+ * @param prog_handle Handle to retrieve for
+ */
+Result PXIPM_GetProgramInfo(EXHEADER_header *exheader, u64 prog_handle);
+
+/**
+ * @brief Unregister a program from PxiPM.
+ * @param prog_handle Program handle to unregister for.
+ */
+Result PXIPM_UnregisterProgram(u64 prog_handle);
--- /dev/null
+#include <3ds.h>
+#include <string.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);
+}
+
+Result PXIPM_RegisterProgram(u64 *prog_handle, FS_ProgramInfo *title, FS_ProgramInfo *update)
+{
+ u32 *cmdbuf = getThreadCommandBuffer();
+
+ cmdbuf[0] = IPC_MakeHeader(0x2, 8, 0); // 0x20200
+ memcpy(&cmdbuf[1], &title->programId, sizeof(u64));
+ *(u8 *)&cmdbuf[3] = title->mediaType;
+ memcpy(((u8 *)&cmdbuf[3]) + 1, &title->padding, 7);
+ memcpy(&cmdbuf[5], &update->programId, sizeof(u64));
+ *(u8 *)&cmdbuf[7] = update->mediaType;
+ memcpy(((u8 *)&cmdbuf[7]) + 1, &update->padding, 7);
+
+ Result ret = 0;
+ if (R_FAILED(ret = svcSendSyncRequest(pxipmHandle)))
+ return ret;
+
+ *prog_handle = *(u64 *)&cmdbuf[2];
+
+ return cmdbuf[1];
+}
+
+Result PXIPM_GetProgramInfo(EXHEADER_header *exheader, u64 prog_handle)
+{
+ u32 *cmdbuf = getThreadCommandBuffer();
+
+ cmdbuf[0] = IPC_MakeHeader(0x1, 2, 2); // 0x10082
+ cmdbuf[1] = (u32)(prog_handle);
+ cmdbuf[2] = (u32)(prog_handle >> 32);
+ cmdbuf[3] = (0x400 << 8) | 0x4;
+ cmdbuf[4] = (u32)exheader;
+
+ Result ret = 0;
+ if (R_FAILED(ret = svcSendSyncRequest(pxipmHandle)))
+ return ret;
+
+ return cmdbuf[1];
+}
+
+Result PXIPM_UnregisterProgram(u64 prog_handle)
+{
+ u32 *cmdbuf = getThreadCommandBuffer();
+
+ cmdbuf[0] = IPC_MakeHeader(0x3, 2, 0); // 0x30080
+ cmdbuf[1] = (u32)(prog_handle);
+ cmdbuf[2] = (u32)(prog_handle >> 32);
+
+ Result ret = 0;
+ if (R_FAILED(ret = svcSendSyncRequest(pxipmHandle)))
+ return ret;
+
+ return cmdbuf[1];
+}