[Ampr] Separate APR guest file IDs from local handles
This commit is contained in:
parent
f1be35aa35
commit
5c347d2cb2
|
|
@ -50,6 +50,23 @@ internal static class AmprFileRegistry
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static uint RegisterAprResolvedPath(string guestPath, string hostPath)
|
||||||
|
{
|
||||||
|
if (TryGetApp0Relative(guestPath, out var relative) && relative.Length != 0)
|
||||||
|
{
|
||||||
|
RegisterApp0Relative(relative, hostPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// APR file ids are part of the guest ABI: ResolveFilepathsToIds returns
|
||||||
|
// the 31-bit FNV-1a hash of the guest path. Keep the collision-safe
|
||||||
|
// process-local handles used by Register() separate from this path so a
|
||||||
|
// title can compare resolved ids with ids baked into its asset tables.
|
||||||
|
var fileId = ComputeFileId(guestPath);
|
||||||
|
_hostPathsById[fileId] = hostPath;
|
||||||
|
_ambiguousCompatibilityIds.TryRemove(fileId, out _);
|
||||||
|
return fileId;
|
||||||
|
}
|
||||||
|
|
||||||
public static bool TryGetHostPath(uint id, out string hostPath)
|
public static bool TryGetHostPath(uint id, out string hostPath)
|
||||||
{
|
{
|
||||||
if ((id & 0x80000000) != 0)
|
if ((id & 0x80000000) != 0)
|
||||||
|
|
|
||||||
|
|
@ -1740,7 +1740,7 @@ public static partial class KernelMemoryCompatExports
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
var fileId = AmprFileRegistry.Register(guestPath, hostPath);
|
var fileId = AmprFileRegistry.RegisterAprResolvedPath(guestPath, hostPath);
|
||||||
LogIoTrace("apr_resolve", guestPath, $"host='{hostPath}' index={i} count={count} id=0x{fileId:X8} size={fileSize}");
|
LogIoTrace("apr_resolve", guestPath, $"host='{hostPath}' index={i} count={count} id=0x{fileId:X8} size={fileSize}");
|
||||||
|
|
||||||
if (idsAddress != 0 &&
|
if (idsAddress != 0 &&
|
||||||
|
|
@ -1832,7 +1832,7 @@ public static partial class KernelMemoryCompatExports
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
var fileId = AmprFileRegistry.Register(guestPath, hostPath);
|
var fileId = AmprFileRegistry.RegisterAprResolvedPath(guestPath, hostPath);
|
||||||
LogIoTrace("apr_resolve_with_prefix", guestPath, $"host='{hostPath}' index={i} count={count} id=0x{fileId:X8} size={fileSize}");
|
LogIoTrace("apr_resolve_with_prefix", guestPath, $"host='{hostPath}' index={i} count={count} id=0x{fileId:X8} size={fileSize}");
|
||||||
|
|
||||||
if (idsAddress != 0 &&
|
if (idsAddress != 0 &&
|
||||||
|
|
@ -1873,7 +1873,8 @@ public static partial class KernelMemoryCompatExports
|
||||||
// IDs, then hand those IDs to sceAmprAprCommandBufferReadFile. Without it
|
// IDs, then hand those IDs to sceAmprAprCommandBufferReadFile. Without it
|
||||||
// the paths never register in AmprFileRegistry, so every subsequent
|
// the paths never register in AmprFileRegistry, so every subsequent
|
||||||
// ReadFile fails with NOT_FOUND and the streaming pipeline stalls forever.
|
// ReadFile fails with NOT_FOUND and the streaming pipeline stalls forever.
|
||||||
// Signature: (const char* const* paths, size_t count, uint32_t* ids).
|
// Signature: (const char* const* paths, uint32_t count, uint32_t* ids,
|
||||||
|
// uint32_t* errorIndex).
|
||||||
[SysAbiExport(
|
[SysAbiExport(
|
||||||
Nid = "WT-5NKy42fw",
|
Nid = "WT-5NKy42fw",
|
||||||
ExportName = "sceKernelAprResolveFilepathsToIds",
|
ExportName = "sceKernelAprResolveFilepathsToIds",
|
||||||
|
|
@ -1884,6 +1885,7 @@ public static partial class KernelMemoryCompatExports
|
||||||
var pathListAddress = ctx[CpuRegister.Rdi];
|
var pathListAddress = ctx[CpuRegister.Rdi];
|
||||||
var count = ctx[CpuRegister.Rsi];
|
var count = ctx[CpuRegister.Rsi];
|
||||||
var idsAddress = ctx[CpuRegister.Rdx];
|
var idsAddress = ctx[CpuRegister.Rdx];
|
||||||
|
var errorIndexAddress = ctx[CpuRegister.Rcx];
|
||||||
if (pathListAddress == 0 || count == 0 || idsAddress == 0 || count > 1024)
|
if (pathListAddress == 0 || count == 0 || idsAddress == 0 || count > 1024)
|
||||||
{
|
{
|
||||||
KernelRuntimeCompatExports.TrySetErrno(ctx, Einval);
|
KernelRuntimeCompatExports.TrySetErrno(ctx, Einval);
|
||||||
|
|
@ -1908,11 +1910,19 @@ public static partial class KernelMemoryCompatExports
|
||||||
if (!TryGetAprFileSize(hostPath, out _))
|
if (!TryGetAprFileSize(hostPath, out _))
|
||||||
{
|
{
|
||||||
LogIoTrace("apr_resolve_ids", guestPath, $"host='{hostPath}' index={i} count={count} result=not_found");
|
LogIoTrace("apr_resolve_ids", guestPath, $"host='{hostPath}' index={i} count={count} result=not_found");
|
||||||
|
if (errorIndexAddress != 0 &&
|
||||||
|
!TryWriteUInt32Compat(ctx, errorIndexAddress, (uint)i))
|
||||||
|
{
|
||||||
|
KernelRuntimeCompatExports.TrySetErrno(ctx, Efault);
|
||||||
|
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
|
||||||
|
}
|
||||||
|
|
||||||
KernelRuntimeCompatExports.TrySetErrno(ctx, 2);
|
KernelRuntimeCompatExports.TrySetErrno(ctx, 2);
|
||||||
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND;
|
ctx[CpuRegister.Rax] = ulong.MaxValue;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
var fileId = AmprFileRegistry.Register(guestPath, hostPath);
|
var fileId = AmprFileRegistry.RegisterAprResolvedPath(guestPath, hostPath);
|
||||||
LogIoTrace("apr_resolve_ids", guestPath, $"host='{hostPath}' index={i} count={count} id=0x{fileId:X8}");
|
LogIoTrace("apr_resolve_ids", guestPath, $"host='{hostPath}' index={i} count={count} id=0x{fileId:X8}");
|
||||||
|
|
||||||
if (!TryWriteUInt32Compat(ctx, idsAddress + (i * sizeof(uint)), fileId))
|
if (!TryWriteUInt32Compat(ctx, idsAddress + (i * sizeof(uint)), fileId))
|
||||||
|
|
@ -4811,6 +4821,17 @@ public static partial class KernelMemoryCompatExports
|
||||||
return CombineWithinMount(app0Root, relative);
|
return CombineWithinMount(app0Root, relative);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (string.Equals(guestPath, "/contents", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return CombineWithinMount(app0Root, "contents");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (guestPath.StartsWith("/contents/", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
var relative = NormalizeMountRelativePath(guestPath[1..]);
|
||||||
|
return CombineWithinMount(app0Root, relative);
|
||||||
|
}
|
||||||
|
|
||||||
if (!Path.IsPathFullyQualified(guestPath) &&
|
if (!Path.IsPathFullyQualified(guestPath) &&
|
||||||
!guestPath.StartsWith("/", StringComparison.Ordinal) &&
|
!guestPath.StartsWith("/", StringComparison.Ordinal) &&
|
||||||
!guestPath.StartsWith("\\", StringComparison.Ordinal))
|
!guestPath.StartsWith("\\", StringComparison.Ordinal))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue