diff --git a/vita3k/modules/CMakeLists.txt b/vita3k/modules/CMakeLists.txt index f85841c0c6..f8757efbca 100644 --- a/vita3k/modules/CMakeLists.txt +++ b/vita3k/modules/CMakeLists.txt @@ -59,6 +59,7 @@ set(SOURCE_LIST SceHid/SceHid.cpp SceHttp/SceHttp.cpp SceIme/SceIme.cpp + SceIpmi/SceIpmi.cpp SceIncomingDialog/SceIncomingDialog.cpp SceIofilemgr/SceIofilemgr.cpp SceJpeg/SceJpegUser.cpp diff --git a/vita3k/modules/SceIpmi/SceIpmi.cpp b/vita3k/modules/SceIpmi/SceIpmi.cpp new file mode 100644 index 0000000000..41c62a8957 --- /dev/null +++ b/vita3k/modules/SceIpmi/SceIpmi.cpp @@ -0,0 +1,153 @@ +// Vita3K emulator project +// Copyright (C) 2024 Vita3K team +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +#include + +#include "modules/module_parent.h" + +#include + +TRACY_MODULE_NAME(SceIpmi); + +static Ptr client_vtable = Ptr(); + +EXPORT(int, _ZN4IPMI6Client10disconnectEv) { + return UNIMPLEMENTED(); +} + +EXPORT(int, _ZN4IPMI6Client11getUserDataEv) { + return UNIMPLEMENTED(); +} + +struct BufferInfo { + Ptr pBuffer; + SceSize bufferSize; + SceSize bufferWrittenSize; // size written by method +}; + +EXPORT(int, _ZN4IPMI6Client12tryGetResultEjPiPvPmm, unsigned int a1, int *a2, void *a3, unsigned long *a4, unsigned long a5) { + return UNIMPLEMENTED(); +} + +EXPORT(int, _ZN4IPMI6Client12tryGetResultEjjPiPNS_10BufferInfoEj) { + return UNIMPLEMENTED(); +} + +EXPORT(int, _ZN4IPMI6Client13pollEventFlagEjjjPj) { + return UNIMPLEMENTED(); +} + +EXPORT(int, _ZN4IPMI6Client13waitEventFlagEjjjPjS1_) { + return UNIMPLEMENTED(); +} + +EXPORT(int, _ZN4IPMI6Client16invokeSyncMethodEjPKNS_8DataInfoEjPiPNS_10BufferInfoEj) { + return UNIMPLEMENTED(); +} + +EXPORT(int, _ZN4IPMI6Client16invokeSyncMethodEjPKvjPiPvPjj) { + return UNIMPLEMENTED(); +} + +EXPORT(int, _ZN4IPMI6Client17invokeAsyncMethodEjPKNS_8DataInfoEjPjPKNS0_12EventNotifeeE) { + return UNIMPLEMENTED(); +} + +EXPORT(int, _ZN4IPMI6Client17invokeAsyncMethodEjPKvjPiPKNS0_12EventNotifeeE) { + return UNIMPLEMENTED(); +} + +EXPORT(int, _ZN4IPMI6Client19terminateConnectionEv) { + return UNIMPLEMENTED(); +} + +// IPMI::Client::Config::estimateClientMemorySize() +EXPORT(int, _ZN4IPMI6Client6Config24estimateClientMemorySizeEv) { + TRACY_FUNC(_ZN4IPMI6Client6Config24estimateClientMemorySizeEv); + STUBBED("stubbed"); + return 0x100; +} + +// IPMI::Client::create(IPMI::Client**, IPMI::Client::Config const*, void*, void*) +EXPORT(int, _ZN4IPMI6Client6createEPPS0_PKNS0_6ConfigEPvS6_, Ptr *client, void const *config, Ptr user_data, Ptr client_memory) { + TRACY_FUNC(_ZN4IPMI6Client6createEPPS0_PKNS0_6ConfigEPvS6_, client, config, user_data, client_memory); + if (!client_vtable) { + // initialize the vtable + client_vtable = create_vtable({ + 0x101C93F8, // destroy + 0xA22C3E01, // connect + 0xEC73331C, // disconnect + 0xD484D36D, // terminateConnection + 0x28BD5F19, // invokeSyncMethod + 0x73C72FBB, // invokeSyncMethod + 0xAFD10F3B, // invokeAsyncMethod + 0x387AFA3F, // invokeAsyncMethod + 0xF8C2B8BA, // tryGetResult + 0x4EBB01A2, // tryGetResult + 0x8FF23C3C, // pollEventFlag + 0x45C32034, // waitEventFlag + 0x004F48ED, // getUserData + 0xA3E650B0, // getMsg + 0x60EFADE7, // tryGetMsg + 0xA5AA193C, // ~Client + }, + emuenv.mem); + } + + *client_memory.cast>().get(emuenv.mem) = client_vtable; + *client = client_memory; + STUBBED("Stubed"); + return 0; +} + +EXPORT(int, _ZN4IPMI6Client6getMsgEjPvPjjS2_) { + return UNIMPLEMENTED(); +} + +EXPORT(int, _ZN4IPMI6Client7connectEPKvjPi, void *client, void const *params, SceSize params_size, SceInt32 *error) { + TRACY_FUNC(_ZN4IPMI6Client7connectEPKvjPi, client, error); + *error = 0; + return UNIMPLEMENTED(); +} + +EXPORT(int, _ZN4IPMI6Client7destroyEv) { + return UNIMPLEMENTED(); +} + +EXPORT(int, _ZN4IPMI6Client9tryGetMsgEjPvPmm) { + return UNIMPLEMENTED(); +} + +EXPORT(int, _ZN4IPMI6ClientD1Ev) { + return UNIMPLEMENTED(); +} + +EXPORT(int, SceIpmi_296D44D4) { + return UNIMPLEMENTED(); +} + +EXPORT(int, SceIpmi_BC3A3031) { + return UNIMPLEMENTED(); +} + +EXPORT(int, SceIpmi_2C6DB642) { + return UNIMPLEMENTED(); +} + +EXPORT(int, SceIpmi_006EFA9D) { + return UNIMPLEMENTED(); +} diff --git a/vita3k/modules/include/modules/module_parent.h b/vita3k/modules/include/modules/module_parent.h index 65d40a4f1e..318a162c1e 100644 --- a/vita3k/modules/include/modules/module_parent.h +++ b/vita3k/modules/include/modules/module_parent.h @@ -52,6 +52,7 @@ bool load_sys_module_internal_with_arg(EmuEnvState &emuenv, SceUID thread_id, Sc Address resolve_export(KernelState &kernel, uint32_t nid); uint32_t resolve_nid(KernelState &kernel, Address addr); +Ptr create_vtable(const std::vector &nids, MemState &mem); struct VarExport { uint32_t nid; diff --git a/vita3k/modules/module_parent.cpp b/vita3k/modules/module_parent.cpp index b8e7bbf8ce..29092915f5 100644 --- a/vita3k/modules/module_parent.cpp +++ b/vita3k/modules/module_parent.cpp @@ -98,6 +98,27 @@ Address resolve_export(KernelState &kernel, uint32_t nid) { return export_address->second; } +Ptr create_vtable(const std::vector &nids, MemState &mem) { + // we need 4 bytes for the function pointer and 12 bytes for the syscall + const uint32_t vtable_size = nids.size() * 4 * sizeof(uint32_t); + Ptr vtable = Ptr(alloc(mem, vtable_size, "vtable")); + uint32_t *function_pointer = vtable.cast().get(mem); + uint32_t *function_svc = function_pointer + nids.size(); + uint32_t function_location = vtable.address() + nids.size() * sizeof(uint32_t); + for (uint32_t nid : nids) { + *function_pointer = function_location; + // encode svc call + function_svc[0] = 0xef000000; // svc #0 - Call our interrupt hook. + function_svc[1] = 0xe1a0f00e; // mov pc, lr - Return to the caller. + function_svc[2] = nid; // Our interrupt hook will read this. + + function_pointer++; + function_svc += 3; + function_location += 3 * sizeof(uint32_t); + } + return vtable; +} + static void log_import_call(char emulation_level, uint32_t nid, SceUID thread_id, const std::unordered_set &nid_blacklist, Address lr) { if (!nid_blacklist.contains(nid)) { const char *const name = import_name(nid); diff --git a/vita3k/nids/include/nids/nids.inc b/vita3k/nids/include/nids/nids.inc index 5b173501fa..2ea08fddd5 100644 --- a/vita3k/nids/include/nids/nids.inc +++ b/vita3k/nids/include/nids/nids.inc @@ -2044,6 +2044,25 @@ NID(sceImeSetCaret, 0xD8342D2A) NID(sceImeSetPreeditGeometry, 0x7B1EFAA5) NID(sceImeSetText, 0xF3BD9A76) NID(sceImeUpdate, 0x71D6898A) +// Library "SceIpmi" // Some nids are fake +NID(_ZN4IPMI6Client10disconnectEv, 0xEC73331C) +NID(_ZN4IPMI6Client11getUserDataEv, 0x004F48ED) +NID(_ZN4IPMI6Client12tryGetResultEjPiPvPmm, 0xF8C2B8BA) +NID(_ZN4IPMI6Client12tryGetResultEjjPiPNS_10BufferInfoEj, 0x4EBB01A2) +NID(_ZN4IPMI6Client13pollEventFlagEjjjPj, 0x8FF23C3C) +NID(_ZN4IPMI6Client13waitEventFlagEjjjPjS1_, 0x45C32034) +NID(_ZN4IPMI6Client16invokeSyncMethodEjPKNS_8DataInfoEjPiPNS_10BufferInfoEj, 0x73C72FBB) +NID(_ZN4IPMI6Client16invokeSyncMethodEjPKvjPiPvPjj, 0x28BD5F19) +NID(_ZN4IPMI6Client17invokeAsyncMethodEjPKNS_8DataInfoEjPjPKNS0_12EventNotifeeE, 0x387AFA3F) +NID(_ZN4IPMI6Client17invokeAsyncMethodEjPKvjPiPKNS0_12EventNotifeeE, 0xAFD10F3B) +NID(_ZN4IPMI6Client19terminateConnectionEv, 0xD484D36D) +NID(_ZN4IPMI6Client6Config24estimateClientMemorySizeEv, 0x4E255C31) +NID(_ZN4IPMI6Client6createEPPS0_PKNS0_6ConfigEPvS6_, 0xB282B430) +NID(_ZN4IPMI6Client6getMsgEjPvPjjS2_, 0xA3E650B0) +NID(_ZN4IPMI6Client7connectEPKvjPi, 0xA22C3E01) +NID(_ZN4IPMI6Client7destroyEv, 0x101C93F8) +NID(_ZN4IPMI6Client9tryGetMsgEjPvPmm, 0x60EFADE7) +NID(_ZN4IPMI6ClientD1Ev, 0xA5AA193C) // Module "SceIncomingDialog" // Library "SceIncomingDialog" NID(sceIncomingDialogClose, 0x126BD15E)