Implement more FS shim functions

- BaseFileSystem
- ErrorInfo
- FsStackUsage
- ImageDirectory
- Logo
- MemoryReportInfoShim
This commit is contained in:
Alex Barney 2022-05-02 18:07:41 -07:00
parent e70e23492f
commit 612359f0a4
8 changed files with 326 additions and 0 deletions

View file

@ -988,6 +988,15 @@ namespace LibHac.Fs.Impl
(byte)'i', (byte)'d', (byte)':', (byte)' ' (byte)'i', (byte)'d', (byte)':', (byte)' '
}; };
/// <summary>"<c>, imagedirectoryid: </c>"</summary>
public static ReadOnlySpan<byte> LogImageDirectoryId => // ", imagedirectoryid: "
new[]
{
(byte)',', (byte)' ', (byte)'i', (byte)'m', (byte)'a', (byte)'g', (byte)'e', (byte)'d',
(byte)'i', (byte)'r', (byte)'e', (byte)'c', (byte)'t', (byte)'o', (byte)'r', (byte)'y',
(byte)'i', (byte)'d', (byte)':', (byte)' '
};
/// <summary>"<c>, gamecard_handle: 0x</c>"</summary> /// <summary>"<c>, gamecard_handle: 0x</c>"</summary>
public static ReadOnlySpan<byte> LogGameCardHandle => // ", gamecard_handle: 0x" public static ReadOnlySpan<byte> LogGameCardHandle => // ", gamecard_handle: 0x"
new[] new[]

View file

@ -0,0 +1,68 @@
using LibHac.Common;
using LibHac.Fs.Fsa;
using LibHac.Fs.Impl;
using LibHac.FsSrv.Sf;
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
namespace LibHac.Fs.Shim;
/// <summary>
/// Contains functions for mounting base file systems.
/// </summary>
/// <remarks>Based on nnSdk 14.3.0</remarks>
public static class BaseFileSystem
{
private static Result OpenBaseFileSystem(FileSystemClient fs, ref SharedRef<IFileSystemSf> outFileSystem,
BaseFileSystemId fileSystemId)
{
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
Result rc = fileSystemProxy.Get.OpenBaseFileSystem(ref outFileSystem, fileSystemId);
if (rc.IsFailure()) return rc.Miss();
return Result.Success;
}
private static Result RegisterFileSystem(FileSystemClient fs, U8Span mountName,
ref SharedRef<IFileSystemSf> fileSystem)
{
using var fileSystemAdapter =
new UniqueRef<IFileSystem>(new FileSystemServiceObjectAdapter(ref fileSystem.Ref()));
Result rc = fs.Register(mountName, ref fileSystemAdapter.Ref());
if (rc.IsFailure()) return rc.Miss();
return Result.Success;
}
public static Result MountBaseFileSystem(this FileSystemClient fs, U8Span mountName, BaseFileSystemId fileSystemId)
{
Result rc = fs.Impl.CheckMountName(mountName);
fs.Impl.AbortIfNeeded(rc);
if (rc.IsFailure()) return rc.Miss();
using var fileSystem = new SharedRef<IFileSystemSf>();
rc = OpenBaseFileSystem(fs, ref fileSystem.Ref(), fileSystemId);
fs.Impl.AbortIfNeeded(rc);
if (rc.IsFailure()) return rc.Miss();
rc = RegisterFileSystem(fs, mountName, ref fileSystem.Ref());
fs.Impl.AbortIfNeeded(rc);
if (rc.IsFailure()) return rc.Miss();
return Result.Success;
}
public static Result FormatBaseFileSystem(this FileSystemClient fs, BaseFileSystemId fileSystemId)
{
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
Result rc = fileSystemProxy.Get.FormatBaseFileSystem(fileSystemId);
fs.Impl.AbortIfNeeded(rc);
if (rc.IsFailure()) return rc.Miss();
return Result.Success;
}
}

View file

@ -0,0 +1,23 @@
using LibHac.Common;
using LibHac.FsSrv.Sf;
namespace LibHac.Fs.Shim;
/// <summary>
/// Contains functions for obtaining error information from the file system proxy service.
/// </summary>
/// <remarks>Based on nnSdk 14.3.0</remarks>
public static class ErrorInfo
{
public static Result GetAndClearFileSystemProxyErrorInfo(this FileSystemClient fs,
out FileSystemProxyErrorInfo outErrorInfo)
{
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
Result rc = fileSystemProxy.Get.GetAndClearErrorInfo(out outErrorInfo);
fs.Impl.AbortIfNeeded(rc);
if (rc.IsFailure()) return rc.Miss();
return Result.Success;
}
}

View file

@ -0,0 +1,21 @@
using LibHac.Common;
using LibHac.Diag;
using LibHac.FsSrv.Sf;
namespace LibHac.Fs.Shim;
/// <summary>
/// Contains functions for getting the amount of stack space used by FS threads.
/// </summary>
/// <remarks>Based on nnSdk 14.3.0</remarks>
public static class FsStackUsage
{
public static uint GetFsStackUsage(this FileSystemClient fs, FsStackUsageThreadType threadType)
{
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
Abort.DoAbortUnlessSuccess(fileSystemProxy.Get.GetFsStackUsage(out uint stackUsage, threadType));
return stackUsage;
}
}

View file

