[rpcsx-os] implement fw simulation

implement impi messages
This commit is contained in:
DH 2023-12-27 20:07:30 +03:00
parent 2278a298ac
commit 6ba0ad0832
8 changed files with 516 additions and 153 deletions

View file

@ -1,6 +1,5 @@
#pragma once
#include "orbis/utils/SharedMutex.hpp"
#include <atomic>
#include <cstdint>
#include <cstring>
@ -8,6 +7,8 @@
#include <orbis/utils/SharedCV.hpp>
namespace amdgpu::bridge {
extern std::uint32_t expGpuPid;
struct PadState {
std::uint64_t timestamp;
std::uint32_t unk;
@ -149,21 +150,21 @@ struct BridgePusher {
void sendMemoryProtect(std::uint32_t pid, std::uint64_t address,
std::uint64_t size, std::uint32_t prot) {
if (pid == 50001) {
if (pid == expGpuPid) {
sendCommand(CommandId::ProtectMemory, {pid, address, size, prot});
}
}
void sendCommandBuffer(std::uint32_t pid, std::uint64_t queue,
std::uint64_t address, std::uint64_t size) {
if (pid == 50001) {
if (pid == expGpuPid) {
sendCommand(CommandId::CommandBuffer, {pid, queue, address, size});
}
}
void sendFlip(std::uint32_t pid, std::uint32_t bufferIndex,
std::uint64_t arg) {
if (pid == 50001) {
if (pid == expGpuPid) {
sendCommand(CommandId::Flip, {pid, bufferIndex, arg});
}
}

View file

@ -8,6 +8,8 @@
static int gShmFd = -1;
static constexpr std::size_t kShmSize = sizeof(amdgpu::bridge::BridgeHeader) +
(sizeof(std::uint64_t) * (1024 * 1024));
std::uint32_t amdgpu::bridge::expGpuPid = 0;
amdgpu::bridge::BridgeHeader *
amdgpu::bridge::createShmCommandBuffer(const char *name) {
if (gShmFd != -1) {

View file

@ -58,6 +58,8 @@ struct IpmiClient : RcBase {
shared_mutex mutex;
shared_cv sessionCv;
sint pid;
kdeque<kvector<std::byte>> messages;
shared_cv messageCv;
explicit IpmiClient(kstring name) : name(std::move(name)) {}
};
@ -150,6 +152,8 @@ SysResult sysIpmiSendConnectResult(Thread *thread, ptr<uint> result, uint kid,
ptr<void> params, uint64_t paramsSz);
SysResult sysIpmiSessionRespondSync(Thread *thread, ptr<uint> result, uint kid,
ptr<void> params, uint64_t paramsSz);
SysResult sysIpmiClientTryGetMessage(Thread *thread, ptr<uint> result, uint kid,
ptr<void> params, uint64_t paramsSz);
SysResult sysIpmiSessionGetClientPid(Thread *thread, ptr<uint> result, uint kid,
ptr<void> params, uint64_t paramsSz);
SysResult sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result,
@ -161,9 +165,8 @@ SysResult sysIpmiSessionGetUserData(Thread *thread, ptr<uint> result, uint kid,
ptr<void> params, uint64_t paramsSz);
SysResult sysIpmiServerGetName(Thread *thread, ptr<uint> result, uint kid,
ptr<void> params, uint64_t paramsSz);
SysResult sysIpmiClientPollEventFlag(Thread *thread, ptr<uint> result,
uint kid, ptr<void> params,
uint64_t paramsSz);
SysResult sysIpmiClientPollEventFlag(Thread *thread, ptr<uint> result, uint kid,
ptr<void> params, uint64_t paramsSz);
SysResult sysIpmiSessionWaitEventFlag(Thread *thread, ptr<uint> result,
uint kid, ptr<void> params,
uint64_t paramsSz);

View file

@ -341,6 +341,54 @@ orbis::SysResult orbis::sysIpmiSessionRespondSync(Thread *thread,
return uwrite(result, 0u);
}
orbis::SysResult orbis::sysIpmiClientTryGetMessage(Thread *thread,
ptr<uint> result, uint kid,
ptr<void> params,
uint64_t paramsSz) {
struct SceIpmiClientTryGetArgs {
uint32_t unk; // 0
uint32_t padding;
ptr<std::byte> message;
ptr<uint64_t> pSize;
uint64_t maxSize;
};
static_assert(sizeof(SceIpmiClientTryGetArgs) == 0x20);
if (paramsSz != sizeof(SceIpmiClientTryGetArgs)) {
return ErrorCode::INVAL;
}
auto client = thread->tproc->ipmiMap.get(kid).cast<IpmiClient>();
if (client == nullptr) {
return ErrorCode::INVAL;
}
SceIpmiClientTryGetArgs _params;
ORBIS_RET_ON_ERROR(uread(_params, ptr<SceIpmiClientTryGetArgs>(params)));
std::lock_guard lock(client->mutex);
if (client->messages.empty()) {
return uwrite<uint>(result,
0x80020000 + static_cast<int>(ErrorCode::AGAIN));
}
auto &message = client->messages.front();
if (_params.maxSize < message.size()) {
ORBIS_LOG_ERROR(__FUNCTION__, "too small buffer");
return uwrite<uint>(result,
0x80020000 + static_cast<int>(ErrorCode::INVAL));
}
ORBIS_RET_ON_ERROR(uwrite(_params.pSize, message.size()));
ORBIS_RET_ON_ERROR(
uwriteRaw(_params.message, message.data(), message.size()));
client->messages.pop_front();
return uwrite<uint>(result, 0);
}
orbis::SysResult orbis::sysIpmiSessionGetClientPid(Thread *thread,
ptr<uint> result, uint kid,
ptr<void> params,

View file

@ -950,25 +950,26 @@ orbis::SysResult orbis::sys_get_self_auth_info(Thread *thread,
ORBIS_LOG_ERROR(__FUNCTION__, path, result);
thread->where();
return uwrite(
result, {
.unk0 = 0x3100000000000001,
.caps =
{
~0ull, ~0ull, ~0ull, ~0ull,
// 0x2000038000000000,
// 0x000000000000FF00,
// 0x0000000000000000,
// 0x0000000000000000,
},
.attrs =
{
0x4000400040000000,
0x4000000000000000,
0x0080000000000004, // lower byte is application type
0xF0000000FFFF4000,
},
});
char _path[512];
ORBIS_RET_ON_ERROR(ureadString(_path, sizeof(_path), path));
struct Result {
std::uint64_t authorityId;
std::uint64_t programType;
std::uint64_t programVersion;
std::uint64_t systemVersion;
char contentId[32];
char hash[32];
};
Result _result{};
_result.authorityId = 0x1000;
_result.programType = 1;
_result.programVersion = 1;
_result.systemVersion = 1;
_result.contentId[24] = 4;
return uwrite((ptr<Result>)result, _result);
return {};
}
@ -1095,8 +1096,7 @@ orbis::SysResult orbis::sys_ipmimgr_call(Thread *thread, uint op, uint kid,
case 0x232:
return sysIpmiSessionRespondSync(thread, result, kid, params, paramsSz);
case 0x252:
// TODO: try get message
return uwrite<uint>(result, 0x80020023);
return sysIpmiClientTryGetMessage(thread, result, kid, params, paramsSz);
case 0x302:
return sysIpmiSessionGetClientPid(thread, result, kid, params, paramsSz);
case 0x320:
@ -1225,8 +1225,8 @@ orbis::SysResult
orbis::sys_get_kernel_mem_statistics(Thread *thread /* TODO */) {
return ErrorCode::NOSYS;
}
orbis::SysResult
orbis::sys_get_sdk_compiled_version(Thread *thread, ptr<const char> path) {
orbis::SysResult orbis::sys_get_sdk_compiled_version(Thread *thread,
ptr<const char> path) {
ORBIS_LOG_ERROR(__FUNCTION__, path);
thread->retval[0] = g_context.sdkVersion;
return {};
@ -1244,8 +1244,8 @@ orbis::SysResult orbis::sys_dynlib_get_obj_member(Thread *thread,
return ErrorCode::NOSYS;
}
orbis::SysResult
orbis::sys_budget_get_ptype_of_budget(Thread *thread, sint budgetId) {
orbis::SysResult orbis::sys_budget_get_ptype_of_budget(Thread *thread,
sint budgetId) {
ORBIS_LOG_WARNING(__FUNCTION__, budgetId);
thread->retval[0] = budgetId;
return {};

View file

@ -92,7 +92,7 @@ int main(int argc, const char *argv[]) {
}
const char *cmdBridgeName = "/rpcsx-gpu-cmds";
const char *shmName = "/rpcsx-os-memory-50001";
const char *shmName = "/rpcsx-os-memory";
unsigned long gpuIndex = 0;
auto presenter = PresenterMode::Window;
bool enableValidation = false;
@ -945,25 +945,15 @@ int main(int argc, const char *argv[]) {
for (auto cmd : std::span(commandsBuffer, pulledCount)) {
switch (cmd.id) {
case amdgpu::bridge::CommandId::ProtectMemory:
if (cmd.memoryProt.pid != 50001) {
continue;
}
device.handleProtectMemory(cmd.memoryProt.address,
cmd.memoryProt.size, cmd.memoryProt.prot);
break;
case amdgpu::bridge::CommandId::CommandBuffer:
if (cmd.memoryProt.pid != 50001) {
continue;
}
device.handleCommandBuffer(cmd.commandBuffer.queue,
cmd.commandBuffer.address,
cmd.commandBuffer.size);
break;
case amdgpu::bridge::CommandId::Flip: {
if (cmd.memoryProt.pid != 50001) {
continue;
}
if (!isImageAcquired) {
Verify() << vkAcquireNextImageKHR(vkDevice, swapchain, UINT64_MAX,
presentCompleteSemaphore, nullptr,

View file

@ -35,6 +35,7 @@
#include <filesystem>
#include <functional>
#include <sstream>
#include <unordered_map>
static int g_gpuPid;
@ -631,36 +632,201 @@ static void createShm(const char *name, uint32_t flags, uint32_t mode,
uint64_t size) {
orbis::Ref<orbis::File> shm;
auto shmDevice = orbis::g_context.shmDevice.staticCast<IoDevice>();
shmDevice->open(&shm, "/SceAvSetting", flags, mode, nullptr);
shmDevice->open(&shm, name, flags, mode, nullptr);
shm->ops->truncate(shm.get(), 4096, nullptr);
}
static orbis::Ref<orbis::IpmiServer> createIpmiServer(
orbis::Process *process, const char *name,
std::function<void(orbis::IpmiSession *, orbis::IpmiSyncMessageHeader *)>
packetHandler) {
struct IpmiServer {
orbis::Ref<orbis::IpmiServer> serverImpl;
std::unordered_map<
std::uint32_t,
std::function<orbis::ErrorCode(
std::int32_t &errorCode, std::vector<std::span<std::byte>> &outData,
const std::vector<std::span<std::byte>> &inData)>>
syncHandlers;
std::vector<std::vector<std::byte>> messages;
IpmiServer &createSyncHandler(std::uint32_t methodId,
std::function<std::int32_t()> handler) {
syncHandlers[methodId] =
[=](std::int32_t &errorCode, std::vector<std::span<std::byte>> &outData,
const std::vector<std::span<std::byte>> &inData)
-> orbis::ErrorCode {
if (!outData.empty() || !inData.empty()) {
return orbis::ErrorCode::INVAL;
}
errorCode = handler();
return {};
};
return *this;
}
IpmiServer &createSyncHandler(
std::uint32_t methodId,
std::function<std::int32_t(void *out, std::uint64_t &outSize)> handler) {
syncHandlers[methodId] =
[=](std::int32_t &errorCode, std::vector<std::span<std::byte>> &outData,
const std::vector<std::span<std::byte>> &inData)
-> orbis::ErrorCode {
if (outData.size() != 1) {
return orbis::ErrorCode::INVAL;
}
std::uint64_t size = outData[0].size();
errorCode = handler(outData[0].data(), size);
outData[0] = outData[0].subspan(0, size);
return {};
};
return *this;
}
template <typename T>
IpmiServer &createSyncHandler(
std::uint32_t methodId,
std::function<std::int32_t(void *out, std::uint64_t &outSize,
const T &param)>
handler) {
syncHandlers[methodId] =
[=](std::int32_t &errorCode, std::vector<std::span<std::byte>> &outData,
const std::vector<std::span<std::byte>> &inData)
-> orbis::ErrorCode {
if (outData.size() != 1 || inData.size() != 1) {
return orbis::ErrorCode::INVAL;
}
if (inData[0].size() != sizeof(T)) {
return orbis::ErrorCode::INVAL;
}
std::uint64_t size = outData[0].size();
errorCode = handler(outData[0].data(), size,
*reinterpret_cast<T *>(inData[0].data()));
outData[0] = outData[0].subspan(0, size);
return {};
};
return *this;
}
template <typename T>
IpmiServer &
createSyncHandler(std::uint32_t methodId,
std::function<std::int32_t(const T &param)> handler) {
syncHandlers[methodId] =
[=](std::int32_t &errorCode, std::vector<std::span<std::byte>> &outData,
const std::vector<std::span<std::byte>> &inData)
-> orbis::ErrorCode {
if (inData.size() != 1 || !outData.empty()) {
return orbis::ErrorCode::INVAL;
}
if (inData[0].size() != sizeof(T)) {
return orbis::ErrorCode::INVAL;
}
errorCode = handler(*reinterpret_cast<T *>(inData[0].data()));
return {};
};
return *this;
}
template <typename T> IpmiServer &sendMsg(const T &data) {
std::vector<std::byte> message(sizeof(T));
std::memcpy(message.data(), &data, sizeof(T));
messages.push_back(std::move(message));
return *this;
}
orbis::ErrorCode handle(orbis::IpmiSession *session,
orbis::IpmiSyncMessageHeader *message) {
std::size_t inBufferOffset = 0;
auto bufLoc = std::bit_cast<std::byte *>(message + 1);
std::vector<std::span<std::byte>> inData;
std::vector<std::span<std::byte>> outData;
for (unsigned i = 0; i < message->numInData; ++i) {
auto size = *std::bit_cast<orbis::uint *>(bufLoc);
bufLoc += sizeof(orbis::uint);
inData.push_back({bufLoc, size});
bufLoc += size;
}
for (unsigned i = 0; i < message->numOutData; ++i) {
auto size = *std::bit_cast<orbis::uint *>(bufLoc);
bufLoc += sizeof(orbis::uint);
outData.push_back({bufLoc, size});
bufLoc += size;
}
if (auto it = syncHandlers.find(message->methodId);
it != syncHandlers.end()) {
auto &handler = it->second;
std::int32_t errorCode = 0;
auto result = handler(errorCode, outData, inData);
if (outData.empty()) {
session->messageResponses.push_front({
.errorCode = errorCode,
.data = {},
});
} else {
session->messageResponses.push_front({
.errorCode = errorCode,
.data = orbis::kvector<std::byte>(
outData[0].data(), outData[0].data() + outData[0].size()),
});
}
session->responseCv.notify_one(session->mutex);
return {};
}
std::fprintf(
stderr,
"Unimplemented sync method %s::%x(inBufCount=%x, outBufCount=%x)\n",
session->server->name.c_str(), message->methodId, message->numInData,
message->numOutData);
std::lock_guard lock(session->mutex);
session->messageResponses.push_front({
.errorCode = 0,
.data = orbis::kvector<std::byte>(
message->numOutData ? outData[0].size() : 0),
});
session->responseCv.notify_one(session->mutex);
return {};
}
};
static IpmiServer &createIpmiServer(orbis::Process *process, const char *name) {
orbis::IpmiCreateServerConfig config{};
orbis::Ref<orbis::IpmiServer> server;
orbis::ipmiCreateServer(process, nullptr, name, config, server);
std::thread{[server, packetHandler = std::move(packetHandler)] {
orbis::Ref<orbis::IpmiServer> serverImpl;
orbis::ipmiCreateServer(process, nullptr, name, config, serverImpl);
auto server = std::make_shared<IpmiServer>();
server->serverImpl = serverImpl;
std::thread{[server, serverImpl] {
while (true) {
orbis::IpmiServer::Packet packet;
{
std::lock_guard lock(server->mutex);
std::lock_guard lock(serverImpl->mutex);
while (server->packets.empty()) {
server->receiveCv.wait(server->mutex);
while (serverImpl->packets.empty()) {
serverImpl->receiveCv.wait(serverImpl->mutex);
}
packet = std::move(server->packets.front());
server->packets.pop_front();
packet = std::move(serverImpl->packets.front());
serverImpl->packets.pop_front();
}
if (packet.info.type == 1) {
std::lock_guard serverLock(server->mutex);
std::lock_guard serverLock(serverImpl->mutex);
for (auto it = server->connectionRequests.begin();
it != server->connectionRequests.end(); ++it) {
for (auto it = serverImpl->connectionRequests.begin();
it != serverImpl->connectionRequests.end(); ++it) {
auto &conReq = *it;
std::lock_guard clientLock(conReq.client->mutex);
if (conReq.client->session != nullptr) {
@ -673,8 +839,13 @@ static orbis::Ref<orbis::IpmiServer> createIpmiServer(
}
session->client = conReq.client;
session->server = server;
session->server = serverImpl;
conReq.client->session = session;
for (auto &message : server->messages) {
conReq.client->messages.push_back(orbis::kvector<std::byte>(message.data(), message.data() + message.size()));
}
conReq.client->sessionCv.notify_all(conReq.client->mutex);
// server->connectionRequests.erase(it);
break;
@ -700,59 +871,59 @@ static orbis::Ref<orbis::IpmiServer> createIpmiServer(
continue;
}
packetHandler(client->session.get(), msgHeader);
server->handle(client->session.get(), msgHeader);
continue;
}
std::fprintf(stderr, "IPMI: Unhandled packet %s::%u\n",
server->name.c_str(), packet.info.type);
serverImpl->name.c_str(), packet.info.type);
}
}}.detach();
return server;
return *server;
}
static std::uint32_t
unimplementedIpmiServer(orbis::IpmiSession *session,
orbis::IpmiSyncMessageHeader *message) {
std::fprintf(
stderr,
"Unimplemented sync method %s::%x(inBufCount=%x, outBufCount=%x)\n",
session->server->name.c_str(), message->methodId, message->numInData,
message->numOutData);
std::size_t inBufferOffset = 0;
auto bufLoc = std::bit_cast<char *>(message + 1);
for (unsigned i = 0; i < message->numInData; ++i) {
bufLoc += *std::bit_cast<orbis::uint *>(bufLoc) + sizeof(orbis::uint);
}
auto outSize = *std::bit_cast<orbis::uint *>(bufLoc);
orbis::kvector<std::byte> output(outSize);
std::lock_guard lock(session->mutex);
session->messageResponses.push_front({
.errorCode = 0,
.data = std::move(output),
});
session->responseCv.notify_one(session->mutex);
return 0;
static void createMiniSysCoreObjects(orbis::Process *process) {
createEventFlag("SceBootStatusFlags", 0x121, 0x2408);
}
static void createSysAvControlObjects(orbis::Process *process) {
createIpmiServer(process, "SceAvSettingIpc", unimplementedIpmiServer);
createIpmiServer(process, "SceAvSettingIpc");
createEventFlag("SceAvSettingEvf", 0x121, 0xffff00000000);
createShm("/SceAvSetting", 0xa02, 0x1a4, 4096);
}
struct SceMbusIpcAddHandleByUserIdMethodArgs {
orbis::uint32_t unk; // 0
orbis::uint32_t deviceId;
orbis::uint32_t userId;
orbis::uint32_t type;
orbis::uint32_t index;
orbis::uint32_t reserved;
orbis::uint32_t pid;
};
static_assert(sizeof(SceMbusIpcAddHandleByUserIdMethodArgs) == 0x1c);
struct SceUserServiceEvent {
std::uint32_t eventType; // 0 - login, 1 - logout
std::uint32_t user;
};
static void createSysCoreObjects(orbis::Process *process) {
createIpmiServer(process, "SceMbusIpc", unimplementedIpmiServer);
createIpmiServer(process, "SceSysCoreApp", unimplementedIpmiServer);
createIpmiServer(process, "SceSysCoreApp2", unimplementedIpmiServer);
createIpmiServer(process, "SceMDBG0SRV", unimplementedIpmiServer);
createIpmiServer(process, "SceMbusIpc")
.createSyncHandler<SceMbusIpcAddHandleByUserIdMethodArgs>(
0xce110007, [](const auto &args) -> std::int32_t {
ORBIS_LOG_TODO("IPMI: SceMbusIpcAddHandleByUserId", args.unk,
args.deviceId, args.userId, args.type, args.index,
args.reserved, args.pid);
return 1;
});
createIpmiServer(process, "SceSysCoreApp");
createIpmiServer(process, "SceSysCoreApp2");
createIpmiServer(process, "SceMDBG0SRV");
createSemaphore("SceSysCoreProcSpawnSema", 0x101, 0, 1);
createSemaphore("SceTraceMemorySem", 0x100, 1, 1);
@ -784,52 +955,94 @@ static void createShellCoreObjects(orbis::Process *process) {
return std::move(ss).str();
};
createIpmiServer(process, "SceSystemLoggerService", unimplementedIpmiServer);
createIpmiServer(process, "SceLoginMgrServer", unimplementedIpmiServer);
createIpmiServer(process, "SceLncService", unimplementedIpmiServer);
createIpmiServer(process, "SceAppMessaging", unimplementedIpmiServer);
createIpmiServer(process, "SceShellCoreUtil", unimplementedIpmiServer);
createIpmiServer(process, "SceNetCtl", unimplementedIpmiServer);
createIpmiServer(process, "SceNpMgrIpc", unimplementedIpmiServer);
createIpmiServer(process, "SceNpService", unimplementedIpmiServer);
createIpmiServer(process, "SceNpTrophyIpc", unimplementedIpmiServer);
createIpmiServer(process, "SceNpUdsIpc", unimplementedIpmiServer);
createIpmiServer(process, "SceLibNpRifMgrIpc", unimplementedIpmiServer);
createIpmiServer(process, "SceNpPartner001", unimplementedIpmiServer);
createIpmiServer(process, "SceNpPartnerSubs", unimplementedIpmiServer);
createIpmiServer(process, "SceNpGameIntent", unimplementedIpmiServer);
createIpmiServer(process, "SceBgft", unimplementedIpmiServer);
createIpmiServer(process, "SceCntMgrService", unimplementedIpmiServer);
createIpmiServer(process, "ScePlayGo", unimplementedIpmiServer);
createIpmiServer(process, "SceCompAppProxyUtil", unimplementedIpmiServer);
createIpmiServer(process, "SceShareSpIpcService", unimplementedIpmiServer);
createIpmiServer(process, "SceRnpsAppMgr", unimplementedIpmiServer);
createIpmiServer(process, "SceUpdateService", unimplementedIpmiServer);
createIpmiServer(process, "ScePatchChecker", unimplementedIpmiServer);
createIpmiServer(process, "SceMorpheusUpdService", unimplementedIpmiServer);
createIpmiServer(process, "ScePsmSharedDmem", unimplementedIpmiServer);
createIpmiServer(process, "SceSaveData", unimplementedIpmiServer);
createIpmiServer(process, "SceStickerCoreServer", unimplementedIpmiServer);
createIpmiServer(process, "SceDbRecoveryShellCore", unimplementedIpmiServer);
createIpmiServer(process, "SceUserService", unimplementedIpmiServer);
createIpmiServer(process, "SceDbPreparationServer", unimplementedIpmiServer);
createIpmiServer(process, "SceScreenShot", unimplementedIpmiServer);
createIpmiServer(process, "SceAppDbIpc", unimplementedIpmiServer);
createIpmiServer(process, "SceAppInst", unimplementedIpmiServer);
createIpmiServer(process, "SceAppContent", unimplementedIpmiServer);
createIpmiServer(process, "SceNpEntAccess", unimplementedIpmiServer);
createIpmiServer(process, "SceMwIPMIServer", unimplementedIpmiServer);
createIpmiServer(process, "SceAutoMounterIpc", unimplementedIpmiServer);
createIpmiServer(process, "SceBackupRestoreUtil", unimplementedIpmiServer);
createIpmiServer(process, "SceDataTransfer", unimplementedIpmiServer);
createIpmiServer(process, "SceEventService", unimplementedIpmiServer);
createIpmiServer(process, "SceShareFactoryUtil", unimplementedIpmiServer);
createIpmiServer(process, "SceCloudConnectManager", unimplementedIpmiServer);
createIpmiServer(process, "SceHubAppUtil", unimplementedIpmiServer);
createIpmiServer(process, "SceTcIPMIServer", unimplementedIpmiServer);
createIpmiServer(process, "SceSystemLoggerService");
createIpmiServer(process, "SceLoginMgrServer");
createIpmiServer(process, "SceLncService")
.createSyncHandler(0x30013,
[](void *out, std::uint64_t &size) -> std::int32_t {
struct SceLncServiceAppStatus {
std::uint32_t unk0;
std::uint32_t unk1;
std::uint32_t unk2;
};
if (size < sizeof(SceLncServiceAppStatus)) {
return -1;
}
*(SceLncServiceAppStatus *)out = {
.unk0 = 1,
.unk1 = 1,
.unk2 = 1,
};
size = sizeof(SceLncServiceAppStatus);
return 0;
});
createIpmiServer(process, "SceAppMessaging");
createIpmiServer(process, "SceShellCoreUtil");
createIpmiServer(process, "SceNetCtl");
createIpmiServer(process, "SceNpMgrIpc")
.createSyncHandler(
0, [=](void *out, std::uint64_t &size) -> std::int32_t {
std::string_view result = "SceNpMgrEvf";
std::strncpy((char *)out, result.data(), result.size() + 1);
size = result.size() + 1;
orbis::g_context.createEventFlag("SceNpMgrEvf", 0x200, 0);
return 0;
});
createIpmiServer(process, "SceNpService");
createIpmiServer(process, "SceNpTrophyIpc");
createIpmiServer(process, "SceNpUdsIpc");
createIpmiServer(process, "SceLibNpRifMgrIpc");
createIpmiServer(process, "SceNpPartner001");
createIpmiServer(process, "SceNpPartnerSubs");
createIpmiServer(process, "SceNpGameIntent");
createIpmiServer(process, "SceBgft");
createIpmiServer(process, "SceCntMgrService");
createIpmiServer(process, "ScePlayGo");
createIpmiServer(process, "SceCompAppProxyUtil");
createIpmiServer(process, "SceShareSpIpcService");
createIpmiServer(process, "SceRnpsAppMgr");
createIpmiServer(process, "SceUpdateService");
createIpmiServer(process, "ScePatchChecker");
createIpmiServer(process, "SceMorpheusUpdService");
createIpmiServer(process, "ScePsmSharedDmem");
createIpmiServer(process, "SceSaveData");
createIpmiServer(process, "SceStickerCoreServer");
createIpmiServer(process, "SceDbRecoveryShellCore");
createIpmiServer(process, "SceUserService")
.sendMsg(SceUserServiceEvent{.eventType = 0, .user = 1})
.createSyncHandler<uint32_t>(
0x30011,
[](void *ptr, std::uint64_t size, uint32_t data) -> std::int32_t {
ORBIS_LOG_TODO("SceUserService: get_initial_user_id");
if (size != sizeof(orbis::uint32_t)) {
return 0x8000'0000;
}
*(uint32_t *)ptr = 1;
return 0;
});
createIpmiServer(process, "SceDbPreparationServer");
createIpmiServer(process, "SceScreenShot");
createIpmiServer(process, "SceAppDbIpc");
createIpmiServer(process, "SceAppInst");
createIpmiServer(process, "SceAppContent");
createIpmiServer(process, "SceNpEntAccess");
createIpmiServer(process, "SceMwIPMIServer");
createIpmiServer(process, "SceAutoMounterIpc");
createIpmiServer(process, "SceBackupRestoreUtil");
createIpmiServer(process, "SceDataTransfer");
createIpmiServer(process, "SceEventService");
createIpmiServer(process, "SceShareFactoryUtil");
createIpmiServer(process, "SceCloudConnectManager");
createIpmiServer(process, "SceHubAppUtil");
createIpmiServer(process, "SceTcIPMIServer");
createSemaphore("SceLncSuspendBlock00000001", 0x101, 1, 1);
createSemaphore("SceAppMessaging00000001", 0x100, 0, 0x7fffffff);
createSemaphore("SceAppMessaging00000001", 0x100, 1, 0x7fffffff);
createEventFlag("SceAutoMountUsbMass", 0x120, 0);
createEventFlag("SceLoginMgrUtilityEventFlag", 0x112, 0);
@ -847,31 +1060,132 @@ static void createShellCoreObjects(orbis::Process *process) {
createEventFlag("SceSystemStateMgrInfo", 0x120, 0x10000000a);
createEventFlag("SceSystemStateMgrStatus", 0x120, 0);
createEventFlag("SceAppInstallerEventFlag", 0x120, 0);
createEventFlag("SceShellCoreUtilPowerControl", 0x120, 0xffff);
createEventFlag("SceShellCoreUtilAppFocus", 0x120, -1);
createEventFlag("SceShellCoreUtilCtrlFocus", 0x120, -1);
createEventFlag("SceShellCoreUtilPowerControl", 0x120, 0x400000);
createEventFlag("SceShellCoreUtilAppFocus", 0x120, 1);
createEventFlag("SceShellCoreUtilCtrlFocus", 0x120, 0);
createEventFlag("SceShellCoreUtilUIStatus", 0x120, 0x20001);
createEventFlag("SceShellCoreUtilDevIdxBehavior", 0x120, 0);
createEventFlag("SceNpMgrVshReq", 0x121, 0);
createEventFlag("SceNpIdMapperVshReq", 0x121, 0);
createEventFlag("SceRtcUtilTzdataUpdateFlag", 0x120, 0);
createEventFlag("SceDataTransfer", 0x120, 0);
createEventFlag("SceShellCoreUtilffffffff", 0x120, 0x3f8c);
createEventFlag("SceSysLogPullEvt_" + fmtHex(process->pid, true), 0x110, 0);
createEventFlag("SceNpIdMapperEvf00" + fmtHex(process->pid), 0x121, 0);
createEventFlag("SceNpBasicPreseEvf00" + fmtHex(process->pid), 0x121, 0);
createEventFlag("SceNpPresenceEvf00" + fmtHex(process->pid), 0x121, 0);
createEventFlag("SceNpInGameMsgEvf00" + fmtHex(process->pid), 0x121, 0);
createEventFlag("SceNpPush2Evf00" + fmtHex(process->pid), 0x121, 0);
createEventFlag("SceUserServiceGetEvent_" + fmtHex(process->pid), 0x110, 0);
createEventFlag("SceLncUtilAppStatus1", 0x100, 0);
createEventFlag("SceAppMessaging1", 0x120, 1);
createEventFlag("SceShellCoreUtil1", 0x120, 0x3f8c);
createEventFlag("SceLncUtilAppStatus00000001", 0x100, 0);
createEventFlag("SceAppMessaging00000001", 0x120, 0);
createSemaphore("SceAppMessaging1", 0x101, 1, 0x7fffffff);
createSemaphore("SceLncSuspendBlock1", 0x101, 1, 10000);
createShm("SceGlsSharedMemory", 0x202, 0x1a4, 262144);
createShm("SceShellCoreUtil", 0x202, 0x1a4, 16384);
createShm("SceNpTpip", 0x202, 0x1ff, 43008);
createShm("vmicDdShmAin", 0x202, 0x1b6, 43008);
createSemaphore("SceNpTpip 0", 0x101, 0, 1);
}
static orbis::SysResult launchDaemon(orbis::Thread *thread, std::string path,
std::vector<std::string> argv,
std::vector<std::string> envv) {
auto childPid = orbis::g_context.allocatePid() * 10000 + 1;
auto flag = orbis::knew<std::atomic<bool>>();
*flag = false;
int hostPid = ::fork();
if (hostPid) {
while (*flag == false) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
orbis::kfree(flag, sizeof(*flag));
return {};
}
auto process = orbis::g_context.createProcess(childPid);
auto logFd = ::open(("log-" + std::to_string(childPid) + ".txt").c_str(),
O_CREAT | O_TRUNC | O_WRONLY, 0666);
dup2(logFd, 1);
dup2(logFd, 2);
process->sysent = thread->tproc->sysent;
process->onSysEnter = thread->tproc->onSysEnter;
process->onSysExit = thread->tproc->onSysExit;
process->ops = thread->tproc->ops;
process->parentProcess = thread->tproc;
process->appInfo = {
.unk4 = orbis::slong(0x80000000'00000000),
};
process->authInfo = {
.unk0 = 0x3100000000000001,
.caps =
{
-1ul,
-1ul,
-1ul,
-1ul,
},
.attrs =
{
0x4000400040000000,
0x4000000000000000,
0x0080000000000002,
0xF0000000FFFF4000,
},
};
process->budgetId = 0;
process->isInSandbox = false;
rx::vm::fork(childPid);
rx::vfs::fork();
*flag = true;
auto [baseId, newThread] = process->threadsMap.emplace();
newThread->tproc = process;
newThread->tid = process->pid + baseId;
newThread->state = orbis::ThreadState::RUNNING;
newThread->context = thread->context;
newThread->fsBase = thread->fsBase;
orbis::g_currentThread = newThread;
thread = orbis::g_currentThread;
setupSigHandlers();
rx::thread::initialize();
rx::thread::setupThisThread();
ORBIS_LOG_ERROR(__FUNCTION__, path);
{
orbis::Ref<orbis::File> file;
auto result = rx::vfs::open(path, kOpenFlagReadOnly, 0, &file, thread);
if (result.isError()) {
return result;
}
}
rx::vm::reset();
thread->tproc->nextTlsSlot = 1;
auto executableModule = rx::linker::loadModuleFile(path, thread);
executableModule->id = thread->tproc->modulesMap.insert(executableModule);
thread->tproc->processParam = executableModule->processParam;
thread->tproc->processParamSize = executableModule->processParamSize;
thread->tproc->event.emit(orbis::kEvFiltProc, orbis::kNoteExec);
std::thread([&] {
rx::thread::setupSignalStack();
rx::thread::setupThisThread();
ps4Exec(thread, executableModule, argv, envv);
}).join();
std::abort();
}
int main(int argc, const char *argv[]) {
@ -1055,6 +1369,7 @@ int main(int argc, const char *argv[]) {
};
if (isSystem) {
amdgpu::bridge::expGpuPid = 50001;
initProcess->authInfo = {
.unk0 = 0x3100000000000001,
.caps =
@ -1075,6 +1390,7 @@ int main(int argc, const char *argv[]) {
initProcess->budgetId = 0;
initProcess->isInSandbox = false;
} else {
amdgpu::bridge::expGpuPid = initProcess->pid;
initProcess->authInfo = {
.unk0 = 0x3100000000000001,
.caps =
@ -1126,10 +1442,14 @@ int main(int argc, const char *argv[]) {
ps4InitFd(mainThread);
if (!isSystem) {
createMiniSysCoreObjects(initProcess);
createSysAvControlObjects(initProcess);
createSysCoreObjects(initProcess);
createGnmCompositorObjects(initProcess);
createShellCoreObjects(initProcess);
launchDaemon(mainThread, "/system/sys/orbis_audiod.elf",
{"/system/sys/orbis_audiod.elf"}, {});
}
std::vector<std::string> ps4Argv(argv + argIndex,

View file

@ -834,7 +834,6 @@ SysResult execve(Thread *thread, ptr<char> fname, ptr<ptr<char>> argv,
std::thread([&] {
rx::thread::setupSignalStack();
rx::thread::setupThisThread();
ORBIS_LOG_ERROR(__FUNCTION__, "exec");
ps4Exec(thread, executableModule, _argv, _envv);
}).join();
std::abort();