mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-06-02 00:33:16 +00:00
Virtual device abstraction (#1577)
* IOFile: removes seek limit checks when file is writable * add virtual devices scaffold * add stdin/out/err as virtual devices * fixed some merging issues * clang-fix --------- Co-authored-by: georgemoralis <giorgosmrls@gmail.com>
This commit is contained in:
parent
c019b54fec
commit
2380f2f9c9
18 changed files with 687 additions and 77 deletions
12
src/core/devices/base_device.cpp
Normal file
12
src/core/devices/base_device.cpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "base_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
BaseDevice::BaseDevice() = default;
|
||||
|
||||
BaseDevice::~BaseDevice() = default;
|
||||
|
||||
} // namespace Core::Devices
|
72
src/core/devices/base_device.h
Normal file
72
src/core/devices/base_device.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <core/libraries/kernel/orbis_error.h>
|
||||
#include "common/types.h"
|
||||
#include "common/va_ctx.h"
|
||||
|
||||
namespace Libraries::Kernel {
|
||||
struct OrbisKernelStat;
|
||||
struct SceKernelIovec;
|
||||
} // namespace Libraries::Kernel
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
class BaseDevice {
|
||||
public:
|
||||
explicit BaseDevice();
|
||||
|
||||
virtual ~BaseDevice() = 0;
|
||||
|
||||
virtual int ioctl(u64 cmd, Common::VaCtx* args) {
|
||||
return ORBIS_KERNEL_ERROR_ENOTTY;
|
||||
}
|
||||
|
||||
virtual s64 write(const void* buf, size_t nbytes) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual size_t readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual s64 preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual s64 lseek(s64 offset, int whence) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual s64 read(void* buf, size_t nbytes) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual int fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual s32 fsync() {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual int ftruncate(s64 length) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual int getdents(void* buf, u32 nbytes, s64* basep) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual s64 pwrite(const void* buf, size_t nbytes, u64 offset) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Core::Devices
|
67
src/core/devices/ioccom.h
Normal file
67
src/core/devices/ioccom.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1982, 1986, 1990, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ioccom.h 8.2 (Berkeley) 3/28/94
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#define IOCPARM_SHIFT 13 /* number of bits for ioctl size */
|
||||
#define IOCPARM_MASK ((1 << IOCPARM_SHIFT) - 1) /* parameter length mask */
|
||||
#define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
|
||||
#define IOCBASECMD(x) ((x) & ~(IOCPARM_MASK << 16))
|
||||
#define IOCGROUP(x) (((x) >> 8) & 0xff)
|
||||
|
||||
#define IOCPARM_MAX (1 << IOCPARM_SHIFT) /* max size of ioctl */
|
||||
#define IOC_VOID 0x20000000 /* no parameters */
|
||||
#define IOC_OUT 0x40000000 /* copy out parameters */
|
||||
#define IOC_IN 0x80000000 /* copy in parameters */
|
||||
#define IOC_INOUT (IOC_IN | IOC_OUT)
|
||||
#define IOC_DIRMASK (IOC_VOID | IOC_OUT | IOC_IN)
|
||||
|
||||
#define _IOC(inout, group, num, len) \
|
||||
((unsigned long)((inout) | (((len) & IOCPARM_MASK) << 16) | ((group) << 8) | (num)))
|
||||
#define _IO(g, n) _IOC(IOC_VOID, (g), (n), 0)
|
||||
#define _IOWINT(g, n) _IOC(IOC_VOID, (g), (n), sizeof(int))
|
||||
#define _IOR(g, n, t) _IOC(IOC_OUT, (g), (n), sizeof(t))
|
||||
#define _IOW(g, n, t) _IOC(IOC_IN, (g), (n), sizeof(t))
|
||||
/* this should be _IORW, but stdio got there first */
|
||||
#define _IOWR(g, n, t) _IOC(IOC_INOUT, (g), (n), sizeof(t))
|
||||
|
||||
/*
|
||||
# Simple parse of ioctl cmd
|
||||
def parse(v):
|
||||
print('inout', (v >> 24 & 0xFF))
|
||||
print('len', hex(v >> 16 & 0xFF))
|
||||
print('group', chr(v >> 8 & 0xFF))
|
||||
print('num', hex(v & 0xFF))
|
||||
*/
|
64
src/core/devices/logger.cpp
Normal file
64
src/core/devices/logger.cpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/libraries/kernel/file_system.h"
|
||||
#include "logger.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
Logger::Logger(std::string prefix, bool is_err) : prefix(std::move(prefix)), is_err(is_err) {}
|
||||
|
||||
Logger::~Logger() = default;
|
||||
|
||||
s64 Logger::write(const void* buf, size_t nbytes) {
|
||||
log(static_cast<const char*>(buf), nbytes);
|
||||
return nbytes;
|
||||
}
|
||||
size_t Logger::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
|
||||
for (int i = 0; i < iovcnt; i++) {
|
||||
log(static_cast<const char*>(iov[i].iov_base), iov[i].iov_len);
|
||||
}
|
||||
return iovcnt;
|
||||
}
|
||||
|
||||
s64 Logger::pwrite(const void* buf, size_t nbytes, u64 offset) {
|
||||
log(static_cast<const char*>(buf), nbytes);
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
s32 Logger::fsync() {
|
||||
log_flush();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Logger::log(const char* buf, size_t nbytes) {
|
||||
std::scoped_lock lock{mtx};
|
||||
const char* end = buf + nbytes;
|
||||
for (const char* it = buf; it < end; ++it) {
|
||||
char c = *it;
|
||||
if (c == '\r') {
|
||||
continue;
|
||||
}
|
||||
if (c == '\n') {
|
||||
log_flush();
|
||||
continue;
|
||||
}
|
||||
buffer.push_back(c);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::log_flush() {
|
||||
std::scoped_lock lock{mtx};
|
||||
if (buffer.empty()) {
|
||||
return;
|
||||
}
|
||||
if (is_err) {
|
||||
LOG_ERROR(Tty, "[{}] {}", prefix, std::string_view{buffer});
|
||||
} else {
|
||||
LOG_INFO(Tty, "[{}] {}", prefix, std::string_view{buffer});
|
||||
}
|
||||
buffer.clear();
|
||||
}
|
||||
|
||||
} // namespace Core::Devices
|
37
src/core/devices/logger.h
Normal file
37
src/core/devices/logger.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base_device.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
class Logger final : BaseDevice {
|
||||
std::string prefix;
|
||||
bool is_err;
|
||||
|
||||
std::recursive_mutex mtx;
|
||||
std::vector<char> buffer;
|
||||
|
||||
public:
|
||||
explicit Logger(std::string prefix, bool is_err);
|
||||
|
||||
~Logger() override;
|
||||
|
||||
s64 write(const void* buf, size_t nbytes) override;
|
||||
size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
|
||||
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override;
|
||||
|
||||
s32 fsync() override;
|
||||
|
||||
private:
|
||||
void log(const char* buf, size_t nbytes);
|
||||
void log_flush();
|
||||
};
|
||||
|
||||
} // namespace Core::Devices
|
55
src/core/devices/nop_device.h
Normal file
55
src/core/devices/nop_device.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
#include "base_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
class NopDevice final : BaseDevice {
|
||||
u32 handle;
|
||||
|
||||
public:
|
||||
explicit NopDevice(u32 handle) : handle(handle) {}
|
||||
|
||||
~NopDevice() override = default;
|
||||
|
||||
int ioctl(u64 cmd, Common::VaCtx* args) override {
|
||||
return 0;
|
||||
}
|
||||
s64 write(const void* buf, size_t nbytes) override {
|
||||
return 0;
|
||||
}
|
||||
size_t readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override {
|
||||
return 0;
|
||||
}
|
||||
size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override {
|
||||
return 0;
|
||||
}
|
||||
s64 preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) override {
|
||||
return 0;
|
||||
}
|
||||
s64 lseek(s64 offset, int whence) override {
|
||||
return 0;
|
||||
}
|
||||
s64 read(void* buf, size_t nbytes) override {
|
||||
return 0;
|
||||
}
|
||||
int fstat(Libraries::Kernel::OrbisKernelStat* sb) override {
|
||||
return 0;
|
||||
}
|
||||
s32 fsync() override {
|
||||
return 0;
|
||||
}
|
||||
int ftruncate(s64 length) override {
|
||||
return 0;
|
||||
}
|
||||
int getdents(void* buf, u32 nbytes, s64* basep) override {
|
||||
return 0;
|
||||
}
|
||||
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Core::Devices
|
Loading…
Add table
Add a link
Reference in a new issue