mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-04 16:32:39 +00:00
add virtual devices scaffold
This commit is contained in:
parent
8ea166ea2f
commit
b9c63b4ae3
@ -472,6 +472,7 @@ set(COMMON src/common/logging/backend.cpp
|
|||||||
src/common/types.h
|
src/common/types.h
|
||||||
src/common/uint128.h
|
src/common/uint128.h
|
||||||
src/common/unique_function.h
|
src/common/unique_function.h
|
||||||
|
src/common/va_ctx.h
|
||||||
src/common/version.h
|
src/common/version.h
|
||||||
src/common/ntapi.h
|
src/common/ntapi.h
|
||||||
src/common/ntapi.cpp
|
src/common/ntapi.cpp
|
||||||
@ -496,6 +497,8 @@ set(CORE src/core/aerolib/stubs.cpp
|
|||||||
src/core/crypto/crypto.cpp
|
src/core/crypto/crypto.cpp
|
||||||
src/core/crypto/crypto.h
|
src/core/crypto/crypto.h
|
||||||
src/core/crypto/keys.h
|
src/core/crypto/keys.h
|
||||||
|
src/core/devices/base_device.cpp
|
||||||
|
src/core/devices/base_device.h
|
||||||
src/core/file_format/pfs.h
|
src/core/file_format/pfs.h
|
||||||
src/core/file_format/pkg.cpp
|
src/core/file_format/pkg.cpp
|
||||||
src/core/file_format/pkg.h
|
src/core/file_format/pkg.h
|
||||||
|
@ -69,6 +69,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
|||||||
SUB(Common, Memory) \
|
SUB(Common, Memory) \
|
||||||
CLS(Core) \
|
CLS(Core) \
|
||||||
SUB(Core, Linker) \
|
SUB(Core, Linker) \
|
||||||
|
SUB(Core, Devices) \
|
||||||
CLS(Config) \
|
CLS(Config) \
|
||||||
CLS(Debug) \
|
CLS(Debug) \
|
||||||
CLS(Kernel) \
|
CLS(Kernel) \
|
||||||
|
@ -35,6 +35,7 @@ enum class Class : u8 {
|
|||||||
Common_Memory, ///< Memory mapping and management functions
|
Common_Memory, ///< Memory mapping and management functions
|
||||||
Core, ///< LLE emulation core
|
Core, ///< LLE emulation core
|
||||||
Core_Linker, ///< The module linker
|
Core_Linker, ///< The module linker
|
||||||
|
Core_Devices, ///< Devices emulation
|
||||||
Config, ///< Emulator configuration (including commandline)
|
Config, ///< Emulator configuration (including commandline)
|
||||||
Debug, ///< Debugging tools
|
Debug, ///< Debugging tools
|
||||||
Kernel, ///< The HLE implementation of the PS4 kernel.
|
Kernel, ///< The HLE implementation of the PS4 kernel.
|
||||||
|
111
src/common/va_ctx.h
Normal file
111
src/common/va_ctx.h
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <xmmintrin.h>
|
||||||
|
#include "common/types.h"
|
||||||
|
|
||||||
|
#define VA_ARGS \
|
||||||
|
uint64_t rdi, uint64_t rsi, uint64_t rdx, uint64_t rcx, uint64_t r8, uint64_t r9, \
|
||||||
|
uint64_t overflow_arg_area, __m128 xmm0, __m128 xmm1, __m128 xmm2, __m128 xmm3, \
|
||||||
|
__m128 xmm4, __m128 xmm5, __m128 xmm6, __m128 xmm7, ...
|
||||||
|
|
||||||
|
#define VA_CTX(ctx) \
|
||||||
|
alignas(16)::Common::VaCtx ctx{}; \
|
||||||
|
(ctx).reg_save_area.gp[0] = rdi; \
|
||||||
|
(ctx).reg_save_area.gp[1] = rsi; \
|
||||||
|
(ctx).reg_save_area.gp[2] = rdx; \
|
||||||
|
(ctx).reg_save_area.gp[3] = rcx; \
|
||||||
|
(ctx).reg_save_area.gp[4] = r8; \
|
||||||
|
(ctx).reg_save_area.gp[5] = r9; \
|
||||||
|
(ctx).reg_save_area.fp[0] = xmm0; \
|
||||||
|
(ctx).reg_save_area.fp[1] = xmm1; \
|
||||||
|
(ctx).reg_save_area.fp[2] = xmm2; \
|
||||||
|
(ctx).reg_save_area.fp[3] = xmm3; \
|
||||||
|
(ctx).reg_save_area.fp[4] = xmm4; \
|
||||||
|
(ctx).reg_save_area.fp[5] = xmm5; \
|
||||||
|
(ctx).reg_save_area.fp[6] = xmm6; \
|
||||||
|
(ctx).reg_save_area.fp[7] = xmm7; \
|
||||||
|
(ctx).va_list.reg_save_area = &(ctx).reg_save_area; \
|
||||||
|
(ctx).va_list.gp_offset = offsetof(::Common::VaRegSave, gp); \
|
||||||
|
(ctx).va_list.fp_offset = offsetof(::Common::VaRegSave, fp); \
|
||||||
|
(ctx).va_list.overflow_arg_area = &overflow_arg_area;
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
|
||||||
|
// https://stackoverflow.com/questions/4958384/what-is-the-format-of-the-x86-64-va-list-structure
|
||||||
|
|
||||||
|
struct VaList {
|
||||||
|
u32 gp_offset;
|
||||||
|
u32 fp_offset;
|
||||||
|
void* overflow_arg_area;
|
||||||
|
void* reg_save_area;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VaRegSave {
|
||||||
|
u64 gp[6];
|
||||||
|
__m128 fp[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VaCtx {
|
||||||
|
VaRegSave reg_save_area;
|
||||||
|
VaList va_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, uint32_t Size>
|
||||||
|
T vaArgRegSaveAreaGp(VaList* l) {
|
||||||
|
auto* addr = reinterpret_cast<T*>(static_cast<u8*>(l->reg_save_area) + l->gp_offset);
|
||||||
|
l->gp_offset += Size;
|
||||||
|
return *addr;
|
||||||
|
}
|
||||||
|
template <class T, u64 Align, u64 Size>
|
||||||
|
T vaArgOverflowArgArea(VaList* l) {
|
||||||
|
auto ptr = ((reinterpret_cast<u64>(l->overflow_arg_area) + (Align - 1)) & ~(Align - 1));
|
||||||
|
auto* addr = reinterpret_cast<T*>(ptr);
|
||||||
|
l->overflow_arg_area = reinterpret_cast<void*>(ptr + Size);
|
||||||
|
return *addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, uint32_t Size>
|
||||||
|
T vaArgRegSaveAreaFp(VaList* l) {
|
||||||
|
auto* addr = reinterpret_cast<T*>(static_cast<u8*>(l->reg_save_area) + l->fp_offset);
|
||||||
|
l->fp_offset += Size;
|
||||||
|
return *addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int vaArgInteger(VaList* l) {
|
||||||
|
if (l->gp_offset <= 40) {
|
||||||
|
return vaArgRegSaveAreaGp<int, 8>(l);
|
||||||
|
}
|
||||||
|
return vaArgOverflowArgArea<int, 1, 8>(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline long long vaArgLongLong(VaList* l) {
|
||||||
|
if (l->gp_offset <= 40) {
|
||||||
|
return vaArgRegSaveAreaGp<long long, 8>(l);
|
||||||
|
}
|
||||||
|
return vaArgOverflowArgArea<long long, 1, 8>(l);
|
||||||
|
}
|
||||||
|
inline long vaArgLong(VaList* l) {
|
||||||
|
if (l->gp_offset <= 40) {
|
||||||
|
return vaArgRegSaveAreaGp<long, 8>(l);
|
||||||
|
}
|
||||||
|
return vaArgOverflowArgArea<long, 1, 8>(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double vaArgDouble(VaList* l) {
|
||||||
|
if (l->fp_offset <= 160) {
|
||||||
|
return vaArgRegSaveAreaFp<double, 16>(l);
|
||||||
|
}
|
||||||
|
return vaArgOverflowArgArea<double, 1, 8>(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
T* vaArgPtr(VaList* l) {
|
||||||
|
if (l->gp_offset <= 40) {
|
||||||
|
return vaArgRegSaveAreaGp<T*, 8>(l);
|
||||||
|
}
|
||||||
|
return vaArgOverflowArgArea<T*, 1, 8>(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Common
|
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 "common/types.h"
|
||||||
|
#include "common/va_ctx.h"
|
||||||
|
#include "core/libraries/error_codes.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))
|
||||||
|
*/
|
@ -135,7 +135,6 @@ int HandleTable::CreateHandle() {
|
|||||||
std::scoped_lock lock{m_mutex};
|
std::scoped_lock lock{m_mutex};
|
||||||
|
|
||||||
auto* file = new File{};
|
auto* file = new File{};
|
||||||
file->is_directory = false;
|
|
||||||
file->is_opened = false;
|
file->is_opened = false;
|
||||||
|
|
||||||
int existingFilesNum = m_files.size();
|
int existingFilesNum = m_files.size();
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <tsl/robin_map.h>
|
#include <tsl/robin_map.h>
|
||||||
#include "common/io_file.h"
|
#include "common/io_file.h"
|
||||||
|
#include "core/devices/base_device.h"
|
||||||
|
|
||||||
namespace Core::FileSys {
|
namespace Core::FileSys {
|
||||||
|
|
||||||
@ -55,15 +56,22 @@ struct DirEntry {
|
|||||||
bool isFile;
|
bool isFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class FileType {
|
||||||
|
Regular, // standard file
|
||||||
|
Directory,
|
||||||
|
Device,
|
||||||
|
};
|
||||||
|
|
||||||
struct File {
|
struct File {
|
||||||
std::atomic_bool is_opened{};
|
std::atomic_bool is_opened{};
|
||||||
std::atomic_bool is_directory{};
|
std::atomic<FileType> type{FileType::Regular};
|
||||||
std::filesystem::path m_host_name;
|
std::filesystem::path m_host_name;
|
||||||
std::string m_guest_name;
|
std::string m_guest_name;
|
||||||
Common::FS::IOFile f;
|
Common::FS::IOFile f;
|
||||||
std::vector<DirEntry> dirents;
|
std::vector<DirEntry> dirents;
|
||||||
u32 dirents_index;
|
u32 dirents_index;
|
||||||
std::mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
|
std::unique_ptr<Devices::BaseDevice> device; // only valid for type == Device
|
||||||
};
|
};
|
||||||
|
|
||||||
class HandleTable {
|
class HandleTable {
|
||||||
|
@ -11,6 +11,14 @@
|
|||||||
#include "core/libraries/libs.h"
|
#include "core/libraries/libs.h"
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <ranges>
|
||||||
|
|
||||||
|
using FactoryDevice = std::function<Core::Devices::BaseDevice*(u32, const char*, int, u16)>;
|
||||||
|
|
||||||
|
// prefix path
|
||||||
|
static std::map<std::string, FactoryDevice> available_device = {};
|
||||||
|
|
||||||
namespace Libraries::Kernel {
|
namespace Libraries::Kernel {
|
||||||
|
|
||||||
auto GetDirectoryEntries(const std::filesystem::path& path) {
|
auto GetDirectoryEntries(const std::filesystem::path& path) {
|
||||||
@ -24,8 +32,8 @@ auto GetDirectoryEntries(const std::filesystem::path& path) {
|
|||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) {
|
int PS4_SYSV_ABI sceKernelOpen(const char* raw_path, int flags, u16 mode) {
|
||||||
LOG_INFO(Kernel_Fs, "path = {} flags = {:#x} mode = {}", path, flags, mode);
|
LOG_INFO(Kernel_Fs, "path = {} flags = {:#x} mode = {}", raw_path, flags, mode);
|
||||||
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
||||||
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
|
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
|
||||||
|
|
||||||
@ -44,22 +52,37 @@ int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) {
|
|||||||
bool direct = (flags & ORBIS_KERNEL_O_DIRECT) != 0;
|
bool direct = (flags & ORBIS_KERNEL_O_DIRECT) != 0;
|
||||||
bool directory = (flags & ORBIS_KERNEL_O_DIRECTORY) != 0;
|
bool directory = (flags & ORBIS_KERNEL_O_DIRECTORY) != 0;
|
||||||
|
|
||||||
if (std::string_view{path} == "/dev/console") {
|
std::string_view path{raw_path};
|
||||||
|
|
||||||
|
if (path == "/dev/console") {
|
||||||
return 2000;
|
return 2000;
|
||||||
}
|
}
|
||||||
if (std::string_view{path} == "/dev/deci_tty6") {
|
if (path == "/dev/deci_tty6") {
|
||||||
return 2001;
|
return 2001;
|
||||||
}
|
}
|
||||||
if (std::string_view{path} == "/dev/stdout") {
|
if (path == "/dev/stdout") {
|
||||||
return 2002;
|
return 2002;
|
||||||
}
|
}
|
||||||
if (std::string_view{path} == "/dev/urandom") {
|
if (path == "/dev/urandom") {
|
||||||
return 2003;
|
return 2003;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 handle = h->CreateHandle();
|
u32 handle = h->CreateHandle();
|
||||||
auto* file = h->GetFile(handle);
|
auto* file = h->GetFile(handle);
|
||||||
|
|
||||||
|
for (const auto& [prefix, factory] : available_device) {
|
||||||
|
if (path.starts_with(prefix)) {
|
||||||
|
file->is_opened = true;
|
||||||
|
file->type = Core::FileSys::FileType::Device;
|
||||||
|
file->m_guest_name = path;
|
||||||
|
file->device = std::unique_ptr<Core::Devices::BaseDevice>{
|
||||||
|
factory(handle, path.data(), flags, mode)};
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (directory) {
|
if (directory) {
|
||||||
file->is_directory = true;
|
file->type = Core::FileSys::FileType::Directory;
|
||||||
file->m_guest_name = path;
|
file->m_guest_name = path;
|
||||||
file->m_host_name = mnt->GetHostPath(file->m_guest_name);
|
file->m_host_name = mnt->GetHostPath(file->m_guest_name);
|
||||||
if (!std::filesystem::is_directory(file->m_host_name)) { // directory doesn't exist
|
if (!std::filesystem::is_directory(file->m_host_name)) { // directory doesn't exist
|
||||||
@ -135,11 +158,12 @@ int PS4_SYSV_ABI sceKernelClose(int d) {
|
|||||||
if (file == nullptr) {
|
if (file == nullptr) {
|
||||||
return SCE_KERNEL_ERROR_EBADF;
|
return SCE_KERNEL_ERROR_EBADF;
|
||||||
}
|
}
|
||||||
if (!file->is_directory) {
|
if (file->type == Core::FileSys::FileType::Regular) {
|
||||||
file->f.Close();
|
file->f.Close();
|
||||||
}
|
}
|
||||||
file->is_opened = false;
|
file->is_opened = false;
|
||||||
LOG_INFO(Kernel_Fs, "Closing {}", file->m_guest_name);
|
LOG_INFO(Kernel_Fs, "Closing {}", file->m_guest_name);
|
||||||
|
// FIXME: Lock file mutex before deleting it?
|
||||||
h->DeleteHandle(d);
|
h->DeleteHandle(d);
|
||||||
return SCE_OK;
|
return SCE_OK;
|
||||||
}
|
}
|
||||||
@ -170,6 +194,9 @@ size_t PS4_SYSV_ABI sceKernelWrite(int d, const void* buf, size_t nbytes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::scoped_lock lk{file->m_mutex};
|
std::scoped_lock lk{file->m_mutex};
|
||||||
|
if (file->type == Core::FileSys::FileType::Device) {
|
||||||
|
return file->device->write(buf, nbytes);
|
||||||
|
}
|
||||||
return file->f.WriteRaw<u8>(buf, nbytes);
|
return file->f.WriteRaw<u8>(buf, nbytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,17 +234,63 @@ int PS4_SYSV_ABI sceKernelUnlink(const char* path) {
|
|||||||
size_t PS4_SYSV_ABI _readv(int d, const SceKernelIovec* iov, int iovcnt) {
|
size_t PS4_SYSV_ABI _readv(int d, const SceKernelIovec* iov, int iovcnt) {
|
||||||
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
||||||
auto* file = h->GetFile(d);
|
auto* file = h->GetFile(d);
|
||||||
size_t total_read = 0;
|
if (file == nullptr) {
|
||||||
|
return SCE_KERNEL_ERROR_EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
std::scoped_lock lk{file->m_mutex};
|
std::scoped_lock lk{file->m_mutex};
|
||||||
|
if (file->type == Core::FileSys::FileType::Device) {
|
||||||
|
int r = file->device->readv(iov, iovcnt);
|
||||||
|
if (r < 0) {
|
||||||
|
ErrSceToPosix(r);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
size_t total_read = 0;
|
||||||
for (int i = 0; i < iovcnt; i++) {
|
for (int i = 0; i < iovcnt; i++) {
|
||||||
total_read += file->f.ReadRaw<u8>(iov[i].iov_base, iov[i].iov_len);
|
total_read += file->f.ReadRaw<u8>(iov[i].iov_base, iov[i].iov_len);
|
||||||
}
|
}
|
||||||
return total_read;
|
return total_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t PS4_SYSV_ABI _writev(int fd, const SceKernelIovec* iov, int iovcn) {
|
||||||
|
if (fd == 1) {
|
||||||
|
size_t total_written = 0;
|
||||||
|
for (int i = 0; i < iovcn; i++) {
|
||||||
|
total_written += ::fwrite(iov[i].iov_base, 1, iov[i].iov_len, stdout);
|
||||||
|
}
|
||||||
|
return total_written;
|
||||||
|
}
|
||||||
|
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
||||||
|
auto* file = h->GetFile(fd);
|
||||||
|
if (file == nullptr) {
|
||||||
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::scoped_lock lk{file->m_mutex};
|
||||||
|
|
||||||
|
if (file->type == Core::FileSys::FileType::Device) {
|
||||||
|
return file->device->writev(iov, iovcn);
|
||||||
|
}
|
||||||
|
size_t total_written = 0;
|
||||||
|
for (int i = 0; i < iovcn; i++) {
|
||||||
|
total_written += file->f.WriteRaw<u8>(iov[i].iov_base, iov[i].iov_len);
|
||||||
|
}
|
||||||
|
return total_written;
|
||||||
|
}
|
||||||
|
|
||||||
s64 PS4_SYSV_ABI sceKernelLseek(int d, s64 offset, int whence) {
|
s64 PS4_SYSV_ABI sceKernelLseek(int d, s64 offset, int whence) {
|
||||||
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
||||||
auto* file = h->GetFile(d);
|
auto* file = h->GetFile(d);
|
||||||
|
if (file == nullptr) {
|
||||||
|
return SCE_KERNEL_ERROR_EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::scoped_lock lk{file->m_mutex};
|
||||||
|
if (file->type == Core::FileSys::FileType::Device) {
|
||||||
|
return file->device->lseek(offset, whence);
|
||||||
|
}
|
||||||
|
|
||||||
Common::FS::SeekOrigin origin{};
|
Common::FS::SeekOrigin origin{};
|
||||||
if (whence == 0) {
|
if (whence == 0) {
|
||||||
@ -228,7 +301,6 @@ s64 PS4_SYSV_ABI sceKernelLseek(int d, s64 offset, int whence) {
|
|||||||
origin = Common::FS::SeekOrigin::End;
|
origin = Common::FS::SeekOrigin::End;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::scoped_lock lk{file->m_mutex};
|
|
||||||
if (!file->f.Seek(offset, origin)) {
|
if (!file->f.Seek(offset, origin)) {
|
||||||
LOG_CRITICAL(Kernel_Fs, "sceKernelLseek: failed to seek");
|
LOG_CRITICAL(Kernel_Fs, "sceKernelLseek: failed to seek");
|
||||||
return SCE_KERNEL_ERROR_EINVAL;
|
return SCE_KERNEL_ERROR_EINVAL;
|
||||||
@ -261,6 +333,9 @@ s64 PS4_SYSV_ABI sceKernelRead(int d, void* buf, size_t nbytes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::scoped_lock lk{file->m_mutex};
|
std::scoped_lock lk{file->m_mutex};
|
||||||
|
if (file->type == Core::FileSys::FileType::Device) {
|
||||||
|
return file->device->read(buf, nbytes);
|
||||||
|
}
|
||||||
return file->f.ReadRaw<u8>(buf, nbytes);
|
return file->f.ReadRaw<u8>(buf, nbytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -409,7 +484,13 @@ int PS4_SYSV_ABI posix_stat(const char* path, OrbisKernelStat* sb) {
|
|||||||
|
|
||||||
int PS4_SYSV_ABI sceKernelCheckReachability(const char* path) {
|
int PS4_SYSV_ABI sceKernelCheckReachability(const char* path) {
|
||||||
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
|
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
|
||||||
const auto path_name = mnt->GetHostPath(path);
|
std::string_view guest_path{path};
|
||||||
|
for (const auto& prefix : available_device | std::views::keys) {
|
||||||
|
if (guest_path.starts_with(prefix)) {
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const auto path_name = mnt->GetHostPath(guest_path);
|
||||||
if (!std::filesystem::exists(path_name)) {
|
if (!std::filesystem::exists(path_name)) {
|
||||||
return SCE_KERNEL_ERROR_ENOENT;
|
return SCE_KERNEL_ERROR_ENOENT;
|
||||||
}
|
}
|
||||||
@ -431,6 +512,10 @@ s64 PS4_SYSV_ABI sceKernelPreadv(int d, SceKernelIovec* iov, int iovcnt, s64 off
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::scoped_lock lk{file->m_mutex};
|
std::scoped_lock lk{file->m_mutex};
|
||||||
|
if (file->type == Core::FileSys::FileType::Device) {
|
||||||
|
return file->device->preadv(iov, iovcnt, offset);
|
||||||
|
}
|
||||||
|
|
||||||
const s64 pos = file->f.Tell();
|
const s64 pos = file->f.Tell();
|
||||||
SCOPE_EXIT {
|
SCOPE_EXIT {
|
||||||
file->f.Seek(pos);
|
file->f.Seek(pos);
|
||||||
@ -466,18 +551,25 @@ int PS4_SYSV_ABI sceKernelFStat(int fd, OrbisKernelStat* sb) {
|
|||||||
}
|
}
|
||||||
std::memset(sb, 0, sizeof(OrbisKernelStat));
|
std::memset(sb, 0, sizeof(OrbisKernelStat));
|
||||||
|
|
||||||
if (file->is_directory) {
|
switch (file->type) {
|
||||||
sb->st_mode = 0000777u | 0040000u;
|
case Core::FileSys::FileType::Device:
|
||||||
sb->st_size = 0;
|
return file->device->fstat(sb);
|
||||||
sb->st_blksize = 512;
|
case Core::FileSys::FileType::Regular:
|
||||||
sb->st_blocks = 0;
|
|
||||||
// TODO incomplete
|
|
||||||
} else {
|
|
||||||
sb->st_mode = 0000777u | 0100000u;
|
sb->st_mode = 0000777u | 0100000u;
|
||||||
sb->st_size = file->f.GetSize();
|
sb->st_size = file->f.GetSize();
|
||||||
sb->st_blksize = 512;
|
sb->st_blksize = 512;
|
||||||
sb->st_blocks = (sb->st_size + 511) / 512;
|
sb->st_blocks = (sb->st_size + 511) / 512;
|
||||||
// TODO incomplete
|
// TODO incomplete
|
||||||
|
break;
|
||||||
|
case Core::FileSys::FileType::Directory:
|
||||||
|
sb->st_mode = 0000777u | 0040000u;
|
||||||
|
sb->st_size = 0;
|
||||||
|
sb->st_blksize = 512;
|
||||||
|
sb->st_blocks = 0;
|
||||||
|
// TODO incomplete
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
@ -495,6 +587,13 @@ int PS4_SYSV_ABI posix_fstat(int fd, OrbisKernelStat* sb) {
|
|||||||
s32 PS4_SYSV_ABI sceKernelFsync(int fd) {
|
s32 PS4_SYSV_ABI sceKernelFsync(int fd) {
|
||||||
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
||||||
auto* file = h->GetFile(fd);
|
auto* file = h->GetFile(fd);
|
||||||
|
if (file == nullptr) {
|
||||||
|
return SCE_KERNEL_ERROR_EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file->type == Core::FileSys::FileType::Device) {
|
||||||
|
return file->device->fsync();
|
||||||
|
}
|
||||||
file->f.Flush();
|
file->f.Flush();
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
@ -517,6 +616,10 @@ int PS4_SYSV_ABI sceKernelFtruncate(int fd, s64 length) {
|
|||||||
return SCE_KERNEL_ERROR_EBADF;
|
return SCE_KERNEL_ERROR_EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (file->type == Core::FileSys::FileType::Device) {
|
||||||
|
return file->device->ftruncate(length);
|
||||||
|
}
|
||||||
|
|
||||||
if (file->m_host_name.empty()) {
|
if (file->m_host_name.empty()) {
|
||||||
return SCE_KERNEL_ERROR_EACCES;
|
return SCE_KERNEL_ERROR_EACCES;
|
||||||
}
|
}
|
||||||
@ -538,10 +641,15 @@ static int GetDents(int fd, char* buf, int nbytes, s64* basep) {
|
|||||||
if (file == nullptr) {
|
if (file == nullptr) {
|
||||||
return ORBIS_KERNEL_ERROR_EBADF;
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
}
|
}
|
||||||
|
if (file->type != Core::FileSys::FileType::Device) {
|
||||||
|
return file->device->getdents(buf, nbytes, basep);
|
||||||
|
}
|
||||||
|
|
||||||
if (file->dirents_index == file->dirents.size()) {
|
if (file->dirents_index == file->dirents.size()) {
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
if (!file->is_directory || nbytes < 512 || file->dirents_index > file->dirents.size()) {
|
if (file->type != Core::FileSys::FileType::Directory || nbytes < 512 ||
|
||||||
|
file->dirents_index > file->dirents.size()) {
|
||||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
}
|
}
|
||||||
const auto& entry = file->dirents.at(file->dirents_index++);
|
const auto& entry = file->dirents.at(file->dirents_index++);
|
||||||
@ -586,6 +694,10 @@ s64 PS4_SYSV_ABI sceKernelPwrite(int d, void* buf, size_t nbytes, s64 offset) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::scoped_lock lk{file->m_mutex};
|
std::scoped_lock lk{file->m_mutex};
|
||||||
|
|
||||||
|
if (file->type == Core::FileSys::FileType::Device) {
|
||||||
|
return file->device->pwrite(buf, nbytes, offset);
|
||||||
|
}
|
||||||
const s64 pos = file->f.Tell();
|
const s64 pos = file->f.Tell();
|
||||||
SCOPE_EXIT {
|
SCOPE_EXIT {
|
||||||
file->f.Seek(pos);
|
file->f.Seek(pos);
|
||||||
@ -637,6 +749,7 @@ void RegisterFileSystem(Core::Loader::SymbolsResolver* sym) {
|
|||||||
LIB_FUNCTION("4wSze92BhLI", "libkernel", 1, "libkernel", 1, 1, sceKernelWrite);
|
LIB_FUNCTION("4wSze92BhLI", "libkernel", 1, "libkernel", 1, 1, sceKernelWrite);
|
||||||
|
|
||||||
LIB_FUNCTION("+WRlkKjZvag", "libkernel", 1, "libkernel", 1, 1, _readv);
|
LIB_FUNCTION("+WRlkKjZvag", "libkernel", 1, "libkernel", 1, 1, _readv);
|
||||||
|
LIB_FUNCTION("YSHRBRLn2pI", "libkernel", 1, "libkernel", 1, 1, _writev);
|
||||||
LIB_FUNCTION("Oy6IpwgtYOk", "libkernel", 1, "libkernel", 1, 1, posix_lseek);
|
LIB_FUNCTION("Oy6IpwgtYOk", "libkernel", 1, "libkernel", 1, 1, posix_lseek);
|
||||||
LIB_FUNCTION("Oy6IpwgtYOk", "libScePosix", 1, "libkernel", 1, 1, posix_lseek);
|
LIB_FUNCTION("Oy6IpwgtYOk", "libScePosix", 1, "libkernel", 1, 1, posix_lseek);
|
||||||
LIB_FUNCTION("oib76F-12fk", "libkernel", 1, "libkernel", 1, 1, sceKernelLseek);
|
LIB_FUNCTION("oib76F-12fk", "libkernel", 1, "libkernel", 1, 1, sceKernelLseek);
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "common/polyfill_thread.h"
|
#include "common/polyfill_thread.h"
|
||||||
#include "common/singleton.h"
|
#include "common/singleton.h"
|
||||||
#include "common/thread.h"
|
#include "common/thread.h"
|
||||||
|
#include "common/va_ctx.h"
|
||||||
#include "core/file_sys/fs.h"
|
#include "core/file_sys/fs.h"
|
||||||
#include "core/libraries/error_codes.h"
|
#include "core/libraries/error_codes.h"
|
||||||
#include "core/libraries/kernel/equeue.h"
|
#include "core/libraries/kernel/equeue.h"
|
||||||
@ -74,19 +75,6 @@ static PS4_SYSV_ABI void stack_chk_fail() {
|
|||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct iovec {
|
|
||||||
void* iov_base; /* Base address. */
|
|
||||||
size_t iov_len; /* Length. */
|
|
||||||
};
|
|
||||||
|
|
||||||
size_t PS4_SYSV_ABI _writev(int fd, const struct iovec* iov, int iovcn) {
|
|
||||||
size_t total_written = 0;
|
|
||||||
for (int i = 0; i < iovcn; i++) {
|
|
||||||
total_written += ::fwrite(iov[i].iov_base, 1, iov[i].iov_len, stdout);
|
|
||||||
}
|
|
||||||
return total_written;
|
|
||||||
}
|
|
||||||
|
|
||||||
static thread_local int g_posix_errno = 0;
|
static thread_local int g_posix_errno = 0;
|
||||||
|
|
||||||
int* PS4_SYSV_ABI __Error() {
|
int* PS4_SYSV_ABI __Error() {
|
||||||
@ -163,16 +151,33 @@ s64 PS4_SYSV_ABI ps4__write(int d, const char* buf, std::size_t nbytes) {
|
|||||||
LOG_INFO(Tty, "{}", str);
|
LOG_INFO(Tty, "{}", str);
|
||||||
return nbytes;
|
return nbytes;
|
||||||
}
|
}
|
||||||
LOG_ERROR(Kernel, "(STUBBED) called d = {} nbytes = {} ", d, nbytes);
|
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
||||||
UNREACHABLE();
|
auto* file = h->GetFile(d);
|
||||||
return ORBIS_OK;
|
if (file == nullptr) {
|
||||||
|
return SCE_KERNEL_ERROR_EBADF;
|
||||||
|
}
|
||||||
|
std::scoped_lock lk{file->m_mutex};
|
||||||
|
if (file->type == Core::FileSys::FileType::Device) {
|
||||||
|
return file->device->write(buf, nbytes);
|
||||||
|
}
|
||||||
|
return file->f.WriteRaw<u8>(buf, nbytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 PS4_SYSV_ABI ps4__read(int d, void* buf, u64 nbytes) {
|
s64 PS4_SYSV_ABI ps4__read(int d, void* buf, u64 nbytes) {
|
||||||
ASSERT_MSG(d == 0, "d is not 0!");
|
if (d == 0) {
|
||||||
|
return static_cast<s64>(
|
||||||
return static_cast<s64>(
|
strlen(std::fgets(static_cast<char*>(buf), static_cast<int>(nbytes), stdin)));
|
||||||
strlen(std::fgets(static_cast<char*>(buf), static_cast<int>(nbytes), stdin)));
|
}
|
||||||
|
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
||||||
|
auto* file = h->GetFile(d);
|
||||||
|
if (file == nullptr) {
|
||||||
|
return SCE_KERNEL_ERROR_EBADF;
|
||||||
|
}
|
||||||
|
std::scoped_lock lk{file->m_mutex};
|
||||||
|
if (file->type == Core::FileSys::FileType::Device) {
|
||||||
|
return file->device->read(buf, nbytes);
|
||||||
|
}
|
||||||
|
return file->f.ReadRaw<u8>(buf, nbytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct OrbisKernelUuid {
|
struct OrbisKernelUuid {
|
||||||
@ -202,6 +207,29 @@ int PS4_SYSV_ABI sceKernelUuidCreate(OrbisKernelUuid* orbisUuid) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI kernel_ioctl(int fd, u64 cmd, VA_ARGS) {
|
||||||
|
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
||||||
|
auto* file = h->GetFile(fd);
|
||||||
|
if (file == nullptr) {
|
||||||
|
LOG_INFO(Lib_Kernel, "ioctl: fd = {:X} cmd = {:X} file == nullptr", fd, cmd);
|
||||||
|
g_posix_errno = POSIX_EBADF;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (file->type != Core::FileSys::FileType::Device) {
|
||||||
|
LOG_WARNING(Lib_Kernel, "ioctl: fd = {:X} cmd = {:X} file->type != Device", fd, cmd);
|
||||||
|
g_posix_errno = ENOTTY;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
VA_CTX(ctx);
|
||||||
|
int result = file->device->ioctl(cmd, &ctx);
|
||||||
|
LOG_TRACE(Lib_Kernel, "ioctl: fd = {:X} cmd = {:X} result = {}", fd, cmd, result);
|
||||||
|
if (result < 0) {
|
||||||
|
ErrSceToPosix(result);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
const char* PS4_SYSV_ABI sceKernelGetFsSandboxRandomWord() {
|
const char* PS4_SYSV_ABI sceKernelGetFsSandboxRandomWord() {
|
||||||
const char* path = "sys";
|
const char* path = "sys";
|
||||||
return path;
|
return path;
|
||||||
@ -232,13 +260,13 @@ void RegisterKernel(Core::Loader::SymbolsResolver* sym) {
|
|||||||
Libraries::Kernel::RegisterException(sym);
|
Libraries::Kernel::RegisterException(sym);
|
||||||
|
|
||||||
LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard);
|
LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard);
|
||||||
|
LIB_FUNCTION("PfccT7qURYE", "libkernel", 1, "libkernel", 1, 1, kernel_ioctl);
|
||||||
LIB_FUNCTION("JGfTMBOdUJo", "libkernel", 1, "libkernel", 1, 1, sceKernelGetFsSandboxRandomWord);
|
LIB_FUNCTION("JGfTMBOdUJo", "libkernel", 1, "libkernel", 1, 1, sceKernelGetFsSandboxRandomWord);
|
||||||
LIB_FUNCTION("XVL8So3QJUk", "libkernel", 1, "libkernel", 1, 1, posix_connect);
|
LIB_FUNCTION("XVL8So3QJUk", "libkernel", 1, "libkernel", 1, 1, posix_connect);
|
||||||
LIB_FUNCTION("6xVpy0Fdq+I", "libkernel", 1, "libkernel", 1, 1, _sigprocmask);
|
LIB_FUNCTION("6xVpy0Fdq+I", "libkernel", 1, "libkernel", 1, 1, _sigprocmask);
|
||||||
LIB_FUNCTION("Xjoosiw+XPI", "libkernel", 1, "libkernel", 1, 1, sceKernelUuidCreate);
|
LIB_FUNCTION("Xjoosiw+XPI", "libkernel", 1, "libkernel", 1, 1, sceKernelUuidCreate);
|
||||||
LIB_FUNCTION("Ou3iL1abvng", "libkernel", 1, "libkernel", 1, 1, stack_chk_fail);
|
LIB_FUNCTION("Ou3iL1abvng", "libkernel", 1, "libkernel", 1, 1, stack_chk_fail);
|
||||||
LIB_FUNCTION("9BcDykPmo1I", "libkernel", 1, "libkernel", 1, 1, __Error);
|
LIB_FUNCTION("9BcDykPmo1I", "libkernel", 1, "libkernel", 1, 1, __Error);
|
||||||
LIB_FUNCTION("YSHRBRLn2pI", "libkernel", 1, "libkernel", 1, 1, _writev);
|
|
||||||
LIB_FUNCTION("DRuBt2pvICk", "libkernel", 1, "libkernel", 1, 1, ps4__read);
|
LIB_FUNCTION("DRuBt2pvICk", "libkernel", 1, "libkernel", 1, 1, ps4__read);
|
||||||
LIB_FUNCTION("k+AXqu2-eBc", "libkernel", 1, "libkernel", 1, 1, posix_getpagesize);
|
LIB_FUNCTION("k+AXqu2-eBc", "libkernel", 1, "libkernel", 1, 1, posix_getpagesize);
|
||||||
LIB_FUNCTION("k+AXqu2-eBc", "libScePosix", 1, "libkernel", 1, 1, posix_getpagesize);
|
LIB_FUNCTION("k+AXqu2-eBc", "libScePosix", 1, "libkernel", 1, 1, posix_getpagesize);
|
||||||
|
@ -20,7 +20,7 @@ int PS4_SYSV_ABI sceKernelIsNeoMode() {
|
|||||||
int PS4_SYSV_ABI sceKernelGetCompiledSdkVersion(int* ver) {
|
int PS4_SYSV_ABI sceKernelGetCompiledSdkVersion(int* ver) {
|
||||||
int version = Common::ElfInfo::Instance().RawFirmwareVer();
|
int version = Common::ElfInfo::Instance().RawFirmwareVer();
|
||||||
*ver = version;
|
*ver = version;
|
||||||
return (version > 0) ? ORBIS_OK : ORBIS_KERNEL_ERROR_EINVAL;
|
return (version >= 0) ? ORBIS_OK : ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceKernelGetCpumode() {
|
int PS4_SYSV_ABI sceKernelGetCpumode() {
|
||||||
|
Loading…
Reference in New Issue
Block a user