diff --git a/orbis-kernel/src/sys/sys_generic.cpp b/orbis-kernel/src/sys/sys_generic.cpp index 2baa58eb8..970dcb281 100644 --- a/orbis-kernel/src/sys/sys_generic.cpp +++ b/orbis-kernel/src/sys/sys_generic.cpp @@ -1,6 +1,7 @@ #include "orbis/utils/Logs.hpp" #include "sys/sysproto.hpp" #include "uio.hpp" +#include orbis::SysResult orbis::sys_read(Thread *thread, sint fd, ptr buf, size_t nbyte) { @@ -292,9 +293,129 @@ orbis::SysResult orbis::sys_freebsd6_ftruncate(Thread *thread, sint fd, sint, off_t length) { return sys_ftruncate(thread, fd, length); } +// clang-format off +#define IOCPARM_SHIFT 13 /* number of bits for ioctl size */ +#define IOCPARM_MASK ((1 << IOCPARM_SHIFT) - 1) /* parameter length mask */ +#define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK) +#define IOCBASECMD(x) ((x) & ~(IOCPARM_MASK << 16)) +#define IOCGROUP(x) (((x) >> 8) & 0xff) + +#define IOCPARM_MAX (1 << IOCPARM_SHIFT) /* max size of ioctl */ +#define IOC_VOID 0x20000000 /* no parameters */ +#define IOC_OUT 0x40000000 /* copy out parameters */ +#define IOC_IN 0x80000000 /* copy in parameters */ +#define IOC_INOUT (IOC_IN | IOC_OUT) +#define IOC_DIRMASK (IOC_VOID | IOC_OUT | IOC_IN) + +#define _IOC(inout, group, num, len) \ + ((unsigned long)((inout) | (((len) & IOCPARM_MASK) << 16) | ((group) << 8) | \ + (num))) +#define _IO(g, n) _IOC(IOC_VOID, (g), (n), 0) +#define _IOWINT(g, n) _IOC(IOC_VOID, (g), (n), sizeof(int)) +#define _IOR(g, n, t) _IOC(IOC_OUT, (g), (n), sizeof(t)) +#define _IOW(g, n, t) _IOC(IOC_IN, (g), (n), sizeof(t)) +/* this should be _IORW, but stdio got there first */ +#define _IOWR(g, n, t) _IOC(IOC_INOUT, (g), (n), sizeof(t)) +// clang-format on + +static std::string iocGroupToString(unsigned iocGroup) { + if (iocGroup >= 128) { + const char *sceGroups[] = { + "DEV", + "DMEM", + "GC", + "DCE", + "UVD", + "VCE", + "DBGGC", + "TWSI", + "MDBG", + "DEVENV", + "AJM", + "TRACE", + "IBS", + "MBUS", + "HDMI", + "CAMERA", + "FAN", + "THERMAL", + "PFS", + "ICC_CONFIG", + "IPC", + "IOSCHED", + "ICC_INDICATOR", + "EXFATFS", + "ICC_NVS", + "DVE", + "ICC_POWER", + "AV_CONTROL", + "ICC_SC_CONFIGURATION", + "ICC_DEVICE_POWER", + "SSHOT", + "DCE_SCANIN", + "FSCTRL", + "HMD", + "SHM", + "PHYSHM", + "HMDDFU", + "BLUETOOTH_HID", + "SBI", + "S3DA", + "SPM", + "BLOCKPOOL", + "SDK_EVENTLOG", + }; + + if (iocGroup - 127 >= std::size(sceGroups)) { + return "'?'"; + } + + return sceGroups[iocGroup - 127]; + } + + if (isprint(iocGroup)) { + return "'" + std::string(1, (char)iocGroup) + "'"; + } + + return "'?'"; +} + +static void printIoctl(unsigned long arg) { + std::printf("0x%lx { IO%s%s %lu(%s), %lu, %lu }\n", arg, + arg & IOC_OUT ? "R" : "", arg & IOC_IN ? "W" : "", IOCGROUP(arg), + iocGroupToString(IOCGROUP(arg)).c_str(), arg & 0xFF, + IOCPARM_LEN(arg)); +} + +static void ioctlToStream(std::ostream &stream, unsigned long arg) { + stream << "0x" << std::hex << arg << " { IO"; + + if ((arg & IOC_OUT) != 0) { + stream << 'R'; + } + + if ((arg & IOC_IN) != 0) { + stream << 'W'; + } + if ((arg & IOC_VOID) != 0) { + stream << 'i'; + } + + stream << " 0x" << IOCGROUP(arg); + stream << "('" << iocGroupToString(IOCGROUP(arg)) << "'), "; + stream << std::dec << (arg & 0xFF) << ", " << IOCPARM_LEN(arg) << " }"; +} + +static std::string ioctlToString(unsigned long arg) { + std::ostringstream stream; + ioctlToStream(stream, arg); + return std::move(stream).str(); +} + orbis::SysResult orbis::sys_ioctl(Thread *thread, sint fd, ulong com, caddr_t data) { - ORBIS_LOG_WARNING(__FUNCTION__, fd, com); + auto str = ioctlToString(com); + ORBIS_LOG_WARNING(__FUNCTION__, fd, com, str); Ref file = thread->tproc->fileDescriptors.get(fd); if (file == nullptr) { return ErrorCode::BADF;