From 9fe1fb841f408e6d83925448b90148f835083021 Mon Sep 17 00:00:00 2001 From: DH Date: Wed, 1 Nov 2023 01:58:03 +0300 Subject: [PATCH] [rpcsx-os] implement sys_execve --- orbis-kernel/include/orbis/AppInfo.hpp | 21 ++ orbis-kernel/include/orbis/evf.hpp | 2 - orbis-kernel/include/orbis/thread/Process.hpp | 3 +- .../include/orbis/thread/ProcessOps.hpp | 2 + orbis-kernel/src/sys/sys_event.cpp | 9 +- orbis-kernel/src/sys/sys_exec.cpp | 4 + orbis-kernel/src/sys/sys_pipe.cpp | 8 +- rpcsx-os/io-device.cpp | 244 ++++++++++++------ rpcsx-os/main.cpp | 83 +++--- rpcsx-os/ops.cpp | 85 +++++- rpcsx-os/vfs.cpp | 4 +- rpcsx-os/vm.cpp | 17 ++ rpcsx-os/vm.hpp | 1 + 13 files changed, 342 insertions(+), 141 deletions(-) create mode 100644 orbis-kernel/include/orbis/AppInfo.hpp diff --git a/orbis-kernel/include/orbis/AppInfo.hpp b/orbis-kernel/include/orbis/AppInfo.hpp new file mode 100644 index 00000000..be5482c0 --- /dev/null +++ b/orbis-kernel/include/orbis/AppInfo.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include "orbis-config.hpp" + +namespace orbis { +struct AppInfo { + uint32_t appId; + uint32_t unk0; + uint32_t unk1; + uint32_t appType; + char titleId[10]; + uint16_t unk2; + uint32_t unk3; + slong unk4; + slong unk5; + slong unk6; + slong unk7; + slong unk8; +}; +static_assert(sizeof(AppInfo) == 72); +} // namespace orbis diff --git a/orbis-kernel/include/orbis/evf.hpp b/orbis-kernel/include/orbis/evf.hpp index 8403109e..79c2fc64 100644 --- a/orbis-kernel/include/orbis/evf.hpp +++ b/orbis-kernel/include/orbis/evf.hpp @@ -1,10 +1,8 @@ #pragma once #include "KernelAllocator.hpp" #include "thread/Thread.hpp" -#include "utils/SharedCV.hpp" #include "utils/SharedMutex.hpp" #include -#include namespace orbis { enum { diff --git a/orbis-kernel/include/orbis/thread/Process.hpp b/orbis-kernel/include/orbis/thread/Process.hpp index fbcfc1c4..cf983804 100644 --- a/orbis-kernel/include/orbis/thread/Process.hpp +++ b/orbis-kernel/include/orbis/thread/Process.hpp @@ -7,6 +7,7 @@ #include "../thread/Thread.hpp" #include "../thread/types.hpp" #include "ProcessState.hpp" +#include "orbis/AppInfo.hpp" #include "orbis/file.hpp" #include "orbis/module/Module.hpp" #include "orbis/utils/IdMap.hpp" @@ -53,10 +54,10 @@ struct Process final { ptr processParam = nullptr; uint64_t processParamSize = 0; const ProcessOps *ops = nullptr; + AppInfo appInfo{}; std::uint64_t nextTlsSlot = 1; std::uint64_t lastTlsOffset = 0; - bool isSystem = false; utils::RcIdMap evfMap; utils::RcIdMap semMap; diff --git a/orbis-kernel/include/orbis/thread/ProcessOps.hpp b/orbis-kernel/include/orbis/thread/ProcessOps.hpp index 5ec8c87c..7cb62fcb 100644 --- a/orbis-kernel/include/orbis/thread/ProcessOps.hpp +++ b/orbis-kernel/include/orbis/thread/ProcessOps.hpp @@ -71,6 +71,8 @@ struct ProcessOps { SysResult (*thr_set_name)(Thread *thread, slong id, ptr name); SysResult (*fork)(Thread *thread, slong status); + SysResult (*execve)(Thread *thread, ptr fname, ptr> argv, + ptr> envv); SysResult (*exit)(Thread *thread, sint status); SysResult (*processNeeded)(Thread *thread); diff --git a/orbis-kernel/src/sys/sys_event.cpp b/orbis-kernel/src/sys/sys_event.cpp index d2b1c8a5..687b521d 100644 --- a/orbis-kernel/src/sys/sys_event.cpp +++ b/orbis-kernel/src/sys/sys_event.cpp @@ -4,8 +4,10 @@ #include "thread/Process.hpp" #include "utils/Logs.hpp" #include "utils/SharedMutex.hpp" +#include #include #include +#include namespace orbis { struct KEvent { @@ -110,7 +112,6 @@ orbis::SysResult orbis::sys_kevent(Thread *thread, sint fd, return orbis::ErrorCode::BADF; } - if (nchanges != 0) { for (auto change : std::span(changelist, nchanges)) { ORBIS_LOG_TODO(__FUNCTION__, change.ident, change.filter, change.flags, @@ -148,6 +149,12 @@ orbis::SysResult orbis::sys_kevent(Thread *thread, sint fd, if (note.event.filter == kEvFiltDisplay || note.event.filter == kEvFiltGraphicsCore) { result.push_back(note.event); } + if (note.event.filter == kEvFiltProc) { + // TODO + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + note.event.data = 0; + result.push_back(note.event); + } } std::memcpy(eventlist, result.data(), result.size() * sizeof(KEvent)); diff --git a/orbis-kernel/src/sys/sys_exec.cpp b/orbis-kernel/src/sys/sys_exec.cpp index 29f9ca43..719d2250 100644 --- a/orbis-kernel/src/sys/sys_exec.cpp +++ b/orbis-kernel/src/sys/sys_exec.cpp @@ -2,6 +2,10 @@ orbis::SysResult orbis::sys_execve(Thread *thread, ptr fname, ptr> argv, ptr> envv) { + if (auto execve = thread->tproc->ops->execve) { + return execve(thread, fname, argv, envv); + } + return ErrorCode::NOSYS; } orbis::SysResult orbis::sys_fexecve(Thread *thread, sint fd, diff --git a/orbis-kernel/src/sys/sys_pipe.cpp b/orbis-kernel/src/sys/sys_pipe.cpp index 82a6ba81..dd20008d 100644 --- a/orbis-kernel/src/sys/sys_pipe.cpp +++ b/orbis-kernel/src/sys/sys_pipe.cpp @@ -1,9 +1,13 @@ #include "sys/sysproto.hpp" +#include "utils/Logs.hpp" #include orbis::SysResult orbis::sys_pipe(Thread *thread) { auto pipe = createPipe(); - thread->retval[0] = thread->tproc->fileDescriptors.insert(pipe); - thread->retval[1] = thread->tproc->fileDescriptors.insert(pipe); + auto fd0 = thread->tproc->fileDescriptors.insert(pipe); + auto fd1 = thread->tproc->fileDescriptors.insert(pipe); + ORBIS_LOG_ERROR(__FUNCTION__, fd0, fd1); + thread->retval[0] = fd0; + thread->retval[1] = fd1; return {}; } diff --git a/rpcsx-os/io-device.cpp b/rpcsx-os/io-device.cpp index ed9c65cb..a755d275 100644 --- a/rpcsx-os/io-device.cpp +++ b/rpcsx-os/io-device.cpp @@ -20,9 +20,10 @@ struct HostFile : orbis::File { int hostFd = -1; + bool closeOnExit = true; ~HostFile() { - if (hostFd > 0) { + if (hostFd > 0 && closeOnExit) { ::close(hostFd); } } @@ -46,86 +47,157 @@ struct HostFsDevice : IoDevice { orbis::ErrorCode open(orbis::Ref *file, const char *path, std::uint32_t flags, std::uint32_t mode, orbis::Thread *thread) override; - orbis::ErrorCode mkdir(const char *path, int mode, orbis::Thread *thread) override; + orbis::ErrorCode mkdir(const char *path, int mode, + orbis::Thread *thread) override; orbis::ErrorCode rmdir(const char *path, orbis::Thread *thread) override; - orbis::ErrorCode rename(const char *from, const char *to, orbis::Thread *thread) override; + orbis::ErrorCode rename(const char *from, const char *to, + orbis::Thread *thread) override; }; static orbis::ErrorCode convertErrc(std::errc errc) { if (errc == std::errc{}) { - return{}; + return {}; } switch (errc) { - case std::errc::address_family_not_supported: return orbis::ErrorCode::AFNOSUPPORT; - case std::errc::address_in_use: return orbis::ErrorCode::ADDRINUSE; - case std::errc::address_not_available: return orbis::ErrorCode::ADDRNOTAVAIL; - case std::errc::already_connected: return orbis::ErrorCode::ISCONN; - case std::errc::argument_out_of_domain: return orbis::ErrorCode::DOM; - case std::errc::bad_address: return orbis::ErrorCode::FAULT; - case std::errc::bad_file_descriptor: return orbis::ErrorCode::BADF; - case std::errc::bad_message: return orbis::ErrorCode::BADMSG; - case std::errc::broken_pipe: return orbis::ErrorCode::PIPE; - case std::errc::connection_aborted: return orbis::ErrorCode::CONNABORTED; - case std::errc::connection_already_in_progress: return orbis::ErrorCode::ALREADY; - case std::errc::connection_refused: return orbis::ErrorCode::CONNREFUSED; - case std::errc::connection_reset: return orbis::ErrorCode::CONNRESET; - case std::errc::cross_device_link: return orbis::ErrorCode::XDEV; - case std::errc::destination_address_required: return orbis::ErrorCode::DESTADDRREQ; - case std::errc::device_or_resource_busy: return orbis::ErrorCode::BUSY; - case std::errc::directory_not_empty: return orbis::ErrorCode::NOTEMPTY; - case std::errc::executable_format_error: return orbis::ErrorCode::NOEXEC; - case std::errc::file_exists: return orbis::ErrorCode::EXIST; - case std::errc::file_too_large: return orbis::ErrorCode::FBIG; - case std::errc::filename_too_long: return orbis::ErrorCode::NAMETOOLONG; - case std::errc::function_not_supported: return orbis::ErrorCode::NOSYS; - case std::errc::host_unreachable: return orbis::ErrorCode::HOSTUNREACH; - case std::errc::identifier_removed: return orbis::ErrorCode::IDRM; - case std::errc::illegal_byte_sequence: return orbis::ErrorCode::ILSEQ; - case std::errc::inappropriate_io_control_operation: return orbis::ErrorCode::NOTTY; - case std::errc::interrupted: return orbis::ErrorCode::INTR; - case std::errc::invalid_argument: return orbis::ErrorCode::INVAL; - case std::errc::invalid_seek: return orbis::ErrorCode::SPIPE; - case std::errc::io_error: return orbis::ErrorCode::IO; - case std::errc::is_a_directory: return orbis::ErrorCode::ISDIR; - case std::errc::message_size: return orbis::ErrorCode::MSGSIZE; - case std::errc::network_down: return orbis::ErrorCode::NETDOWN; - case std::errc::network_reset: return orbis::ErrorCode::NETRESET; - case std::errc::network_unreachable: return orbis::ErrorCode::NETUNREACH; - case std::errc::no_buffer_space: return orbis::ErrorCode::NOBUFS; - case std::errc::no_child_process: return orbis::ErrorCode::CHILD; - case std::errc::no_link: return orbis::ErrorCode::NOLINK; - case std::errc::no_lock_available: return orbis::ErrorCode::NOLCK; - case std::errc::no_message: return orbis::ErrorCode::NOMSG; - case std::errc::no_protocol_option: return orbis::ErrorCode::NOPROTOOPT; - case std::errc::no_space_on_device: return orbis::ErrorCode::NOSPC; - case std::errc::no_such_device_or_address: return orbis::ErrorCode::NXIO; - case std::errc::no_such_device: return orbis::ErrorCode::NODEV; - case std::errc::no_such_file_or_directory: return orbis::ErrorCode::NOENT; - case std::errc::no_such_process: return orbis::ErrorCode::SRCH; - case std::errc::not_a_directory: return orbis::ErrorCode::NOTDIR; - case std::errc::not_a_socket: return orbis::ErrorCode::NOTSOCK; - case std::errc::not_connected: return orbis::ErrorCode::NOTCONN; - case std::errc::not_enough_memory: return orbis::ErrorCode::NOMEM; - case std::errc::not_supported: return orbis::ErrorCode::NOTSUP; - case std::errc::operation_canceled: return orbis::ErrorCode::CANCELED; - case std::errc::operation_in_progress: return orbis::ErrorCode::INPROGRESS; - case std::errc::operation_not_permitted: return orbis::ErrorCode::PERM; - case std::errc::operation_would_block: return orbis::ErrorCode::WOULDBLOCK; - case std::errc::permission_denied: return orbis::ErrorCode::ACCES; - case std::errc::protocol_error: return orbis::ErrorCode::PROTO; - case std::errc::protocol_not_supported: return orbis::ErrorCode::PROTONOSUPPORT; - case std::errc::read_only_file_system: return orbis::ErrorCode::ROFS; - case std::errc::resource_deadlock_would_occur: return orbis::ErrorCode::DEADLK; - case std::errc::result_out_of_range: return orbis::ErrorCode::RANGE; - case std::errc::text_file_busy: return orbis::ErrorCode::TXTBSY; - case std::errc::timed_out: return orbis::ErrorCode::TIMEDOUT; - case std::errc::too_many_files_open_in_system: return orbis::ErrorCode::NFILE; - case std::errc::too_many_files_open: return orbis::ErrorCode::MFILE; - case std::errc::too_many_links: return orbis::ErrorCode::MLINK; - case std::errc::too_many_symbolic_link_levels: return orbis::ErrorCode::LOOP; - case std::errc::value_too_large: return orbis::ErrorCode::OVERFLOW; - case std::errc::wrong_protocol_type: return orbis::ErrorCode::PROTOTYPE; + case std::errc::address_family_not_supported: + return orbis::ErrorCode::AFNOSUPPORT; + case std::errc::address_in_use: + return orbis::ErrorCode::ADDRINUSE; + case std::errc::address_not_available: + return orbis::ErrorCode::ADDRNOTAVAIL; + case std::errc::already_connected: + return orbis::ErrorCode::ISCONN; + case std::errc::argument_out_of_domain: + return orbis::ErrorCode::DOM; + case std::errc::bad_address: + return orbis::ErrorCode::FAULT; + case std::errc::bad_file_descriptor: + return orbis::ErrorCode::BADF; + case std::errc::bad_message: + return orbis::ErrorCode::BADMSG; + case std::errc::broken_pipe: + return orbis::ErrorCode::PIPE; + case std::errc::connection_aborted: + return orbis::ErrorCode::CONNABORTED; + case std::errc::connection_already_in_progress: + return orbis::ErrorCode::ALREADY; + case std::errc::connection_refused: + return orbis::ErrorCode::CONNREFUSED; + case std::errc::connection_reset: + return orbis::ErrorCode::CONNRESET; + case std::errc::cross_device_link: + return orbis::ErrorCode::XDEV; + case std::errc::destination_address_required: + return orbis::ErrorCode::DESTADDRREQ; + case std::errc::device_or_resource_busy: + return orbis::ErrorCode::BUSY; + case std::errc::directory_not_empty: + return orbis::ErrorCode::NOTEMPTY; + case std::errc::executable_format_error: + return orbis::ErrorCode::NOEXEC; + case std::errc::file_exists: + return orbis::ErrorCode::EXIST; + case std::errc::file_too_large: + return orbis::ErrorCode::FBIG; + case std::errc::filename_too_long: + return orbis::ErrorCode::NAMETOOLONG; + case std::errc::function_not_supported: + return orbis::ErrorCode::NOSYS; + case std::errc::host_unreachable: + return orbis::ErrorCode::HOSTUNREACH; + case std::errc::identifier_removed: + return orbis::ErrorCode::IDRM; + case std::errc::illegal_byte_sequence: + return orbis::ErrorCode::ILSEQ; + case std::errc::inappropriate_io_control_operation: + return orbis::ErrorCode::NOTTY; + case std::errc::interrupted: + return orbis::ErrorCode::INTR; + case std::errc::invalid_argument: + return orbis::ErrorCode::INVAL; + case std::errc::invalid_seek: + return orbis::ErrorCode::SPIPE; + case std::errc::io_error: + return orbis::ErrorCode::IO; + case std::errc::is_a_directory: + return orbis::ErrorCode::ISDIR; + case std::errc::message_size: + return orbis::ErrorCode::MSGSIZE; + case std::errc::network_down: + return orbis::ErrorCode::NETDOWN; + case std::errc::network_reset: + return orbis::ErrorCode::NETRESET; + case std::errc::network_unreachable: + return orbis::ErrorCode::NETUNREACH; + case std::errc::no_buffer_space: + return orbis::ErrorCode::NOBUFS; + case std::errc::no_child_process: + return orbis::ErrorCode::CHILD; + case std::errc::no_link: + return orbis::ErrorCode::NOLINK; + case std::errc::no_lock_available: + return orbis::ErrorCode::NOLCK; + case std::errc::no_message: + return orbis::ErrorCode::NOMSG; + case std::errc::no_protocol_option: + return orbis::ErrorCode::NOPROTOOPT; + case std::errc::no_space_on_device: + return orbis::ErrorCode::NOSPC; + case std::errc::no_such_device_or_address: + return orbis::ErrorCode::NXIO; + case std::errc::no_such_device: + return orbis::ErrorCode::NODEV; + case std::errc::no_such_file_or_directory: + return orbis::ErrorCode::NOENT; + case std::errc::no_such_process: + return orbis::ErrorCode::SRCH; + case std::errc::not_a_directory: + return orbis::ErrorCode::NOTDIR; + case std::errc::not_a_socket: + return orbis::ErrorCode::NOTSOCK; + case std::errc::not_connected: + return orbis::ErrorCode::NOTCONN; + case std::errc::not_enough_memory: + return orbis::ErrorCode::NOMEM; + case std::errc::not_supported: + return orbis::ErrorCode::NOTSUP; + case std::errc::operation_canceled: + return orbis::ErrorCode::CANCELED; + case std::errc::operation_in_progress: + return orbis::ErrorCode::INPROGRESS; + case std::errc::operation_not_permitted: + return orbis::ErrorCode::PERM; + case std::errc::operation_would_block: + return orbis::ErrorCode::WOULDBLOCK; + case std::errc::permission_denied: + return orbis::ErrorCode::ACCES; + case std::errc::protocol_error: + return orbis::ErrorCode::PROTO; + case std::errc::protocol_not_supported: + return orbis::ErrorCode::PROTONOSUPPORT; + case std::errc::read_only_file_system: + return orbis::ErrorCode::ROFS; + case std::errc::resource_deadlock_would_occur: + return orbis::ErrorCode::DEADLK; + case std::errc::result_out_of_range: + return orbis::ErrorCode::RANGE; + case std::errc::text_file_busy: + return orbis::ErrorCode::TXTBSY; + case std::errc::timed_out: + return orbis::ErrorCode::TIMEDOUT; + case std::errc::too_many_files_open_in_system: + return orbis::ErrorCode::NFILE; + case std::errc::too_many_files_open: + return orbis::ErrorCode::MFILE; + case std::errc::too_many_links: + return orbis::ErrorCode::MLINK; + case std::errc::too_many_symbolic_link_levels: + return orbis::ErrorCode::LOOP; + case std::errc::value_too_large: + return orbis::ErrorCode::OVERFLOW; + case std::errc::wrong_protocol_type: + return orbis::ErrorCode::PROTOTYPE; default: return orbis::ErrorCode::FAULT; } @@ -133,7 +205,7 @@ static orbis::ErrorCode convertErrc(std::errc errc) { static orbis::ErrorCode convertErrorCode(const std::error_code &code) { if (!code) { - return{}; + return {}; } return convertErrc(static_cast(code.value())); } @@ -219,20 +291,21 @@ static orbis::ErrorCode host_write(orbis::File *file, orbis::Uio *uio, vec.push_back({.iov_base = entry.base, .iov_len = entry.len}); } - ssize_t cnt = 0; - if (hostFile->hostFd == 1 || hostFile->hostFd == 2) { + ssize_t cnt = ::pwritev(hostFile->hostFd, vec.data(), vec.size(), uio->offset); + + if (cnt < 0) { for (auto io : vec) { - cnt += ::write(hostFile->hostFd, io.iov_base, io.iov_len); + auto result = ::write(hostFile->hostFd, io.iov_base, io.iov_len); + if (result < 0) { + return convertErrno(); + } + + cnt += result; if (cnt != io.iov_len) { break; } } - } else { - cnt = ::pwritev(hostFile->hostFd, vec.data(), vec.size(), uio->offset); - } - if (cnt < 0) { - return convertErrno(); } uio->resid -= cnt; @@ -461,7 +534,8 @@ orbis::ErrorCode HostFsDevice::open(orbis::Ref *file, return {}; } -orbis::ErrorCode HostFsDevice::mkdir(const char *path, int mode, orbis::Thread *thread) { +orbis::ErrorCode HostFsDevice::mkdir(const char *path, int mode, + orbis::Thread *thread) { std::error_code ec; std::filesystem::create_directories(hostPath + "/" + path, ec); return convertErrorCode(ec); @@ -471,7 +545,8 @@ orbis::ErrorCode HostFsDevice::rmdir(const char *path, orbis::Thread *thread) { std::filesystem::remove(hostPath + "/" + path, ec); return convertErrorCode(ec); } -orbis::ErrorCode HostFsDevice::rename(const char *from, const char *to, orbis::Thread *thread) { +orbis::ErrorCode HostFsDevice::rename(const char *from, const char *to, + orbis::Thread *thread) { std::error_code ec; std::filesystem::rename(hostPath + "/" + from, hostPath + "/" + to, ec); return convertErrorCode(ec); @@ -492,6 +567,7 @@ struct FdWrapDevice : public IoDevice { std::uint32_t flags, std::uint32_t mode, orbis::Thread *thread) override { *file = createHostFile(fd, this); + static_cast(file->get())->closeOnExit = false; return {}; } }; diff --git a/rpcsx-os/main.cpp b/rpcsx-os/main.cpp index e1a6e3f3..402b2d08 100644 --- a/rpcsx-os/main.cpp +++ b/rpcsx-os/main.cpp @@ -251,7 +251,7 @@ static const char *getSyscallName(orbis::Thread *thread, int sysno) { } static void onSysEnter(orbis::Thread *thread, int id, uint64_t *args, int argsCount) { - if (!g_traceSyscalls && thread->tid < 10000) { + if (!g_traceSyscalls) { return; } flockfile(stderr); @@ -277,7 +277,7 @@ static void onSysEnter(orbis::Thread *thread, int id, uint64_t *args, static void onSysExit(orbis::Thread *thread, int id, uint64_t *args, int argsCount, orbis::SysResult result) { - if (!result.isError() && !g_traceSyscalls && thread->tid < 10000) { + if (!result.isError() && !g_traceSyscalls) { return; } @@ -305,26 +305,13 @@ static void onSysExit(orbis::Thread *thread, int id, uint64_t *args, funlockfile(stderr); } -static int ps4Exec(orbis::Thread *mainThread, - orbis::utils::Ref executableModule, - std::span argv, std::span envp) { - const auto stackEndAddress = 0x7'ffff'c000ull; - const auto stackSize = 0x40000 * 16; - auto stackStartAddress = stackEndAddress - stackSize; - mainThread->stackStart = - rx::vm::map(reinterpret_cast(stackStartAddress), stackSize, - rx::vm::kMapProtCpuWrite | rx::vm::kMapProtCpuRead, - rx::vm::kMapFlagAnonymous | rx::vm::kMapFlagFixed | - rx::vm::kMapFlagPrivate | rx::vm::kMapFlagStack); - - mainThread->stackEnd = - reinterpret_cast(mainThread->stackStart) + stackSize; - +static void ps4InitDev() { auto dmem1 = createDmemCharacterDevice(1); orbis::g_context.dmemDevice = dmem1; - auto stdoutFd = ::open("stdout.txt", O_CREAT | O_TRUNC | O_WRONLY, 0666); - auto stderrFd = ::open("stderr.txt", O_CREAT | O_TRUNC | O_WRONLY, 0666); + auto stdoutDev = createFdWrapDevice(::open("stdout.txt", O_CREAT | O_TRUNC | O_WRONLY, 0666)); + auto stderrDev = createFdWrapDevice(::open("stderr.txt", O_CREAT | O_TRUNC | O_WRONLY, 0666)); + auto stdinDev = createFdWrapDevice(STDIN_FILENO); rx::vfs::addDevice("dmem0", createDmemCharacterDevice(0)); rx::vfs::addDevice("npdrm", createNpdrmCharacterDevice()); @@ -334,12 +321,12 @@ static int ps4Exec(orbis::Thread *mainThread, rx::vfs::addDevice("camera", createCameraCharacterDevice()); rx::vfs::addDevice("dmem1", dmem1); rx::vfs::addDevice("dmem2", createDmemCharacterDevice(2)); - rx::vfs::addDevice("stdout", createFdWrapDevice(stdoutFd)); - rx::vfs::addDevice("stderr", createFdWrapDevice(stderrFd)); - rx::vfs::addDevice("deci_stdin", createFdWrapDevice(STDIN_FILENO)); - rx::vfs::addDevice("deci_stdout", createFdWrapDevice(stdoutFd)); - rx::vfs::addDevice("deci_stderr", createFdWrapDevice(stderrFd)); - rx::vfs::addDevice("stdin", createFdWrapDevice(STDIN_FILENO)); + rx::vfs::addDevice("stdout", stdoutDev); + rx::vfs::addDevice("stderr", stderrDev); + rx::vfs::addDevice("deci_stdin", stdinDev); + rx::vfs::addDevice("deci_stdout", stdoutDev); + rx::vfs::addDevice("deci_stderr", stderrDev); + rx::vfs::addDevice("stdin", stdinDev); rx::vfs::addDevice("zero", createZeroCharacterDevice()); rx::vfs::addDevice("null", createNullCharacterDevice()); rx::vfs::addDevice("dipsw", createDipswCharacterDevice()); @@ -366,6 +353,11 @@ static int ps4Exec(orbis::Thread *mainThread, rx::vfs::addDevice("notification4", createNotificationCharacterDevice(4)); rx::vfs::addDevice("notification5", createNotificationCharacterDevice(5)); + orbis::g_context.shmDevice = createShmDevice(); + orbis::g_context.blockpoolDevice = createBlockPoolDevice(); +} + +static void ps4InitFd(orbis::Thread *mainThread) { orbis::Ref stdinFile; orbis::Ref stdoutFile; orbis::Ref stderrFile; @@ -376,9 +368,22 @@ static int ps4Exec(orbis::Thread *mainThread, mainThread->tproc->fileDescriptors.insert(stdinFile); mainThread->tproc->fileDescriptors.insert(stdoutFile); mainThread->tproc->fileDescriptors.insert(stderrFile); +} - orbis::g_context.shmDevice = createShmDevice(); - orbis::g_context.blockpoolDevice = createBlockPoolDevice(); +int ps4Exec(orbis::Thread *mainThread, + orbis::utils::Ref executableModule, + std::span argv, std::span envp) { + const auto stackEndAddress = 0x7'ffff'c000ull; + const auto stackSize = 0x40000 * 16; + auto stackStartAddress = stackEndAddress - stackSize; + mainThread->stackStart = + rx::vm::map(reinterpret_cast(stackStartAddress), stackSize, + rx::vm::kMapProtCpuWrite | rx::vm::kMapProtCpuRead, + rx::vm::kMapFlagAnonymous | rx::vm::kMapFlagFixed | + rx::vm::kMapFlagPrivate | rx::vm::kMapFlagStack); + + mainThread->stackEnd = + reinterpret_cast(mainThread->stackStart) + stackSize; std::vector argvOffsets; std::vector envpOffsets; @@ -412,14 +417,14 @@ static int ps4Exec(orbis::Thread *mainThread, StackWriter stack{reinterpret_cast(mainThread->stackEnd)}; - for (auto elem : argv) { - argvOffsets.push_back(stack.pushString(elem)); + for (auto &elem : argv) { + argvOffsets.push_back(stack.pushString(elem.data())); } argvOffsets.push_back(0); - for (auto elem : envp) { - envpOffsets.push_back(stack.pushString(elem)); + for (auto &elem : envp) { + envpOffsets.push_back(stack.pushString(elem.data())); } envpOffsets.push_back(0); @@ -647,8 +652,8 @@ int main(int argc, const char *argv[]) { // rx::vm::printHostStats(); orbis::g_context.allocatePid(); - auto initProcess = orbis::g_context.createProcess(asRoot ? 1 : 11); - pthread_setname_np(pthread_self(), "11.MAINTHREAD"); + auto initProcess = orbis::g_context.createProcess(asRoot ? 1 : 10); + pthread_setname_np(pthread_self(), "10.MAINTHREAD"); std::thread{[] { pthread_setname_np(pthread_self(), "Bridge"); @@ -718,7 +723,9 @@ int main(int argc, const char *argv[]) { initProcess->onSysEnter = onSysEnter; initProcess->onSysExit = onSysExit; initProcess->ops = &rx::procOpsTable; - initProcess->isSystem = isSystem; + initProcess->appInfo = { + .unk4 = (isSystem ? orbis::slong(0x80000000'00000000) : 0), + }; auto [baseId, mainThread] = initProcess->threadsMap.emplace(); mainThread->tproc = initProcess; @@ -740,9 +747,11 @@ int main(int argc, const char *argv[]) { if (executableModule->type == rx::linker::kElfTypeSceDynExec || executableModule->type == rx::linker::kElfTypeSceExec || executableModule->type == rx::linker::kElfTypeExec) { - status = ps4Exec(mainThread, std::move(executableModule), - std::span(argv + argIndex, argc - argIndex), - std::span()); + ps4InitDev(); + ps4InitFd(mainThread); + std::vector ps4Argv(argv + argIndex, + argv + argIndex + argc - argIndex); + status = ps4Exec(mainThread, std::move(executableModule), ps4Argv, {}); } else { std::fprintf(stderr, "Unexpected executable type\n"); status = 1; diff --git a/rpcsx-os/ops.cpp b/rpcsx-os/ops.cpp index d4c875b2..199ca710 100644 --- a/rpcsx-os/ops.cpp +++ b/rpcsx-os/ops.cpp @@ -5,7 +5,9 @@ #include "iodev/blockpool.hpp" #include "iodev/dmem.hpp" #include "linker.hpp" +#include "orbis-config.hpp" #include "orbis/KernelContext.hpp" +#include "orbis/file.hpp" #include "orbis/module/ModuleHandle.hpp" #include "orbis/thread/Process.hpp" #include "orbis/thread/Thread.hpp" @@ -34,6 +36,9 @@ using namespace orbis; extern "C" void __register_frame(const void *); void setupSigHandlers(); +int ps4Exec(orbis::Thread *mainThread, + orbis::utils::Ref executableModule, + std::span argv, std::span envp); namespace { static std::pair> @@ -629,19 +634,20 @@ SysResult fork(Thread *thread, slong flags) { auto childPid = g_context.allocatePid() * 10000 + 1; auto mtx = knew(); auto cv = knew(); + mtx->lock(); int hostPid = ::fork(); if (hostPid) { - mtx->lock(); cv->wait(*mtx); + mtx->unlock(); kdelete(cv); kdelete(mtx); thread->retval[0] = childPid; thread->retval[1] = 0; - return{}; + return {}; } auto process = g_context.createProcess(childPid); @@ -649,7 +655,6 @@ SysResult fork(Thread *thread, slong flags) { process->onSysEnter = thread->tproc->onSysEnter; process->onSysExit = thread->tproc->onSysExit; process->ops = thread->tproc->ops; - process->isSystem = thread->tproc->isSystem; process->parentProcess = thread->tproc; for (auto [id, mod] : thread->tproc->modulesMap) { if (!process->modulesMap.insert(id, mod)) { @@ -669,7 +674,7 @@ SysResult fork(Thread *thread, slong flags) { rx::vm::fork(thread->tproc->pid); rx::vfs::fork(); - cv->notify_one(*mtx); + cv->notify_all(*mtx); auto [baseId, newThread] = process->threadsMap.emplace(); newThread->tproc = process; @@ -693,8 +698,11 @@ SysResult fork(Thread *thread, slong flags) { std::exit(-1); } - auto ttyFd = - ::open(("tty-" + std::to_string(thread->tproc->pid) + ".txt").c_str(), + auto stdoutFd = + ::open(("stdout-" + std::to_string(thread->tproc->pid) + ".txt").c_str(), + O_CREAT | O_TRUNC | O_WRONLY, 0666); + auto stderrFd = + ::open(("stderr-" + std::to_string(thread->tproc->pid) + ".txt").c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0666); auto logFd = ::open(("log-" + std::to_string(thread->tproc->pid) + ".txt").c_str(), @@ -703,13 +711,65 @@ SysResult fork(Thread *thread, slong flags) { dup2(logFd, 1); dup2(logFd, 2); - auto tty = createFdWrapDevice(ttyFd); + auto stdoutDev = createFdWrapDevice(stdoutFd); + auto stderrDev = createFdWrapDevice(stderrFd); + + rx::vfs::addDevice("stdout", stdoutDev); + rx::vfs::addDevice("stderr", stderrDev); + rx::vfs::addDevice("deci_stdout", stdoutDev); + rx::vfs::addDevice("deci_stderr", stderrDev); + return {}; +} + +SysResult execve(Thread *thread, ptr fname, ptr> argv, + ptr> envv) { + ORBIS_LOG_ERROR(__FUNCTION__, fname); + + std::vector _argv; + std::vector _envv; + + if (auto ptr = argv) { + char *p; + while (uread(p, ptr) == ErrorCode{} && p != nullptr) { + ORBIS_LOG_ERROR(" argv ", p); + _argv.push_back(p); + ++ptr; + } + } + + if (auto ptr = envv) { + char *p; + while (uread(p, ptr) == ErrorCode{} && p != nullptr) { + ORBIS_LOG_ERROR(" envv ", p); + _envv.push_back(p); + ++ptr; + } + } + + { + orbis::Ref file; + auto result = rx::vfs::open(fname, kOpenFlagReadOnly, 0, &file, thread); + if (result.isError()) { + return result; + } + } + + std::string path = fname; + rx::vm::reset(); + + thread->tproc->nextTlsSlot = 1; + for (auto [id, mod] : thread->tproc->modulesMap) { + thread->tproc->modulesMap.close(id); + } + + auto executableModule = rx::linker::loadModuleFile(path, thread); + + executableModule->id = thread->tproc->modulesMap.insert(executableModule); + thread->tproc->processParam = executableModule->processParam; + thread->tproc->processParamSize = executableModule->processParamSize; - rx::vfs::addDevice("stdout", tty); - rx::vfs::addDevice("stderr", tty); - rx::vfs::addDevice("deci_stdout", tty); - rx::vfs::addDevice("deci_stderr", tty); - return{}; + ps4Exec(thread, executableModule, _argv, _envv); + std::abort(); } SysResult registerEhFrames(Thread *thread) { @@ -766,6 +826,7 @@ ProcessOps rx::procOpsTable = { .thr_wake = thr_wake, .thr_set_name = thr_set_name, .fork = fork, + .execve = execve, .exit = exit, .processNeeded = processNeeded, .registerEhFrames = registerEhFrames, diff --git a/rpcsx-os/vfs.cpp b/rpcsx-os/vfs.cpp index b9974f6d..c419e610 100644 --- a/rpcsx-os/vfs.cpp +++ b/rpcsx-os/vfs.cpp @@ -49,8 +49,8 @@ void rx::vfs::fork() { } gDevFs = orbis::knew(); - gMountsMap.emplace("/dev/", gDevFs); - gMountsMap.emplace("/proc/", orbis::knew()); + gMountsMap["/dev/"] = gDevFs; + gMountsMap["/proc/"] = orbis::knew(); for (auto &fs : parentDevFs->devices) { gDevFs->devices[fs.first] = fs.second; diff --git a/rpcsx-os/vm.cpp b/rpcsx-os/vm.cpp index 72dfad33..6aad562d 100644 --- a/rpcsx-os/vm.cpp +++ b/rpcsx-os/vm.cpp @@ -673,6 +673,23 @@ void rx::vm::fork(std::uint64_t pid) { } } +void rx::vm::reset() { + std::memset(gBlocks, 0, sizeof(gBlocks)); + + utils::unmap(reinterpret_cast(kMinAddress), + kMaxAddress - kMinAddress); + if (::ftruncate64(gMemoryShm, 0) < 0) { + std::abort(); + } + if (::ftruncate64(gMemoryShm, kMemorySize) < 0) { + std::abort(); + } + + reserve(0, kMinAddress); + utils::reserve(reinterpret_cast(kMinAddress), + kMaxAddress - kMinAddress); +} + void rx::vm::initialize() { std::printf("Memory: initialization\n"); diff --git a/rpcsx-os/vm.hpp b/rpcsx-os/vm.hpp index 850c6e9f..ca49921b 100644 --- a/rpcsx-os/vm.hpp +++ b/rpcsx-os/vm.hpp @@ -68,6 +68,7 @@ std::string mapProtToString(std::int32_t prot); void printHostStats(); void fork(std::uint64_t pid); +void reset(); void initialize(); void deinitialize(); void *map(void *addr, std::uint64_t len, std::int32_t prot, std::int32_t flags,