2023-06-24 22:48:25 +02:00
|
|
|
#include "amdgpu/bridge/bridge.hpp"
|
2023-07-07 13:23:54 +02:00
|
|
|
#include "backtrace.hpp"
|
2023-06-24 22:48:25 +02:00
|
|
|
#include "bridge.hpp"
|
2023-06-23 02:28:14 +02:00
|
|
|
#include "io-device.hpp"
|
|
|
|
|
#include "io-devices.hpp"
|
2024-01-13 18:57:02 +01:00
|
|
|
#include "iodev/mbus.hpp"
|
2023-12-31 15:07:46 +01:00
|
|
|
#include "iodev/mbus_av.hpp"
|
2023-06-23 02:28:14 +02:00
|
|
|
#include "linker.hpp"
|
|
|
|
|
#include "ops.hpp"
|
2023-07-06 18:16:25 +02:00
|
|
|
#include "thread.hpp"
|
2023-06-23 02:28:14 +02:00
|
|
|
#include "vfs.hpp"
|
|
|
|
|
#include "vm.hpp"
|
2023-12-31 12:30:49 +01:00
|
|
|
#include "xbyak/xbyak.h"
|
2023-11-10 21:41:44 +01:00
|
|
|
#include <rx/Version.hpp>
|
2024-09-03 12:25:06 +02:00
|
|
|
#include <rx/align.hpp>
|
|
|
|
|
#include <rx/hexdump.hpp>
|
2023-06-23 02:28:14 +02:00
|
|
|
|
2023-07-07 13:23:54 +02:00
|
|
|
#include <elf.h>
|
2023-11-02 14:26:58 +01:00
|
|
|
#include <linux/prctl.h>
|
2023-06-23 02:28:14 +02:00
|
|
|
#include <orbis/KernelContext.hpp>
|
|
|
|
|
#include <orbis/module.hpp>
|
|
|
|
|
#include <orbis/module/Module.hpp>
|
|
|
|
|
#include <orbis/sys/sysentry.hpp>
|
|
|
|
|
#include <orbis/sys/sysproto.hpp>
|
|
|
|
|
#include <orbis/thread/Process.hpp>
|
|
|
|
|
#include <orbis/thread/ProcessOps.hpp>
|
|
|
|
|
#include <orbis/thread/Thread.hpp>
|
|
|
|
|
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <pthread.h>
|
2023-07-27 02:03:02 +02:00
|
|
|
#include <sys/mman.h>
|
2023-11-02 14:26:58 +01:00
|
|
|
#include <sys/prctl.h>
|
2023-07-06 13:26:57 +02:00
|
|
|
#include <ucontext.h>
|
2023-06-23 02:28:14 +02:00
|
|
|
|
2023-11-15 11:59:24 +01:00
|
|
|
#include <atomic>
|
2023-06-23 02:28:14 +02:00
|
|
|
#include <csignal>
|
|
|
|
|
#include <cstddef>
|
|
|
|
|
#include <cstdint>
|
2023-11-15 11:59:24 +01:00
|
|
|
#include <filesystem>
|
|
|
|
|
#include <functional>
|
|
|
|
|
#include <sstream>
|
2023-12-27 18:07:30 +01:00
|
|
|
#include <unordered_map>
|
2023-06-23 02:28:14 +02:00
|
|
|
|
2023-06-24 22:48:25 +02:00
|
|
|
static int g_gpuPid;
|
2024-01-13 18:57:02 +01:00
|
|
|
extern bool allowMonoDebug;
|
|
|
|
|
|
2024-09-01 17:51:47 +02:00
|
|
|
template <typename T> std::vector<std::byte> toBytes(const T &value) {
|
|
|
|
|
std::vector<std::byte> result(sizeof(T));
|
|
|
|
|
std::memcpy(result.data(), &value, sizeof(value));
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-23 02:28:14 +02:00
|
|
|
__attribute__((no_stack_protector)) static void
|
|
|
|
|
handle_signal(int sig, siginfo_t *info, void *ucontext) {
|
2023-07-06 15:55:25 +02:00
|
|
|
if (auto hostFs = _readgsbase_u64()) {
|
2023-06-24 22:48:25 +02:00
|
|
|
_writefsbase_u64(hostFs);
|
|
|
|
|
}
|
2023-06-23 02:28:14 +02:00
|
|
|
|
2023-07-27 02:03:02 +02:00
|
|
|
auto signalAddress = reinterpret_cast<std::uintptr_t>(info->si_addr);
|
|
|
|
|
|
2024-09-01 17:51:47 +02:00
|
|
|
if (orbis::g_currentThread != nullptr &&
|
|
|
|
|
orbis::g_currentThread->tproc->vmId >= 0 && sig == SIGSEGV &&
|
2023-07-27 02:03:02 +02:00
|
|
|
signalAddress >= 0x40000 && signalAddress < 0x100'0000'0000) {
|
2024-09-01 16:43:45 +02:00
|
|
|
auto vmid = orbis::g_currentThread->tproc->vmId;
|
2023-07-27 02:03:02 +02:00
|
|
|
auto ctx = reinterpret_cast<ucontext_t *>(ucontext);
|
|
|
|
|
bool isWrite = (ctx->uc_mcontext.gregs[REG_ERR] & 0x2) != 0;
|
|
|
|
|
auto origVmProt = rx::vm::getPageProtection(signalAddress);
|
|
|
|
|
int prot = 0;
|
|
|
|
|
auto page = signalAddress / amdgpu::bridge::kHostPageSize;
|
|
|
|
|
|
|
|
|
|
if (origVmProt & rx::vm::kMapProtCpuRead) {
|
|
|
|
|
prot |= PROT_READ;
|
|
|
|
|
}
|
|
|
|
|
if (origVmProt & rx::vm::kMapProtCpuWrite) {
|
|
|
|
|
prot |= PROT_WRITE;
|
|
|
|
|
}
|
|
|
|
|
if (origVmProt & rx::vm::kMapProtCpuExec) {
|
|
|
|
|
prot |= PROT_EXEC;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (prot & (isWrite ? PROT_WRITE : PROT_READ)) {
|
|
|
|
|
auto bridge = rx::bridge.header;
|
|
|
|
|
|
|
|
|
|
while (true) {
|
2024-09-01 17:51:47 +02:00
|
|
|
auto flags =
|
|
|
|
|
bridge->cachePages[vmid][page].load(std::memory_order::relaxed);
|
2023-07-27 02:03:02 +02:00
|
|
|
|
|
|
|
|
if ((flags & amdgpu::bridge::kPageReadWriteLock) != 0) {
|
2023-08-06 16:18:40 +02:00
|
|
|
if ((flags & amdgpu::bridge::kPageLazyLock) != 0) {
|
|
|
|
|
if (std::uint32_t gpuCommand = 0;
|
2024-09-01 16:43:45 +02:00
|
|
|
!bridge->gpuCacheCommand[vmid].compare_exchange_weak(gpuCommand,
|
2024-09-01 17:51:47 +02:00
|
|
|
page)) {
|
2023-08-06 16:18:40 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-01 16:43:45 +02:00
|
|
|
while (!bridge->cachePages[vmid][page].compare_exchange_weak(
|
2023-08-06 16:18:40 +02:00
|
|
|
flags, flags & ~amdgpu::bridge::kPageLazyLock,
|
|
|
|
|
std::memory_order::relaxed)) {
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-07-27 02:03:02 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((flags & amdgpu::bridge::kPageWriteWatch) == 0) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!isWrite) {
|
|
|
|
|
prot &= ~PROT_WRITE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-01 16:43:45 +02:00
|
|
|
if (bridge->cachePages[vmid][page].compare_exchange_weak(
|
2023-07-27 02:03:02 +02:00
|
|
|
flags, amdgpu::bridge::kPageInvalidated,
|
|
|
|
|
std::memory_order::relaxed)) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (::mprotect((void *)(page * amdgpu::bridge::kHostPageSize),
|
|
|
|
|
amdgpu::bridge::kHostPageSize, prot)) {
|
|
|
|
|
std::perror("cache reprotection error");
|
|
|
|
|
std::abort();
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-31 12:22:22 +01:00
|
|
|
_writefsbase_u64(orbis::g_currentThread->fsBase);
|
2023-07-27 02:03:02 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::fprintf(stderr, "SIGSEGV, address %lx, access %s, prot %s\n",
|
|
|
|
|
signalAddress, isWrite ? "write" : "read",
|
|
|
|
|
rx::vm::mapProtToString(origVmProt).c_str());
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-04 01:53:58 +01:00
|
|
|
if (orbis::g_currentThread != nullptr) {
|
2024-09-01 16:43:45 +02:00
|
|
|
orbis::g_currentThread->tproc->exitStatus = sig;
|
2024-01-13 18:57:02 +01:00
|
|
|
orbis::g_currentThread->tproc->event.emit(orbis::kEvFiltProc,
|
|
|
|
|
orbis::kNoteExit, sig);
|
2024-01-04 01:53:58 +01:00
|
|
|
}
|
|
|
|
|
|
2023-06-24 22:48:25 +02:00
|
|
|
if (g_gpuPid > 0) {
|
|
|
|
|
// stop gpu thread
|
2023-12-31 12:30:49 +01:00
|
|
|
// ::kill(g_gpuPid, SIGINT);
|
2023-06-24 22:48:25 +02:00
|
|
|
}
|
|
|
|
|
|
2024-01-13 18:57:02 +01:00
|
|
|
allowMonoDebug = true;
|
2023-06-24 22:48:25 +02:00
|
|
|
if (sig != SIGINT) {
|
|
|
|
|
char buf[128] = "";
|
|
|
|
|
int len = snprintf(buf, sizeof(buf), " [%s] %u: Signal address=%p\n",
|
2023-10-31 12:22:22 +01:00
|
|
|
orbis::g_currentThread ? "guest" : "host",
|
|
|
|
|
orbis::g_currentThread ? orbis::g_currentThread->tid
|
|
|
|
|
: ::gettid(),
|
2023-07-06 18:16:25 +02:00
|
|
|
info->si_addr);
|
2023-06-24 22:48:25 +02:00
|
|
|
write(2, buf, len);
|
|
|
|
|
|
2023-07-06 18:16:25 +02:00
|
|
|
if (std::size_t printed =
|
2023-10-31 12:22:22 +01:00
|
|
|
rx::printAddressLocation(buf, sizeof(buf), orbis::g_currentThread,
|
2023-07-08 20:47:06 +02:00
|
|
|
(std::uint64_t)info->si_addr)) {
|
2023-06-24 22:48:25 +02:00
|
|
|
printed += std::snprintf(buf + printed, sizeof(buf) - printed, "\n");
|
|
|
|
|
write(2, buf, printed);
|
|
|
|
|
}
|
2023-06-23 02:28:14 +02:00
|
|
|
|
2023-10-31 12:22:22 +01:00
|
|
|
if (orbis::g_currentThread) {
|
2023-07-07 13:23:54 +02:00
|
|
|
rx::printStackTrace(reinterpret_cast<ucontext_t *>(ucontext),
|
2023-10-31 12:22:22 +01:00
|
|
|
orbis::g_currentThread, 2);
|
2023-06-24 22:48:25 +02:00
|
|
|
} else {
|
2023-07-07 13:23:54 +02:00
|
|
|
rx::printStackTrace(reinterpret_cast<ucontext_t *>(ucontext), 2);
|
2023-06-24 22:48:25 +02:00
|
|
|
}
|
2023-06-23 02:28:14 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-31 22:31:45 +02:00
|
|
|
struct sigaction act{};
|
2023-06-23 02:28:14 +02:00
|
|
|
sigset_t mask;
|
|
|
|
|
sigemptyset(&mask);
|
|
|
|
|
|
|
|
|
|
act.sa_handler = SIG_DFL;
|
|
|
|
|
act.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
|
|
|
|
act.sa_mask = mask;
|
|
|
|
|
|
|
|
|
|
if (sigaction(sig, &act, NULL)) {
|
|
|
|
|
perror("Error sigaction:");
|
|
|
|
|
std::exit(-1);
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-24 22:48:25 +02:00
|
|
|
if (sig == SIGINT) {
|
|
|
|
|
std::raise(SIGINT);
|
2023-06-23 02:28:14 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-31 12:22:22 +01:00
|
|
|
void setupSigHandlers() {
|
2024-01-13 18:57:02 +01:00
|
|
|
rx::thread::setupSignalStack();
|
2023-07-13 15:18:38 +02:00
|
|
|
|
2024-08-31 22:31:45 +02:00
|
|
|
struct sigaction act{};
|
2023-06-23 02:28:14 +02:00
|
|
|
act.sa_sigaction = handle_signal;
|
2024-01-13 18:57:02 +01:00
|
|
|
act.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_NODEFER;
|
2023-06-23 02:28:14 +02:00
|
|
|
|
|
|
|
|
if (sigaction(SIGSYS, &act, NULL)) {
|
|
|
|
|
perror("Error sigaction:");
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sigaction(SIGILL, &act, NULL)) {
|
|
|
|
|
perror("Error sigaction:");
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sigaction(SIGSEGV, &act, NULL)) {
|
|
|
|
|
perror("Error sigaction:");
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sigaction(SIGBUS, &act, NULL)) {
|
|
|
|
|
perror("Error sigaction:");
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sigaction(SIGABRT, &act, NULL)) {
|
|
|
|
|
perror("Error sigaction:");
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
2023-06-24 22:48:25 +02:00
|
|
|
|
|
|
|
|
if (sigaction(SIGINT, &act, NULL)) {
|
|
|
|
|
perror("Error sigaction:");
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
2024-01-13 18:57:02 +01:00
|
|
|
|
|
|
|
|
if (sigaction(SIGFPE, &act, NULL)) {
|
|
|
|
|
perror("Error sigaction:");
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
2023-06-23 02:28:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct StackWriter {
|
|
|
|
|
std::uint64_t address;
|
|
|
|
|
|
|
|
|
|
template <typename T> std::uint64_t push(T value) {
|
|
|
|
|
address -= sizeof(value);
|
|
|
|
|
address &= ~(alignof(T) - 1);
|
|
|
|
|
*reinterpret_cast<T *>(address) = value;
|
|
|
|
|
return address;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void align(std::uint64_t alignment) { address &= ~(alignment - 1); }
|
|
|
|
|
|
|
|
|
|
std::uint64_t pushString(const char *value) {
|
|
|
|
|
auto len = std::strlen(value);
|
|
|
|
|
address -= len + 1;
|
|
|
|
|
std::memcpy(reinterpret_cast<void *>(address), value, len + 1);
|
|
|
|
|
return address;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::uint64_t alloc(std::uint64_t size, std::uint64_t alignment) {
|
|
|
|
|
address -= size;
|
|
|
|
|
address &= ~(alignment - 1);
|
|
|
|
|
return address;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static bool g_traceSyscalls = false;
|
|
|
|
|
static const char *getSyscallName(orbis::Thread *thread, int sysno) {
|
|
|
|
|
auto sysvec = thread->tproc->sysent;
|
|
|
|
|
|
|
|
|
|
if (sysno >= sysvec->size) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return orbis::getSysentName(sysvec->table[sysno].call);
|
|
|
|
|
}
|
|
|
|
|
static void onSysEnter(orbis::Thread *thread, int id, uint64_t *args,
|
|
|
|
|
int argsCount) {
|
2023-10-31 23:58:03 +01:00
|
|
|
if (!g_traceSyscalls) {
|
2023-06-23 02:28:14 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2023-07-18 14:56:22 +02:00
|
|
|
flockfile(stderr);
|
|
|
|
|
std::fprintf(stderr, " [%u] ", thread->tid);
|
2023-06-23 02:28:14 +02:00
|
|
|
|
|
|
|
|
if (auto name = getSyscallName(thread, id)) {
|
2023-07-18 14:56:22 +02:00
|
|
|
std::fprintf(stderr, "%s(", name);
|
2023-06-23 02:28:14 +02:00
|
|
|
} else {
|
2023-07-18 14:56:22 +02:00
|
|
|
std::fprintf(stderr, "sys_%u(", id);
|
2023-06-23 02:28:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < argsCount; ++i) {
|
|
|
|
|
if (i != 0) {
|
2023-07-18 14:56:22 +02:00
|
|
|
std::fprintf(stderr, ", ");
|
2023-06-23 02:28:14 +02:00
|
|
|
}
|
|
|
|
|
|
2023-07-18 14:56:22 +02:00
|
|
|
std::fprintf(stderr, "%#lx", args[i]);
|
2023-06-23 02:28:14 +02:00
|
|
|
}
|
|
|
|
|
|
2023-07-18 14:56:22 +02:00
|
|
|
std::fprintf(stderr, ")\n");
|
|
|
|
|
funlockfile(stderr);
|
2023-06-23 02:28:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void onSysExit(orbis::Thread *thread, int id, uint64_t *args,
|
|
|
|
|
int argsCount, orbis::SysResult result) {
|
2023-10-31 23:58:03 +01:00
|
|
|
if (!result.isError() && !g_traceSyscalls) {
|
2023-06-23 02:28:14 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-18 14:56:22 +02:00
|
|
|
flockfile(stderr);
|
|
|
|
|
std::fprintf(stderr, "%c: [%u] ", result.isError() ? 'E' : 'S', thread->tid);
|
2023-06-23 02:28:14 +02:00
|
|
|
|
|
|
|
|
if (auto name = getSyscallName(thread, id)) {
|
2023-07-18 14:56:22 +02:00
|
|
|
std::fprintf(stderr, "%s(", name);
|
2023-06-23 02:28:14 +02:00
|
|
|
} else {
|
2023-07-18 14:56:22 +02:00
|
|
|
std::fprintf(stderr, "sys_%u(", id);
|
2023-06-23 02:28:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < argsCount; ++i) {
|
|
|
|
|
if (i != 0) {
|
2023-07-18 14:56:22 +02:00
|
|
|
std::fprintf(stderr, ", ");
|
2023-06-23 02:28:14 +02:00
|
|
|
}
|
|
|
|
|
|
2023-07-18 14:56:22 +02:00
|
|
|
std::fprintf(stderr, "%#lx", args[i]);
|
2023-06-23 02:28:14 +02:00
|
|
|
}
|
|
|
|
|
|
2023-07-18 14:56:22 +02:00
|
|
|
std::fprintf(stderr, ") -> Status %d, Value %lx:%lx\n", result.value(),
|
|
|
|
|
thread->retval[0], thread->retval[1]);
|
2023-07-29 23:34:52 +02:00
|
|
|
|
2023-12-31 12:30:49 +01:00
|
|
|
if (result.isError()) {
|
|
|
|
|
thread->where();
|
|
|
|
|
}
|
2023-07-18 14:56:22 +02:00
|
|
|
funlockfile(stderr);
|
2023-06-23 02:28:14 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-31 23:58:03 +01:00
|
|
|
static void ps4InitDev() {
|
2023-07-30 00:30:36 +02:00
|
|
|
auto dmem1 = createDmemCharacterDevice(1);
|
|
|
|
|
orbis::g_context.dmemDevice = dmem1;
|
|
|
|
|
|
2024-01-13 18:57:02 +01:00
|
|
|
auto ttyFd = ::open("tty.txt", O_CREAT | O_TRUNC | O_WRONLY, 0666);
|
|
|
|
|
auto consoleDev = createConsoleCharacterDevice(STDIN_FILENO, ttyFd);
|
|
|
|
|
auto mbus = static_cast<MBusDevice *>(createMBusCharacterDevice());
|
|
|
|
|
auto mbusAv = static_cast<MBusAVDevice *>(createMBusAVCharacterDevice());
|
2023-10-30 20:03:38 +01:00
|
|
|
|
2023-10-29 10:30:37 +01:00
|
|
|
rx::vfs::addDevice("dmem0", createDmemCharacterDevice(0));
|
|
|
|
|
rx::vfs::addDevice("npdrm", createNpdrmCharacterDevice());
|
2023-10-31 12:22:22 +01:00
|
|
|
rx::vfs::addDevice("icc_configuration",
|
|
|
|
|
createIccConfigurationCharacterDevice());
|
2023-11-02 14:26:58 +01:00
|
|
|
rx::vfs::addDevice("console", consoleDev);
|
2023-10-29 10:30:37 +01:00
|
|
|
rx::vfs::addDevice("camera", createCameraCharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("dmem1", dmem1);
|
|
|
|
|
rx::vfs::addDevice("dmem2", createDmemCharacterDevice(2));
|
2023-11-02 14:26:58 +01:00
|
|
|
rx::vfs::addDevice("stdout", consoleDev);
|
|
|
|
|
rx::vfs::addDevice("stderr", consoleDev);
|
|
|
|
|
rx::vfs::addDevice("deci_stdin", consoleDev);
|
|
|
|
|
rx::vfs::addDevice("deci_stdout", consoleDev);
|
|
|
|
|
rx::vfs::addDevice("deci_stderr", consoleDev);
|
2024-01-13 18:57:02 +01:00
|
|
|
rx::vfs::addDevice("deci_tty1", consoleDev);
|
|
|
|
|
rx::vfs::addDevice("deci_tty2", consoleDev);
|
|
|
|
|
rx::vfs::addDevice("deci_tty3", consoleDev);
|
|
|
|
|
rx::vfs::addDevice("deci_tty4", consoleDev);
|
|
|
|
|
rx::vfs::addDevice("deci_tty5", consoleDev);
|
|
|
|
|
rx::vfs::addDevice("deci_tty6", consoleDev);
|
|
|
|
|
rx::vfs::addDevice("deci_tty7", consoleDev);
|
2023-11-02 14:26:58 +01:00
|
|
|
rx::vfs::addDevice("stdin", consoleDev);
|
2023-10-29 10:30:37 +01:00
|
|
|
rx::vfs::addDevice("zero", createZeroCharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("null", createNullCharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("dipsw", createDipswCharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("dce", createDceCharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("hmd_cmd", createHmdCmdCharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("hmd_snsr", createHmdSnsrCharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("hmd_3da", createHmd3daCharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("hmd_dist", createHmdMmapCharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("hid", createHidCharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("gc", createGcCharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("rng", createRngCharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("sbl_srv", createSblSrvCharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("ajm", createAjmCharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("urandom", createUrandomCharacterDevice());
|
2024-01-13 18:57:02 +01:00
|
|
|
rx::vfs::addDevice("mbus", mbus);
|
2023-10-31 19:28:40 +01:00
|
|
|
rx::vfs::addDevice("metadbg", createMetaDbgCharacterDevice());
|
2023-10-31 12:22:22 +01:00
|
|
|
rx::vfs::addDevice("bt", createBtCharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("xpt0", createXptCharacterDevice());
|
2024-01-13 18:57:02 +01:00
|
|
|
rx::vfs::addDevice("cd0", createCdCharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("da0",
|
|
|
|
|
createHddCharacterDevice(250ull * 1024 * 1024 * 1024));
|
|
|
|
|
rx::vfs::addDevice("da0x0.crypt", createHddCharacterDevice(0x20000000));
|
|
|
|
|
rx::vfs::addDevice("da0x1.crypt", createHddCharacterDevice(0x40000000));
|
|
|
|
|
rx::vfs::addDevice("da0x2", createHddCharacterDevice(0x1000000));
|
|
|
|
|
rx::vfs::addDevice("da0x2.crypt", createHddCharacterDevice(0x1000000));
|
|
|
|
|
rx::vfs::addDevice("da0x3.crypt", createHddCharacterDevice(0x8000000));
|
|
|
|
|
rx::vfs::addDevice("da0x4.crypt", createHddCharacterDevice(0x40000000));
|
|
|
|
|
rx::vfs::addDevice("da0x4b.crypt", createHddCharacterDevice(0x40000000));
|
|
|
|
|
rx::vfs::addDevice("da0x5.crypt", createHddCharacterDevice(0x40000000));
|
|
|
|
|
rx::vfs::addDevice("da0x5b.crypt", createHddCharacterDevice(0x40000000));
|
2023-11-02 14:26:58 +01:00
|
|
|
// rx::vfs::addDevice("da0x6x0", createHddCharacterDevice()); // boot log
|
2024-01-13 18:57:02 +01:00
|
|
|
rx::vfs::addDevice("da0x6", createHddCharacterDevice(0x200000000));
|
|
|
|
|
rx::vfs::addDevice("da0x6x2.crypt", createHddCharacterDevice(0x200000000));
|
|
|
|
|
rx::vfs::addDevice("da0x8", createHddCharacterDevice(0x40000000));
|
|
|
|
|
rx::vfs::addDevice("da0x8.crypt", createHddCharacterDevice(0x40000000));
|
|
|
|
|
rx::vfs::addDevice("da0x9.crypt", createHddCharacterDevice(0x200000000));
|
|
|
|
|
rx::vfs::addDevice("da0x12.crypt", createHddCharacterDevice(0x180000000));
|
|
|
|
|
rx::vfs::addDevice("da0x13.crypt", createHddCharacterDevice(0));
|
|
|
|
|
rx::vfs::addDevice("da0x14.crypt", createHddCharacterDevice(0x40000000));
|
|
|
|
|
rx::vfs::addDevice("da0x15", createHddCharacterDevice(0));
|
|
|
|
|
rx::vfs::addDevice("da0x15.crypt", createHddCharacterDevice(0x400000000));
|
2023-10-30 20:03:38 +01:00
|
|
|
rx::vfs::addDevice("notification0", createNotificationCharacterDevice(0));
|
|
|
|
|
rx::vfs::addDevice("notification1", createNotificationCharacterDevice(1));
|
|
|
|
|
rx::vfs::addDevice("notification2", createNotificationCharacterDevice(2));
|
|
|
|
|
rx::vfs::addDevice("notification3", createNotificationCharacterDevice(3));
|
|
|
|
|
rx::vfs::addDevice("notification4", createNotificationCharacterDevice(4));
|
|
|
|
|
rx::vfs::addDevice("notification5", createNotificationCharacterDevice(5));
|
2023-11-03 20:41:32 +01:00
|
|
|
rx::vfs::addDevice("aout0", createAoutCharacterDevice());
|
2023-11-11 18:27:01 +01:00
|
|
|
rx::vfs::addDevice("aout1", createAoutCharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("aout2", createAoutCharacterDevice());
|
2023-11-03 20:41:32 +01:00
|
|
|
rx::vfs::addDevice("av_control", createAVControlCharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("hdmi", createHDMICharacterDevice());
|
2023-12-31 15:07:46 +01:00
|
|
|
rx::vfs::addDevice("mbus_av", mbusAv);
|
2023-11-03 20:41:32 +01:00
|
|
|
rx::vfs::addDevice("scanin", createScaninCharacterDevice());
|
2023-11-11 18:27:01 +01:00
|
|
|
rx::vfs::addDevice("s3da", createS3DACharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("gbase", createGbaseCharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("devstat", createDevStatCharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("devact", createDevActCharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("devctl", createDevCtlCharacterDevice());
|
2023-12-31 12:30:49 +01:00
|
|
|
rx::vfs::addDevice("uvd", createUVDCharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("vce", createVCECharacterDevice());
|
2024-01-13 18:57:02 +01:00
|
|
|
rx::vfs::addDevice("evlg1", createEvlgCharacterDevice(ttyFd));
|
|
|
|
|
rx::vfs::addDevice("srtc", createSrtcCharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("sshot", createScreenShotCharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("lvdctl", createLvdCtlCharacterDevice());
|
|
|
|
|
rx::vfs::addDevice("lvd0", createHddCharacterDevice(0x100000000));
|
|
|
|
|
rx::vfs::addDevice("icc_power", createIccPowerCharacterDevice());
|
2024-08-31 22:55:47 +02:00
|
|
|
rx::vfs::addDevice("cayman/reg", createCaymanRegCharacterDevice());
|
2024-08-31 23:41:32 +02:00
|
|
|
rx::vfs::addDevice("hctrl", createHidCharacterDevice());
|
2024-01-13 18:57:02 +01:00
|
|
|
|
|
|
|
|
// mbus->emitEvent({
|
|
|
|
|
// .system = 2,
|
|
|
|
|
// .eventId = 1,
|
|
|
|
|
// .deviceId = 0,
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
// mbus->emitEvent({
|
|
|
|
|
// .system = 9,
|
|
|
|
|
// .eventId = 1,
|
|
|
|
|
// .deviceId = 100,
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
mbusAv->emitEvent({
|
|
|
|
|
.system = 9,
|
|
|
|
|
.eventId = 1,
|
|
|
|
|
.deviceId = 100,
|
|
|
|
|
});
|
2023-11-11 18:27:01 +01:00
|
|
|
|
|
|
|
|
auto shm = createShmDevice();
|
|
|
|
|
rx::vfs::addDevice("shm", shm);
|
|
|
|
|
orbis::g_context.shmDevice = shm;
|
2023-10-31 23:58:03 +01:00
|
|
|
orbis::g_context.blockpoolDevice = createBlockPoolDevice();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ps4InitFd(orbis::Thread *mainThread) {
|
2023-07-29 18:53:34 +02:00
|
|
|
orbis::Ref<orbis::File> stdinFile;
|
|
|
|
|
orbis::Ref<orbis::File> stdoutFile;
|
|
|
|
|
orbis::Ref<orbis::File> stderrFile;
|
|
|
|
|
rx::procOpsTable.open(mainThread, "/dev/stdin", 0, 0, &stdinFile);
|
|
|
|
|
rx::procOpsTable.open(mainThread, "/dev/stdout", 0, 0, &stdoutFile);
|
|
|
|
|
rx::procOpsTable.open(mainThread, "/dev/stderr", 0, 0, &stderrFile);
|
|
|
|
|
|
|
|
|
|
mainThread->tproc->fileDescriptors.insert(stdinFile);
|
|
|
|
|
mainThread->tproc->fileDescriptors.insert(stdoutFile);
|
|
|
|
|
mainThread->tproc->fileDescriptors.insert(stderrFile);
|
2023-10-31 23:58:03 +01:00
|
|
|
}
|
2023-06-23 02:28:14 +02:00
|
|
|
|
2023-12-29 14:27:32 +01:00
|
|
|
struct ExecEnv {
|
|
|
|
|
std::uint64_t entryPoint;
|
|
|
|
|
std::uint64_t interpBase;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
int ps4Exec(orbis::Thread *mainThread, ExecEnv execEnv,
|
2023-10-31 23:58:03 +01:00
|
|
|
orbis::utils::Ref<orbis::Module> executableModule,
|
|
|
|
|
std::span<std::string> argv, std::span<std::string> envp) {
|
|
|
|
|
const auto stackEndAddress = 0x7'ffff'c000ull;
|
2023-11-02 14:26:58 +01:00
|
|
|
const auto stackSize = 0x40000 * 32;
|
2023-10-31 23:58:03 +01:00
|
|
|
auto stackStartAddress = stackEndAddress - stackSize;
|
|
|
|
|
mainThread->stackStart =
|
|
|
|
|
rx::vm::map(reinterpret_cast<void *>(stackStartAddress), stackSize,
|
|
|
|
|
rx::vm::kMapProtCpuWrite | rx::vm::kMapProtCpuRead,
|
|
|
|
|
rx::vm::kMapFlagAnonymous | rx::vm::kMapFlagFixed |
|
|
|
|
|
rx::vm::kMapFlagPrivate | rx::vm::kMapFlagStack);
|
|
|
|
|
|
|
|
|
|
mainThread->stackEnd =
|
|
|
|
|
reinterpret_cast<std::byte *>(mainThread->stackStart) + stackSize;
|
2023-07-29 21:46:28 +02:00
|
|
|
|
2023-06-23 02:28:14 +02:00
|
|
|
std::vector<std::uint64_t> argvOffsets;
|
|
|
|
|
std::vector<std::uint64_t> envpOffsets;
|
|
|
|
|
|
2023-07-06 15:55:25 +02:00
|
|
|
StackWriter stack{reinterpret_cast<std::uint64_t>(mainThread->stackEnd)};
|
2023-06-23 02:28:14 +02:00
|
|
|
|
2023-10-31 23:58:03 +01:00
|
|
|
for (auto &elem : argv) {
|
|
|
|
|
argvOffsets.push_back(stack.pushString(elem.data()));
|
2023-06-23 02:28:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
argvOffsets.push_back(0);
|
|
|
|
|
|
2023-10-31 23:58:03 +01:00
|
|
|
for (auto &elem : envp) {
|
|
|
|
|
envpOffsets.push_back(stack.pushString(elem.data()));
|
2023-06-23 02:28:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
envpOffsets.push_back(0);
|
|
|
|
|
|
|
|
|
|
// clang-format off
|
|
|
|
|
std::uint64_t auxv[] = {
|
|
|
|
|
AT_ENTRY, executableModule->entryPoint,
|
2023-12-29 14:27:32 +01:00
|
|
|
AT_BASE, execEnv.interpBase,
|
2024-08-31 22:31:45 +02:00
|
|
|
AT_PHDR, executableModule->phdrAddress,
|
|
|
|
|
AT_PHENT, sizeof(Elf64_Phdr),
|
|
|
|
|
AT_PHNUM, executableModule->phNum,
|
2023-06-23 02:28:14 +02:00
|
|
|
AT_NULL, 0
|
|
|
|
|
};
|
|
|
|
|
// clang-format on
|
|
|
|
|
|
|
|
|
|
std::size_t argSize =
|
|
|
|
|
sizeof(std::uint64_t) + sizeof(std::uint64_t) * argvOffsets.size() +
|
|
|
|
|
sizeof(std::uint64_t) * envpOffsets.size() + sizeof(auxv);
|
|
|
|
|
|
|
|
|
|
auto sp = stack.alloc(argSize, 32);
|
|
|
|
|
|
|
|
|
|
auto arg = reinterpret_cast<std::uint64_t *>(sp);
|
|
|
|
|
*arg++ = argvOffsets.size() - 1;
|
|
|
|
|
|
|
|
|
|
for (auto argvOffsets : argvOffsets) {
|
|
|
|
|
*arg++ = argvOffsets;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto envpOffset : envpOffsets) {
|
|
|
|
|
*arg++ = envpOffset;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
executableModule = {};
|
|
|
|
|
|
|
|
|
|
memcpy(arg, auxv, sizeof(auxv));
|
|
|
|
|
|
2023-07-06 13:26:57 +02:00
|
|
|
auto context = new ucontext_t{};
|
2023-06-23 02:28:14 +02:00
|
|
|
|
2023-07-06 13:26:57 +02:00
|
|
|
context->uc_mcontext.gregs[REG_RDI] = sp;
|
|
|
|
|
context->uc_mcontext.gregs[REG_RSP] = sp;
|
|
|
|
|
|
|
|
|
|
// FIXME: should be at guest user space
|
2023-07-06 18:16:25 +02:00
|
|
|
context->uc_mcontext.gregs[REG_RDX] =
|
|
|
|
|
reinterpret_cast<std::uint64_t>(+[] { std::printf("At exit\n"); });
|
2023-12-29 14:27:32 +01:00
|
|
|
context->uc_mcontext.gregs[REG_RIP] = execEnv.entryPoint;
|
2023-07-06 13:26:57 +02:00
|
|
|
|
2023-07-06 15:55:25 +02:00
|
|
|
mainThread->context = context;
|
|
|
|
|
rx::thread::invoke(mainThread);
|
2023-07-06 13:26:57 +02:00
|
|
|
std::abort();
|
2023-06-23 02:28:14 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-31 22:31:45 +02:00
|
|
|
struct Ps4ProcessParam {
|
|
|
|
|
orbis::size_t size;
|
|
|
|
|
orbis::uint32_t magic;
|
|
|
|
|
orbis::uint32_t version;
|
|
|
|
|
orbis::uint32_t sdkVersion;
|
|
|
|
|
orbis::uint32_t reserved;
|
|
|
|
|
orbis::ptr<char> processName;
|
|
|
|
|
orbis::ptr<char> userMainThreadName;
|
|
|
|
|
orbis::ptr<orbis::uint> userMainThreadPriority;
|
|
|
|
|
orbis::ptr<orbis::uint> userMainThreadStackSize;
|
|
|
|
|
orbis::ptr<void> libcParam;
|
|
|
|
|
};
|
|
|
|
|
|
2023-12-29 14:27:32 +01:00
|
|
|
ExecEnv ps4CreateExecEnv(orbis::Thread *mainThread,
|
|
|
|
|
orbis::Ref<orbis::Module> executableModule,
|
|
|
|
|
bool isSystem) {
|
|
|
|
|
std::uint64_t interpBase = 0;
|
|
|
|
|
std::uint64_t entryPoint = executableModule->entryPoint;
|
|
|
|
|
|
2024-08-31 22:31:45 +02:00
|
|
|
if (mainThread->tproc->processParam != nullptr &&
|
2024-09-02 19:32:27 +02:00
|
|
|
mainThread->tproc->processParamSize >= sizeof(Ps4ProcessParam)) {
|
2023-12-29 14:27:32 +01:00
|
|
|
auto processParam =
|
|
|
|
|
reinterpret_cast<std::byte *>(mainThread->tproc->processParam);
|
|
|
|
|
|
|
|
|
|
auto sdkVersion = processParam //
|
|
|
|
|
+ sizeof(uint64_t) // size
|
|
|
|
|
+ sizeof(uint32_t) // magic
|
|
|
|
|
+ sizeof(uint32_t); // entryCount
|
|
|
|
|
|
2024-01-13 18:57:02 +01:00
|
|
|
mainThread->tproc->sdkVersion = *(uint32_t *)sdkVersion;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (orbis::g_context.sdkVersion == 0 && mainThread->tproc->sdkVersion != 0) {
|
|
|
|
|
orbis::g_context.sdkVersion = mainThread->tproc->sdkVersion;
|
|
|
|
|
}
|
|
|
|
|
if (mainThread->tproc->sdkVersion == 0) {
|
|
|
|
|
mainThread->tproc->sdkVersion = orbis::g_context.sdkVersion;
|
2023-12-29 14:27:32 +01:00
|
|
|
}
|
|
|
|
|
|
2024-08-31 22:31:45 +02:00
|
|
|
if (executableModule->interp.empty()) {
|
|
|
|
|
return {.entryPoint = entryPoint, .interpBase = interpBase};
|
|
|
|
|
}
|
2023-12-29 14:27:32 +01:00
|
|
|
|
2024-08-31 22:31:45 +02:00
|
|
|
if (rx::vfs::exists(executableModule->interp, mainThread)) {
|
|
|
|
|
auto loader =
|
|
|
|
|
rx::linker::loadModuleFile(executableModule->interp, mainThread);
|
|
|
|
|
loader->id = mainThread->tproc->modulesMap.insert(loader);
|
|
|
|
|
interpBase = reinterpret_cast<std::uint64_t>(loader->base);
|
|
|
|
|
entryPoint = loader->entryPoint;
|
2023-12-29 14:27:32 +01:00
|
|
|
|
2024-08-31 22:31:45 +02:00
|
|
|
return {.entryPoint = entryPoint, .interpBase = interpBase};
|
|
|
|
|
}
|
2023-12-29 14:27:32 +01:00
|
|
|
|
2024-08-31 22:31:45 +02:00
|
|
|
auto libSceLibcInternal = rx::linker::loadModuleFile(
|
|
|
|
|
"/system/common/lib/libSceLibcInternal.sprx", mainThread);
|
2023-12-29 14:27:32 +01:00
|
|
|
|
2024-08-31 22:31:45 +02:00
|
|
|
if (libSceLibcInternal == nullptr) {
|
|
|
|
|
std::fprintf(stderr, "libSceLibcInternal not found\n");
|
|
|
|
|
std::abort();
|
|
|
|
|
}
|
2023-12-29 14:27:32 +01:00
|
|
|
|
2024-08-31 22:31:45 +02:00
|
|
|
libSceLibcInternal->id =
|
|
|
|
|
mainThread->tproc->modulesMap.insert(libSceLibcInternal);
|
2023-12-31 12:30:49 +01:00
|
|
|
|
2024-08-31 22:31:45 +02:00
|
|
|
auto libkernel = rx::linker::loadModuleFile(
|
|
|
|
|
(isSystem ? "/system/common/lib/libkernel_sys.sprx"
|
|
|
|
|
: "/system/common/lib/libkernel.sprx"),
|
|
|
|
|
mainThread);
|
|
|
|
|
|
|
|
|
|
if (libkernel == nullptr) {
|
|
|
|
|
std::fprintf(stderr, "libkernel not found\n");
|
|
|
|
|
std::abort();
|
|
|
|
|
}
|
2023-12-31 12:30:49 +01:00
|
|
|
|
2024-08-31 22:31:45 +02:00
|
|
|
for (auto sym : libkernel->symbols) {
|
|
|
|
|
if (sym.id == 0xd2f4e7e480cc53d0) {
|
|
|
|
|
auto address = (uint64_t)libkernel->base + sym.address;
|
2024-09-03 12:25:06 +02:00
|
|
|
::mprotect((void *)rx::alignDown(address, 0x1000),
|
|
|
|
|
rx::alignUp(sym.size + sym.address, 0x1000), PROT_WRITE);
|
2024-08-31 22:31:45 +02:00
|
|
|
std::printf("patching sceKernelGetMainSocId\n");
|
|
|
|
|
struct GetMainSocId : Xbyak::CodeGenerator {
|
|
|
|
|
GetMainSocId(std::uint64_t address, std::uint64_t size)
|
|
|
|
|
: Xbyak::CodeGenerator(size, (void *)address) {
|
|
|
|
|
mov(eax, 0x710f00);
|
|
|
|
|
ret();
|
|
|
|
|
}
|
|
|
|
|
} gen{address, sym.size};
|
|
|
|
|
|
2024-09-03 12:25:06 +02:00
|
|
|
::mprotect((void *)rx::alignDown(address, 0x1000),
|
|
|
|
|
rx::alignUp(sym.size + sym.address, 0x1000),
|
2024-08-31 22:31:45 +02:00
|
|
|
PROT_READ | PROT_EXEC);
|
|
|
|
|
break;
|
2023-12-29 14:27:32 +01:00
|
|
|
}
|
2024-08-31 22:31:45 +02:00
|
|
|
}
|
2023-12-29 14:27:32 +01:00
|
|
|
|
2024-08-31 22:31:45 +02:00
|
|
|
if (orbis::g_context.fwSdkVersion == 0) {
|
|
|
|
|
auto moduleParam = reinterpret_cast<std::byte *>(libkernel->moduleParam);
|
|
|
|
|
auto fwSdkVersion = moduleParam //
|
|
|
|
|
+ sizeof(uint64_t) // size
|
|
|
|
|
+ sizeof(uint64_t); // magic
|
|
|
|
|
orbis::g_context.fwSdkVersion = *(uint32_t *)fwSdkVersion;
|
|
|
|
|
std::printf("fw sdk version: %x\n", orbis::g_context.fwSdkVersion);
|
2023-12-29 14:27:32 +01:00
|
|
|
}
|
|
|
|
|
|
2024-08-31 22:31:45 +02:00
|
|
|
libkernel->id = mainThread->tproc->modulesMap.insert(libkernel);
|
|
|
|
|
interpBase = reinterpret_cast<std::uint64_t>(libkernel->base);
|
|
|
|
|
entryPoint = libkernel->entryPoint;
|
|
|
|
|
|
2023-12-29 14:27:32 +01:00
|
|
|
return {.entryPoint = entryPoint, .interpBase = interpBase};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int ps4Exec(orbis::Thread *mainThread,
|
|
|
|
|
orbis::utils::Ref<orbis::Module> executableModule,
|
|
|
|
|
std::span<std::string> argv, std::span<std::string> envp) {
|
|
|
|
|
auto execEnv = ps4CreateExecEnv(mainThread, executableModule, true);
|
|
|
|
|
return ps4Exec(mainThread, execEnv, std::move(executableModule), argv, envp);
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-23 02:28:14 +02:00
|
|
|
static void usage(const char *argv0) {
|
|
|
|
|
std::printf("%s [<options>...] <virtual path to elf> [args...]\n", argv0);
|
|
|
|
|
std::printf(" options:\n");
|
2023-11-10 21:41:44 +01:00
|
|
|
std::printf(" --version, -v - print version\n");
|
2023-06-23 02:28:14 +02:00
|
|
|
std::printf(" -m, --mount <host path> <virtual path>\n");
|
2023-08-13 22:46:03 +02:00
|
|
|
std::printf(" -a, --enable-audio\n");
|
2023-07-06 18:16:25 +02:00
|
|
|
std::printf(" -o, --override <original module name> <virtual path to "
|
|
|
|
|
"overriden module>\n");
|
2023-06-23 02:28:14 +02:00
|
|
|
std::printf(" --trace\n");
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-24 22:48:25 +02:00
|
|
|
static std::filesystem::path getSelfDir() {
|
|
|
|
|
char path[PATH_MAX];
|
|
|
|
|
int len = ::readlink("/proc/self/exe", path, sizeof(path));
|
|
|
|
|
if (len < 0 || len >= sizeof(path)) {
|
|
|
|
|
// TODO
|
|
|
|
|
return std::filesystem::current_path();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return std::filesystem::path(path).parent_path();
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-05 19:31:36 +02:00
|
|
|
static bool isRpcsxGpuPid(int pid) {
|
2023-06-24 22:48:25 +02:00
|
|
|
if (pid <= 0 || ::kill(pid, 0) != 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char path[PATH_MAX];
|
|
|
|
|
std::string procPath = "/proc/" + std::to_string(pid) + "/exe";
|
|
|
|
|
auto len = ::readlink(procPath.c_str(), path, sizeof(path));
|
|
|
|
|
|
|
|
|
|
if (len < 0 || len >= std::size(path)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
path[len] = 0;
|
|
|
|
|
|
2023-07-06 18:16:25 +02:00
|
|
|
std::printf("filename is '%s'\n",
|
|
|
|
|
std::filesystem::path(path).filename().c_str());
|
2023-06-24 22:48:25 +02:00
|
|
|
|
2024-09-05 19:31:36 +02:00
|
|
|
return std::filesystem::path(path).filename().string().starts_with("rpcsx-gpu");
|
2023-06-24 22:48:25 +02:00
|
|
|
}
|
2024-09-05 19:31:36 +02:00
|
|
|
static void runRpcsxGpu() {
|
2023-06-24 22:48:25 +02:00
|
|
|
const char *cmdBufferName = "/rpcsx-gpu-cmds";
|
2023-07-06 18:16:25 +02:00
|
|
|
amdgpu::bridge::BridgeHeader *bridgeHeader =
|
|
|
|
|
amdgpu::bridge::openShmCommandBuffer(cmdBufferName);
|
2023-06-24 22:48:25 +02:00
|
|
|
|
2023-07-06 18:16:25 +02:00
|
|
|
if (bridgeHeader != nullptr && bridgeHeader->pullerPid > 0 &&
|
2024-09-05 19:31:36 +02:00
|
|
|
isRpcsxGpuPid(bridgeHeader->pullerPid)) {
|
2023-06-24 22:48:25 +02:00
|
|
|
bridgeHeader->pusherPid = ::getpid();
|
|
|
|
|
g_gpuPid = bridgeHeader->pullerPid;
|
2023-12-31 12:30:49 +01:00
|
|
|
rx::bridge.header = bridgeHeader;
|
2023-06-24 22:48:25 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::printf("Starting rpcsx-gpu\n");
|
|
|
|
|
|
|
|
|
|
if (bridgeHeader == nullptr) {
|
|
|
|
|
bridgeHeader = amdgpu::bridge::createShmCommandBuffer(cmdBufferName);
|
|
|
|
|
}
|
|
|
|
|
bridgeHeader->pusherPid = ::getpid();
|
2023-12-31 12:30:49 +01:00
|
|
|
rx::bridge.header = bridgeHeader;
|
2023-06-24 22:48:25 +02:00
|
|
|
|
|
|
|
|
auto rpcsxGpuPath = getSelfDir() / "rpcsx-gpu";
|
|
|
|
|
|
|
|
|
|
if (!std::filesystem::is_regular_file(rpcsxGpuPath)) {
|
|
|
|
|
std::printf("failed to find rpcsx-gpu, continue without GPU emulation\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_gpuPid = ::fork();
|
|
|
|
|
|
|
|
|
|
if (g_gpuPid == 0) {
|
|
|
|
|
// TODO
|
|
|
|
|
const char *argv[] = {rpcsxGpuPath.c_str(), nullptr};
|
|
|
|
|
|
|
|
|
|
::execv(rpcsxGpuPath.c_str(), const_cast<char **>(argv));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-15 11:59:24 +01:00
|
|
|
static orbis::Semaphore *createSemaphore(std::string_view name, uint32_t attrs,
|
|
|
|
|
uint64_t initCount,
|
|
|
|
|
uint64_t maxCount) {
|
2024-01-13 18:57:02 +01:00
|
|
|
auto result =
|
|
|
|
|
orbis::g_context
|
|
|
|
|
.createSemaphore(orbis::kstring(name), attrs, initCount, maxCount)
|
|
|
|
|
.first;
|
2024-01-04 01:53:58 +01:00
|
|
|
std::memcpy(result->name, name.data(), name.size());
|
|
|
|
|
result->name[name.size()] = 0;
|
|
|
|
|
return result;
|
2023-11-15 11:59:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static orbis::EventFlag *createEventFlag(std::string_view name, uint32_t attrs,
|
|
|
|
|
uint64_t initPattern) {
|
|
|
|
|
return orbis::g_context
|
|
|
|
|
.createEventFlag(orbis::kstring(name), attrs, initPattern)
|
|
|
|
|
.first;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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>();
|
2023-12-27 18:07:30 +01:00
|
|
|
shmDevice->open(&shm, name, flags, mode, nullptr);
|
2024-01-13 18:57:02 +01:00
|
|
|
shm->ops->truncate(shm.get(), size, nullptr);
|
2023-11-15 11:59:24 +01:00
|
|
|
}
|
|
|
|
|
|
2023-12-27 18:07:30 +01:00
|
|
|
struct IpmiServer {
|
|
|
|
|
orbis::Ref<orbis::IpmiServer> serverImpl;
|
|
|
|
|
|
2024-09-01 17:51:47 +02:00
|
|
|
std::unordered_map<std::uint32_t,
|
|
|
|
|
std::function<orbis::ErrorCode(
|
|
|
|
|
orbis::IpmiSession &session, std::int32_t &errorCode,
|
|
|
|
|
std::vector<std::vector<std::byte>> &outData,
|
|
|
|
|
const std::vector<std::span<std::byte>> &inData)>>
|
|
|
|
|
syncMethods;
|
|
|
|
|
std::unordered_map<std::uint32_t,
|
|
|
|
|
std::function<orbis::ErrorCode(
|
|
|
|
|
orbis::IpmiSession &session, std::int32_t &errorCode,
|
|
|
|
|
std::vector<std::vector<std::byte>> &outData,
|
|
|
|
|
const std::vector<std::span<std::byte>> &inData)>>
|
|
|
|
|
asyncMethods;
|
2023-12-27 18:07:30 +01:00
|
|
|
std::vector<std::vector<std::byte>> messages;
|
|
|
|
|
|
2024-09-01 17:51:47 +02:00
|
|
|
IpmiServer &addSyncMethodStub(
|
|
|
|
|
std::uint32_t methodId,
|
|
|
|
|
std::function<std::int32_t()> handler = [] -> std::int32_t {
|
|
|
|
|
return 0;
|
|
|
|
|
}) {
|
|
|
|
|
syncMethods[methodId] = [=](orbis::IpmiSession &session,
|
|
|
|
|
std::int32_t &errorCode,
|
|
|
|
|
std::vector<std::vector<std::byte>> &outData,
|
|
|
|
|
const std::vector<std::span<std::byte>> &inData)
|
2023-12-31 12:30:49 +01:00
|
|
|
-> orbis::ErrorCode {
|
|
|
|
|
if (!outData.empty()) {
|
|
|
|
|
return orbis::ErrorCode::INVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
errorCode = handler();
|
|
|
|
|
return {};
|
|
|
|
|
};
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-01 17:51:47 +02:00
|
|
|
IpmiServer &addSyncMethod(
|
2023-12-27 18:07:30 +01:00
|
|
|
std::uint32_t methodId,
|
|
|
|
|
std::function<std::int32_t(void *out, std::uint64_t &outSize)> handler) {
|
2024-09-01 17:51:47 +02:00
|
|
|
syncMethods[methodId] = [=](orbis::IpmiSession &session,
|
|
|
|
|
std::int32_t &errorCode,
|
|
|
|
|
std::vector<std::vector<std::byte>> &outData,
|
|
|
|
|
const std::vector<std::span<std::byte>> &inData)
|
2023-12-27 18:07:30 +01:00
|
|
|
-> orbis::ErrorCode {
|
2023-12-31 12:30:49 +01:00
|
|
|
if (outData.size() < 1) {
|
2023-12-27 18:07:30 +01:00
|
|
|
return orbis::ErrorCode::INVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::uint64_t size = outData[0].size();
|
|
|
|
|
errorCode = handler(outData[0].data(), size);
|
2024-09-01 17:51:47 +02:00
|
|
|
outData[0].resize(size);
|
2023-12-27 18:07:30 +01:00
|
|
|
return {};
|
|
|
|
|
};
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
2024-09-01 17:51:47 +02:00
|
|
|
IpmiServer &
|
|
|
|
|
addSyncMethod(std::uint32_t methodId,
|
|
|
|
|
std::function<std::int32_t(void *out, std::uint64_t &outSize,
|
|
|
|
|
const T ¶m)>
|
|
|
|
|
handler) {
|
|
|
|
|
syncMethods[methodId] = [=](orbis::IpmiSession &session,
|
|
|
|
|
std::int32_t &errorCode,
|
|
|
|
|
std::vector<std::vector<std::byte>> &outData,
|
|
|
|
|
const std::vector<std::span<std::byte>> &inData)
|
2023-12-27 18:07:30 +01:00
|
|
|
-> 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()));
|
2024-09-01 17:51:47 +02:00
|
|
|
outData[0].resize(size);
|
2023-12-27 18:07:30 +01:00
|
|
|
return {};
|
|
|
|
|
};
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-31 12:30:49 +01:00
|
|
|
template <typename OutT, typename InT>
|
2024-09-01 17:51:47 +02:00
|
|
|
IpmiServer &addSyncMethod(
|
2023-12-31 12:30:49 +01:00
|
|
|
std::uint32_t methodId,
|
|
|
|
|
std::function<std::int32_t(OutT &out, const InT ¶m)> handler) {
|
2024-09-01 17:51:47 +02:00
|
|
|
syncMethods[methodId] = [=](orbis::IpmiSession &session,
|
|
|
|
|
std::int32_t &errorCode,
|
|
|
|
|
std::vector<std::vector<std::byte>> &outData,
|
|
|
|
|
const std::vector<std::span<std::byte>> &inData)
|
2023-12-31 12:30:49 +01:00
|
|
|
-> orbis::ErrorCode {
|
|
|
|
|
if (outData.size() != 1 || inData.size() != 1) {
|
|
|
|
|
return orbis::ErrorCode::INVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (inData[0].size() != sizeof(InT)) {
|
|
|
|
|
return orbis::ErrorCode::INVAL;
|
|
|
|
|
}
|
|
|
|
|
if (outData[0].size() < sizeof(OutT)) {
|
|
|
|
|
return orbis::ErrorCode::INVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OutT out;
|
|
|
|
|
errorCode = handler(out, *reinterpret_cast<InT *>(inData[0].data()));
|
|
|
|
|
std::memcpy(outData[0].data(), &out, sizeof(out));
|
2024-09-01 17:51:47 +02:00
|
|
|
outData[0].resize(sizeof(OutT));
|
2023-12-31 12:30:49 +01:00
|
|
|
return {};
|
|
|
|
|
};
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-27 18:07:30 +01:00
|
|
|
template <typename T>
|
|
|
|
|
IpmiServer &
|
2024-09-01 17:51:47 +02:00
|
|
|
addSyncMethod(std::uint32_t methodId,
|
|
|
|
|
std::function<std::int32_t(const T ¶m)> handler) {
|
|
|
|
|
syncMethods[methodId] = [=](orbis::IpmiSession &session,
|
|
|
|
|
std::int32_t &errorCode,
|
|
|
|
|
std::vector<std::vector<std::byte>> &outData,
|
|
|
|
|
const std::vector<std::span<std::byte>> &inData)
|
2023-12-27 18:07:30 +01:00
|
|
|
-> 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;
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-01 17:51:47 +02:00
|
|
|
IpmiServer &
|
|
|
|
|
addSyncMethod(std::uint32_t methodId,
|
|
|
|
|
std::function<std::int32_t(
|
|
|
|
|
std::vector<std::vector<std::byte>> &outData,
|
|
|
|
|
const std::vector<std::span<std::byte>> &inData)>
|
|
|
|
|
handler) {
|
|
|
|
|
syncMethods[methodId] = [=](orbis::IpmiSession &session,
|
|
|
|
|
std::int32_t &errorCode,
|
|
|
|
|
std::vector<std::vector<std::byte>> &outData,
|
|
|
|
|
const std::vector<std::span<std::byte>> &inData)
|
|
|
|
|
-> orbis::ErrorCode {
|
|
|
|
|
errorCode = handler(outData, inData);
|
|
|
|
|
return {};
|
|
|
|
|
};
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IpmiServer &
|
|
|
|
|
addSyncMethod(std::uint32_t methodId,
|
|
|
|
|
std::function<orbis::ErrorCode(
|
|
|
|
|
std::vector<std::vector<std::byte>> &outData,
|
|
|
|
|
const std::vector<std::span<std::byte>> &inData)>
|
|
|
|
|
handler) {
|
|
|
|
|
syncMethods[methodId] = [=](orbis::IpmiSession &session,
|
|
|
|
|
std::int32_t &errorCode,
|
|
|
|
|
std::vector<std::vector<std::byte>> &outData,
|
|
|
|
|
const std::vector<std::span<std::byte>> &inData)
|
|
|
|
|
-> orbis::ErrorCode { return handler(outData, inData); };
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IpmiServer &
|
|
|
|
|
addAsyncMethod(std::uint32_t methodId,
|
|
|
|
|
std::function<orbis::ErrorCode(
|
|
|
|
|
orbis::IpmiSession &session,
|
|
|
|
|
std::vector<std::vector<std::byte>> &outData,
|
|
|
|
|
const std::vector<std::span<std::byte>> &inData)>
|
|
|
|
|
handler) {
|
|
|
|
|
asyncMethods[methodId] =
|
|
|
|
|
[=](orbis::IpmiSession &session, std::int32_t &errorCode,
|
|
|
|
|
std::vector<std::vector<std::byte>> &outData,
|
|
|
|
|
const std::vector<std::span<std::byte>> &inData)
|
|
|
|
|
-> orbis::ErrorCode { return handler(session, outData, inData); };
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IpmiServer &
|
|
|
|
|
addSyncMethod(std::uint32_t methodId,
|
|
|
|
|
std::function<orbis::ErrorCode(
|
|
|
|
|
orbis::IpmiSession &session,
|
|
|
|
|
std::vector<std::vector<std::byte>> &outData,
|
|
|
|
|
const std::vector<std::span<std::byte>> &inData)>
|
|
|
|
|
handler) {
|
|
|
|
|
asyncMethods[methodId] =
|
|
|
|
|
[=](orbis::IpmiSession &session, std::int32_t &errorCode,
|
|
|
|
|
std::vector<std::vector<std::byte>> &outData,
|
|
|
|
|
const std::vector<std::span<std::byte>> &inData)
|
|
|
|
|
-> orbis::ErrorCode { return handler(session, outData, inData); };
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-27 18:07:30 +01:00
|
|
|
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,
|
2024-09-01 17:51:47 +02:00
|
|
|
orbis::IpmiAsyncMessageHeader *message) {
|
|
|
|
|
std::vector<std::span<std::byte>> inData;
|
|
|
|
|
std::vector<std::vector<std::byte>> outData;
|
|
|
|
|
auto bufLoc = std::bit_cast<std::byte *>(message + 1);
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
orbis::IpmiClient::AsyncResponse response;
|
|
|
|
|
response.methodId = message->methodId + 1;
|
|
|
|
|
response.errorCode = 0;
|
|
|
|
|
orbis::ErrorCode result{};
|
|
|
|
|
|
|
|
|
|
if (auto it = asyncMethods.find(message->methodId);
|
|
|
|
|
it != asyncMethods.end()) {
|
|
|
|
|
auto &handler = it->second;
|
|
|
|
|
|
|
|
|
|
result = handler(*session, response.errorCode, outData, inData);
|
|
|
|
|
} else {
|
|
|
|
|
std::fprintf(stderr, "Unimplemented async method %s::%x(inBufCount=%u)\n",
|
|
|
|
|
session->server->name.c_str(), message->methodId,
|
|
|
|
|
message->numInData);
|
|
|
|
|
|
|
|
|
|
for (auto in : inData) {
|
|
|
|
|
std::fprintf(stderr, "in %zu\n", in.size());
|
|
|
|
|
rx::hexdump(in);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto out : outData) {
|
|
|
|
|
response.data.push_back({out.data(), out.data() + out.size()});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::lock_guard clientLock(session->client->mutex);
|
|
|
|
|
session->client->asyncResponses.push_front(std::move(response));
|
|
|
|
|
std::fprintf(stderr, "%s:%x: sending async response\n",
|
|
|
|
|
session->client->name.c_str(), message->methodId);
|
|
|
|
|
session->client->asyncResponseCv.notify_all(session->client->mutex);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
orbis::ErrorCode handle(orbis::IpmiSession *session,
|
|
|
|
|
orbis::IpmiServer::Packet &packet,
|
2023-12-27 18:07:30 +01:00
|
|
|
orbis::IpmiSyncMessageHeader *message) {
|
|
|
|
|
std::size_t inBufferOffset = 0;
|
|
|
|
|
auto bufLoc = std::bit_cast<std::byte *>(message + 1);
|
|
|
|
|
std::vector<std::span<std::byte>> inData;
|
2024-09-01 17:51:47 +02:00
|
|
|
std::vector<std::vector<std::byte>> outData;
|
2023-12-27 18:07:30 +01:00
|
|
|
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);
|
2024-09-01 17:51:47 +02:00
|
|
|
outData.push_back(std::vector<std::byte>(size));
|
2023-12-27 18:07:30 +01:00
|
|
|
}
|
|
|
|
|
|
2024-01-13 18:57:02 +01:00
|
|
|
orbis::IpmiSession::SyncResponse response;
|
|
|
|
|
response.errorCode = 0;
|
|
|
|
|
orbis::ErrorCode result{};
|
|
|
|
|
|
2024-09-01 17:51:47 +02:00
|
|
|
if (auto it = syncMethods.find(message->methodId);
|
|
|
|
|
it != syncMethods.end()) {
|
2023-12-27 18:07:30 +01:00
|
|
|
auto &handler = it->second;
|
|
|
|
|
|
2024-09-01 17:51:47 +02:00
|
|
|
result = handler(*session, response.errorCode, outData, inData);
|
2024-01-13 18:57:02 +01:00
|
|
|
} else {
|
|
|
|
|
std::fprintf(
|
|
|
|
|
stderr,
|
2024-09-01 17:51:47 +02:00
|
|
|
"Unimplemented sync method %s::%x(inBufCount=%u, outBufCount=%u)\n",
|
2024-01-13 18:57:02 +01:00
|
|
|
session->server->name.c_str(), message->methodId, message->numInData,
|
|
|
|
|
message->numOutData);
|
|
|
|
|
|
2024-09-01 17:51:47 +02:00
|
|
|
for (auto in : inData) {
|
|
|
|
|
std::fprintf(stderr, "in %zu\n", in.size());
|
|
|
|
|
rx::hexdump(in);
|
|
|
|
|
}
|
2024-01-13 18:57:02 +01:00
|
|
|
|
2024-09-01 17:51:47 +02:00
|
|
|
for (auto out : outData) {
|
|
|
|
|
std::fprintf(stderr, "out %zx\n", out.size());
|
|
|
|
|
}
|
2024-01-13 18:57:02 +01:00
|
|
|
|
|
|
|
|
for (auto out : outData) {
|
|
|
|
|
std::memset(out.data(), 0, out.size());
|
2023-12-27 18:07:30 +01:00
|
|
|
}
|
2024-01-13 18:57:02 +01:00
|
|
|
// TODO:
|
|
|
|
|
// response.errorCode = message->numOutData == 0 ||
|
|
|
|
|
// (message->numOutData == 1 && outData[0].empty())
|
|
|
|
|
// ? 0
|
|
|
|
|
// : -1,
|
2023-12-27 18:07:30 +01:00
|
|
|
}
|
|
|
|
|
|
2024-09-01 17:51:47 +02:00
|
|
|
response.callerTid = packet.clientTid;
|
2024-01-13 18:57:02 +01:00
|
|
|
for (auto out : outData) {
|
2024-09-01 17:51:47 +02:00
|
|
|
response.data.push_back({out.data(), out.data() + out.size()});
|
2024-01-13 18:57:02 +01:00
|
|
|
}
|
2023-12-31 12:30:49 +01:00
|
|
|
|
2023-12-27 18:07:30 +01:00
|
|
|
std::lock_guard lock(session->mutex);
|
2024-01-13 18:57:02 +01:00
|
|
|
session->syncResponses.push_front(std::move(response));
|
2024-09-01 17:51:47 +02:00
|
|
|
session->responseCv.notify_all(session->mutex);
|
2024-01-13 18:57:02 +01:00
|
|
|
|
|
|
|
|
return result;
|
2023-12-27 18:07:30 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static IpmiServer &createIpmiServer(orbis::Process *process, const char *name) {
|
2023-11-15 11:59:24 +01:00
|
|
|
orbis::IpmiCreateServerConfig config{};
|
2023-12-27 18:07:30 +01:00
|
|
|
orbis::Ref<orbis::IpmiServer> serverImpl;
|
|
|
|
|
orbis::ipmiCreateServer(process, nullptr, name, config, serverImpl);
|
|
|
|
|
auto server = std::make_shared<IpmiServer>();
|
|
|
|
|
server->serverImpl = serverImpl;
|
|
|
|
|
|
2024-01-13 18:57:02 +01:00
|
|
|
std::thread{[server, serverImpl, name] {
|
|
|
|
|
pthread_setname_np(pthread_self(), name);
|
2023-11-15 11:59:24 +01:00
|
|
|
while (true) {
|
|
|
|
|
orbis::IpmiServer::Packet packet;
|
|
|
|
|
{
|
2023-12-27 18:07:30 +01:00
|
|
|
std::lock_guard lock(serverImpl->mutex);
|
2023-11-15 11:59:24 +01:00
|
|
|
|
2023-12-27 18:07:30 +01:00
|
|
|
while (serverImpl->packets.empty()) {
|
|
|
|
|
serverImpl->receiveCv.wait(serverImpl->mutex);
|
2023-11-15 11:59:24 +01:00
|
|
|
}
|
|
|
|
|
|
2023-12-27 18:07:30 +01:00
|
|
|
packet = std::move(serverImpl->packets.front());
|
|
|
|
|
serverImpl->packets.pop_front();
|
2023-11-15 11:59:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (packet.info.type == 1) {
|
2023-12-27 18:07:30 +01:00
|
|
|
std::lock_guard serverLock(serverImpl->mutex);
|
2023-11-15 11:59:24 +01:00
|
|
|
|
2023-12-27 18:07:30 +01:00
|
|
|
for (auto it = serverImpl->connectionRequests.begin();
|
|
|
|
|
it != serverImpl->connectionRequests.end(); ++it) {
|
2023-11-15 11:59:24 +01:00
|
|
|
auto &conReq = *it;
|
|
|
|
|
std::lock_guard clientLock(conReq.client->mutex);
|
|
|
|
|
if (conReq.client->session != nullptr) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto session = orbis::knew<orbis::IpmiSession>();
|
|
|
|
|
if (session == nullptr) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
session->client = conReq.client;
|
2023-12-27 18:07:30 +01:00
|
|
|
session->server = serverImpl;
|
2023-11-15 11:59:24 +01:00
|
|
|
conReq.client->session = session;
|
2023-12-27 18:07:30 +01:00
|
|
|
|
|
|
|
|
for (auto &message : server->messages) {
|
2024-01-13 18:57:02 +01:00
|
|
|
conReq.client->messageQueues[0].messages.push_back(
|
|
|
|
|
orbis::kvector<std::byte>(message.data(),
|
|
|
|
|
message.data() + message.size()));
|
2023-12-27 18:07:30 +01:00
|
|
|
}
|
|
|
|
|
|
2024-09-02 19:44:25 +02:00
|
|
|
conReq.client->connectionStatus = 0;
|
2023-11-15 11:59:24 +01:00
|
|
|
conReq.client->sessionCv.notify_all(conReq.client->mutex);
|
2024-09-02 19:44:25 +02:00
|
|
|
conReq.client->connectCv.notify_all(conReq.client->mutex);
|
2023-11-15 11:59:24 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((packet.info.type & ~0x8010) == 0x41) {
|
|
|
|
|
auto msgHeader = std::bit_cast<orbis::IpmiSyncMessageHeader *>(
|
|
|
|
|
packet.message.data());
|
|
|
|
|
auto process = orbis::g_context.findProcessById(msgHeader->pid);
|
|
|
|
|
if (process == nullptr) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2024-09-02 19:29:31 +02:00
|
|
|
auto client = orbis::g_context.ipmiMap.get(packet.info.clientKid)
|
2023-11-15 11:59:24 +01:00
|
|
|
.cast<orbis::IpmiClient>();
|
|
|
|
|
if (client == nullptr) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
auto session = client->session;
|
|
|
|
|
if (session == nullptr) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-01 17:51:47 +02:00
|
|
|
server->handle(client->session.get(), packet, msgHeader);
|
|
|
|
|
packet = {};
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((packet.info.type & ~0x10) == 0x43) {
|
|
|
|
|
auto msgHeader = (orbis::IpmiAsyncMessageHeader *)packet.message.data();
|
|
|
|
|
auto process = orbis::g_context.findProcessById(msgHeader->pid);
|
|
|
|
|
if (process == nullptr) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2024-09-02 19:29:31 +02:00
|
|
|
auto client = orbis::g_context.ipmiMap.get(packet.info.clientKid)
|
2024-09-01 17:51:47 +02:00
|
|
|
.cast<orbis::IpmiClient>();
|
|
|
|
|
if (client == nullptr) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
auto session = client->session;
|
|
|
|
|
if (session == nullptr) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-27 18:07:30 +01:00
|
|
|
server->handle(client->session.get(), msgHeader);
|
2023-11-15 11:59:24 +01:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::fprintf(stderr, "IPMI: Unhandled packet %s::%u\n",
|
2023-12-27 18:07:30 +01:00
|
|
|
serverImpl->name.c_str(), packet.info.type);
|
2023-11-15 11:59:24 +01:00
|
|
|
}
|
|
|
|
|
}}.detach();
|
|
|
|
|
|
2023-12-27 18:07:30 +01:00
|
|
|
return *server;
|
|
|
|
|
}
|
2023-11-15 11:59:24 +01:00
|
|
|
|
2023-12-27 18:07:30 +01:00
|
|
|
static void createMiniSysCoreObjects(orbis::Process *process) {
|
2023-12-29 14:27:32 +01:00
|
|
|
createEventFlag("SceBootStatusFlags", 0x121, ~0ull);
|
2023-11-15 11:59:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void createSysAvControlObjects(orbis::Process *process) {
|
2023-12-27 18:07:30 +01:00
|
|
|
createIpmiServer(process, "SceAvSettingIpc");
|
2023-11-15 11:59:24 +01:00
|
|
|
|
2023-12-31 12:30:49 +01:00
|
|
|
createIpmiServer(process, "SceAvCaptureIpc");
|
|
|
|
|
createEventFlag("SceAvCaptureIpc", 0x121, 0);
|
2023-11-15 11:59:24 +01:00
|
|
|
createEventFlag("SceAvSettingEvf", 0x121, 0xffff00000000);
|
|
|
|
|
|
|
|
|
|
createShm("/SceAvSetting", 0xa02, 0x1a4, 4096);
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-25 13:54:28 +02:00
|
|
|
struct SceSysAudioSystemThreadArgs {
|
|
|
|
|
uint32_t threadId;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct SceSysAudioSystemPortAndThreadArgs {
|
|
|
|
|
uint32_t audioPort;
|
|
|
|
|
uint32_t threadId;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void createAudioSystemObjects(orbis::Process *process) {
|
|
|
|
|
createIpmiServer(process, "SceSysAudioSystemIpc")
|
|
|
|
|
.addSyncMethod<SceSysAudioSystemThreadArgs>(
|
|
|
|
|
0x12340000, [](const auto &args) -> std::int32_t {
|
|
|
|
|
ORBIS_LOG_TODO("IPMI: SceSysAudioSystemCreateControl", args.threadId);
|
|
|
|
|
if (auto audioOut = orbis::g_context.audioOut) {
|
|
|
|
|
audioOut->channelInfo.idControl = args.threadId;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
})
|
|
|
|
|
.addSyncMethod<SceSysAudioSystemThreadArgs>(
|
|
|
|
|
0x1234000f, [](const auto &args) -> std::int32_t {
|
|
|
|
|
ORBIS_LOG_TODO("IPMI: SceSysAudioSystemOpenMixFlag", args.threadId);
|
|
|
|
|
if (auto audioOut = orbis::g_context.audioOut) {
|
|
|
|
|
// very bad
|
|
|
|
|
char buffer[32];
|
|
|
|
|
std::snprintf(buffer, sizeof(buffer), "sceAudioOutMix%x",
|
|
|
|
|
args.threadId);
|
|
|
|
|
auto [eventFlag, inserted] = orbis::g_context.createEventFlag(buffer, 0x100, 0);
|
|
|
|
|
|
|
|
|
|
if (!inserted) {
|
|
|
|
|
return 17; // FIXME: verify
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
audioOut->channelInfo.evf = eventFlag;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
})
|
|
|
|
|
.addSyncMethod<SceSysAudioSystemPortAndThreadArgs>(
|
|
|
|
|
0x12340001, [](const auto &args) -> std::int32_t {
|
|
|
|
|
ORBIS_LOG_TODO("IPMI: SceSysAudioSystemOpenPort", args.threadId, args.audioPort);
|
|
|
|
|
if (auto audioOut = orbis::g_context.audioOut) {
|
|
|
|
|
audioOut->channelInfo.port = args.audioPort;
|
|
|
|
|
audioOut->channelInfo.channel = args.threadId;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
})
|
|
|
|
|
.addSyncMethod<SceSysAudioSystemPortAndThreadArgs>(
|
|
|
|
|
0x12340002, [](const auto &args) -> std::int32_t {
|
|
|
|
|
ORBIS_LOG_TODO("IPMI: SceSysAudioSystemStartListening", args.threadId, args.audioPort);
|
|
|
|
|
if (auto audioOut = orbis::g_context.audioOut) {
|
|
|
|
|
audioOut->start();
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
})
|
|
|
|
|
.addSyncMethod<SceSysAudioSystemPortAndThreadArgs>(
|
|
|
|
|
0x12340006, [](const auto &args) -> std::int32_t {
|
|
|
|
|
ORBIS_LOG_TODO("IPMI: SceSysAudioSystemStopListening", args.audioPort, args.threadId);
|
|
|
|
|
// TODO: implement
|
|
|
|
|
return 0;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-27 18:07:30 +01:00
|
|
|
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;
|
|
|
|
|
};
|
|
|
|
|
|
2023-11-15 11:59:24 +01:00
|
|
|
static void createSysCoreObjects(orbis::Process *process) {
|
2023-12-27 18:07:30 +01:00
|
|
|
createIpmiServer(process, "SceMbusIpc")
|
2024-09-01 17:51:47 +02:00
|
|
|
.addSyncMethod<SceMbusIpcAddHandleByUserIdMethodArgs>(
|
2023-12-27 18:07:30 +01:00
|
|
|
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);
|
2023-12-29 14:27:32 +01:00
|
|
|
return 0;
|
2023-12-27 18:07:30 +01:00
|
|
|
});
|
|
|
|
|
createIpmiServer(process, "SceSysCoreApp");
|
|
|
|
|
createIpmiServer(process, "SceSysCoreApp2");
|
|
|
|
|
createIpmiServer(process, "SceMDBG0SRV");
|
2023-11-15 11:59:24 +01:00
|
|
|
|
|
|
|
|
createSemaphore("SceSysCoreProcSpawnSema", 0x101, 0, 1);
|
|
|
|
|
createSemaphore("SceTraceMemorySem", 0x100, 1, 1);
|
|
|
|
|
createSemaphore("SceSysCoreEventSemaphore", 0x101, 0, 0x2d2);
|
|
|
|
|
createSemaphore("SceSysCoreProcSema", 0x101, 0, 1);
|
|
|
|
|
createSemaphore("AppmgrCoredumpHandlingEventSema", 0x101, 0, 4);
|
|
|
|
|
|
|
|
|
|
createEventFlag("SceMdbgVrTriggerDump", 0x121, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void createGnmCompositorObjects(orbis::Process *process) {
|
|
|
|
|
createEventFlag("SceCompositorCrashEventFlags", 0x122, 0);
|
|
|
|
|
createEventFlag("SceCompositorEventflag", 0x122, 0);
|
|
|
|
|
createEventFlag("SceCompositorResetStatusEVF", 0x122, 0);
|
|
|
|
|
|
|
|
|
|
createShm("/tmp/SceHmd/Vr2d_shm_pass", 0xa02, 0x1b6, 16384);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void createShellCoreObjects(orbis::Process *process) {
|
|
|
|
|
|
|
|
|
|
// FIXME: replace with fmt library
|
|
|
|
|
auto fmtHex = [](auto value, bool upperCase = false) {
|
|
|
|
|
std::stringstream ss;
|
|
|
|
|
ss << std::hex << std::setw(8) << std::setfill('0');
|
|
|
|
|
if (upperCase) {
|
|
|
|
|
ss << std::uppercase;
|
|
|
|
|
}
|
|
|
|
|
ss << value;
|
|
|
|
|
return std::move(ss).str();
|
|
|
|
|
};
|
|
|
|
|
|
2023-12-27 18:07:30 +01:00
|
|
|
createIpmiServer(process, "SceSystemLoggerService");
|
|
|
|
|
createIpmiServer(process, "SceLoginMgrServer");
|
|
|
|
|
createIpmiServer(process, "SceLncService")
|
2024-09-01 17:51:47 +02:00
|
|
|
.addSyncMethod(orbis::g_context.fwSdkVersion > 0x6000000 ? 0x30013
|
|
|
|
|
: 0x30010,
|
|
|
|
|
[](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;
|
|
|
|
|
});
|
2023-12-27 18:07:30 +01:00
|
|
|
createIpmiServer(process, "SceAppMessaging");
|
|
|
|
|
createIpmiServer(process, "SceShellCoreUtil");
|
|
|
|
|
createIpmiServer(process, "SceNetCtl");
|
|
|
|
|
createIpmiServer(process, "SceNpMgrIpc")
|
2024-09-01 17:51:47 +02:00
|
|
|
.addSyncMethod(
|
2023-12-31 12:30:49 +01:00
|
|
|
0,
|
|
|
|
|
[=](void *out, std::uint64_t &size) -> std::int32_t {
|
2023-12-27 18:07:30 +01:00
|
|
|
std::string_view result = "SceNpMgrEvf";
|
2023-12-31 12:30:49 +01:00
|
|
|
if (size < result.size() + 1) {
|
|
|
|
|
return 0x8002'0000 + static_cast<int>(orbis::ErrorCode::INVAL);
|
|
|
|
|
}
|
2023-12-27 18:07:30 +01:00
|
|
|
std::strncpy((char *)out, result.data(), result.size() + 1);
|
|
|
|
|
size = result.size() + 1;
|
2023-12-31 12:30:49 +01:00
|
|
|
orbis::g_context.createEventFlag(orbis::kstring(result), 0x200, 0);
|
|
|
|
|
return 0;
|
|
|
|
|
})
|
2024-09-01 17:51:47 +02:00
|
|
|
.addSyncMethodStub(0xd);
|
2023-12-31 12:30:49 +01:00
|
|
|
createIpmiServer(process, "SceNpService")
|
2024-09-01 17:51:47 +02:00
|
|
|
.addSyncMethod<std::uint32_t>(0, [=](void *out, std::uint64_t &size,
|
|
|
|
|
std::uint32_t val) { return 0; })
|
|
|
|
|
.addSyncMethod(0xa0001,
|
|
|
|
|
[=](void *out, std::uint64_t &size) -> std::int32_t {
|
|
|
|
|
if (size < 1) {
|
|
|
|
|
return 0x8002'0000 +
|
|
|
|
|
static_cast<int>(orbis::ErrorCode::INVAL);
|
|
|
|
|
}
|
|
|
|
|
size = 1;
|
|
|
|
|
*reinterpret_cast<std::uint8_t *>(out) = 1;
|
|
|
|
|
return 0;
|
|
|
|
|
})
|
|
|
|
|
.addSyncMethod(0xa0002,
|
|
|
|
|
[=](void *out, std::uint64_t &size) -> std::int32_t {
|
|
|
|
|
if (size < 1) {
|
|
|
|
|
return 0x8002'0000 +
|
|
|
|
|
static_cast<int>(orbis::ErrorCode::INVAL);
|
|
|
|
|
}
|
|
|
|
|
size = 1;
|
|
|
|
|
*reinterpret_cast<std::uint8_t *>(out) = 1;
|
|
|
|
|
return 0;
|
|
|
|
|
})
|
|
|
|
|
.addSyncMethod<std::uint32_t, std::uint32_t>(
|
2023-12-31 12:30:49 +01:00
|
|
|
0xd0000, // sceNpTpipIpcClientGetShmIndex
|
|
|
|
|
[=](std::uint32_t &shmIndex, std::uint32_t appId) -> std::int32_t {
|
|
|
|
|
shmIndex = 0;
|
2023-12-27 18:07:30 +01:00
|
|
|
return 0;
|
|
|
|
|
});
|
2023-12-31 12:30:49 +01:00
|
|
|
|
2024-09-01 17:51:47 +02:00
|
|
|
createIpmiServer(process, "SceNpTrophyIpc")
|
|
|
|
|
.addSyncMethod(2,
|
|
|
|
|
[](std::vector<std::vector<std::byte>> &out,
|
|
|
|
|
const std::vector<std::span<std::byte>> &in) {
|
|
|
|
|
if (out.size() != 1 ||
|
|
|
|
|
out[0].size() < sizeof(std::uint32_t)) {
|
|
|
|
|
return orbis::ErrorCode::INVAL;
|
|
|
|
|
}
|
|
|
|
|
out = {toBytes<std::uint32_t>(0)};
|
|
|
|
|
return orbis::ErrorCode{};
|
|
|
|
|
})
|
|
|
|
|
.addAsyncMethod(0x30040,
|
|
|
|
|
[](orbis::IpmiSession &session,
|
|
|
|
|
std::vector<std::vector<std::byte>> &out,
|
|
|
|
|
const std::vector<std::span<std::byte>> &in) {
|
|
|
|
|
session.client->eventFlags[0].set(1);
|
|
|
|
|
return orbis::ErrorCode{};
|
|
|
|
|
})
|
|
|
|
|
.addSyncMethod(0x90000,
|
|
|
|
|
[](std::vector<std::vector<std::byte>> &out,
|
|
|
|
|
const std::vector<std::span<std::byte>> &in) {
|
|
|
|
|
if (out.size() != 1 ||
|
|
|
|
|
out[0].size() < sizeof(std::uint32_t)) {
|
|
|
|
|
return orbis::ErrorCode::INVAL;
|
|
|
|
|
}
|
|
|
|
|
out = {toBytes<std::uint32_t>(1)};
|
|
|
|
|
return orbis::ErrorCode{};
|
|
|
|
|
})
|
|
|
|
|
.addSyncMethod(0x90003,
|
|
|
|
|
[](std::vector<std::vector<std::byte>> &out,
|
|
|
|
|
const std::vector<std::span<std::byte>> &in) {
|
|
|
|
|
if (out.size() != 1 ||
|
|
|
|
|
out[0].size() < sizeof(std::uint32_t)) {
|
|
|
|
|
return orbis::ErrorCode::INVAL;
|
|
|
|
|
}
|
|
|
|
|
out = {toBytes<std::uint32_t>(1)};
|
|
|
|
|
return orbis::ErrorCode{};
|
|
|
|
|
})
|
|
|
|
|
.addAsyncMethod(0x90024,
|
|
|
|
|
[](orbis::IpmiSession &session,
|
|
|
|
|
std::vector<std::vector<std::byte>> &out,
|
|
|
|
|
const std::vector<std::span<std::byte>> &in) {
|
|
|
|
|
out.push_back(toBytes<std::uint32_t>(0));
|
|
|
|
|
// session.client->eventFlags[0].set(1);
|
|
|
|
|
return orbis::ErrorCode{};
|
|
|
|
|
})
|
|
|
|
|
.addAsyncMethod(0x90026, [](orbis::IpmiSession &session,
|
|
|
|
|
std::vector<std::vector<std::byte>> &out,
|
|
|
|
|
const std::vector<std::span<std::byte>> &in) {
|
|
|
|
|
session.client->eventFlags[0].set(1);
|
|
|
|
|
return orbis::ErrorCode{};
|
|
|
|
|
});
|
2023-12-27 18:07:30 +01:00
|
|
|
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");
|
2023-12-31 12:30:49 +01:00
|
|
|
createIpmiServer(process, "SceSaveData")
|
2024-09-01 17:51:47 +02:00
|
|
|
.addSyncMethod(
|
2023-12-31 12:30:49 +01:00
|
|
|
0x12340001,
|
|
|
|
|
[](void *out, std::uint64_t &size) -> std::int32_t {
|
|
|
|
|
{
|
|
|
|
|
auto [dev, devPath] = rx::vfs::get("/app0");
|
|
|
|
|
if (auto hostFs = dev.cast<HostFsDevice>()) {
|
|
|
|
|
std::error_code ec;
|
|
|
|
|
auto saveDir = hostFs->hostPath + "/.rpcsx/saves/";
|
|
|
|
|
if (!std::filesystem::exists(saveDir)) {
|
|
|
|
|
return 0x8002'0000 +
|
|
|
|
|
static_cast<int>(orbis::ErrorCode::NOENT);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
std::string_view result = "/saves";
|
|
|
|
|
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;
|
|
|
|
|
})
|
2024-09-01 17:51:47 +02:00
|
|
|
.addSyncMethod(
|
2023-12-31 12:30:49 +01:00
|
|
|
0x12340002, [](void *out, std::uint64_t &size) -> std::int32_t {
|
|
|
|
|
{
|
|
|
|
|
auto [dev, devPath] = rx::vfs::get("/app0");
|
|
|
|
|
if (auto hostFs = dev.cast<HostFsDevice>()) {
|
|
|
|
|
std::error_code ec;
|
|
|
|
|
auto saveDir = hostFs->hostPath + "/.rpcsx/saves/";
|
|
|
|
|
std::filesystem::create_directories(saveDir, ec);
|
|
|
|
|
rx::vfs::mount("/saves/",
|
|
|
|
|
createHostIoDevice(saveDir, "/saves/"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
});
|
|
|
|
|
|
2023-12-27 18:07:30 +01:00
|
|
|
createIpmiServer(process, "SceStickerCoreServer");
|
|
|
|
|
createIpmiServer(process, "SceDbRecoveryShellCore");
|
|
|
|
|
createIpmiServer(process, "SceUserService")
|
|
|
|
|
.sendMsg(SceUserServiceEvent{.eventType = 0, .user = 1})
|
2024-09-01 17:51:47 +02:00
|
|
|
.addSyncMethod(0x30011,
|
|
|
|
|
[](void *ptr, std::uint64_t &size) -> std::int32_t {
|
|
|
|
|
if (size < sizeof(orbis::uint32_t)) {
|
|
|
|
|
return 0x8000'0000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*(orbis::uint32_t *)ptr = 1;
|
|
|
|
|
size = sizeof(orbis::uint32_t);
|
|
|
|
|
return 0;
|
|
|
|
|
});
|
|
|
|
|
|
2023-12-27 18:07:30 +01:00
|
|
|
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");
|
2023-11-15 11:59:24 +01:00
|
|
|
|
|
|
|
|
createSemaphore("SceLncSuspendBlock00000001", 0x101, 1, 1);
|
2023-12-27 18:07:30 +01:00
|
|
|
createSemaphore("SceAppMessaging00000001", 0x100, 1, 0x7fffffff);
|
2023-11-15 11:59:24 +01:00
|
|
|
|
|
|
|
|
createEventFlag("SceAutoMountUsbMass", 0x120, 0);
|
|
|
|
|
createEventFlag("SceLoginMgrUtilityEventFlag", 0x112, 0);
|
|
|
|
|
createEventFlag("SceLoginMgrSharePlayEventFlag", 0x112, 0);
|
|
|
|
|
createEventFlag("SceLoginMgrServerHmdConnect", 0x112, 0);
|
|
|
|
|
createEventFlag("SceLoginMgrServerDialogRequest", 0x112, 0);
|
|
|
|
|
createEventFlag("SceLoginMgrServerDialogResponse", 0x112, 0);
|
|
|
|
|
createEventFlag("SceGameLiveStreamingSpectator", 0x120, 0x8000000000000000);
|
|
|
|
|
createEventFlag("SceGameLiveStreamingUserId", 0x120, 0x8000000000000000);
|
|
|
|
|
createEventFlag("SceGameLiveStreamingMsgCount", 0x120, 0x8000000000000000);
|
|
|
|
|
createEventFlag("SceGameLiveStreamingBCCtrl", 0x120, 0);
|
|
|
|
|
createEventFlag("SceGameLiveStreamingEvntArg", 0x120, 0);
|
|
|
|
|
createEventFlag("SceLncUtilSystemStatus", 0x120, 0);
|
|
|
|
|
createEventFlag("SceShellCoreUtilRunLevel", 0x100, 0);
|
|
|
|
|
createEventFlag("SceSystemStateMgrInfo", 0x120, 0x10000000a);
|
|
|
|
|
createEventFlag("SceSystemStateMgrStatus", 0x120, 0);
|
|
|
|
|
createEventFlag("SceAppInstallerEventFlag", 0x120, 0);
|
2023-12-27 18:07:30 +01:00
|
|
|
createEventFlag("SceShellCoreUtilPowerControl", 0x120, 0x400000);
|
|
|
|
|
createEventFlag("SceShellCoreUtilAppFocus", 0x120, 1);
|
|
|
|
|
createEventFlag("SceShellCoreUtilCtrlFocus", 0x120, 0);
|
2023-11-15 11:59:24 +01:00
|
|
|
createEventFlag("SceShellCoreUtilUIStatus", 0x120, 0x20001);
|
|
|
|
|
createEventFlag("SceShellCoreUtilDevIdxBehavior", 0x120, 0);
|
|
|
|
|
createEventFlag("SceNpMgrVshReq", 0x121, 0);
|
|
|
|
|
createEventFlag("SceNpIdMapperVshReq", 0x121, 0);
|
|
|
|
|
createEventFlag("SceRtcUtilTzdataUpdateFlag", 0x120, 0);
|
|
|
|
|
createEventFlag("SceDataTransfer", 0x120, 0);
|
|
|
|
|
|
2023-12-27 18:07:30 +01:00
|
|
|
createEventFlag("SceLncUtilAppStatus1", 0x100, 0);
|
|
|
|
|
createEventFlag("SceAppMessaging1", 0x120, 1);
|
|
|
|
|
createEventFlag("SceShellCoreUtil1", 0x120, 0x3f8c);
|
2023-12-31 12:30:49 +01:00
|
|
|
createEventFlag("SceNpScoreIpc_" + fmtHex(process->pid), 0x120, 0);
|
|
|
|
|
createEventFlag("/vmicDdEvfAin", 0x120, 0);
|
2023-11-15 11:59:24 +01:00
|
|
|
|
2023-12-27 18:07:30 +01:00
|
|
|
createSemaphore("SceAppMessaging1", 0x101, 1, 0x7fffffff);
|
|
|
|
|
createSemaphore("SceLncSuspendBlock1", 0x101, 1, 10000);
|
2023-11-15 11:59:24 +01:00
|
|
|
|
|
|
|
|
createShm("SceGlsSharedMemory", 0x202, 0x1a4, 262144);
|
|
|
|
|
createShm("SceShellCoreUtil", 0x202, 0x1a4, 16384);
|
|
|
|
|
createShm("SceNpTpip", 0x202, 0x1ff, 43008);
|
2023-12-27 18:07:30 +01:00
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
2023-12-31 16:58:02 +01:00
|
|
|
process->hostPid = ::getpid();
|
2023-12-27 18:07:30 +01:00
|
|
|
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 = {
|
2023-12-31 12:30:49 +01:00
|
|
|
.unk0 = 0x380000000000000f,
|
2023-12-27 18:07:30 +01:00
|
|
|
.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();
|
|
|
|
|
|
2023-12-29 14:27:32 +01:00
|
|
|
ps4InitFd(newThread);
|
|
|
|
|
|
|
|
|
|
orbis::Ref<orbis::File> socket;
|
|
|
|
|
createSocket(&socket, "", 1, 1, 0);
|
|
|
|
|
process->fileDescriptors.insert(socket);
|
|
|
|
|
|
2023-12-27 18:07:30 +01:00
|
|
|
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;
|
|
|
|
|
|
2023-12-31 12:30:49 +01:00
|
|
|
g_traceSyscalls = false;
|
|
|
|
|
|
2023-12-27 18:07:30 +01:00
|
|
|
thread->tproc->event.emit(orbis::kEvFiltProc, orbis::kNoteExec);
|
|
|
|
|
|
|
|
|
|
std::thread([&] {
|
|
|
|
|
rx::thread::setupSignalStack();
|
|
|
|
|
rx::thread::setupThisThread();
|
|
|
|
|
ps4Exec(thread, executableModule, argv, envv);
|
|
|
|
|
}).join();
|
|
|
|
|
std::abort();
|
2023-11-15 11:59:24 +01:00
|
|
|
}
|
|
|
|
|
|
2023-06-23 02:28:14 +02:00
|
|
|
int main(int argc, const char *argv[]) {
|
|
|
|
|
if (argc == 2) {
|
|
|
|
|
if (std::strcmp(argv[1], "-h") == 0 ||
|
|
|
|
|
std::strcmp(argv[1], "--help") == 0) {
|
|
|
|
|
usage(argv[0]);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2023-11-10 21:41:44 +01:00
|
|
|
|
|
|
|
|
if (argv[1] == std::string_view("-v") ||
|
|
|
|
|
argv[1] == std::string_view("--version")) {
|
|
|
|
|
std::printf("v%s\n", rx::getVersion().toString().c_str());
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2023-06-23 02:28:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (argc < 2) {
|
|
|
|
|
usage(argv[0]);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setupSigHandlers();
|
|
|
|
|
rx::vfs::initialize();
|
|
|
|
|
|
2023-08-15 02:04:25 +02:00
|
|
|
bool enableAudio = false;
|
2023-09-03 21:23:50 +02:00
|
|
|
bool asRoot = false;
|
2023-10-30 20:08:18 +01:00
|
|
|
bool isSystem = false;
|
2024-01-13 18:57:02 +01:00
|
|
|
bool isSafeMode = false;
|
2023-08-15 02:04:25 +02:00
|
|
|
|
2023-06-23 02:28:14 +02:00
|
|
|
int argIndex = 1;
|
|
|
|
|
while (argIndex < argc) {
|
|
|
|
|
if (argv[argIndex] == std::string_view("--mount") ||
|
|
|
|
|
argv[argIndex] == std::string_view("-m")) {
|
|
|
|
|
if (argc <= argIndex + 2) {
|
|
|
|
|
usage(argv[0]);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::printf("mounting '%s' to virtual '%s'\n", argv[argIndex + 1],
|
|
|
|
|
argv[argIndex + 2]);
|
|
|
|
|
if (!std::filesystem::is_directory(argv[argIndex + 1])) {
|
|
|
|
|
std::fprintf(stderr, "Directory '%s' not exists\n", argv[argIndex + 1]);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-31 12:30:49 +01:00
|
|
|
rx::vfs::mount(
|
|
|
|
|
argv[argIndex + 2],
|
|
|
|
|
createHostIoDevice(argv[argIndex + 1], argv[argIndex + 2]));
|
2023-06-23 02:28:14 +02:00
|
|
|
argIndex += 3;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (argv[argIndex] == std::string_view("--trace")) {
|
|
|
|
|
argIndex++;
|
|
|
|
|
g_traceSyscalls = true;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-03 21:23:50 +02:00
|
|
|
if (argv[argIndex] == std::string_view("--root")) {
|
|
|
|
|
argIndex++;
|
|
|
|
|
asRoot = true;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-30 20:08:18 +01:00
|
|
|
if (argv[argIndex] == std::string_view("--system")) {
|
|
|
|
|
argIndex++;
|
|
|
|
|
isSystem = true;
|
2024-01-13 18:57:02 +01:00
|
|
|
asRoot = true;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (argv[argIndex] == std::string_view("--safemode")) {
|
|
|
|
|
argIndex++;
|
|
|
|
|
isSafeMode = true;
|
|
|
|
|
asRoot = true;
|
2023-10-30 20:08:18 +01:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-29 12:51:08 +02:00
|
|
|
if (argv[argIndex] == std::string_view("--override") ||
|
|
|
|
|
argv[argIndex] == std::string_view("-o")) {
|
|
|
|
|
if (argc <= argIndex + 2) {
|
|
|
|
|
usage(argv[0]);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rx::linker::override(argv[argIndex + 1], argv[argIndex + 2]);
|
|
|
|
|
|
|
|
|
|
argIndex += 3;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-13 22:46:03 +02:00
|
|
|
if (argv[argIndex] == std::string_view("--enable-audio") ||
|
|
|
|
|
argv[argIndex] == std::string_view("-a")) {
|
|
|
|
|
argIndex++;
|
2023-08-15 02:04:25 +02:00
|
|
|
enableAudio = true;
|
2023-08-13 22:46:03 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-23 02:28:14 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (argIndex >= argc) {
|
|
|
|
|
usage(argv[0]);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-06 13:26:57 +02:00
|
|
|
rx::thread::initialize();
|
2024-09-01 17:51:47 +02:00
|
|
|
|
|
|
|
|
// rx::vm::printHostStats();
|
|
|
|
|
orbis::g_context.allocatePid();
|
|
|
|
|
auto initProcess = orbis::g_context.createProcess(asRoot ? 1 : 10);
|
|
|
|
|
// pthread_setname_np(pthread_self(), "10.MAINTHREAD");
|
|
|
|
|
|
2024-09-01 17:52:32 +02:00
|
|
|
rx::vm::initialize(initProcess->pid);
|
2024-09-05 19:31:36 +02:00
|
|
|
runRpcsxGpu();
|
2023-06-24 22:48:25 +02:00
|
|
|
|
2023-08-15 02:04:25 +02:00
|
|
|
if (enableAudio) {
|
|
|
|
|
orbis::g_context.audioOut = orbis::knew<orbis::AudioOut>();
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-23 02:28:14 +02:00
|
|
|
int status = 0;
|
|
|
|
|
|
2023-07-29 18:53:34 +02:00
|
|
|
initProcess->sysent = &orbis::ps4_sysvec;
|
|
|
|
|
initProcess->onSysEnter = onSysEnter;
|
|
|
|
|
initProcess->onSysExit = onSysExit;
|
|
|
|
|
initProcess->ops = &rx::procOpsTable;
|
2024-01-13 18:57:02 +01:00
|
|
|
initProcess->hostPid = ::getpid();
|
2023-10-31 23:58:03 +01:00
|
|
|
initProcess->appInfo = {
|
|
|
|
|
.unk4 = (isSystem ? orbis::slong(0x80000000'00000000) : 0),
|
|
|
|
|
};
|
2023-07-29 18:53:34 +02:00
|
|
|
|
2023-11-11 15:12:08 +01:00
|
|
|
if (isSystem) {
|
2024-01-13 18:57:02 +01:00
|
|
|
orbis::g_context.safeMode = isSafeMode ? 1 : 0;
|
2024-09-01 16:43:45 +02:00
|
|
|
initProcess->authInfo = {.unk0 = 0x380000000000000f,
|
|
|
|
|
.caps =
|
|
|
|
|
{
|
|
|
|
|
-1ul,
|
|
|
|
|
-1ul,
|
|
|
|
|
-1ul,
|
|
|
|
|
-1ul,
|
|
|
|
|
},
|
|
|
|
|
.attrs =
|
|
|
|
|
{
|
|
|
|
|
0x4000400040000000,
|
|
|
|
|
0x4000000000000000,
|
|
|
|
|
0x0080000000000002,
|
|
|
|
|
0xF0000000FFFF4000,
|
|
|
|
|
},
|
|
|
|
|
.ucred = {
|
|
|
|
|
-1ul,
|
|
|
|
|
-1ul,
|
|
|
|
|
0x3800000000000022,
|
|
|
|
|
-1ul,
|
|
|
|
|
(1ul << 0x3a),
|
|
|
|
|
-1ul,
|
|
|
|
|
-1ul,
|
|
|
|
|
}};
|
2023-11-11 20:12:07 +01:00
|
|
|
initProcess->budgetId = 0;
|
|
|
|
|
initProcess->isInSandbox = false;
|
2023-11-11 15:12:08 +01:00
|
|
|
} else {
|
|
|
|
|
initProcess->authInfo = {
|
|
|
|
|
.unk0 = 0x3100000000000001,
|
|
|
|
|
.caps =
|
|
|
|
|
{
|
|
|
|
|
0x2000038000000000,
|
|
|
|
|
0x000000000000FF00,
|
|
|
|
|
0x0000000000000000,
|
|
|
|
|
0x0000000000000000,
|
|
|
|
|
},
|
|
|
|
|
.attrs =
|
|
|
|
|
{
|
|
|
|
|
0x4000400040000000,
|
|
|
|
|
0x4000000000000000,
|
|
|
|
|
0x0080000000000002,
|
|
|
|
|
0xF0000000FFFF4000,
|
|
|
|
|
},
|
|
|
|
|
};
|
2023-11-11 20:12:07 +01:00
|
|
|
initProcess->budgetId = 1;
|
|
|
|
|
initProcess->isInSandbox = true;
|
2023-11-11 15:12:08 +01:00
|
|
|
}
|
|
|
|
|
|
2023-07-29 18:53:34 +02:00
|
|
|
auto [baseId, mainThread] = initProcess->threadsMap.emplace();
|
|
|
|
|
mainThread->tproc = initProcess;
|
|
|
|
|
mainThread->tid = initProcess->pid + baseId;
|
|
|
|
|
mainThread->state = orbis::ThreadState::RUNNING;
|
2024-01-13 18:57:02 +01:00
|
|
|
mainThread->hostTid = ::gettid();
|
2024-09-05 21:12:59 +02:00
|
|
|
orbis::g_currentThread = mainThread;
|
2023-07-29 18:53:34 +02:00
|
|
|
|
|
|
|
|
auto executableModule =
|
|
|
|
|
rx::linker::loadModuleFile(argv[argIndex], mainThread);
|
|
|
|
|
|
|
|
|
|
if (executableModule == nullptr) {
|
|
|
|
|
std::fprintf(stderr, "Failed to open '%s'\n", argv[argIndex]);
|
|
|
|
|
std::abort();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
executableModule->id = initProcess->modulesMap.insert(executableModule);
|
|
|
|
|
initProcess->processParam = executableModule->processParam;
|
|
|
|
|
initProcess->processParamSize = executableModule->processParamSize;
|
|
|
|
|
|
2023-11-02 14:26:58 +01:00
|
|
|
if (prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_ON,
|
|
|
|
|
(void *)0x100'0000'0000, ~0ull - 0x100'0000'0000, nullptr)) {
|
|
|
|
|
perror("prctl failed\n");
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-23 02:28:14 +02:00
|
|
|
if (executableModule->type == rx::linker::kElfTypeSceDynExec ||
|
2023-10-30 23:43:20 +01:00
|
|
|
executableModule->type == rx::linker::kElfTypeSceExec ||
|
|
|
|
|
executableModule->type == rx::linker::kElfTypeExec) {
|
2023-10-31 23:58:03 +01:00
|
|
|
ps4InitDev();
|
|
|
|
|
ps4InitFd(mainThread);
|
2023-11-15 11:59:24 +01:00
|
|
|
|
2023-12-29 14:27:32 +01:00
|
|
|
std::vector<std::string> ps4Argv(argv + argIndex,
|
|
|
|
|
argv + argIndex + argc - argIndex);
|
|
|
|
|
|
|
|
|
|
auto execEnv = ps4CreateExecEnv(mainThread, executableModule, isSystem);
|
|
|
|
|
|
2024-01-13 18:57:02 +01:00
|
|
|
// data transfer mode
|
|
|
|
|
// 0 - normal
|
|
|
|
|
// 1 - source
|
|
|
|
|
// 2 - ?
|
|
|
|
|
orbis::g_context.regMgrInt[0x2110000] = 0;
|
|
|
|
|
|
|
|
|
|
orbis::g_context.regMgrInt[0x20b0000] = 1; // prefer X
|
|
|
|
|
orbis::g_context.regMgrInt[0x2020000] = 1; // region
|
|
|
|
|
|
|
|
|
|
// orbis::g_context.regMgrInt[0x2130000] = 0x1601;
|
|
|
|
|
orbis::g_context.regMgrInt[0x2130000] = 0;
|
|
|
|
|
orbis::g_context.regMgrInt[0x73800200] = 1;
|
|
|
|
|
orbis::g_context.regMgrInt[0x73800300] = 0;
|
|
|
|
|
orbis::g_context.regMgrInt[0x73800400] = 0;
|
|
|
|
|
orbis::g_context.regMgrInt[0x73800500] = 0; // enable log
|
|
|
|
|
|
|
|
|
|
// user settings
|
|
|
|
|
orbis::g_context.regMgrInt[0x7800100] = 0;
|
|
|
|
|
orbis::g_context.regMgrInt[0x7810100] = 0;
|
|
|
|
|
orbis::g_context.regMgrInt[0x7820100] = 0;
|
|
|
|
|
orbis::g_context.regMgrInt[0x7830100] = 0;
|
|
|
|
|
orbis::g_context.regMgrInt[0x7840100] = 0;
|
|
|
|
|
orbis::g_context.regMgrInt[0x7850100] = 0;
|
|
|
|
|
orbis::g_context.regMgrInt[0x7860100] = 0;
|
|
|
|
|
orbis::g_context.regMgrInt[0x7870100] = 0;
|
|
|
|
|
orbis::g_context.regMgrInt[0x7880100] = 0;
|
|
|
|
|
orbis::g_context.regMgrInt[0x7890100] = 0;
|
|
|
|
|
orbis::g_context.regMgrInt[0x78a0100] = 0;
|
|
|
|
|
orbis::g_context.regMgrInt[0x78b0100] = 0;
|
|
|
|
|
orbis::g_context.regMgrInt[0x78c0100] = 0;
|
|
|
|
|
orbis::g_context.regMgrInt[0x78d0100] = 0;
|
|
|
|
|
orbis::g_context.regMgrInt[0x78e0100] = 0;
|
|
|
|
|
orbis::g_context.regMgrInt[0x78f0100] = 0;
|
|
|
|
|
|
|
|
|
|
orbis::g_context.regMgrInt[0x2040000] = 0; // do not require initial setup
|
|
|
|
|
orbis::g_context.regMgrInt[0x2800600] = 0; // IDU version
|
|
|
|
|
orbis::g_context.regMgrInt[0x2860100] = 0; // IDU mode
|
|
|
|
|
orbis::g_context.regMgrInt[0x2860300] = 0; // Arcade mode
|
|
|
|
|
orbis::g_context.regMgrInt[0x7010000] = 0; // auto login
|
|
|
|
|
orbis::g_context.regMgrInt[0x9010000] = 0; // video out color effect
|
|
|
|
|
|
2023-11-15 11:59:24 +01:00
|
|
|
if (!isSystem) {
|
2023-12-27 18:07:30 +01:00
|
|
|
createMiniSysCoreObjects(initProcess);
|
2023-11-15 11:59:24 +01:00
|
|
|
createSysAvControlObjects(initProcess);
|
|
|
|
|
createSysCoreObjects(initProcess);
|
|
|
|
|
createGnmCompositorObjects(initProcess);
|
|
|
|
|
createShellCoreObjects(initProcess);
|
2024-09-25 13:54:28 +02:00
|
|
|
if (enableAudio) {
|
|
|
|
|
createAudioSystemObjects(initProcess);
|
|
|
|
|
}
|
2023-12-27 18:07:30 +01:00
|
|
|
|
2024-01-04 01:53:58 +01:00
|
|
|
// ?
|
|
|
|
|
createIpmiServer(initProcess, "SceCdlgRichProf");
|
2024-01-13 18:57:02 +01:00
|
|
|
createIpmiServer(initProcess, "SceRemoteplayIpc");
|
2024-01-04 01:53:58 +01:00
|
|
|
createIpmiServer(initProcess, "SceGlsIpc");
|
2024-01-13 18:57:02 +01:00
|
|
|
createIpmiServer(initProcess, "SceImeService");
|
|
|
|
|
createIpmiServer(initProcess, "SceErrorDlgServ");
|
|
|
|
|
|
|
|
|
|
createEventFlag("SceNpTusIpc_0000000a", 0x120, 0);
|
|
|
|
|
createSemaphore("SceLncSuspendBlock00000000", 0x101, 1, 1);
|
|
|
|
|
createSemaphore("SceNpPlusLogger 0", 0x101, 0, 0x7fffffff);
|
|
|
|
|
|
|
|
|
|
createSemaphore("SceSaveData0000000000000001", 0x101, 0, 1);
|
|
|
|
|
createSemaphore("SceSaveData0000000000000001_0", 0x101, 0, 1);
|
|
|
|
|
createShm("SceSaveData0000000000000001_0", 0x202, 0x1b6, 0x40000);
|
|
|
|
|
createShm("SceSaveDataI0000000000000001", 0x202, 0x1b6, 43008);
|
|
|
|
|
createShm("SceSaveDataI0000000000000001_0", 0x202, 0x1b6, 43008);
|
2024-09-01 17:51:47 +02:00
|
|
|
createShm("SceNpPlusLogger", 0x202, 0x1b6, 0x40000);
|
2024-01-13 18:57:02 +01:00
|
|
|
createEventFlag("SceSaveDataMemoryRUI00000010", 0x120, 1);
|
2023-12-31 12:30:49 +01:00
|
|
|
initProcess->cwd = "/app0/";
|
|
|
|
|
|
2024-09-25 13:54:28 +02:00
|
|
|
if (!enableAudio) {
|
|
|
|
|
launchDaemon(mainThread, "/system/sys/orbis_audiod.elf",
|
2023-12-27 18:07:30 +01:00
|
|
|
{"/system/sys/orbis_audiod.elf"}, {});
|
2024-09-25 13:54:28 +02:00
|
|
|
}
|
2023-12-29 14:27:32 +01:00
|
|
|
status = ps4Exec(mainThread, execEnv, std::move(executableModule),
|
|
|
|
|
ps4Argv, {});
|
2023-11-15 11:59:24 +01:00
|
|
|
}
|
2023-12-29 14:27:32 +01:00
|
|
|
status =
|
|
|
|
|
ps4Exec(mainThread, execEnv, std::move(executableModule), ps4Argv, {});
|
2023-06-23 02:28:14 +02:00
|
|
|
} else {
|
|
|
|
|
std::fprintf(stderr, "Unexpected executable type\n");
|
|
|
|
|
status = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// rx::vm::printHostStats();
|
2023-06-29 12:33:21 +02:00
|
|
|
rx::vm::deinitialize();
|
2023-07-06 13:26:57 +02:00
|
|
|
rx::thread::deinitialize();
|
2023-06-23 02:28:14 +02:00
|
|
|
|
|
|
|
|
return status;
|
|
|
|
|
}
|