diff --git a/config/SALP4Q/splits.txt b/config/SALP4Q/splits.txt index b6afe92..1112c33 100644 --- a/config/SALP4Q/splits.txt +++ b/config/SALP4Q/splits.txt @@ -133,6 +133,16 @@ Revolution/FS/fs.c: .sdata start:0x805F3878 end:0x805F3888 .sbss start:0x805F5F10 end:0x805F5F28 +Revolution/IPC/ipcMain.c: + .text start:0x803B2C50 end:0x803B2D38 + .sbss start:0x805F5F28 end:0x805F5F3C + +Revolution/IPC/ipcclt.c: + .text start:0x803B2D40 end:0x803B472C + .bss start:0x805A4800 end:0x805A48C0 + .sdata start:0x805F3888 end:0x805F3890 + .sbss start:0x805F5F40 end:0x805F5F50 + Revolution/NAND/NANDOpenClose.c: .text start:0x803B5EF0 end:0x803B63FC diff --git a/config/SALP4Q/symbols.txt b/config/SALP4Q/symbols.txt index 1d6dff7..83f2289 100644 --- a/config/SALP4Q/symbols.txt +++ b/config/SALP4Q/symbols.txt @@ -36643,7 +36643,7 @@ fn_80373A40 = .text:0x80373A40; // type:function size:0x144 fn_80373B90 = .text:0x80373B90; // type:function size:0x29C fn_80373E30 = .text:0x80373E30; // type:function size:0x18C OSSleepThread = .text:0x80373FC0; // type:function size:0xF0 scope:global -fn_803740B0 = .text:0x803740B0; // type:function size:0xF8 +OSWakeupThread = .text:0x803740B0; // type:function size:0xF8 fn_803741B0 = .text:0x803741B0; // type:function size:0xEC fn_803742A0 = .text:0x803742A0; // type:function size:0x30 fn_803742D0 = .text:0x803742D0; // type:function size:0x38 @@ -37746,17 +37746,17 @@ ISFS_Close = .text:0x803B2B20; // type:function size:0x4 ISFS_CloseAsync = .text:0x803B2B30; // type:function size:0x84 fn_803B2BC0 = .text:0x803B2BC0; // type:function size:0x90 IPCInit = .text:0x803B2C50; // type:function size:0x4C scope:global -fn_803B2CA0 = .text:0x803B2CA0; // type:function size:0x48 +IPCReInit = .text:0x803B2CA0; // type:function size:0x48 IPCReadReg = .text:0x803B2CF0; // type:function size:0x10 scope:global IPCWriteReg = .text:0x803B2D00; // type:function size:0x10 scope:global IPCGetBufferHi = .text:0x803B2D10; // type:function size:0x8 scope:global IPCGetBufferLo = .text:0x803B2D20; // type:function size:0x8 scope:global IPCSetBufferLo = .text:0x803B2D30; // type:function size:0x8 scope:global strnlen = .text:0x803B2D40; // type:function size:0x2C scope:global -fn_803B2D70 = .text:0x803B2D70; // type:function size:0x258 +IpcReplyHandler = .text:0x803B2D70; // type:function size:0x258 IPCInterruptHandler = .text:0x803B2FD0; // type:function size:0x1AC scope:local IPCCltInit = .text:0x803B3180; // type:function size:0xC0 scope:global -fn_803B3240 = .text:0x803B3240; // type:function size:0x74 +IPCCltReInit = .text:0x803B3240; // type:function size:0x74 __ios_Ipc2 = .text:0x803B32C0; // type:function size:0x240 scope:local IOS_OpenAsync = .text:0x803B3500; // type:function size:0x11C scope:global IOS_Open = .text:0x803B3620; // type:function size:0x124 scope:global @@ -37770,18 +37770,18 @@ IOS_SeekAsync = .text:0x803B3CE0; // type:function size:0xE0 IOS_Seek = .text:0x803B3DC0; // type:function size:0xE8 IOS_IoctlAsync = .text:0x803B3EB0; // type:function size:0x138 scope:global IOS_Ioctl = .text:0x803B3FF0; // type:function size:0x130 -fn_803B4120 = .text:0x803B4120; // type:function size:0x13C +__ios_Ioctlv = .text:0x803B4120; // type:function size:0x13C IOS_IoctlvAsync = .text:0x803B4260; // type:function size:0xE4 IOS_Ioctlv = .text:0x803B4350; // type:function size:0xDC scope:global -fn_803B4430 = .text:0x803B4430; // type:function size:0x2FC +IOS_IoctlvReboot = .text:0x803B4430; // type:function size:0x2FC iosCreateHeap = .text:0x803B4730; // type:function size:0x130 scope:global fn_803B4860 = .text:0x803B4860; // type:function size:0x1FC iosAllocAligned = .text:0x803B4A60; // type:function size:0x4 scope:global iosFree = .text:0x803B4A70; // type:function size:0x1E8 scope:global IPCiProfInit = .text:0x803B4C60; // type:function size:0xB8 scope:global IPCiProfQueueReq = .text:0x803B4D20; // type:function size:0x84 scope:global -fn_803B4DB0 = .text:0x803B4DB0; // type:function size:0x10 -fn_803B4DC0 = .text:0x803B4DC0; // type:function size:0x7C +IPCiProfAck = .text:0x803B4DB0; // type:function size:0x10 +IPCiProfReply = .text:0x803B4DC0; // type:function size:0x7C fn_803B4E40 = .text:0x803B4E40; // type:function size:0x108 fn_803B4F50 = .text:0x803B4F50; // type:function size:0xF0 fn_803B5040 = .text:0x803B5040; // type:function size:0x118 @@ -48272,7 +48272,7 @@ lbl_805A47C0 = .bss:0x805A47C0; // type:object size:0x10 lbl_805A47D0 = .bss:0x805A47D0; // type:object size:0x30 __responses = .bss:0x805A4800; // type:object size:0x50 scope:local data:4byte __timeout_alarm = .bss:0x805A4850; // type:object size:0x30 scope:local -lbl_805A4880 = .bss:0x805A4880; // type:object size:0x40 +__rpcBuf = .bss:0x805A4880; // type:object size:0x40 lbl_805A48C0 = .bss:0x805A48C0; // type:object size:0x80 data:4byte IpcFdArray = .bss:0x805A4940; // type:object size:0x80 scope:local data:4byte IpcReqPtrArray = .bss:0x805A49C0; // type:object size:0x80 scope:local data:4byte @@ -51297,14 +51297,14 @@ _asynCnt = .sbss:0x805F5F18; // type:object size:0x4 scope:local data:4byte @LOCAL@ISFS_OpenLib__Fv@lo = .sbss:0x805F5F1C; // type:object size:0x4 scope:weak data:4byte @LOCAL@ISFS_OpenLib__Fv@hi@0 = .sbss:0x805F5F20; // type:object size:0x4 scope:weak data:4byte hId = .sbss:0x805F5F24; // type:object size:0x4 scope:global data:4byte -lbl_805F5F28 = .sbss:0x805F5F28; // type:object size:0x1 data:byte -lbl_805F5F2C = .sbss:0x805F5F2C; // type:object size:0x4 data:4byte -lbl_805F5F30 = .sbss:0x805F5F30; // type:object size:0x4 data:4byte -lbl_805F5F34 = .sbss:0x805F5F34; // type:object size:0x4 data:4byte -lbl_805F5F38 = .sbss:0x805F5F38; // type:object size:0x8 data:4byte -lbl_805F5F40 = .sbss:0x805F5F40; // type:object size:0x4 data:4byte -lbl_805F5F44 = .sbss:0x805F5F44; // type:object size:0x4 data:4byte -lbl_805F5F48 = .sbss:0x805F5F48; // type:object size:0x4 data:4byte +Initialized = .sbss:0x805F5F28; // type:object size:0x1 scope:local data:byte +IPCCurrentBufferLo = .sbss:0x805F5F2C; // type:object size:0x4 scope:local data:4byte +IPCCurrentBufferHi = .sbss:0x805F5F30; // type:object size:0x4 scope:local data:4byte +IPCBufferLo = .sbss:0x805F5F34; // type:object size:0x4 scope:local data:4byte +IPCBufferHi = .sbss:0x805F5F38; // type:object size:0x4 scope:local data:4byte +__relnchFl = .sbss:0x805F5F40; // type:object size:0x4 scope:local data:4byte +__relnchRpc = .sbss:0x805F5F44; // type:object size:0x4 scope:local data:4byte +__relnchRpcSave = .sbss:0x805F5F48; // type:object size:0x4 scope:local data:4byte @LOCAL@IPCCltInit__Fv@initialized = .sbss:0x805F5F4C; // type:object size:0x4 scope:weak data:4byte IpcNumPendingReqs = .sbss:0x805F5F50; // type:object size:0x4 scope:local data:4byte IpcNumUnIssuedReqs = .sbss:0x805F5F54; // type:object size:0x4 scope:local data:4byte diff --git a/configure.py b/configure.py index 1936829..fbbe969 100644 --- a/configure.py +++ b/configure.py @@ -210,17 +210,18 @@ '-pragma "cats off"', '-pragma "warning off (10184)"', '-pragma "warn_notinlined off"', - '-pragma "warn_filenamecaps on"', - '-pragma "warn_filenamecaps_system on"', "-RTTI on", "-Cpp_exceptions off", - "-str noreuse", + "-str noreuse,noreadonly", "-i src", f"-i build/{config.version}/include", f"-DBUILD_VERSION={version_num}", - f"-DVERSION_{config.version}" + f"-DVERSION_{config.version}", + + "-O4,p", + "-inline auto", ] # Debug flags @@ -258,9 +259,7 @@ def MatchingFor(*versions): "mw_version": config.linker_version, "cflags": [ *cflags_base, - "-O4,p", "-lang=c99", - "-inline auto", "-func_align 4", "-rostr" ], @@ -281,9 +280,7 @@ def MatchingFor(*versions): "mw_version": config.linker_version, "cflags": [ *cflags_base, - "-O4,p", "-lang=c99", - "-d NDEBUG", "-str reuse", ], "host": False, @@ -297,6 +294,9 @@ def MatchingFor(*versions): Object(MatchingFor("SALP4Q"), "Revolution/FS/fs.c"), # GX Object(MatchingFor("SALP4Q"), "Revolution/GX/GXBump.c"), + # IPC + Object(MatchingFor("SALP4Q"), "Revolution/IPC/ipcMain.c"), + Object(MatchingFor(), "Revolution/IPC/ipcclt.c"), # NAND Object(MatchingFor("SALP4Q"), "Revolution/NAND/NANDLogging.c"), Object(MatchingFor("SALP4Q"), "Revolution/NAND/NANDOpenClose.c"), @@ -316,7 +316,6 @@ def MatchingFor(*versions): "mw_version": config.linker_version, "cflags": [ *cflags_base, - "-O4,p", "-lang=c99", "-use_lmw_stmw on", "-func_align 4" @@ -345,7 +344,6 @@ def MatchingFor(*versions): "mw_version": config.linker_version, "cflags": [ *cflags_base, - "-O4,p", "-func_align 4", "-inline all", "-fp_contract on", @@ -364,7 +362,6 @@ def MatchingFor(*versions): "mw_version": config.linker_version, "cflags": [ *cflags_base, - "-O4,p", "-func_align 4", "-inline all", "-fp_contract on", diff --git a/src/Revolution/IPC/ipcMain.c b/src/Revolution/IPC/ipcMain.c new file mode 100644 index 0000000..09bd7fd --- /dev/null +++ b/src/Revolution/IPC/ipcMain.c @@ -0,0 +1,40 @@ +#include "Revolution/IPC.h" // IWYU pragma: keep +#include "Revolution/OS.h" // IWYU pragma: keep + +static u8 Initialized = FALSE; +static void* IPCCurrentBufferLo = NULL; +static void* IPCCurrentBufferHi = NULL; +static void* IPCBufferLo = NULL; +static void* IPCBufferHi = NULL; + +void IPCInit(void) { + if (!Initialized) { + IPCBufferHi = __OSGetIPCBufferHi(); + IPCBufferLo = __OSGetIPCBufferLo(); + IPCCurrentBufferHi = IPCBufferHi; + IPCCurrentBufferLo = IPCBufferLo; + Initialized = TRUE; + } +} + +void IPCReInit(void) { + Initialized = FALSE; + IPCBufferHi = __OSGetIPCBufferHi(); + IPCBufferLo = __OSGetIPCBufferLo(); + IPCCurrentBufferHi = IPCBufferHi; + IPCCurrentBufferLo = IPCBufferLo; + Initialized = TRUE; +} + +u32 IPCReadReg(s32 index) { return IPC_HW_REGS[index]; } + +void IPCWriteReg(s32 index, u32 value) { IPC_HW_REGS[index] = value; } + +void* IPCGetBufferHi(void) { return IPCCurrentBufferHi; } + +void* IPCGetBufferLo(void) { return IPCCurrentBufferLo; } + +//unused +void IPCSetBufferHi(void* hi) { IPCCurrentBufferHi = hi; } + +void IPCSetBufferLo(void* lo) { IPCCurrentBufferLo = lo; } diff --git a/src/Revolution/IPC/ipcclt.c b/src/Revolution/IPC/ipcclt.c new file mode 100644 index 0000000..f661c0c --- /dev/null +++ b/src/Revolution/IPC/ipcclt.c @@ -0,0 +1,712 @@ +#include "Revolution/IPC.h" // IWYU pragma: keep +#include "Revolution/OS.h" // IWYU pragma: keep +#include "PowerPC_EABI_Support/MSL/MSL_C/string.h" // IWYU pragma: keep + +#define IPC_QUEUE_CAPACITY 16 +#define IPC_HEAP_SIZE_OLD 0x800 +#define IPC_HEAP_SIZE 0x1000 + +typedef struct IPCRequestQueue { + u32 sent; // at 0x0 + u32 queued; // at 0x4 + u32 front; // at 0x8 + u32 back; // at 0xC + IPCRequestEx* queue[IPC_QUEUE_CAPACITY]; // at 0x10 +} IPCRequestQueue; + +static s32 __mailboxAck = 1; +static s32 hid = -1; + +static BOOL __relnchFl = FALSE; +static IPCRequestEx* __relnchRpc = NULL; +static IPCRequestEx* __relnchRpcSave = NULL; + +static IPCRequestQueue __responses; + +static OSAlarm __timeout_alarm; + +static IPCRequestEx __rpcBuf; + +size_t strnlen(const char* s, size_t maxlen); + +size_t strnlen(const char* s, size_t maxlen) { + const u8* p = (const u8*)s; + while (*p && maxlen-- > 0) { + p++; + } + return (uintptr_t)p - (uintptr_t)s; +} + +inline IPCRequestEx* ipcAllocReq(void) { + return (IPCRequestEx*)iosAllocAligned(hid, sizeof(IPCRequestEx), 32); +} + +inline s32 ipcFree(void* block) { + iosFree(hid, block); + return IPC_RESULT_OK; +} + +inline s32 __ipcQueueRequest(IPCRequestEx* req) { + s32 ret = IPC_RESULT_OK; + s32 waiting; + + waiting = + (__responses.queued < __responses.sent) + // Difference of count + ? __responses.queued - __responses.sent + // Is queue full? + : (__responses.queued - __responses.sent) >= IPC_QUEUE_CAPACITY; + + if (waiting != 0) { + ret = IPC_RESULT_BUSY_INTERNAL; + } else { + __responses.queue[__responses.back] = req; + __responses.back = (__responses.back + 1) % IPC_QUEUE_CAPACITY; + __responses.queued++; + IPCiProfQueueReq(req, req->base.fd); + } + + return ret; +} + +inline s32 __ipcSendRequest(void) { + s32 ret = IPC_RESULT_OK; + IPCRequestEx* req; + s32 waiting; + + waiting = (__responses.queued < __responses.sent) + // Difference of sent/queued + ? __responses.queued - __responses.sent + // Are no requests waiting + : (__responses.queued - __responses.sent) == 0; + + if (waiting != 0) { + ret = IPC_RESULT_BUSY_INTERNAL; + } else { + req = __responses.queue[__responses.front]; + if (req == NULL) { + goto exit; + } + + if (req->reboot) { + __mailboxAck--; + } + + IPCWriteReg(0, (u32)OSCachedToPhysical(req)); + __responses.front = (__responses.front + 1) % IPC_QUEUE_CAPACITY; + __responses.sent++; + __mailboxAck--; + IPCWriteReg(1, (IPCReadReg(1) & 0x30) | 1); + } + +exit: + return ret; +} + +static void IpcReplyHandler(s32 intr, OSContext* ctx) { +#pragma unused(intr) + + IPCRequestEx* req; + IPCIoctlvArgs* args; + u32 reg; + OSContext temp; + int i; + + reg = IPCReadReg(2); + if (reg != 0) { + req = (IPCRequestEx*)OSPhysicalToCached(reg); + + IPCWriteReg(1, (IPCReadReg(1) & 0x30) | 4); + ACRWriteReg(0x30, 0x40000000); + DCInvalidateRange(&req->base, sizeof(IPCRequest)); + + // Not type?? + switch (req->base.fd) { + case IPC_REQ_IOCTL: + req->base.ioctl.out = + (req->base.ioctl.out != NULL) + ? OSPhysicalToCached((u32)req->base.ioctl.out) + : NULL; + + DCInvalidateRange(req->base.ioctl.in, req->base.ioctl.inSize); + DCInvalidateRange(req->base.ioctl.out, req->base.ioctl.outSize); + break; + case IPC_REQ_READ: + req->base.rw.data = (req->base.rw.data != NULL) + ? OSPhysicalToCached((u32)req->base.rw.data) + : NULL; + + if (req->base.ret > 0) { + DCInvalidateRange(req->base.rw.data, req->base.ret); + } + break; + case IPC_REQ_IOCTLV: + args = &req->base.ioctlv; + + req->base.ioctlv.vectors = + (req->base.ioctlv.vectors != NULL) + ? OSPhysicalToCached((u32)req->base.ioctlv.vectors) + : NULL; + + DCInvalidateRange(req->base.ioctlv.vectors, + (args->inCount + args->outCount) * + sizeof(IPCIOVector)); + + for (i = 0; i < args->inCount + args->outCount; i++) { + // Just trust me + i++; + i--; + + req->base.ioctlv.vectors[i].base = + (args->vectors[i].base != NULL) + ? OSPhysicalToCached((u32)args->vectors[i].base) + : NULL; + DCInvalidateRange(args->vectors[i].base, + req->base.ioctlv.vectors[i].length); + } + + if (__relnchFl && __relnchRpcSave == req) { + __relnchFl = FALSE; + if (__mailboxAck < 1) { + __mailboxAck++; + } + } + break; + } + + if (req->callback != NULL) { + OSClearContext(&temp); + OSSetCurrentContext(&temp); + req->callback(req->base.ret, req->callbackArg); + OSClearContext(&temp); + OSSetCurrentContext(ctx); + ipcFree(req); + } else { + OSWakeupThread(&req->queue); + } + + IPCWriteReg(1, (IPCReadReg(1) & 0x30) | 8); + IPCiProfReply(req, req->base.fd); + } +} + +inline void IpcAckHandler(u8 intr, OSContext* ctx) { +#pragma unused(intr) +#pragma unused(ctx) + + IPCWriteReg(1, (IPCReadReg(1) & 0x30) | 2); + ACRWriteReg(0x30, 0x40000000); + + if (__mailboxAck < 1) { + __mailboxAck++; + IPCiProfAck(); + } + + if (__mailboxAck > 0) { + if (__relnchFl) { + __relnchRpc->base.ret = IPC_RESULT_OK; + __relnchFl = FALSE; + OSWakeupThread(&__relnchRpc->queue); + IPCWriteReg(1, (IPCReadReg(1) & 0x30) | 8); + } + __ipcSendRequest(); + } +} + +static void IPCInterruptHandler(s32 intr, OSContext* ctx) { + if ((IPCReadReg(1) & 0x14) == 0x14) { + IpcReplyHandler(intr, ctx); + } + + if ((IPCReadReg(1) & 0x22) == 0x22) { + IpcAckHandler(intr, ctx); + } +} + +s32 IPCCltInit(void) { + static BOOL initialized = FALSE; + + s32 err = 0; + void* lo; + + if (!initialized) { + initialized = TRUE; + IPCInit(); + + lo = IPCGetBufferLo(); + if ((char*)lo + IPC_HEAP_SIZE > IPCGetBufferHi()) { + err = IPC_RESULT_ALLOC_FAILED; + } else { + hid = iosCreateHeap(lo, IPC_HEAP_SIZE); + IPCSetBufferLo((char*)lo + IPC_HEAP_SIZE); + __OSSetInterruptHandler(OS_INTR_PI_ACR, IPCInterruptHandler); + __OSUnmaskInterrupts(OS_INTR_MASK(OS_INTR_PI_ACR)); + IPCWriteReg(1, 0x38); + IPCiProfInit(); + OSCreateAlarm(&__timeout_alarm); + } + } + + return err; +} + + +s32 IPCCltReInit(void) { + s32 err = 0; + void* lo; + + lo = IPCGetBufferLo(); + if ((char*)lo + IPC_HEAP_SIZE_OLD > IPCGetBufferHi()) { + err = IPC_RESULT_ALLOC_FAILED; + } else { + hid = iosCreateHeap(lo, IPC_HEAP_SIZE_OLD); + IPCSetBufferLo((char*)lo + IPC_HEAP_SIZE_OLD); + } + + return err; +} + +inline s32 __ios_Ipc1(s32 fd, IPCRequestType type, IPCAsyncCallback callback, void* callbackArg, IPCRequestEx** out) +{ + IPCRequest* req; + s32 ret = IPC_RESULT_OK; + + if (out == NULL) { + ret = IPC_RESULT_INVALID_INTERNAL; + } else { + *out = ipcAllocReq(); + if (*out == NULL) { + ret = IPC_RESULT_ALLOC_FAILED; + } else { + req = &(*out)->base; + + (*out)->callback = callback; + (*out)->callbackArg = callbackArg; + (*out)->reboot = FALSE; + + req->type = type; + req->fd = fd; + } + } + + return ret; +} + +static s32 __ios_Ipc2(IPCRequestEx* req, IPCAsyncCallback callback) +{ + s32 ret = IPC_RESULT_OK; + BOOL enabled; + + if (req == NULL) { + ret = IPC_RESULT_INVALID_INTERNAL; + } else { + if (callback == NULL) { + OSInitThreadQueue(&req->queue); + } + DCFlushRange(&req->base, sizeof(IPCRequest)); + + enabled = OSDisableInterrupts(); + + ret = __ipcQueueRequest(req); + if (ret != IPC_RESULT_OK) { + OSRestoreInterrupts(enabled); + if (callback != NULL) { + ipcFree(req); + } + } else { + if (__mailboxAck > 0) { + __ipcSendRequest(); + } + + if (callback == NULL) { + OSSleepThread(&req->queue); + } + + OSRestoreInterrupts(enabled); + + if (callback == NULL) { + ret = req->base.ret; + } + } + } + + if (req != NULL && callback == NULL) { + ipcFree(req); + } + + return ret; +} + +//unused +inline void __ios_Ipc2WithTimeout() {} + +//unused +inline void __timeout_cb() {} + +inline s32 __ios_Open(IPCRequestEx* req, const char* path, IPCOpenMode mode) +{ + s32 ret = IPC_RESULT_OK; + + if (req == NULL) { + ret = IPC_RESULT_INVALID_INTERNAL; + } else { + DCFlushRange(path, strnlen(path, 64) + 1); + req->base.open.path = (const char*)OSCachedToPhysical(path); + req->base.open.mode = mode; + } + + return ret; +} + +s32 IOS_OpenAsync(const char* path, IPCOpenMode mode, IPCAsyncCallback callback, void* callbackArg) +{ + IPCRequestEx* req; + s32 ret = __ios_Ipc1(0, IPC_REQ_OPEN, callback, callbackArg, &req); + if (ret == IPC_RESULT_OK) { + ret = __ios_Open(req, path, mode); + if (ret == IPC_RESULT_OK) { + ret = __ios_Ipc2(req, callback); + } + } + + return ret; +} + +s32 IOS_Open(const char* path, IPCOpenMode mode) { + IPCRequestEx* req; + s32 ret = __ios_Ipc1(0, IPC_REQ_OPEN, NULL, NULL, &req); + if (ret == IPC_RESULT_OK) { + ret = __ios_Open(req, path, mode); + if (ret == IPC_RESULT_OK) { + ret = __ios_Ipc2(req, NULL); + } + } + + return ret; +} + +//unused +inline void IOS_OpenWithTimeout() {} + +s32 IOS_CloseAsync(s32 fd, IPCAsyncCallback callback, void* callbackArg) { + IPCRequestEx* req; + s32 ret = __ios_Ipc1(fd, IPC_REQ_CLOSE, callback, callbackArg, &req); + if (ret == IPC_RESULT_OK) { + ret = __ios_Ipc2(req, callback); + } + + return ret; +} + +s32 IOS_Close(s32 fd) { + IPCRequestEx* req; + s32 ret = __ios_Ipc1(fd, IPC_REQ_CLOSE, NULL, NULL, &req); + if (ret == IPC_RESULT_OK) { + ret = __ios_Ipc2(req, NULL); + } + + return ret; +} + +//unused +inline void IOS_CloseWithTimeout() {} + +inline s32 __ios_Read(IPCRequestEx* req, void* buf, s32 len) { + s32 ret = IPC_RESULT_OK; + + if (req == NULL) { + ret = IPC_RESULT_INVALID_INTERNAL; + } else { + DCInvalidateRange(buf, len); + req->base.rw.data = (buf != NULL) ? OSCachedToPhysical(buf) : NULL; + req->base.rw.length = len; + } + + return ret; +} + +s32 IOS_ReadAsync(s32 fd, void* buf, s32 len, IPCAsyncCallback callback, + void* callbackArg) { + IPCRequestEx* req; + s32 ret = __ios_Ipc1(fd, IPC_REQ_READ, callback, callbackArg, &req); + if (ret == IPC_RESULT_OK) { + ret = __ios_Read(req, buf, len); + if (ret == IPC_RESULT_OK) { + ret = __ios_Ipc2(req, callback); + } + } + + return ret; +} + +s32 IOS_Read(s32 fd, void* buf, s32 len) { + IPCRequestEx* req; + s32 ret = __ios_Ipc1(fd, IPC_REQ_READ, NULL, NULL, &req); + if (ret == IPC_RESULT_OK) { + ret = __ios_Read(req, buf, len); + if (ret == IPC_RESULT_OK) { + ret = __ios_Ipc2(req, NULL); + } + } + + return ret; +} + +inline s32 __ios_Write(IPCRequestEx* req, const void* buf, s32 len) { + s32 ret = IPC_RESULT_OK; + + if (req == NULL) { + ret = IPC_RESULT_INVALID_INTERNAL; + } else { + req->base.rw.data = (buf != NULL) ? OSCachedToPhysical(buf) : NULL; + req->base.rw.length = len; + DCFlushRange(buf, len); + } + + return ret; +} + +s32 IOS_WriteAsync(s32 fd, const void* buf, s32 len, IPCAsyncCallback callback, + void* callbackArg) { + IPCRequestEx* req; + s32 ret = __ios_Ipc1(fd, IPC_REQ_WRITE, callback, callbackArg, &req); + if (ret == IPC_RESULT_OK) { + ret = __ios_Write(req, buf, len); + if (ret == IPC_RESULT_OK) { + ret = __ios_Ipc2(req, callback); + } + } + + return ret; +} + +s32 IOS_Write(s32 fd, const void* buf, s32 len) { + IPCRequestEx* req; + s32 ret = __ios_Ipc1(fd, IPC_REQ_WRITE, NULL, NULL, &req); + if (ret == IPC_RESULT_OK) { + ret = __ios_Write(req, buf, len); + if (ret == IPC_RESULT_OK) { + ret = __ios_Ipc2(req, NULL); + } + } + + return ret; +} + +inline s32 __ios_Seek(IPCRequestEx* req, s32 offset, IPCSeekMode mode) { + s32 ret = IPC_RESULT_OK; + + if (req == NULL) { + ret = IPC_RESULT_INVALID_INTERNAL; + } else { + req->base.seek.offset = offset; + req->base.seek.mode = mode; + } + + return ret; +} + +s32 IOS_SeekAsync(s32 fd, s32 offset, IPCSeekMode mode, + IPCAsyncCallback callback, void* callbackArg) { + IPCRequestEx* req; + s32 ret = __ios_Ipc1(fd, IPC_REQ_SEEK, callback, callbackArg, &req); + if (ret == IPC_RESULT_OK) { + ret = __ios_Seek(req, offset, mode); + if (ret == IPC_RESULT_OK) { + ret = __ios_Ipc2(req, callback); + } + } + + return ret; +} + +s32 IOS_Seek(s32 fd, s32 offset, IPCSeekMode mode) { + IPCRequestEx* req; + s32 ret = __ios_Ipc1(fd, IPC_REQ_SEEK, NULL, NULL, &req); + if (ret == IPC_RESULT_OK) { + ret = __ios_Seek(req, offset, mode); + if (ret == IPC_RESULT_OK) { + ret = __ios_Ipc2(req, NULL); + } + } + + return ret; +} + +inline s32 __ios_Ioctl(IPCRequestEx* req, s32 type, void* in, s32 inSize, + void* out, s32 outSize) { + s32 ret = IPC_RESULT_OK; + + if (req == NULL) { + ret = IPC_RESULT_INVALID_INTERNAL; + } else { + req->base.ioctl.type = type; + req->base.ioctl.out = (out != NULL) ? OSCachedToPhysical(out) : NULL; + req->base.ioctl.outSize = outSize; + req->base.ioctl.in = (in != NULL) ? OSCachedToPhysical(in) : NULL; + req->base.ioctl.inSize = inSize; + + DCFlushRange(in, inSize); + DCFlushRange(out, outSize); + } + + return ret; +} + +s32 IOS_IoctlAsync(s32 fd, s32 type, void* in, s32 inSize, void* out, + s32 outSize, IPCAsyncCallback callback, void* callbackArg) { + IPCRequestEx* req; + s32 ret = __ios_Ipc1(fd, IPC_REQ_IOCTL, callback, callbackArg, &req); + if (ret == IPC_RESULT_OK) { + ret = __ios_Ioctl(req, type, in, inSize, out, outSize); + if (ret == IPC_RESULT_OK) { + ret = __ios_Ipc2(req, callback); + } + } + + return ret; +} + +s32 IOS_Ioctl(s32 fd, s32 type, void* in, s32 inSize, void* out, s32 outSize) { + IPCRequestEx* req; + s32 ret = __ios_Ipc1(fd, IPC_REQ_IOCTL, NULL, NULL, &req); + if (ret == IPC_RESULT_OK) { + ret = __ios_Ioctl(req, type, in, inSize, out, outSize); + if (ret == IPC_RESULT_OK) { + ret = __ios_Ipc2(req, NULL); + } + } + + return ret; +} + +static s32 __ios_Ioctlv(IPCRequestEx* req, s32 type, s32 inCount, s32 outCount, + IPCIOVector* vectors) { + int i; + s32 ret = IPC_RESULT_OK; + + if (req == NULL) { + ret = IPC_RESULT_INVALID_INTERNAL; + } else { + req->base.ioctlv.type = type; + req->base.ioctlv.inCount = inCount; + req->base.ioctlv.outCount = outCount; + req->base.ioctlv.vectors = vectors; + + for (i = 0; i < req->base.ioctlv.outCount; i++) { + DCFlushRange(req->base.ioctlv.vectors[inCount + i].base, + req->base.ioctlv.vectors[inCount + i].length); + + req->base.ioctlv.vectors[inCount + i].base = + (req->base.ioctlv.vectors[inCount + i].base != NULL) + ? OSCachedToPhysical( + req->base.ioctlv.vectors[inCount + i].base) + : NULL; + } + + for (i = 0; i < req->base.ioctlv.inCount; i++) { + DCFlushRange(req->base.ioctlv.vectors[i].base, + req->base.ioctlv.vectors[i].length); + + req->base.ioctlv.vectors[i].base = + (req->base.ioctlv.vectors[i].base != NULL) + ? OSCachedToPhysical(req->base.ioctlv.vectors[i].base) + : NULL; + } + + DCFlushRange(req->base.ioctlv.vectors, + (req->base.ioctlv.inCount + req->base.ioctlv.outCount) * + sizeof(IPCIOVector)); + + req->base.ioctlv.vectors = + (vectors != NULL) ? OSCachedToPhysical(vectors) : NULL; + } + + return ret; +} + +s32 IOS_IoctlvAsync(s32 fd, s32 type, s32 inCount, s32 outCount, + IPCIOVector* vectors, IPCAsyncCallback callback, + void* callbackArg) { + IPCRequestEx* req; + s32 ret = __ios_Ipc1(fd, IPC_REQ_IOCTLV, callback, callbackArg, &req); + if (ret == IPC_RESULT_OK) { + ret = __ios_Ioctlv(req, type, inCount, outCount, vectors); + if (ret == IPC_RESULT_OK) { + ret = __ios_Ipc2(req, callback); + } + } + + return ret; +} + +s32 IOS_Ioctlv(s32 fd, s32 type, s32 inCount, s32 outCount, + IPCIOVector* vectors) { + IPCRequestEx* req; + s32 ret = __ios_Ipc1(fd, IPC_REQ_IOCTLV, NULL, NULL, &req); + if (ret == IPC_RESULT_OK) { + ret = __ios_Ioctlv(req, type, inCount, outCount, vectors); + if (ret == IPC_RESULT_OK) { + ret = __ios_Ipc2(req, NULL); + } + } + + return ret; +} + +s32 IOS_IoctlvReboot(s32 fd, s32 type, s32 inCount, s32 outCount, IPCIOVector* vectors) { + IPCRequestEx* req; + BOOL enabled; + s32 ret; + + enabled = OSDisableInterrupts(); + + if(__relnchFl){ + OSRestoreInterrupts(enabled); + ret = -10; + }else{ + __relnchFl = TRUE; + OSRestoreInterrupts(enabled); + ret = __ios_Ipc1(fd, IPC_REQ_IOCTLV, NULL, NULL, &req); + + if (ret == IPC_RESULT_OK) { + __relnchRpcSave = req; + req->reboot = TRUE; + + ret = __ios_Ioctlv(req, type, inCount, outCount, vectors); + if (ret == IPC_RESULT_OK) { + memcpy(&__rpcBuf,req,sizeof(IPCRequestEx)); + + __relnchRpc = &__rpcBuf; + + OSInitThreadQueue(&req->queue); + DCFlushRange(&req->base, sizeof(IPCRequest)); + + enabled = OSDisableInterrupts(); + ret = __ipcQueueRequest(req); + + if (ret != IPC_RESULT_OK) { + OSRestoreInterrupts(enabled); + } else { + if (__mailboxAck > 0) { + __ipcSendRequest(); + } + + OSSleepThread(&__relnchRpc->queue); + OSRestoreInterrupts(enabled); + ret = __relnchRpc->base.ret; + } + } + } + + __relnchFl = FALSE; + __relnchRpcSave = NULL; + + if (req != NULL && ret) { + ipcFree(req); + } + + } + + return ret; +} diff --git a/src/Revolution/IPC/ipcclt.h b/src/Revolution/IPC/ipcclt.h index 60787fe..809939b 100644 --- a/src/Revolution/IPC/ipcclt.h +++ b/src/Revolution/IPC/ipcclt.h @@ -48,7 +48,7 @@ IPC_REQ_WRITE, IPC_REQ_SEEK, IPC_REQ_IOCTL, - IPC_REQ_IOCTLV + IPC_REQ_IOCTLV, } IPCRequestType; typedef enum {