From 25d4e355093343044dcc38481ca9049d94324d20 Mon Sep 17 00:00:00 2001 From: DH Date: Sun, 30 Jul 2023 00:44:24 +0300 Subject: [PATCH] [orbis-kernel] stub ipmi server/client --- orbis-kernel/include/orbis/KernelContext.hpp | 26 ++++ orbis-kernel/include/orbis/ipmi.hpp | 19 +++ orbis-kernel/include/orbis/thread/Process.hpp | 2 + orbis-kernel/src/sys/sys_sce.cpp | 131 +++++++++++++++--- 4 files changed, 162 insertions(+), 16 deletions(-) create mode 100644 orbis-kernel/include/orbis/ipmi.hpp diff --git a/orbis-kernel/include/orbis/KernelContext.hpp b/orbis-kernel/include/orbis/KernelContext.hpp index 858f2bc2e..fad666ec7 100644 --- a/orbis-kernel/include/orbis/KernelContext.hpp +++ b/orbis-kernel/include/orbis/KernelContext.hpp @@ -1,5 +1,6 @@ #pragma once #include "evf.hpp" +#include "ipmi.hpp" #include "osem.hpp" #include "utils/LinkedNode.hpp" #include "utils/SharedCV.hpp" @@ -104,6 +105,28 @@ public: return {}; } + std::pair createIpmiServer(utils::kstring name, + std::uint32_t attrs, + std::int32_t initCount, + std::int32_t maxCount) { + std::lock_guard lock(m_sem_mtx); + auto [it, inserted] = mIpmiServers.try_emplace(std::move(name), nullptr); + if (inserted) { + it->second = knew(name); + } + + return {it->second.get(), inserted}; + } + + Ref findIpmiServer(std::string_view name) { + std::lock_guard lock(m_sem_mtx); + if (auto it = mIpmiServers.find(name); it != mIpmiServers.end()) { + return it->second; + } + + return {}; + } + enum { c_golden_ratio_prime = 2654404609u, c_umtx_chains = 512, @@ -145,6 +168,9 @@ private: shared_mutex m_sem_mtx; utils::kmap> m_semaphores; + + shared_mutex mIpmiServerMtx; + utils::kmap> mIpmiServers; }; extern KernelContext &g_context; diff --git a/orbis-kernel/include/orbis/ipmi.hpp b/orbis-kernel/include/orbis/ipmi.hpp new file mode 100644 index 000000000..7f3aeddda --- /dev/null +++ b/orbis-kernel/include/orbis/ipmi.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "KernelAllocator.hpp" +#include "utils/Rc.hpp" + +namespace orbis { +struct IpmiServer : RcBase { + kstring name; + + explicit IpmiServer(kstring name) : name(std::move(name)) {} +}; + +struct IpmiClient : RcBase { + Ref connection; + kstring name; + + explicit IpmiClient(kstring name) : name(std::move(name)) {} +}; +} // namespace orbis diff --git a/orbis-kernel/include/orbis/thread/Process.hpp b/orbis-kernel/include/orbis/thread/Process.hpp index 6599bc390..f2af8ae4b 100644 --- a/orbis-kernel/include/orbis/thread/Process.hpp +++ b/orbis-kernel/include/orbis/thread/Process.hpp @@ -2,6 +2,7 @@ #include "orbis-config.hpp" #include "../evf.hpp" +#include "../ipmi.hpp" #include "../osem.hpp" #include "../thread/Thread.hpp" #include "../thread/types.hpp" @@ -58,6 +59,7 @@ struct Process final { utils::RcIdMap evfMap; utils::RcIdMap semMap; + utils::RcIdMap ipmiClientMap; utils::RcIdMap modulesMap; utils::OwningIdMap threadsMap; utils::RcIdMap fileDescriptors; diff --git a/orbis-kernel/src/sys/sys_sce.cpp b/orbis-kernel/src/sys/sys_sce.cpp index d990cf311..84decafd7 100644 --- a/orbis-kernel/src/sys/sys_sce.cpp +++ b/orbis-kernel/src/sys/sys_sce.cpp @@ -847,9 +847,12 @@ orbis::sys_dynlib_get_info_ex(Thread *thread, SceKernelModule handle, sizeof(ModuleSegment) * module->segmentCount); result.segmentCount = module->segmentCount; result.refCount = module->references.load(std::memory_order::relaxed); - uwrite(destModuleInfoEx, result); - - return {}; + ORBIS_LOG_WARNING(__FUNCTION__, result.id, result.name, result.tlsIndex, + result.tlsInit, result.tlsInitSize, result.tlsSize, + result.tlsOffset, result.tlsAlign, result.initProc, + result.finiProc, result.ehFrameHdr, result.ehFrame, + result.ehFrameHdrSize, result.ehFrameSize); + return uwrite(destModuleInfoEx, result); } orbis::SysResult orbis::sys_budget_getid(Thread *thread) { return ErrorCode::NOSYS; @@ -922,6 +925,24 @@ struct IpmiCreateClientParams { static_assert(sizeof(IpmiCreateClientParams) == 0x18); +struct IpmiBufferInfo {}; +struct IpmiDataInfo { + orbis::ptr data; + orbis::uint64_t size; +}; + +struct IpmiSyncCallParams { + orbis::uint32_t method; + orbis::uint32_t dataCount; + orbis::uint64_t flags; // ? + orbis::ptr pData; + orbis::ptr pBuffers; + orbis::ptr pResult; + orbis::uint32_t resultCount; +}; + +static_assert(sizeof(IpmiSyncCallParams) == 0x30); + orbis::SysResult orbis::sys_ipmimgr_call(Thread *thread, uint op, uint kid, ptr result, ptr params, uint64_t paramsSz, uint64_t arg6) { @@ -937,38 +958,117 @@ orbis::SysResult orbis::sys_ipmimgr_call(Thread *thread, uint op, uint kid, ORBIS_LOG_TODO("IPMI: create client", createParams->arg0, createParams->name, createParams->arg2); - uwrite(result, 0x1); + // auto server = g_context.findIpmiServer(createParams->name); + + // if (server == nullptr) { + // ORBIS_LOG_TODO("IPMI: failed to find server", createParams->name); + // } + + auto ipmiClient = knew(createParams->name); + // ipmiClient->connection = server; + auto id = thread->tproc->ipmiClientMap.insert(ipmiClient); + return uwrite(result, id); } if (op == kImpiDestroyClient) { ORBIS_LOG_TODO("IPMI: destroy client"); - if (result) - uwrite(result, 0); + thread->tproc->ipmiClientMap.close(kid); + if (result) { + return uwrite(result, 0); + } + + return {}; + } + + auto client = thread->tproc->ipmiClientMap.get(kid); + + if (client == nullptr) { + return ErrorCode::INVAL; } if (op == 0x400) { ORBIS_LOG_TODO("IMPI: connect?"); - if (result) - uwrite(result, 0); + if (result) { + return uwrite(result, 0); + } } if (op == 0x320) { - ORBIS_LOG_TODO("IMPI: sync?"); - if (result) - uwrite(result, 1); + ORBIS_LOG_TODO("IMPI: invoke sync method"); + + if (paramsSz != sizeof(IpmiSyncCallParams)) { + return ErrorCode::INVAL; + } + + IpmiSyncCallParams syncCallParams; + auto errorCode = uread(syncCallParams, (ptr)params); + if (errorCode != ErrorCode{}) { + return errorCode; + } + + ORBIS_LOG_TODO("impi: invokeSyncMethod", client->name, + syncCallParams.method, syncCallParams.dataCount, + syncCallParams.flags, syncCallParams.pData, + syncCallParams.pBuffers, syncCallParams.pResult, + syncCallParams.resultCount); + + IpmiDataInfo dataInfo; + uread(dataInfo, syncCallParams.pData); + + ORBIS_LOG_TODO("", dataInfo.data, dataInfo.size); + + if (client->name == "SceMbusIpc") { + if (syncCallParams.method == 0xce110007) { // SceMbusIpcAddHandleByUserId + struct SceMbusIpcAddHandleByUserIdMethodArgs { + uint32_t unk; // 0 + uint32_t deviceId; + uint32_t userId; + uint32_t type; + uint32_t index; + uint32_t reserved; + uint32_t pid; + }; + + static_assert(sizeof(SceMbusIpcAddHandleByUserIdMethodArgs) == 0x1c); + + if (dataInfo.size != sizeof(SceMbusIpcAddHandleByUserIdMethodArgs)) { + return ErrorCode::INVAL; + } + + SceMbusIpcAddHandleByUserIdMethodArgs args; + uread(args, ptr(dataInfo.data)); + + ORBIS_LOG_TODO("impi: SceMbusIpcAddHandleByUserId", args.unk, + args.deviceId, args.userId, args.type, args.index, + args.reserved, args.pid); + } + + return uwrite(result, 1); + } + + if (result != nullptr) { + return uwrite(result, 1); + } + + return {}; } if (op == 0x310) { ORBIS_LOG_TODO("IMPI: disconnect?"); - if (result) - uwrite(result, 0); + if (result) { + return uwrite(result, 0); + } + + return {}; } if (op == 0x252) { ORBIS_LOG_TODO("IMPI: try get client message?"); thread->where(); - if (result) - uwrite(result, 0x80020003); + if (result) { + return uwrite(result, 0x80020003); + } + return {}; } if (op == 0x46b) { @@ -976,7 +1076,6 @@ orbis::SysResult orbis::sys_ipmimgr_call(Thread *thread, uint op, uint kid, return {}; } - thread->retval[0] = 0; return {}; } orbis::SysResult orbis::sys_get_gpo(Thread *thread /* TODO */) {