[Kernel] sceKernelAprGetFileSize writes the resolved file size
The export was a success stub that never wrote its out parameter, so callers sized buffers from uninitialized memory. The signature is (id, uint64_t* size); it now answers from the APR file registry like sceKernelAprGetFileStat.
This commit is contained in:
parent
9e1e15cc5c
commit
bedf4c44c7
|
|
@ -166,19 +166,6 @@ public static class KernelAprCompatExports
|
|||
return (int)OrbisGen2Result.ORBIS_GEN2_OK;
|
||||
}
|
||||
|
||||
// Success stub: the argument layout is unknown and callers tolerate the
|
||||
// empty answer (Quake streams fine), so no output payload is written until
|
||||
// the real signature is reversed.
|
||||
[SysAbiExport(
|
||||
Nid = "WvEu7yl3Ivg",
|
||||
ExportName = "sceKernelAprGetFileSize",
|
||||
Target = Generation.Gen4 | Generation.Gen5,
|
||||
LibraryName = "libKernel")]
|
||||
public static int KernelAprGetFileSize(CpuContext ctx)
|
||||
{
|
||||
return ctx.SetReturn(0);
|
||||
}
|
||||
|
||||
private static bool TryWriteAprResult(
|
||||
CpuContext ctx,
|
||||
ulong resultAddress,
|
||||
|
|
|
|||
|
|
@ -1993,6 +1993,48 @@ public static partial class KernelMemoryCompatExports
|
|||
return (int)OrbisGen2Result.ORBIS_GEN2_OK;
|
||||
}
|
||||
|
||||
// Signature: (SceKernelAprFileId id, uint64_t* size). Callers size their read buffer from the
|
||||
// answer and may pass an uninitialized slot, so the size must always be written on success.
|
||||
[SysAbiExport(
|
||||
Nid = "WvEu7yl3Ivg",
|
||||
ExportName = "sceKernelAprGetFileSize",
|
||||
Target = Generation.Gen4 | Generation.Gen5,
|
||||
LibraryName = "libKernel")]
|
||||
public static int KernelAprGetFileSize(CpuContext ctx)
|
||||
{
|
||||
var fileId = unchecked((uint)ctx[CpuRegister.Rdi]);
|
||||
var sizeAddress = ctx[CpuRegister.Rsi];
|
||||
if (sizeAddress == 0)
|
||||
{
|
||||
KernelRuntimeCompatExports.TrySetErrno(ctx, Einval);
|
||||
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (!AmprFileRegistry.TryGetHostPath(fileId, out var hostPath))
|
||||
{
|
||||
LogIoTrace("apr_get_file_size", $"id=0x{fileId:X8}", "result=id_not_registered");
|
||||
KernelRuntimeCompatExports.TrySetErrno(ctx, 2);
|
||||
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (!TryGetAprFileSize(hostPath, out var size))
|
||||
{
|
||||
LogIoTrace("apr_get_file_size", hostPath, $"id=0x{fileId:X8} result=not_found");
|
||||
KernelRuntimeCompatExports.TrySetErrno(ctx, 2);
|
||||
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (!TryWriteUInt64Compat(ctx, sizeAddress, size))
|
||||
{
|
||||
KernelRuntimeCompatExports.TrySetErrno(ctx, Efault);
|
||||
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
|
||||
}
|
||||
|
||||
LogIoTrace("apr_get_file_size", hostPath, $"id=0x{fileId:X8} size={size}");
|
||||
ctx[CpuRegister.Rax] = 0;
|
||||
return (int)OrbisGen2Result.ORBIS_GEN2_OK;
|
||||
}
|
||||
|
||||
[SysAbiExport(
|
||||
Nid = "kBwCPsYX-m4",
|
||||
ExportName = "sceKernelFstat",
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ public sealed class AprStreamingContractTests
|
|||
const ulong pathAddress = memoryBase + 0x200;
|
||||
const ulong idsAddress = memoryBase + 0x800;
|
||||
const ulong statAddress = memoryBase + 0x900;
|
||||
const ulong sizeAddress = memoryBase + 0x9A0;
|
||||
const ulong commandBufferAddress = memoryBase + 0x1000;
|
||||
const ulong recordBufferAddress = memoryBase + 0x1100;
|
||||
const ulong destinationAddress = memoryBase + 0x2000;
|
||||
|
|
@ -68,6 +69,16 @@ public sealed class AprStreamingContractTests
|
|||
Assert.True(memory.TryRead(statAddress, stat));
|
||||
Assert.Equal(fileContents.Length, BinaryPrimitives.ReadInt64LittleEndian(stat[72..]));
|
||||
|
||||
WriteUInt64(memory, sizeAddress, 0xDEAD_BEEF);
|
||||
context[CpuRegister.Rdi] = fileId;
|
||||
context[CpuRegister.Rsi] = sizeAddress;
|
||||
|
||||
Assert.Equal(0, KernelMemoryCompatExports.KernelAprGetFileSize(context));
|
||||
Assert.Equal((ulong)fileContents.Length, ReadUInt64(memory, sizeAddress));
|
||||
|
||||
context[CpuRegister.Rdi] = 0xFFFF_FFFE;
|
||||
Assert.NotEqual(0, KernelMemoryCompatExports.KernelAprGetFileSize(context));
|
||||
|
||||
context[CpuRegister.Rdi] = commandBufferAddress;
|
||||
context[CpuRegister.Rsi] = recordBufferAddress;
|
||||
context[CpuRegister.Rdx] = 0x100;
|
||||
|
|
|
|||
Loading…
Reference in New Issue