From 27b7c1dc14a993765644a7ca1b0f07bfa4eec219 Mon Sep 17 00:00:00 2001 From: Stephen Miller Date: Mon, 21 Apr 2025 15:30:25 -0500 Subject: [PATCH] Implement sceKernelMapNamedSystemFlexibleMemory Needed for libSceGnmDriver init --- src/core/libraries/kernel/memory.cpp | 32 ++++++++++++++++++++++++++++ src/core/memory.cpp | 11 ++++++++++ src/core/memory.h | 3 +++ 3 files changed, 46 insertions(+) diff --git a/src/core/libraries/kernel/memory.cpp b/src/core/libraries/kernel/memory.cpp index 8a0c91479..3a5a9a703 100644 --- a/src/core/libraries/kernel/memory.cpp +++ b/src/core/libraries/kernel/memory.cpp @@ -234,6 +234,37 @@ s32 PS4_SYSV_ABI sceKernelMapNamedFlexibleMemory(void** addr_in_out, std::size_t Core::VMAType::Flexible, name); } +s32 PS4_SYSV_ABI sceKernelMapNamedSystemFlexibleMemory(void** addr_in_out, std::size_t len, int prot, + int flags, const char* name) { + if (len == 0 || !Common::Is16KBAligned(len)) { + LOG_ERROR(Kernel_Vmm, "len is 0 or not 16kb multiple"); + return ORBIS_KERNEL_ERROR_EINVAL; + } + + static constexpr size_t MaxNameSize = 32; + if (std::strlen(name) > MaxNameSize) { + LOG_ERROR(Kernel_Vmm, "name exceeds 32 bytes!"); + return ORBIS_KERNEL_ERROR_ENAMETOOLONG; + } + + if (name == nullptr) { + LOG_ERROR(Kernel_Vmm, "name is invalid!"); + return ORBIS_KERNEL_ERROR_EFAULT; + } + + const VAddr in_addr = reinterpret_cast(*addr_in_out); + const auto mem_prot = static_cast(prot); + const auto map_flags = static_cast(flags); + SCOPE_EXIT { + LOG_INFO(Kernel_Vmm, + "in_addr = {:#x}, out_addr = {}, len = {:#x}, prot = {:#x}, flags = {:#x}", + in_addr, fmt::ptr(*addr_in_out), len, prot, flags); + }; + auto* memory = Core::Memory::Instance(); + return memory->MapSystemMemory(addr_in_out, in_addr, len, mem_prot, map_flags, + Core::VMAType::Flexible, name); +} + s32 PS4_SYSV_ABI sceKernelMapFlexibleMemory(void** addr_in_out, std::size_t len, int prot, int flags) { return sceKernelMapNamedFlexibleMemory(addr_in_out, len, prot, flags, ""); @@ -578,6 +609,7 @@ void RegisterMemory(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("PGhQHd-dzv8", "libkernel", 1, "libkernel", 1, 1, sceKernelMmap); LIB_FUNCTION("cQke9UuBQOk", "libkernel", 1, "libkernel", 1, 1, sceKernelMunmap); LIB_FUNCTION("mL8NDH86iQI", "libkernel", 1, "libkernel", 1, 1, sceKernelMapNamedFlexibleMemory); + LIB_FUNCTION("kc+LEEIYakc", "libkernel", 1, "libkernel", 1, 1, sceKernelMapNamedSystemFlexibleMemory); LIB_FUNCTION("aNz11fnnzi4", "libkernel", 1, "libkernel", 1, 1, sceKernelAvailableFlexibleMemorySize); LIB_FUNCTION("aNz11fnnzi4", "libkernel_avlfmem", 1, "libkernel", 1, 1, diff --git a/src/core/memory.cpp b/src/core/memory.cpp index cb80d6be4..fe52abff7 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -360,6 +360,17 @@ int MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, size_t size, M return ORBIS_OK; } +int MemoryManager::MapSystemMemory(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot, + MemoryMapFlags flags, VMAType type, std::string_view name) { + // If address is 0, this maps to System Reserved memory instead, which starts at address 0x880000000 + VAddr in_addr = virtual_addr; + if (in_addr == 0) { + static constexpr VAddr KernelAllocBase = 0x880000000ULL; + in_addr = SearchFree(KernelAllocBase, size, 1); + } + return MapMemory(out_addr, in_addr, size, prot, flags, type, name); +} + int MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot, MemoryMapFlags flags, uintptr_t fd, size_t offset) { VAddr mapped_addr = (virtual_addr == 0) ? impl.SystemManagedVirtualBase() : virtual_addr; diff --git a/src/core/memory.h b/src/core/memory.h index a6a55e288..f8ab7efd7 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -189,6 +189,9 @@ public: MemoryMapFlags flags, VMAType type, std::string_view name = "", bool is_exec = false, PAddr phys_addr = -1, u64 alignment = 0); + int MapSystemMemory(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot, + MemoryMapFlags flags, VMAType type, std::string_view name = ""); + int MapFile(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot, MemoryMapFlags flags, uintptr_t fd, size_t offset);