@ -0,0 +1,75 @@
using System;
using LibHac.Common;
using LibHac.Fs.Fsa;
using LibHac.Fs.Impl;
using LibHac.FsSrv.Sf;
using LibHac.Os;
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
using static LibHac.Fs.Impl.AccessLogStrings;
namespace LibHac.Fs.Shim;
/// <summary>
/// Contains functions for mounting the directories where images and videos are saved.
/// </summary>
/// <remarks>Based on nnSdk 14.3.0</remarks>
public static class ImageDirectory
{
public static Result MountImageDirectory(this FileSystemClient fs, U8Span mountName, ImageDirectoryId directoryId)
{
Result rc;
Span<byte> logBuffer = stackalloc byte[0x50];
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System))
{
Tick start = fs.Hos.Os.GetSystemTick();
rc = Mount(fs, mountName, directoryId);
Tick end = fs.Hos.Os.GetSystemTick();
var idString = new IdString();
var sb = new U8StringBuilder(logBuffer, true);
sb.Append(LogName).Append(mountName).Append(LogQuote)
.Append(LogImageDirectoryId).Append(idString.ToString(directoryId));
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
}
else
{
rc = Mount(fs, mountName, directoryId);
}
fs.Impl.AbortIfNeeded(rc);
if (rc.IsFailure()) return rc.Miss();
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System))
fs.Impl.EnableFileSystemAccessorAccessLog(mountName);
return Result.Success;
static Result Mount(FileSystemClient fs, U8Span mountName, ImageDirectoryId directoryId)
{
Result rc = fs.Impl.CheckMountName(mountName);
if (rc.IsFailure()) return rc.Miss();
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
using var fileSystem = new SharedRef<IFileSystemSf>();
rc = fileSystemProxy.Get.OpenImageDirectoryFileSystem(ref fileSystem.Ref(), directoryId);
if (rc.IsFailure()) return rc.Miss();
using var fileSystemAdapter =
new UniqueRef<IFileSystem>(new FileSystemServiceObjectAdapter(ref fileSystem.Ref()));
if (!fileSystemAdapter.HasValue)
return ResultFs.AllocationMemoryFailedInImageDirectoryA.Log();
rc = fs.Impl.Fs.Register(mountName, ref fileSystemAdapter.Ref());
if (rc.IsFailure()) return rc.Miss();
return Result.Success;
}
}
}

View file

@ -0,0 +1,80 @@
using System;
using LibHac.Common;
using LibHac.Fs.Fsa;
using LibHac.Fs.Impl;
using LibHac.FsSrv.Sf;
using LibHac.Ncm;
using LibHac.Os;
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
using static LibHac.Fs.Impl.AccessLogStrings;
namespace LibHac.Fs.Shim;
/// <summary>
/// Contains functions for opening the logo partitions of NCA files.
/// </summary>
/// <remarks>Based on nnSdk 14.3.0</remarks>
public static class Logo
{
public static Result MountLogo(this FileSystemClient fs, U8Span mountName, U8Span path, ProgramId programId)
{
Result rc;
Span<byte> logBuffer = stackalloc byte[0x300];
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System))
{
Tick start = fs.Hos.Os.GetSystemTick();
rc = Mount(fs, mountName, path, programId);
Tick end = fs.Hos.Os.GetSystemTick();
var sb = new U8StringBuilder(logBuffer, true);
sb.Append(LogName).Append(mountName).Append(LogQuote)
.Append(LogPath).Append(path).Append(LogQuote)
.Append(LogProgramId).AppendFormat(programId.Value, 'X');
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
}
else
{
rc = Mount(fs, mountName, path, programId);
}
fs.Impl.AbortIfNeeded(rc);
if (rc.IsFailure()) return rc.Miss();
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System))
fs.Impl.EnableFileSystemAccessorAccessLog(mountName);
return Result.Success;
static Result Mount(FileSystemClient fs, U8Span mountName, U8Span path, ProgramId programId)
{
Result rc = fs.Impl.CheckMountName(mountName);
if (rc.IsFailure()) return rc.Miss();
rc = PathUtility.ConvertToFspPath(out FspPath sfPath, path);
if (rc.IsFailure()) return rc;
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
using var fileSystem = new SharedRef<IFileSystemSf>();
rc = fileSystemProxy.Get.OpenFileSystemWithId(ref fileSystem.Ref(), in sfPath, programId.Value,
FileSystemProxyType.Logo);
if (rc.IsFailure()) return rc.Miss();
using var fileSystemAdapter =
new UniqueRef<IFileSystem>(new FileSystemServiceObjectAdapter(ref fileSystem.Ref()));
if (!fileSystemAdapter.HasValue)
return ResultFs.AllocationMemoryFailedInLogoA.Log();
rc = fs.Impl.Fs.Register(mountName, ref fileSystemAdapter.Ref());
if (rc.IsFailure()) return rc.Miss();
return Result.Success;
}
}
}

View file

@ -0,0 +1,22 @@
using LibHac.Common;
using LibHac.FsSrv.Sf;
namespace LibHac.Fs.Shim;
/// <summary>
/// Contains functions for obtaining reports on memory usage from the file system proxy service.
/// </summary>
/// <remarks>Based on nnSdk 14.3.0</remarks>
public static class MemoryReportInfoShim
{
public static Result GetAndClearMemoryReportInfo(this FileSystemClient fs, out MemoryReportInfo reportInfo)
{
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
Result rc = fileSystemProxy.Get.GetAndClearMemoryReportInfo(out reportInfo);
fs.Impl.AbortIfNeeded(rc);
if (rc.IsFailure()) return rc.Miss();
return Result.Success;
}
}

View file

@ -0,0 +1,28 @@
using System;
namespace LibHac.Fs
{
public enum SpeedEmulationMode
{
None = 0,
Faster = 1,
Slower = 2,
Random = 3
}
}
namespace LibHac.Fs.Shim
{
public static class SpeedEmulationShim
{
public static Result SetSpeedEmulationMode(this FileSystemClient fs, SpeedEmulationMode mode)
{
throw new NotImplementedException();
}
public static Result GetSpeedEmulationMode(this FileSystemClient fs, out SpeedEmulationMode outMode)
{
throw new NotImplementedException();
}
}
}