HLE: 6.60 kernel NIDs for module loading, memset and strnlen

The firmware's POPS manager imports these by their 6.60 NIDs:
sceKernelLoadModuleForKernel and sceKernelStartModule from ModuleMgrForKernel,
SysMem's sceKernelMemset and sceKernelGetUIDcontrolBlock, Sysclib's strnlen,
and sceKernelExtendKernelStack, which runs the callback like
sceKernelExtendThreadStack does.

sceKernelGetUIDcontrolBlock reports no such UID: the manager uses it to make
a descriptor it opened in kernel mode usable from user mode, and ours aren't
access-checked.
This commit is contained in:
Francisco José García García authored and Henrik Rydgård committed 2026-10-20 21:49:42 +02:00
1 parent 47c97b92aa
commit e9515d0f8a
4 files changed
+34 -1

No files matched your search

+6 -1
View File
@@ -916,6 +916,11 @@ const HLEFunction ThreadManForUser[] =
{0x65F54FFB, &WrapI_IUU<_sceKernelAllocateTlspl>, "_sceKernelAllocateTlspl", 'i', "ixp" },
};
// The type picks one of the kernel's preset stack sizes. This is enough for any of them.
static u32 sceKernelExtendKernelStack(MIPSState *mipsState, int type, u32 cb, u32 arg) {
return sceKernelExtendThreadStack(mipsState, 0x4000, cb, arg);
}
const HLEFunction ThreadManForKernel[] =
{
{0xCEADEB47, &WrapI_U<sceKernelDelayThread>, "sceKernelDelayThread", 'i', "x", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED | HLE_KERNEL_SYSCALL },
@@ -970,7 +975,7 @@ const HLEFunction ThreadManForKernel[] =
{0xB736E9FF, &WrapI_IU<sceKernelFreeVpl>, "sceKernelFreeVpl", 'i', "ix", HLE_KERNEL_SYSCALL },
{0x1D371B8A, &WrapI_IU<sceKernelCancelVpl>, "sceKernelCancelVpl", 'i', "ix", HLE_KERNEL_SYSCALL },
{0x39810265, &WrapI_IU<sceKernelReferVplStatus>, "sceKernelReferVplStatus", 'i', "ip", HLE_KERNEL_SYSCALL },
{0xBC31C1B9, nullptr, "sceKernelExtendKernelStack"},
{0xBC31C1B9, &WrapU_IUU<sceKernelExtendKernelStack>, "sceKernelExtendKernelStack", 'x', "ixx", HLE_KERNEL_SYSCALL },
// New entries must go here at the end, not inserted earlier in this table - the funcindex
// (this array position) gets baked directly into resolved-import syscall opcodes written
// into guest RAM (see GetSyscallOp() in HLE.cpp), which savestates capture verbatim. Inserting
+16
View File
@@ -9,6 +9,7 @@
#include "Core/HLE/sceKernel.h"
#include "Core/HLE/sceKernelHeap.h"
#include "Core/HLE/sceKernelMemory.h"
#include "Core/MemMapHelpers.h"
#include "Core/Reporting.h"
#include "Core/Util/BlockAllocator.h"
@@ -215,6 +216,19 @@ static int sceKernelSetUmdCacheOn(int on) {
return hleLogWarning(Log::sceKernel, 0, "UNIMPL");
}
static u32 sceKernelMemset(u32 addr, int value, u32 size) {
if (Memory::IsValidRange(addr, size)) {
Memory::Memset(addr, (u8)value, size, "KernelMemset");
}
return hleLogDebug(Log::sceKernel, addr);
}
// The POPS manager uses it to make a file descriptor it opened usable from user mode. Ours
// aren't access-checked, so report no such UID and it skips that.
static int sceKernelGetUIDcontrolBlock(SceUID uid, u32 controlBlockPtr) {
return hleLogDebug(Log::sceKernel, SCE_KERNEL_ERROR_UNKNOWN_UID, "no control blocks");
}
const HLEFunction SysMemForKernel[] = {
{ 0X96A3CE2C, &WrapI_U<sceKernelSetRebootKernel>, "sceKernelSetRebootKernel", 'i', "x", HLE_KERNEL_SYSCALL },
{ 0X1404C1AA, &WrapI_I<sceKernelSetUmdCacheOn>, "sceKernelSetUmdCacheOn", 'i', "i", HLE_KERNEL_SYSCALL },
@@ -243,6 +257,8 @@ const HLEFunction SysMemForKernel[] = {
{ 0xF91FE6AA, &WrapI_V<sceKernelSetParamSfo>, "sceKernelSetParamSfo", 'i', "", HLE_KERNEL_SYSCALL },
{ 0xC2460DD5, &WrapI_V<sceKernelSetParamSfo>, "sceKernelSetParamSfo", 'i', "", HLE_KERNEL_SYSCALL },
{ 0x807179E7, &WrapI_V<sceKernelSetParamSfo>, "sceKernelSetParamSfo", 'i', "", HLE_KERNEL_SYSCALL },
{ 0x8AE776AF, &WrapU_UIU<sceKernelMemset>, "sceKernelMemset", 'x', "xix", HLE_KERNEL_SYSCALL },
{ 0xC90B0992, &WrapI_IU<sceKernelGetUIDcontrolBlock>, "sceKernelGetUIDcontrolBlock", 'i', "ix", HLE_KERNEL_SYSCALL },
};
void Register_SysMemForKernel() {
+9
View File
@@ -844,6 +844,14 @@ static u32 sysclib_strlen(u32 src) {
}
}
static u32 sysclib_strnlen(u32 src, u32 maxLen) {
u32 len = 0;
while (len < maxLen && Memory::IsValidAddress(src + len) && Memory::ReadUnchecked_U8(src + len) != 0) {
len++;
}
return hleLogVerbose(Log::sceKernel, len);
}
static int sysclib_memcmp(u32 dst, u32 src, u32 size) {
if (Memory::IsValidRange(dst, size) && Memory::IsValidRange(src, size)) {
const int retval = memcmp(Memory::GetCharPointerUnchecked(dst), Memory::GetCharPointerUnchecked(src), size);
@@ -1015,6 +1023,7 @@ const HLEFunction SysclibForKernel[] =
{0x4C0E0274, &WrapU_UI<sysclib_strrchr>, "strrchr", 'x', "xx", HLE_KERNEL_SYSCALL },
{0xCE2F7487, &WrapU_U<sysclib_toupper>, "toupper", 'x', "x", HLE_KERNEL_SYSCALL },
{0XC2145E80, &WrapI_UIU<sysclib_snprintf>, "snprintf", 'i', "xx", HLE_KERNEL_SYSCALL },
{0x90C5573D, &WrapU_UU<sysclib_strnlen>, "strnlen", 'x', "xx", HLE_KERNEL_SYSCALL },
};
void Register_Kernel_Library()
+3
View File
@@ -3703,6 +3703,9 @@ const HLEFunction ModuleMgrForKernel[] = {
{0x329C89DB, &WrapU_CUU<sceKernelLoadModuleVSH>, "sceKernelLoadModuleVSH", 'x', "sxx", HLE_KERNEL_SYSCALL },
{0x8909A807, &WrapU_CUU<sceKernelLoadModuleVSH>, "sceKernelLoadModuleVSH", 'x', "sxx", HLE_KERNEL_SYSCALL },
{0xBDFEEC4F, &WrapU_CUU<sceKernelLoadModuleVSH>, "sceKernelLoadModuleVSH", 'x', "sxx", HLE_KERNEL_SYSCALL },
// 6.60 NIDs.
{0x939E4270, &WrapU_CUU<sceKernelLoadModule>, "sceKernelLoadModuleForKernel", 'x', "sxx", HLE_KERNEL_SYSCALL },
{0x3FF74DF1, &WrapU_UUUUU<sceKernelStartModule>, "sceKernelStartModule", 'v', "xxxxx", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED | HLE_KERNEL_SYSCALL },
};
void Register_ModuleMgrForUser() {