implement unix socket ops

implement cross process dmem support
implement ipmi try send message
implement sys_batch_map
store saves to game directory (.rpcsx subfolder)
fix get dir entries
added uvd & vce devices
This commit is contained in:
DH 2023-12-31 14:30:49 +03:00
parent a6211b514f
commit 6e25f347d3
39 changed files with 1526 additions and 294 deletions

View file

@ -0,0 +1,9 @@
#pragma once
namespace orbis {
struct SocketAddress {
unsigned char len;
unsigned char family;
char data[14];
};
} // namespace orbis

View file

@ -14,6 +14,9 @@ struct KNote;
struct Thread;
struct Stat;
struct Uio;
struct SocketAddress;
struct msghdr;
struct sf_hdtr;
struct FileOps {
std::int32_t flags;
@ -41,6 +44,33 @@ struct FileOps {
Thread *thread) = nullptr;
ErrorCode (*munmap)(File *file, void **address, std::uint64_t size,
Thread *thread) = nullptr;
ErrorCode (*bind)(orbis::File *file, SocketAddress *address,
std::size_t addressLen, Thread *thread) = nullptr;
ErrorCode (*listen)(orbis::File *file, int backlog, Thread *thread) = nullptr;
ErrorCode (*accept)(orbis::File *file, SocketAddress *address,
std::uint32_t *addressLen, Thread *thread) = nullptr;
ErrorCode (*connect)(orbis::File *file, SocketAddress *address,
std::uint32_t addressLen, Thread *thread) = nullptr;
ErrorCode (*sendto)(orbis::File *file, const void *buf, size_t len,
sint flags, caddr_t to, sint tolen,
Thread *thread) = nullptr;
ErrorCode (*sendmsg)(orbis::File *file, msghdr *msg, sint flags,
Thread *thread) = nullptr;
ErrorCode (*recvfrom)(orbis::File *file, void *buf, size_t len,
sint flags, SocketAddress *from, uint32_t *fromlenaddr,
Thread *thread) = nullptr;
ErrorCode (*recvmsg)(orbis::File *file, msghdr *msg, sint flags,
Thread *thread) = nullptr;
ErrorCode (*shutdown)(orbis::File *file, sint how, Thread *thread) = nullptr;
ErrorCode (*setsockopt)(orbis::File *file, sint level, sint name,
const void *val, sint valsize,
Thread *thread) = nullptr;
ErrorCode (*getsockopt)(orbis::File *file, sint level, sint name, void *val,
sint *avalsize, Thread *thread) = nullptr;
ErrorCode (*sendfile)(orbis::File *file, sint fd, off_t offset, size_t nbytes,
ptr<struct sf_hdtr> hdtr, ptr<off_t> sbytes, sint flags,
Thread *thread) = nullptr;
};
struct File : RcBase {
@ -49,6 +79,7 @@ struct File : RcBase {
const FileOps *ops = nullptr;
Ref<RcBase> device;
std::uint64_t nextOff = 0;
int hostFd = -1;
utils::kvector<Dirent> dirEntries;
};
} // namespace orbis

View file

@ -80,7 +80,6 @@ struct IpmiSession : RcBase {
EventFlag evf{0, 0};
shared_cv connectCv;
bool expectedOutput = false; // TODO: verify
bool connected = false; // TODO: implement more states
sint connectionStatus{0};
};
@ -152,8 +151,16 @@ SysResult sysIpmiSendConnectResult(Thread *thread, ptr<uint> result, uint kid,
ptr<void> params, uint64_t paramsSz);
SysResult sysIpmiSessionRespondSync(Thread *thread, ptr<uint> result, uint kid,
ptr<void> params, uint64_t paramsSz);
SysResult sysIpmiClientGetMessage(Thread *thread, ptr<uint> result, uint kid,
ptr<void> params, uint64_t paramsSz);
SysResult sysIpmiClientTryGetMessage(Thread *thread, ptr<uint> result, uint kid,
ptr<void> params, uint64_t paramsSz);
SysResult sysIpmiSessionTrySendMessage(Thread *thread, ptr<uint> result,
uint kid, ptr<void> params,
uint64_t paramsSz);
SysResult sysIpmiClientDisconnect(Thread *thread, ptr<uint> result,
uint kid, ptr<void> params,
uint64_t paramsSz);
SysResult sysIpmiSessionGetClientPid(Thread *thread, ptr<uint> result, uint kid,
ptr<void> params, uint64_t paramsSz);
SysResult sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result,

View file

