diff --git a/orbis-kernel/src/ipmi.cpp b/orbis-kernel/src/ipmi.cpp index 177470af9..88dae98ff 100644 --- a/orbis-kernel/src/ipmi.cpp +++ b/orbis-kernel/src/ipmi.cpp @@ -330,6 +330,7 @@ orbis::SysResult orbis::sysIpmiSendConnectResult(Thread *thread, std::lock_guard lock(client->mutex); client->connectionStatus = status; client->connectCv.notify_all(client->mutex); + client->sessionCv.notify_all(client->mutex); return uwrite(result, 0u); } orbis::SysResult orbis::sysIpmiSessionRespondSync(Thread *thread, @@ -386,12 +387,6 @@ orbis::SysResult orbis::sysIpmiSessionRespondSync(Thread *thread, if (_params.errorCode != 0) { ORBIS_LOG_ERROR(__FUNCTION__, session->client->name, _params.errorCode); thread->where(); - - // HACK: completely broken audio support should not be visible - if (session->client->name == "SceSysAudioSystemIpc" && - _params.errorCode == -1) { - _params.errorCode = 0; - } } session->syncResponses.push_front({ @@ -990,10 +985,6 @@ orbis::sysIpmiClientInvokeSyncMethod(Thread *thread, ptr result, uint kid, } } - if (response.errorCode != 0) { - thread->where(); - } - ORBIS_RET_ON_ERROR(uwrite(_params.pResult, response.errorCode)); if (response.data.size() != _params.numOutData) { @@ -1019,8 +1010,9 @@ orbis::sysIpmiClientInvokeSyncMethod(Thread *thread, ptr result, uint kid, continue; } - ORBIS_LOG_ERROR(__FUNCTION__, i, _outData.data, _outData.capacity, - data.size()); + // ORBIS_LOG_ERROR(__FUNCTION__, server->name, i, _outData.data, + // _outData.capacity, + // data.size()); _outData.size = data.size(); ORBIS_RET_ON_ERROR(uwriteRaw(_outData.data, data.data(), data.size())); @@ -1138,7 +1130,7 @@ orbis::SysResult orbis::sysIpmiClientConnect(Thread *thread, ptr result, server->receiveCv.notify_one(server->mutex); } - while (client->session == nullptr) { + while (client->session == nullptr && !client->connectionStatus) { client->sessionCv.wait(client->mutex); } diff --git a/rpcsx/ipmi.cpp b/rpcsx/ipmi.cpp index 5635a43bc..caebdb3b0 100644 --- a/rpcsx/ipmi.cpp +++ b/rpcsx/ipmi.cpp @@ -584,9 +584,9 @@ void ipmi::createShellCoreObjects(orbis::Process *process) { } *(SceLncServiceAppStatus *)out = { - .unk0 = 1, - .unk1 = 1, - .unk2 = 1, + .unk0 = 1u, + .unk1 = 0u, + .unk2 = 5u, }; size = sizeof(SceLncServiceAppStatus); @@ -685,7 +685,10 @@ void ipmi::createShellCoreObjects(orbis::Process *process) { }); createIpmiServer(process, "SceAppMessaging"); createIpmiServer(process, "SceShellCoreUtil"); - createIpmiServer(process, "SceNetCtl"); + createIpmiServer(process, "SceNetCtl") + .addSyncMethod(0x20004, [](void *out, std::uint64_t &size) { + return 0x8002'0000 + static_cast(orbis::ErrorCode::AUTH); + }); createIpmiServer(process, "SceNpMgrIpc") .addSyncMethod( 0, @@ -825,26 +828,157 @@ void ipmi::createShellCoreObjects(orbis::Process *process) { }) .addSyncMethod( 0x12340001, - [](void *out, std::uint64_t &size) -> std::int32_t { - { - auto [dev, devPath] = vfs::get("/app0"); - if (auto hostFs = dev.cast()) { - std::error_code ec; - auto saveDir = hostFs->hostPath + "/.rpcsx/savedata/"; - if (!std::filesystem::exists(saveDir)) { - return 0x8002'0000 + - static_cast(orbis::ErrorCode::NOENT); + [](std::vector> &outData, + const std::vector> &inData) -> std::int32_t { + std::println(stderr, "SceSaveData: 0x12340001"); + if (inData.size() != 2 || outData.size() != 2) { + return 0x8002000 + + static_cast(orbis::ErrorCode::INVAL); + } + if (inData[0].size() != sizeof(orbis::uint64_t) || + outData[1].size() != sizeof(orbis::uint64_t)) { + return 0x8002000 + + static_cast(orbis::ErrorCode::INVAL); + } + + auto outputLen = + *reinterpret_cast(inData[0].data()); + + if (outputLen != outData[0].size()) { + return 0x8002000 + + static_cast(orbis::ErrorCode::INVAL); + } + + struct Request { + orbis::uint32_t unk0; + orbis::uint32_t id; + orbis::uint32_t unk1[31]; + }; + + static_assert(sizeof(Request) == 132); + + if (inData[1].size() != sizeof(Request)) { + return 0x8002000 + + static_cast(orbis::ErrorCode::INVAL); + } + + auto request = reinterpret_cast(inData[1].data()); + + std::println(stderr, "SceSaveData: 0x12340001, message {}", + request->id); + + for (std::size_t index = 0; auto &in : inData) { + std::println(stderr, "in {} - {}", index++, in.size()); + rx::hexdump(in); + } + + for (std::size_t index = 0; auto &out : outData) { + std::println(stderr, "out {} - {}", index++, out.size()); + } + + if (request->id == 2) { + return 0; + } + + if (request->id == 3) { + struct MountInfo { + std::uint64_t blocks; + std::uint64_t freeBlocks; + }; + + std::memset(outData[0].data(), 0xff, outData[0].size()); + + auto info = (MountInfo *)outData[0].data(); + info->blocks = 1024 * 32; + info->freeBlocks = 1024 * 16; + return 0; + } + + if (request->id == 4) { + return 0; + } + + if (request->id == 6) { + struct Entry { + char string[32]; + }; + + struct SearchResults { + std::uint32_t totalCount; + std::uint32_t count; + Entry entries[]; + }; + + std::uint32_t fillOffset = 4 + sizeof(Entry) + 1024; + + std::memset(outData[0].data() + fillOffset, 0xff, + outData[0].size() - fillOffset); + + auto results = (SearchResults *)outData[0].data(); + std::vector searchResults; + searchResults.emplace_back("TEST"); + results->totalCount = searchResults.size(); + + Entry *entries = results->entries; + results->count = searchResults.size(); + + for (auto &str : searchResults) { + std::strncpy(entries->string, str.data(), + sizeof(entries->string)); + entries->string[std::size(entries->string) - 1] = 0; + + entries++; + } + + return 0; + } + + if (request->id == 7) { + return 0; + } + + if (request->id == 8) { + return 0; + } + + if (request->id == 9) { + return 0; + } + + if (request->id == 10) { + return 0; + } + + if (request->id == 1 || request->id == 60) { + { + auto [dev, devPath] = vfs::get("/app0"); + if (auto hostFs = dev.cast()) { + std::error_code ec; + auto saveDir = hostFs->hostPath + "/.rpcsx/savedata/"; + if (!std::filesystem::exists(saveDir)) { + return 0x8002'0000 + + static_cast(orbis::ErrorCode::NOENT); + } } } + + // umount + std::string_view result = "/savedata"; + if (outData[0].size() < result.size() + 1) { + return 0x8002'0000 + static_cast(orbis::ErrorCode::INVAL); + } + std::strncpy((char *)outData[0].data(), result.data(), + result.size() + 1); + outData[0].resize(result.size() + 1); + orbis::g_context.createEventFlag(orbis::kstring(result), 0x200, + 0); + + outData[1] = toBytes(0); + return 0; } - std::string_view result = "/savedata"; - if (size < result.size() + 1) { - return 0x8002'0000 + static_cast(orbis::ErrorCode::INVAL); - } - std::strncpy((char *)out, result.data(), result.size() + 1); - size = result.size() + 1; - orbis::g_context.createEventFlag(orbis::kstring(result), 0x200, 0); - return 0; + + return 0x8002000 + + static_cast(orbis::ErrorCode::INVAL); }) .addSyncMethod(0x12340002, [](void *, std::uint64_t &) -> std::int32_t { { @@ -878,7 +1012,27 @@ void ipmi::createShellCoreObjects(orbis::Process *process) { createIpmiServer(process, "SceScreenShot"); createIpmiServer(process, "SceAppDbIpc"); createIpmiServer(process, "SceAppInst"); - createIpmiServer(process, "SceAppContent"); + createIpmiServer(process, "SceAppContent") + .addSyncMethod( + 0x20001, + [](orbis::uint32_t &out, orbis::uint32_t param) -> std::int32_t { + switch (param) { + case 0: // sku + out = 3; + return 0; + + case 1: // user defined param 0 + case 2: // user defined param 1 + case 3: // user defined param 2 + case 4: // user defined param 3 + ORBIS_LOG_ERROR("SceAppContent: get user defined param"); + out = 0; + return 0; + } + + return 0x8002000 + static_cast(orbis::ErrorCode::INVAL); + }); + createIpmiServer(process, "SceNpEntAccess"); createIpmiServer(process, "SceMwIPMIServer"); createIpmiServer(process, "SceAutoMounterIpc");