ipmi: fix dead lock on connection error

improved ipmi client simulators
This commit is contained in:
DH 2024-11-13 21:28:15 +03:00
parent 2bf0824a5c
commit c19c70eb77
2 changed files with 181 additions and 35 deletions

View File

@ -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<uint> 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<uint> 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<uint> result,
server->receiveCv.notify_one(server->mutex);
}
while (client->session == nullptr) {
while (client->session == nullptr && !client->connectionStatus) {
client->sessionCv.wait(client->mutex);
}

View File

@ -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<int>(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<HostFsDevice>()) {
std::error_code ec;
auto saveDir = hostFs->hostPath + "/.rpcsx/savedata/";
if (!std::filesystem::exists(saveDir)) {
return 0x8002'0000 +
static_cast<int>(orbis::ErrorCode::NOENT);
[](std::vector<std::vector<std::byte>> &outData,
const std::vector<std::span<std::byte>> &inData) -> std::int32_t {
std::println(stderr, "SceSaveData: 0x12340001");
if (inData.size() != 2 || outData.size() != 2) {
return 0x8002000 +
static_cast<std::uint32_t>(orbis::ErrorCode::INVAL);
}
if (inData[0].size() != sizeof(orbis::uint64_t) ||
outData[1].size() != sizeof(orbis::uint64_t)) {
return 0x8002000 +
static_cast<std::uint32_t>(orbis::ErrorCode::INVAL);
}
auto outputLen =
*reinterpret_cast<orbis::uint64_t *>(inData[0].data());
if (outputLen != outData[0].size()) {
return 0x8002000 +
static_cast<std::uint32_t>(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<std::uint32_t>(orbis::ErrorCode::INVAL);
}
auto request = reinterpret_cast<Request *>(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<std::string> 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<HostFsDevice>()) {
std::error_code ec;
auto saveDir = hostFs->hostPath + "/.rpcsx/savedata/";
if (!std::filesystem::exists(saveDir)) {
return 0x8002'0000 +
static_cast<int>(orbis::ErrorCode::NOENT);
}
}
}
// umount
std::string_view result = "/savedata";
if (outData[0].size() < result.size() + 1) {
return 0x8002'0000 + static_cast<int>(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<orbis::uint64_t>(0);
return 0;
}
std::string_view result = "/savedata";
if (size < result.size() + 1) {
return 0x8002'0000 + static_cast<int>(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<std::uint32_t>(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<orbis::uint32_t, orbis::uint32_t>(
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<std::uint32_t>(orbis::ErrorCode::INVAL);
});
createIpmiServer(process, "SceNpEntAccess");
createIpmiServer(process, "SceMwIPMIServer");
createIpmiServer(process, "SceAutoMounterIpc");