@ -7,7 +7,7 @@
#include <set>
namespace orbis {
struct File;
static constexpr auto kEvFiltRead = -1;
static constexpr auto kEvFiltWrite = -2;
static constexpr auto kEvFiltAio = -3;
@ -75,6 +75,7 @@ struct KQueue;
struct KNote {
shared_mutex mutex;
Ref<KQueue> queue;
Ref<File> file;
KEvent event{};
bool enabled = true;
bool triggered = false;

View file

@ -20,6 +20,7 @@ struct timespec;
struct Stat;
struct stack_t;
struct IoVec;
struct BatchMapEntry;
SysResult nosys(Thread *thread);
@ -53,13 +54,13 @@ SysResult sys_recvmsg(Thread *thread, sint s, ptr<struct msghdr> msg,
SysResult sys_sendmsg(Thread *thread, sint s, ptr<struct msghdr> msg,
sint flags);
SysResult sys_recvfrom(Thread *thread, sint s, caddr_t buf, size_t len,
sint flags, ptr<struct sockaddr> from,
sint flags, ptr<SocketAddress> from,
ptr<uint32_t> fromlenaddr);
SysResult sys_accept(Thread *thread, sint s, ptr<struct sockaddr> from,
SysResult sys_accept(Thread *thread, sint s, ptr<SocketAddress> from,
ptr<uint32_t> fromlenaddr);
SysResult sys_getpeername(Thread *thread, sint fdes, ptr<struct sockaddr> asa,
SysResult sys_getpeername(Thread *thread, sint fdes, ptr<SocketAddress> asa,
ptr<uint32_t> alen);
SysResult sys_getsockname(Thread *thread, sint fdes, ptr<struct sockaddr> asa,
SysResult sys_getsockname(Thread *thread, sint fdes, ptr<SocketAddress> asa,
ptr<uint32_t> alen);
SysResult sys_access(Thread *thread, ptr<char> path, sint flags);
SysResult sys_chflags(Thread *thread, ptr<char> path, sint flags);
@ -634,7 +635,8 @@ SysResult sys_evf_cancel(Thread *thread, sint id, uint64_t value,
ptr<sint> pNumWaitThreads);
SysResult sys_query_memory_protection(Thread *thread, ptr<void> address,
ptr<MemoryProtection> protection);
SysResult sys_batch_map(Thread *thread /* TODO */);
SysResult sys_batch_map(Thread *thread, sint unk, sint flags, ptr<BatchMapEntry> entries,
sint entriesCount, ptr<sint> processedCount);
SysResult sys_osem_create(Thread *thread, ptr<const char[32]> name, uint attrs,
sint initCount, sint maxCount);
SysResult sys_osem_delete(Thread *thread, sint id);
@ -720,7 +722,8 @@ SysResult sys_get_proc_type_info(Thread *thread, ptr<sint> destProcessInfo);
SysResult sys_get_resident_count(Thread *thread, pid_t pid);
SysResult sys_prepare_to_suspend_process(Thread *thread, pid_t pid);
SysResult sys_get_resident_fmem_count(Thread *thread, pid_t pid);
SysResult sys_thr_get_name(Thread *thread, lwpid_t lwpid);
SysResult sys_thr_get_name(Thread *thread, lwpid_t lwpid, char *buf,
size_t buflen);
SysResult sys_set_gpo(Thread *thread /* TODO */);
SysResult sys_get_paging_stats_of_all_objects(Thread *thread /* TODO */);
SysResult sys_test_debug_rwmem(Thread *thread /* TODO */);

View file

@ -51,6 +51,8 @@ struct ProcessOps {
SysResult (*blockpool_unmap)(Thread *thread, caddr_t addr, size_t len);
SysResult (*socket)(Thread *thread, ptr<const char> name, sint domain,
sint type, sint protocol, Ref<File> *file);
SysResult (*socketpair)(Thread *thread, sint domain, sint type, sint protocol,
Ref<File> *a, Ref<File> *b);
SysResult (*shm_unlink)(Thread *thread, const char *path);
SysResult (*dynlib_get_obj_member)(Thread *thread, ModuleHandle handle,
uint64_t index, ptr<ptr<void>> addrp);

View file

@ -1,6 +1,9 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <span>
namespace orbis {
struct IoVec {
@ -25,5 +28,27 @@ struct Uio {
UioSeg segflg;
UioRw rw;
void *td;
std::size_t write(const void *data, std::size_t size) {
auto pos = reinterpret_cast<const std::byte *>(data);
auto end = pos + size;
for (auto vec : std::span(iov, iovcnt)) {
if (pos >= end) {
break;
}
auto nextPos = std::min(pos + vec.len, end);
std::memcpy(vec.base, pos, nextPos - pos);
pos = nextPos;
}
return size - (end - pos);
}
template<typename T>
std::size_t write(const T &object) {
return write(&object, sizeof(T));
}
};
} // namespace orbis

View file

@ -20,7 +20,7 @@ struct RcBase {
void incRef() {
if (!_total_size)
std::abort();
if (references.fetch_add(1, std::memory_order::relaxed) > 512) {
if (references.fetch_add(1, std::memory_order::relaxed) > 4096) {
assert(!"too many references");
}
}
@ -81,7 +81,7 @@ public:
template <typename OT>
requires(std::is_base_of_v<T, OT>)
Ref &operator=(Ref<OT> &&other) {
other.swap(*this);
other.template cast<T>().swap(*this);
return *this;
}

View file

@ -340,6 +340,23 @@ orbis::SysResult orbis::sysIpmiSessionRespondSync(Thread *thread,
session->responseCv.notify_one(session->mutex);
return uwrite(result, 0u);
}
orbis::SysResult orbis::sysIpmiClientGetMessage(Thread *thread,
ptr<uint> result, uint kid,
ptr<void> params,
uint64_t paramsSz) {
auto client = thread->tproc->ipmiMap.get(kid).cast<IpmiClient>();
if (client == nullptr) {
return ErrorCode::INVAL;
}
ORBIS_LOG_ERROR(__FUNCTION__, client->name, client->messages.size(),
paramsSz);
while (true) {
std::this_thread::sleep_for(std::chrono::days(1));
}
return uwrite<uint>(result, 0x80020000 + static_cast<int>(ErrorCode::AGAIN));
}
orbis::SysResult orbis::sysIpmiClientTryGetMessage(Thread *thread,
ptr<uint> result, uint kid,
@ -365,6 +382,8 @@ orbis::SysResult orbis::sysIpmiClientTryGetMessage(Thread *thread,
return ErrorCode::INVAL;
}
// ORBIS_LOG_ERROR(__FUNCTION__, client->name, client->messages.size());
SceIpmiClientTryGetArgs _params;
ORBIS_RET_ON_ERROR(uread(_params, ptr<SceIpmiClientTryGetArgs>(params)));
@ -389,6 +408,81 @@ orbis::SysResult orbis::sysIpmiClientTryGetMessage(Thread *thread,
return uwrite<uint>(result, 0);
}
orbis::SysResult orbis::sysIpmiSessionTrySendMessage(Thread *thread,
ptr<uint> result, uint kid,
ptr<void> params,
uint64_t paramsSz) {
struct SceIpmiClientTrySendArgs {
uint32_t unk; // 0
uint32_t padding;
ptr<std::byte> message;
uint64_t size;
};
static_assert(sizeof(SceIpmiClientTrySendArgs) == 0x18);
if (paramsSz != sizeof(SceIpmiClientTrySendArgs)) {
return ErrorCode::INVAL;
}
auto session = thread->tproc->ipmiMap.get(kid).cast<IpmiSession>();
if (session == nullptr) {
return ErrorCode::INVAL;
}
SceIpmiClientTrySendArgs _params;
ORBIS_RET_ON_ERROR(uread(_params, ptr<SceIpmiClientTrySendArgs>(params)));
std::lock_guard lock(session->mutex);
if (session->client == nullptr) {
return ErrorCode::INVAL;
}
auto client = session->client;
std::lock_guard lockClient(client->mutex);
ORBIS_LOG_ERROR(__FUNCTION__, session->server->name, client->name,
client->messages.size(), _params.message, _params.size);
auto &message = client->messages.emplace_back();
message.resize(_params.size);
ORBIS_RET_ON_ERROR(ureadRaw(message.data(), _params.message, _params.size));
client->messageCv.notify_one(client->mutex);
return uwrite<uint>(result, 0);
}
orbis::SysResult orbis::sysIpmiClientDisconnect(Thread *thread,
ptr<uint> result, uint kid,
ptr<void> params,
uint64_t paramsSz) {
struct SceIpmiClientDisconnectArgs {
ptr<sint> status;
};
if (paramsSz != sizeof(SceIpmiClientDisconnectArgs)) {
return ErrorCode::INVAL;
}
auto client = thread->tproc->ipmiMap.get(kid).cast<IpmiClient>();
if (client == nullptr) {
return ErrorCode::INVAL;
}
SceIpmiClientDisconnectArgs _params;
ORBIS_RET_ON_ERROR(uread(_params, ptr<SceIpmiClientDisconnectArgs>(params)));
ORBIS_LOG_ERROR(__FUNCTION__, client->name, _params.status);
std::lock_guard lock(client->mutex);
auto &message = client->messages.front();
ORBIS_RET_ON_ERROR(uwrite(_params.status, 0));
return uwrite<uint>(result, 0);
}
orbis::SysResult orbis::sysIpmiSessionGetClientPid(Thread *thread,
ptr<uint> result, uint kid,
ptr<void> params,
@ -474,7 +568,6 @@ orbis::sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result, uint kid,
// _params.numInData, _params.unk, _params.numOutData,
// _params.pInData, _params.pOutData, _params.pResult,
// _params.flags);
std::size_t inSize = 0;
for (auto &data : std::span(_params.pInData, _params.numInData)) {
inSize += data.size;
@ -499,8 +592,6 @@ orbis::sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result, uint kid,
ORBIS_LOG_TODO("IPMI: sync call", client->name, _params.method,
thread->tproc->pid);
thread->where();
auto bufLoc = std::bit_cast<char *>(msg + 1);
for (auto &data : std::span(_params.pInData, _params.numInData)) {
@ -539,6 +630,10 @@ orbis::sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result, uint kid,
auto response = std::move(session->messageResponses.front());
session->messageResponses.pop_front();
if (response.errorCode != 0) {
thread->where();
}
ORBIS_RET_ON_ERROR(uwrite(_params.pResult, response.errorCode));
if (_params.numOutData > 0 && _params.pOutData->size < response.data.size()) {
return ErrorCode::INVAL;
@ -753,11 +848,12 @@ orbis::SysResult orbis::sysIpmiClientPollEventFlag(Thread *thread,
return ErrorCode::INVAL;
}
ORBIS_LOG_TODO(__FUNCTION__, client->name, _params.index, _params.patternSet,
_params.mode, _params.pPatternSet);
// ORBIS_LOG_TODO(__FUNCTION__, client->name, _params.index,
// _params.patternSet,
// _params.mode, _params.pPatternSet);
ORBIS_RET_ON_ERROR(uwrite(_params.pPatternSet, 0u));
// client->evf.set(_params.a);
return ErrorCode::BUSY;
return SysResult::notAnError(ErrorCode::BUSY);
}
orbis::SysResult orbis::sysIpmiSessionWaitEventFlag(Thread *thread,

View file

@ -1,7 +1,9 @@
#include "pipe.hpp"
#include "error/ErrorCode.hpp"
#include "file.hpp"
#include "thread/Thread.hpp"
#include "uio.hpp"
#include "utils/Logs.hpp"
#include <span>
static orbis::ErrorCode pipe_read(orbis::File *file, orbis::Uio *uio,
@ -9,16 +11,31 @@ static orbis::ErrorCode pipe_read(orbis::File *file, orbis::Uio *uio,
auto pipe = static_cast<orbis::Pipe *>(file);
while (true) {
if (pipe->data.empty()) {
pipe->cv.wait(file->mtx);
continue;
// pipe->cv.wait(file->mtx);
// ORBIS_LOG_ERROR(__FUNCTION__, "wakeup", thread->name, thread->tid, file);
// continue;
return orbis::ErrorCode::WOULDBLOCK;
}
for (auto vec : std::span(uio->iov, uio->iovcnt)) {
auto size = std::min<std::size_t>(pipe->data.size(), vec.len);
if (size == 0) {
pipe->data.clear();
continue;
}
if (size > pipe->data.size()) {
size = pipe->data.size();
}
uio->offset += size;
std::memcpy(vec.base, pipe->data.data(), size);
ORBIS_LOG_ERROR(__FUNCTION__, thread->name, thread->tid, file, size, pipe->data.size(), uio->offset, file->nextOff);
if (pipe->data.size() == size) {
pipe->data.clear();
break;
}
@ -37,20 +54,30 @@ static orbis::ErrorCode pipe_read(orbis::File *file, orbis::Uio *uio,
static orbis::ErrorCode pipe_write(orbis::File *file, orbis::Uio *uio,
orbis::Thread *thread) {
auto pipe = static_cast<orbis::Pipe *>(file);
ORBIS_LOG_ERROR(__FUNCTION__, thread->name, thread->tid, file);
std::size_t cnt = 0;
for (auto vec : std::span(uio->iov, uio->iovcnt)) {
auto offset = pipe->data.size();
pipe->data.resize(offset + vec.len);
std::memcpy(pipe->data.data(), vec.base, vec.len);
ORBIS_RET_ON_ERROR(orbis::ureadRaw(pipe->data.data(), vec.base, vec.len));
cnt += vec.len;
}
file->event.emit(orbis::kEvFiltRead);
pipe->cv.notify_one(file->mtx);
uio->resid = 0;
return {};
uio->resid -= cnt;
uio->offset += cnt;
ORBIS_LOG_ERROR(__FUNCTION__, thread->name, thread->tid, file, uio->resid, uio->offset, file->nextOff, cnt);
thread->where();
return{};
}
static orbis::FileOps pipe_ops = {.read = pipe_read, .write = pipe_write};
static orbis::FileOps pipe_ops = {
.read = pipe_read,
.write = pipe_write,
};
orbis::Ref<orbis::Pipe> orbis::createPipe() {
auto result = knew<Pipe>();

View file

@ -7,6 +7,7 @@
#include <chrono>
#include <list>
#include <span>
#include <sys/select.h>
orbis::SysResult orbis::sys_kqueue(Thread *thread) {
auto queue = knew<KQueue>();
@ -33,6 +34,28 @@ orbis::SysResult orbis::sys_kqueueex(Thread *thread, ptr<char> name,
return {};
}
static bool isReadEventTriggered(int hostFd) {
fd_set fds{};
FD_SET(hostFd, &fds);
timeval timeout{};
if (::select(hostFd + 1, &fds, nullptr, nullptr, &timeout) < 0) {
return false;
}
return FD_ISSET(hostFd, &fds);
}
static bool isWriteEventTriggered(int hostFd) {
fd_set fds{};
FD_SET(hostFd, &fds);
timeval timeout{};
if (::select(hostFd + 1, nullptr, &fds, nullptr, &timeout) < 0) {
return false;
}
return FD_ISSET(hostFd, &fds);
}
namespace orbis {
static SysResult keventChange(KQueue *kq, KEvent &change, Thread *thread) {
auto nodeIt = kq->notes.end();
@ -82,11 +105,11 @@ static SysResult keventChange(KQueue *kq, KEvent &change, Thread *thread) {
}
std::unique_lock lock(fd->event.mutex);
if (change.filter == kEvFiltWrite) {
nodeIt->triggered = true;
kq->cv.notify_all(kq->mtx);
}
nodeIt->file = fd;
// if (change.filter == kEvFiltWrite) {
// nodeIt->triggered = true;
// kq->cv.notify_all(kq->mtx);
// }
fd->event.notes.insert(&*nodeIt);
}
@ -176,14 +199,16 @@ orbis::SysResult orbis::sys_kevent(Thread *thread, sint fd,
for (auto &changePtr : std::span(changelist, nchanges)) {
KEvent change;
ORBIS_RET_ON_ERROR(uread(change, &changePtr));
ORBIS_LOG_TODO(__FUNCTION__, change.ident, change.filter, change.flags,
change.fflags, change.data, change.udata);
ORBIS_LOG_TODO(__FUNCTION__, fd, change.ident, change.filter,
change.flags, change.fflags, change.data, change.udata);
if (auto result = keventChange(kq.get(), change, thread);
result.value() != 0) {
return result;
}
}
kq->cv.notify_all(kq->mtx);
}
}
@ -217,7 +242,17 @@ orbis::SysResult orbis::sys_kevent(Thread *thread, sint fd,
std::vector<KEvent> result;
result.reserve(nevents);
if (kq->notes.empty()) {
// ORBIS_LOG_ERROR(__FUNCTION__, "attempt to wait empty kqueue", fd,
// nevents, timeoutPoint.time_since_epoch().count()); thread->where();
// return{};
// std::abort();
return {};
}
while (true) {
bool waitHack = false;
bool canSleep = true;
std::lock_guard lock(kq->mtx);
for (auto it = kq->notes.begin(); it != kq->notes.end();) {
if (result.size() >= nevents) {
@ -227,9 +262,32 @@ orbis::SysResult orbis::sys_kevent(Thread *thread, sint fd,
auto &note = *it;
std::lock_guard lock(note.mutex);
if (!note.triggered) {
if (note.event.filter == kEvFiltRead) {
if (note.file->hostFd < 0 ||
isReadEventTriggered(note.file->hostFd)) {
note.triggered = true;
} else {
canSleep = false;
}
} else if (note.event.filter == kEvFiltWrite) {
if (note.file->hostFd < 0 ||
isWriteEventTriggered(note.file->hostFd)) {
note.triggered = true;
} else {
canSleep = false;
}
}
}
if (note.enabled && note.triggered) {
result.push_back(note.event);
if (note.event.filter == kEvFiltGraphicsCore ||
note.event.filter == kEvFiltDisplay) {
waitHack = true;
}
if (note.event.flags & kEvDispatch) {
note.enabled = false;
}
@ -244,6 +302,9 @@ orbis::SysResult orbis::sys_kevent(Thread *thread, sint fd,
}
if (!result.empty()) {
// if (waitHack) {
// std::this_thread::sleep_for(std::chrono::milliseconds(3));
// }
break;
}
@ -256,9 +317,13 @@ orbis::SysResult orbis::sys_kevent(Thread *thread, sint fd,
auto waitTimeout = std::chrono::duration_cast<std::chrono::microseconds>(
timeoutPoint - now);
kq->cv.wait(kq->mtx, waitTimeout.count());
if (canSleep) {
kq->cv.wait(kq->mtx, waitTimeout.count());
}
} else {
kq->cv.wait(kq->mtx);
if (canSleep) {
kq->cv.wait(kq->mtx);
}
}
}

View file

@ -137,6 +137,11 @@ orbis::SysResult orbis::sys_regmgr_call(Thread *thread, uint32_t op,
return {};
}
if (int_value->encoded_id == 0x29b56169422aa3dd) {
int_value->value = 2;
return {};
}
// 0x503f69bde385a6ac // allow loading from dev machine?
// 0x2d946f62aef8f878
@ -162,7 +167,6 @@ orbis::SysResult orbis::sys_dl_notify_event(Thread *thread /* TODO */) {
}
orbis::SysResult orbis::sys_evf_create(Thread *thread, ptr<const char[32]> name,
sint attrs, uint64_t initPattern) {
ORBIS_LOG_WARNING(__FUNCTION__, name, attrs, initPattern);
if (name == nullptr) {
return ErrorCode::INVAL;
}
@ -215,7 +219,9 @@ orbis::SysResult orbis::sys_evf_create(Thread *thread, ptr<const char[32]> name,
std::strncpy(eventFlag->name, _name, 32);
}
thread->retval[0] = thread->tproc->evfMap.insert(eventFlag);
auto fd = thread->tproc->evfMap.insert(eventFlag);
thread->retval[0] = fd;
ORBIS_LOG_WARNING(__FUNCTION__, name, attrs, initPattern, fd);
return {};
}
orbis::SysResult orbis::sys_evf_delete(Thread *thread, sint id) {
@ -229,7 +235,6 @@ orbis::SysResult orbis::sys_evf_delete(Thread *thread, sint id) {
return {};
}
orbis::SysResult orbis::sys_evf_open(Thread *thread, ptr<const char[32]> name) {
ORBIS_LOG_WARNING(__FUNCTION__, name);
char _name[32];
if (auto result = ureadString(_name, sizeof(_name), (const char *)name);
result != ErrorCode{}) {
@ -239,10 +244,13 @@ orbis::SysResult orbis::sys_evf_open(Thread *thread, ptr<const char[32]> name) {
auto eventFlag = thread->tproc->context->findEventFlag(_name);
if (eventFlag == nullptr) {
ORBIS_LOG_ERROR(__FUNCTION__, _name, "not exists");
return ErrorCode::NOENT;
}
thread->retval[0] = thread->tproc->evfMap.insert(eventFlag);
auto fd = thread->tproc->evfMap.insert(eventFlag);
thread->retval[0] = fd;
ORBIS_LOG_WARNING(__FUNCTION__, name, fd);
return {};
}
orbis::SysResult orbis::sys_evf_close(Thread *thread, sint id) {
@ -370,8 +378,70 @@ orbis::sys_query_memory_protection(Thread *thread, ptr<void> address,
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_batch_map(Thread *thread /* TODO */) {
return ErrorCode::NOSYS;
namespace orbis {
struct BatchMapEntry {
ptr<char> start;
off_t offset;
size_t length;
char protection;
char type;
short reserved;
sint operation; // 0 - map direct
// 1 - unmap
// 2 - protect
// 3 - map flexible
// 4 - type protect
};
} // namespace orbis
orbis::SysResult orbis::sys_batch_map(Thread *thread, sint unk, sint flags,
ptr<BatchMapEntry> entries,
sint entriesCount,
ptr<sint> processedCount) {
auto ops = thread->tproc->ops;
SysResult result = ErrorCode{};
ORBIS_LOG_ERROR(__FUNCTION__, unk, flags, entries, entriesCount,
processedCount);
int processed = 0;
for (int i = 0; i < entriesCount; ++i) {
BatchMapEntry _entry;
ORBIS_RET_ON_ERROR(uread(_entry, entries + i));
ORBIS_LOG_ERROR(__FUNCTION__, _entry.operation, ptr<void>(_entry.start),
_entry.length, int(_entry.type), int(_entry.protection),
_entry.offset);
switch (_entry.operation) {
case 0:
result = ops->dmem_mmap(thread, _entry.start, _entry.length, _entry.type,
_entry.protection, flags, _entry.offset);
break;
case 1:
result = ops->munmap(thread, _entry.start, _entry.length);
break;
case 2:
result =
ops->mprotect(thread, _entry.start, _entry.length, _entry.protection);
break;
default:
result = ErrorCode::INVAL;
break;
}
ORBIS_LOG_ERROR(__FUNCTION__, result.value());
if (result.value()) {
ORBIS_LOG_ERROR(__FUNCTION__, result.value());
break;
}
++processed;
}
thread->retval[0] = 0;
ORBIS_RET_ON_ERROR(uwrite(processedCount, processed));
return result;
}
orbis::SysResult orbis::sys_osem_create(Thread *thread,
ptr<const char[32]> name, uint attrs,
@ -418,6 +488,7 @@ orbis::SysResult orbis::sys_osem_create(Thread *thread,
sem = insertedSem;
} else {
sem = knew<Semaphore>(attrs, initCount, maxCount);
std::strncpy(sem->name, _name, 32);
}
thread->retval[0] = thread->tproc->semMap.insert(sem);
@ -1048,8 +1119,26 @@ orbis::SysResult orbis::sys_prepare_to_suspend_process(Thread *thread,
orbis::SysResult orbis::sys_get_resident_fmem_count(Thread *thread, pid_t pid) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_thr_get_name(Thread *thread, lwpid_t lwpid) {
return ErrorCode::NOSYS;
orbis::SysResult orbis::sys_thr_get_name(Thread *thread, lwpid_t lwpid,
char *buf, size_t buflen) {
Thread *searchThread;
if (thread->tid == lwpid) {
searchThread = thread;
} else {
searchThread = thread->tproc->threadsMap.get(lwpid);
if (searchThread == nullptr) {
return ErrorCode::SRCH;
}
}
auto namelen = std::strlen(searchThread->name);
if (namelen >= buflen) {
return ErrorCode::INVAL;
}
ORBIS_RET_ON_ERROR(uwriteRaw(buf, searchThread->name, namelen));
return {};
}
orbis::SysResult orbis::sys_set_gpo(Thread *thread /* TODO */) {
return ErrorCode::NOSYS;
@ -1095,10 +1184,16 @@ orbis::SysResult orbis::sys_ipmimgr_call(Thread *thread, uint op, uint kid,
return sysIpmiSendConnectResult(thread, result, kid, params, paramsSz);
case 0x232:
return sysIpmiSessionRespondSync(thread, result, kid, params, paramsSz);
case 0x251:
return sysIpmiClientGetMessage(thread, result, kid, params, paramsSz);
case 0x252:
return sysIpmiClientTryGetMessage(thread, result, kid, params, paramsSz);
case 0x254:
return sysIpmiSessionTrySendMessage(thread, result, kid, params, paramsSz);
case 0x302:
return sysIpmiSessionGetClientPid(thread, result, kid, params, paramsSz);
case 0x310:
return sysIpmiClientDisconnect(thread, result, kid, params, paramsSz);
case 0x320:
return sysIpmiClientInvokeSyncMethod(thread, result, kid, params, paramsSz);
case 0x400:

View file

@ -1,10 +1,7 @@
#include "pipe.hpp"
#include "sys/sysproto.hpp"
#include "uio.hpp"
#include "utils/Logs.hpp"
#include <chrono>
#include <sys/socket.h>
#include <thread>
orbis::SysResult orbis::sys_socket(Thread *thread, sint domain, sint type,
sint protocol) {
@ -24,37 +21,89 @@ orbis::SysResult orbis::sys_socket(Thread *thread, sint domain, sint type,
}
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_bind(Thread *thread, sint s, caddr_t name,
sint namelen) {
ORBIS_LOG_ERROR(__FUNCTION__, s, name, namelen);
return {};
// ORBIS_LOG_ERROR(__FUNCTION__, s, name, namelen);
auto file = thread->tproc->fileDescriptors.get(s);
if (file == nullptr) {
return ErrorCode::BADF;
}
if (auto bind = file->ops->bind) {
return bind(file.get(), ptr<SocketAddress>(name), namelen, thread);
}
return ErrorCode::NOTSUP;
}
orbis::SysResult orbis::sys_listen(Thread *thread, sint s, sint backlog) {
ORBIS_LOG_ERROR(__FUNCTION__, s, backlog);
return {};
auto file = thread->tproc->fileDescriptors.get(s);
if (file == nullptr) {
return ErrorCode::BADF;
}
if (auto listen = file->ops->listen) {
return listen(file.get(), backlog, thread);
}
return ErrorCode::NOTSUP;
}
orbis::SysResult orbis::sys_accept(Thread *thread, sint s,
ptr<struct sockaddr> from,
ptr<SocketAddress> from,
ptr<uint32_t> fromlenaddr) {
ORBIS_LOG_ERROR(__FUNCTION__, s, from, fromlenaddr);
std::this_thread::sleep_for(std::chrono::days(1));
return SysResult::notAnError(ErrorCode::WOULDBLOCK);
auto file = thread->tproc->fileDescriptors.get(s);
if (file == nullptr) {
return ErrorCode::BADF;
}
if (auto accept = file->ops->accept) {
return accept(file.get(), from, fromlenaddr, thread);
}
return ErrorCode::NOTSUP;
}
orbis::SysResult orbis::sys_connect(Thread *thread, sint s, caddr_t name,
sint namelen) {
return ErrorCode::NOSYS;
auto file = thread->tproc->fileDescriptors.get(s);
if (file == nullptr) {
return ErrorCode::BADF;
}
if (auto connect = file->ops->connect) {
return connect(file.get(), ptr<SocketAddress>(name), namelen, thread);
}
return ErrorCode::NOTSUP;
}
orbis::SysResult orbis::sys_socketpair(Thread *thread, sint domain, sint type,
sint protocol, ptr<sint> rsv) {
ORBIS_LOG_ERROR(__FUNCTION__, domain, type, protocol, rsv);
ORBIS_LOG_TODO(__FUNCTION__, domain, type, protocol, rsv);
if (auto socketpair = thread->tproc->ops->socketpair) {
Ref<File> a;
Ref<File> b;
auto result = socketpair(thread, domain, type, protocol, &a, &b);
auto pipe = createPipe();
auto a = thread->tproc->fileDescriptors.insert(pipe);
auto b = thread->tproc->fileDescriptors.insert(pipe);
if (auto errc = uwrite(rsv, a); errc != ErrorCode{}) {
return errc;
if (result.isError()) {
return result;
}
auto aFd = thread->tproc->fileDescriptors.insert(a);
auto bFd = thread->tproc->fileDescriptors.insert(b);
if (auto errc = uwrite(rsv, aFd); errc != ErrorCode{}) {
return errc;
}
return uwrite(rsv + 1, bFd);
}
return uwrite(rsv + 1, b);
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_sendto(Thread *thread, sint s, caddr_t buf,
size_t len, sint flags, caddr_t to,
@ -67,54 +116,82 @@ orbis::SysResult orbis::sys_sendmsg(Thread *thread, sint s,
}
orbis::SysResult orbis::sys_recvfrom(Thread *thread, sint s, caddr_t buf,
size_t len, sint flags,
ptr<struct sockaddr> from,
ptr<SocketAddress> from,
ptr<uint32_t> fromlenaddr) {
auto pipe = thread->tproc->fileDescriptors.get(s).cast<Pipe>();
if (pipe == nullptr) {
return ErrorCode::INVAL;
auto file = thread->tproc->fileDescriptors.get(s);
if (file == nullptr) {
return ErrorCode::BADF;
}
std::lock_guard lock(pipe->mtx);
IoVec io = {
.base = buf,
.len = len,
};
Uio uio{
.iov = &io,
.iovcnt = 1,
.segflg = UioSeg::UserSpace,
.rw = UioRw::Read,
.td = thread,
};
pipe->ops->read(pipe.get(), &uio, thread);
thread->retval[0] = uio.offset;
return {};
if (auto recvfrom = file->ops->recvfrom) {
return SysResult::notAnError(recvfrom(file.get(), buf, len, flags, from, fromlenaddr, thread));
}
return ErrorCode::NOTSUP;
}
orbis::SysResult orbis::sys_recvmsg(Thread *thread, sint s,
ptr<struct msghdr> msg, sint flags) {
return ErrorCode::NOSYS;
auto file = thread->tproc->fileDescriptors.get(s);
if (file == nullptr) {
return ErrorCode::BADF;
}
if (auto recvmsg = file->ops->recvmsg) {
return recvmsg(file.get(), msg, flags, thread);
}
return ErrorCode::NOTSUP;
}
orbis::SysResult orbis::sys_shutdown(Thread *thread, sint s, sint how) {
return ErrorCode::NOSYS;
auto file = thread->tproc->fileDescriptors.get(s);
if (file == nullptr) {
return ErrorCode::BADF;
}
if (auto shutdown = file->ops->shutdown) {
return shutdown(file.get(), how, thread);
}
return ErrorCode::NOTSUP;
}
orbis::SysResult orbis::sys_setsockopt(Thread *thread, sint s, sint level,
sint name, caddr_t val, sint valsize) {
ORBIS_LOG_TODO(__FUNCTION__, s, level, name, val, valsize);
return {};
auto file = thread->tproc->fileDescriptors.get(s);
if (file == nullptr) {
return ErrorCode::BADF;
}
if (auto setsockopt = file->ops->setsockopt) {
return setsockopt(file.get(), level, name, val, valsize, thread);
}
return ErrorCode::NOTSUP;
}
orbis::SysResult orbis::sys_getsockopt(Thread *thread, sint s, sint level,
sint name, caddr_t val,
ptr<sint> avalsize) {
ORBIS_LOG_TODO(__FUNCTION__, s, level, name, val, avalsize);
return {};
auto file = thread->tproc->fileDescriptors.get(s);
if (file == nullptr) {
return ErrorCode::BADF;
}
if (auto getsockopt = file->ops->getsockopt) {
return getsockopt(file.get(), level, name, val, avalsize, thread);
}
return ErrorCode::NOTSUP;
}
orbis::SysResult orbis::sys_getsockname(Thread *thread, sint fdes,
ptr<struct sockaddr> asa,
ptr<SocketAddress> asa,
ptr<uint32_t> alen) {
return ErrorCode::NOSYS;
// return uwrite<uint32_t>(alen, sizeof(SockAddr));
ORBIS_LOG_TODO(__FUNCTION__);
return {};
}
orbis::SysResult orbis::sys_getpeername(Thread *thread, sint fdes,
ptr<struct sockaddr> asa,
ptr<SocketAddress> asa,
ptr<uint32_t> alen) {
return ErrorCode::NOSYS;
}

View file

@ -2,19 +2,52 @@
#include "sys/sysproto.hpp"
#include "utils/Logs.hpp"
#include <filesystem>
#include <span>
orbis::SysResult orbis::sys_sync(Thread *thread) { return ErrorCode::NOSYS; }
orbis::SysResult orbis::sys_quotactl(Thread *thread, ptr<char> path, sint cmd,
sint uid, caddr_t arg) {
return ErrorCode::NOSYS;
}
namespace orbis {
struct statfs {
char pad[0x118];
char f_fstypename[16]; /* filesystem type name */
char f_mntfromname[88]; /* mounted filesystem */
char f_mntonname[88]; /* directory on which mounted */
};
} // namespace orbis
orbis::SysResult orbis::sys_statfs(Thread *thread, ptr<char> path,
ptr<struct statfs> buf) {
return ErrorCode::NOSYS;
if (buf == 0) {
thread->retval[0] = 1;
return {};
}
std::strncpy(buf->f_fstypename, "exfatfs", sizeof(buf->f_fstypename));
std::strncpy(buf->f_mntfromname, "/dev/super-hdd",
sizeof(buf->f_mntfromname));
std::strncpy(buf->f_mntonname, "/system/", sizeof(buf->f_mntonname));
thread->retval[0] = 1;
return {};
}
orbis::SysResult orbis::sys_fstatfs(Thread *thread, sint fd,
ptr<struct statfs> buf) {
return ErrorCode::NOSYS;
if (buf == 0) {
thread->retval[0] = 1;
return {};
}
std::strncpy(buf->f_fstypename, "exfatfs", sizeof(buf->f_fstypename));
std::strncpy(buf->f_mntfromname, "/dev/super-hdd",
sizeof(buf->f_mntfromname));
std::strncpy(buf->f_mntonname, "/system/", sizeof(buf->f_mntonname));
thread->retval[0] = 1;
return {};
}
orbis::SysResult orbis::sys_getfsstat(Thread *thread, ptr<struct statfs> buf,
slong bufsize, sint flags) {
@ -231,7 +264,7 @@ orbis::SysResult orbis::sys_fchflags(Thread *thread, sint fd, sint flags) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_chmod(Thread *thread, ptr<char> path, sint mode) {
return ErrorCode::NOSYS;
return {};
}
orbis::SysResult orbis::sys_fchmodat(Thread *thread, sint fd, ptr<char> path,
mode_t mode, sint flag) {
@ -353,7 +386,7 @@ orbis::SysResult orbis::sys_getdirentries(Thread *thread, sint fd,
auto next = std::min<uint64_t>(file->dirEntries.size(), pos + rmax);
file->nextOff = next * sizeof(orbis::Dirent);
SysResult result{};
result = uwrite((orbis::Dirent *)buf, entries + pos, next - pos);
result = uwrite(ptr<orbis::Dirent>(buf), entries + pos, next - pos);
if (result.isError())
return result;