From 27b87ebc35b2fca009ff478d6a7c070a0cc61f89 Mon Sep 17 00:00:00 2001 From: "Daniel R." <47796739+polybiusproxy@users.noreply.github.com> Date: Wed, 10 Jul 2024 14:59:43 +0200 Subject: [PATCH] Implement `sceKernelReserveVirtualRange`, misc fixes --- CMakeLists.txt | 1 + src/common/io_file.cpp | 22 ++++ src/common/io_file.h | 2 + src/common/ntapi.h | 120 ++++++++++++++++++ src/core/libraries/kernel/file_system.cpp | 20 +-- src/core/libraries/kernel/libkernel.cpp | 1 + .../libraries/kernel/memory_management.cpp | 27 ++++ src/core/libraries/kernel/memory_management.h | 1 + src/core/libraries/kernel/time_management.cpp | 6 +- src/core/memory.cpp | 1 - 10 files changed, 180 insertions(+), 21 deletions(-) create mode 100644 src/common/ntapi.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 89b1f03ee..ed86ddaa6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -261,6 +261,7 @@ set(COMMON src/common/logging/backend.cpp src/common/types.h src/common/uint128.h src/common/version.h + src/common/ntapi.h ) set(CORE src/core/aerolib/stubs.cpp diff --git a/src/common/io_file.cpp b/src/common/io_file.cpp index 077c8a318..456da4fc9 100644 --- a/src/common/io_file.cpp +++ b/src/common/io_file.cpp @@ -11,6 +11,8 @@ #include "common/path_util.h" #ifdef _WIN32 +#include "common/ntapi.h" + #include #include #include @@ -216,6 +218,26 @@ void IOFile::Close() { #endif } +void IOFile::Unlink() { + if (!IsOpen()) { + return; + } + + // Mark the file for deletion + // TODO: Also remove the file path? +#if _WIN64 + FILE_DISPOSITION_INFORMATION disposition; + IO_STATUS_BLOCK iosb; + + const int fd = fileno(file); + HANDLE hfile = reinterpret_cast(_get_osfhandle(fd)); + + disposition.DeleteFile = TRUE; + NtSetInformationFile(hfile, &iosb, &disposition, sizeof(disposition), + FileDispositionInformation); +#endif +} + uintptr_t IOFile::GetFileMapping() { if (file_mapping) { return file_mapping; diff --git a/src/common/io_file.h b/src/common/io_file.h index c6dd8082b..3b734e628 100644 --- a/src/common/io_file.h +++ b/src/common/io_file.h @@ -107,6 +107,8 @@ public: FileShareFlag flag = FileShareFlag::ShareReadOnly); void Close(); + void Unlink(); + bool Flush() const; bool Commit() const; diff --git a/src/common/ntapi.h b/src/common/ntapi.h new file mode 100644 index 000000000..8ea9fe368 --- /dev/null +++ b/src/common/ntapi.h @@ -0,0 +1,120 @@ +#pragma once + +#ifdef _WIN32 + +#include "common/types.h" + +#include + +typedef enum _FILE_INFORMATION_CLASS { + FileDirectoryInformation = 1, + FileFullDirectoryInformation = 2, + FileBothDirectoryInformation = 3, + FileBasicInformation = 4, + FileStandardInformation = 5, + FileInternalInformation = 6, + FileEaInformation = 7, + FileAccessInformation = 8, + FileNameInformation = 9, + FileRenameInformation = 10, + FileLinkInformation = 11, + FileNamesInformation = 12, + FileDispositionInformation = 13, + FilePositionInformation = 14, + FileFullEaInformation = 15, + FileModeInformation = 16, + FileAlignmentInformation = 17, + FileAllInformation = 18, + FileAllocationInformation = 19, + FileEndOfFileInformation = 20, + FileAlternateNameInformation = 21, + FileStreamInformation = 22, + FilePipeInformation = 23, + FilePipeLocalInformation = 24, + FilePipeRemoteInformation = 25, + FileMailslotQueryInformation = 26, + FileMailslotSetInformation = 27, + FileCompressionInformation = 28, + FileObjectIdInformation = 29, + FileCompletionInformation = 30, + FileMoveClusterInformation = 31, + FileQuotaInformation = 32, + FileReparsePointInformation = 33, + FileNetworkOpenInformation = 34, + FileAttributeTagInformation = 35, + FileTrackingInformation = 36, + FileIdBothDirectoryInformation = 37, + FileIdFullDirectoryInformation = 38, + FileValidDataLengthInformation = 39, + FileShortNameInformation = 40, + FileIoCompletionNotificationInformation = 41, + FileIoStatusBlockRangeInformation = 42, + FileIoPriorityHintInformation = 43, + FileSfioReserveInformation = 44, + FileSfioVolumeInformation = 45, + FileHardLinkInformation = 46, + FileProcessIdsUsingFileInformation = 47, + FileNormalizedNameInformation = 48, + FileNetworkPhysicalNameInformation = 49, + FileIdGlobalTxDirectoryInformation = 50, + FileIsRemoteDeviceInformation = 51, + FileUnusedInformation = 52, + FileNumaNodeInformation = 53, + FileStandardLinkInformation = 54, + FileRemoteProtocolInformation = 55, + FileRenameInformationBypassAccessCheck = 56, + FileLinkInformationBypassAccessCheck = 57, + FileVolumeNameInformation = 58, + FileIdInformation = 59, + FileIdExtdDirectoryInformation = 60, + FileReplaceCompletionInformation = 61, + FileHardLinkFullIdInformation = 62, + FileIdExtdBothDirectoryInformation = 63, + FileDispositionInformationEx = 64, + FileRenameInformationEx = 65, + FileRenameInformationExBypassAccessCheck = 66, + FileDesiredStorageClassInformation = 67, + FileStatInformation = 68, + FileMemoryPartitionInformation = 69, + FileStatLxInformation = 70, + FileCaseSensitiveInformation = 71, + FileLinkInformationEx = 72, + FileLinkInformationExBypassAccessCheck = 73, + FileStorageReserveIdInformation = 74, + FileCaseSensitiveInformationForceAccessCheck = 75, + FileKnownFolderInformation = 76, + FileStatBasicInformation = 77, + FileId64ExtdDirectoryInformation = 78, + FileId64ExtdBothDirectoryInformation = 79, + FileIdAllExtdDirectoryInformation = 80, + FileIdAllExtdBothDirectoryInformation = 81, + FileStreamReservationInformation, + FileMupProviderInfo, + FileMaximumInformation +} FILE_INFORMATION_CLASS, + *PFILE_INFORMATION_CLASS; + +typedef struct _IO_STATUS_BLOCK { + union { + u32 Status; + PVOID Pointer; + }; + ULONG_PTR Information; +} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; + +typedef struct _FILE_DISPOSITION_INFORMATION { + BOOLEAN DeleteFile; +} FILE_DISPOSITION_INFORMATION, *PFILE_DISPOSITION_INFORMATION; + +// http://stackoverflow.com/a/31411628/4725495 +static u32(__stdcall* NtDelayExecution)(BOOL Alertable, PLARGE_INTEGER DelayInterval) = + (u32(__stdcall*)(BOOL, PLARGE_INTEGER))GetProcAddress(GetModuleHandleA("ntdll.dll"), + "NtDelayExecution"); + +static u32(__stdcall* NtSetInformationFile)(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, + PVOID FileInformation, ULONG Length, + FILE_INFORMATION_CLASS FileInformationClass) = + (u32(__stdcall*)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS)) + GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtSetInformationFile"); + +#endif diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index a499f245e..2e4676d3e 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -179,16 +179,11 @@ int PS4_SYSV_ABI sceKernelUnlink(const char* path) { } auto* file = h->getFile(host_path); - if (file == nullptr) { - return SCE_KERNEL_ERROR_EIO; + if (file != nullptr) { + file->f.Unlink(); } - file->f.Close(); - if (!std::filesystem::remove(host_path)) { - return SCE_KERNEL_ERROR_ENOENT; - } - - LOG_INFO(Kernel_Fs, "Deleted {}", path); + LOG_INFO(Kernel_Fs, "Unlinked {}", path); return SCE_OK; } @@ -403,14 +398,7 @@ int PS4_SYSV_ABI sceKernelFtruncate(int fd, s64 length) { return SCE_KERNEL_ERROR_EACCES; } - // CUSA05289 (PSPHD emulator): Tries to resize a temporary file after deleting it - try { - // TODO: Check for sufficient space? - std::filesystem::resize_file(file->m_host_name, length); - } catch (std::filesystem::filesystem_error& e) { - LOG_ERROR(Kernel_Fs, "Error: {}", e.what()); - } - + file->f.SetSize(length); return SCE_OK; } diff --git a/src/core/libraries/kernel/libkernel.cpp b/src/core/libraries/kernel/libkernel.cpp index ce17a3f2d..fc5c7acd0 100644 --- a/src/core/libraries/kernel/libkernel.cpp +++ b/src/core/libraries/kernel/libkernel.cpp @@ -326,6 +326,7 @@ void LibKernel_Register(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("hwVSPCmp5tM", "libkernel", 1, "libkernel", 1, 1, sceKernelCheckedReleaseDirectMemory); LIB_FUNCTION("rVjRvHJ0X6c", "libkernel", 1, "libkernel", 1, 1, sceKernelVirtualQuery); + LIB_FUNCTION("7oxv3PPCumo", "libkernel", 1, "libkernel", 1, 1, sceKernelReserveVirtualRange); LIB_FUNCTION("pO96TwzOm5E", "libkernel", 1, "libkernel", 1, 1, sceKernelGetDirectMemorySize); LIB_FUNCTION("NcaWUxfMNIQ", "libkernel", 1, "libkernel", 1, 1, sceKernelMapNamedDirectMemory); LIB_FUNCTION("L-Q3LEjIbgA", "libkernel", 1, "libkernel", 1, 1, sceKernelMapDirectMemory); diff --git a/src/core/libraries/kernel/memory_management.cpp b/src/core/libraries/kernel/memory_management.cpp index b6e3054cd..61a6ae734 100644 --- a/src/core/libraries/kernel/memory_management.cpp +++ b/src/core/libraries/kernel/memory_management.cpp @@ -87,6 +87,33 @@ s32 PS4_SYSV_ABI sceKernelVirtualQuery(const void* addr, int flags, OrbisVirtual return memory->VirtualQuery(std::bit_cast(addr), flags, info); } +s32 PS4_SYSV_ABI sceKernelReserveVirtualRange(void** addr, u64 len, int flags, u64 alignment) { + LOG_INFO(Kernel_Vmm, "addr = {}, len = {:#x}, flags = {:#x}, alignment = {:#x}", + fmt::ptr(*addr), len, flags, alignment); + + if (addr == nullptr) { + LOG_ERROR(Kernel_Vmm, "Address is invalid!"); + return SCE_KERNEL_ERROR_EINVAL; + } + if (len == 0 || !Common::Is16KBAligned(len)) { + LOG_ERROR(Kernel_Vmm, "Map size is either zero or not 16KB aligned!"); + return SCE_KERNEL_ERROR_EINVAL; + } + if (alignment != 0) { + if ((!std::has_single_bit(alignment) && !Common::Is16KBAligned(alignment))) { + LOG_ERROR(Kernel_Vmm, "Alignment value is invalid!"); + return SCE_KERNEL_ERROR_EINVAL; + } + } + + auto* memory = Core::Memory::Instance(); + const auto map_flags = static_cast(flags); + memory->MapMemory(addr, 0, len, Core::MemoryProt::NoAccess, map_flags, Core::VMAType::Direct, + "", false, -1, alignment); + + return SCE_OK; +} + int PS4_SYSV_ABI sceKernelMapNamedDirectMemory(void** addr, u64 len, int prot, int flags, s64 directMemoryStart, u64 alignment, const char* name) { diff --git a/src/core/libraries/kernel/memory_management.h b/src/core/libraries/kernel/memory_management.h index 6e3a0660b..81f8bd7a8 100644 --- a/src/core/libraries/kernel/memory_management.h +++ b/src/core/libraries/kernel/memory_management.h @@ -70,6 +70,7 @@ s32 PS4_SYSV_ABI sceKernelAvailableDirectMemorySize(u64 searchStart, u64 searchE size_t* sizeOut); s32 PS4_SYSV_ABI sceKernelVirtualQuery(const void* addr, int flags, OrbisVirtualQueryInfo* info, size_t infoSize); +s32 PS4_SYSV_ABI sceKernelReserveVirtualRange(void** addr, u64 len, int flags, u64 alignment); s32 PS4_SYSV_ABI sceKernelMapNamedFlexibleMemory(void** addrInOut, std::size_t len, int prot, int flags, const char* name); s32 PS4_SYSV_ABI sceKernelMapFlexibleMemory(void** addr_in_out, std::size_t len, int prot, diff --git a/src/core/libraries/kernel/time_management.cpp b/src/core/libraries/kernel/time_management.cpp index 8101ab6d1..fbbcfdcfc 100644 --- a/src/core/libraries/kernel/time_management.cpp +++ b/src/core/libraries/kernel/time_management.cpp @@ -12,10 +12,8 @@ #include #include -// http://stackoverflow.com/a/31411628/4725495 -static u32(__stdcall* NtDelayExecution)(BOOL Alertable, PLARGE_INTEGER DelayInterval) = - (u32(__stdcall*)(BOOL, PLARGE_INTEGER))GetProcAddress(GetModuleHandleA("ntdll.dll"), - "NtDelayExecution"); +#include "common/ntapi.h" + #else #include #include diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 5166908a1..7eb9a0fa7 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -146,7 +146,6 @@ int MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, size_t size, M int MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot, MemoryMapFlags flags, uintptr_t fd, size_t offset) { - ASSERT(virtual_addr == 0); virtual_addr = impl.VirtualBase(); const size_t size_aligned = Common::AlignUp(size, 16_KB);