From 612359f0a4eb96aebe55d1577d8a4e5ba81537d7 Mon Sep 17 00:00:00 2001 From: Alex Barney Date: Mon, 2 May 2022 18:07:41 -0700 Subject: [PATCH] Implement more FS shim functions - BaseFileSystem - ErrorInfo - FsStackUsage - ImageDirectory - Logo - MemoryReportInfoShim --- src/LibHac/Fs/AccessLog.cs | 9 +++ src/LibHac/Fs/Shim/BaseFileSystem.cs | 68 ++++++++++++++++++++++ src/LibHac/Fs/Shim/ErrorInfo.cs | 23 ++++++++ src/LibHac/Fs/Shim/FsStackUsage.cs | 21 +++++++ src/LibHac/Fs/Shim/ImageDirectory.cs | 75 ++++++++++++++++++++++++ src/LibHac/Fs/Shim/Logo.cs | 80 ++++++++++++++++++++++++++ src/LibHac/Fs/Shim/MemoryReportInfo.cs | 22 +++++++ src/LibHac/Fs/Shim/SpeedEmulation.cs | 28 +++++++++ 8 files changed, 326 insertions(+) create mode 100644 src/LibHac/Fs/Shim/BaseFileSystem.cs create mode 100644 src/LibHac/Fs/Shim/ErrorInfo.cs create mode 100644 src/LibHac/Fs/Shim/FsStackUsage.cs create mode 100644 src/LibHac/Fs/Shim/ImageDirectory.cs create mode 100644 src/LibHac/Fs/Shim/Logo.cs create mode 100644 src/LibHac/Fs/Shim/MemoryReportInfo.cs create mode 100644 src/LibHac/Fs/Shim/SpeedEmulation.cs diff --git a/src/LibHac/Fs/AccessLog.cs b/src/LibHac/Fs/AccessLog.cs index 7f631a58..5039acf4 100644 --- a/src/LibHac/Fs/AccessLog.cs +++ b/src/LibHac/Fs/AccessLog.cs @@ -988,6 +988,15 @@ namespace LibHac.Fs.Impl (byte)'i', (byte)'d', (byte)':', (byte)' ' }; + /// ", imagedirectoryid: " + public static ReadOnlySpan 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)' ' + }; + /// ", gamecard_handle: 0x" public static ReadOnlySpan LogGameCardHandle => // ", gamecard_handle: 0x" new[] diff --git a/src/LibHac/Fs/Shim/BaseFileSystem.cs b/src/LibHac/Fs/Shim/BaseFileSystem.cs new file mode 100644 index 00000000..a5563819 --- /dev/null +++ b/src/LibHac/Fs/Shim/BaseFileSystem.cs @@ -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; + +/// +/// Contains functions for mounting base file systems. +/// +/// Based on nnSdk 14.3.0 +public static class BaseFileSystem +{ + private static Result OpenBaseFileSystem(FileSystemClient fs, ref SharedRef outFileSystem, + BaseFileSystemId fileSystemId) + { + using SharedRef 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 fileSystem) + { + using var fileSystemAdapter = + new UniqueRef(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(); + 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 fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject(); + + Result rc = fileSystemProxy.Get.FormatBaseFileSystem(fileSystemId); + fs.Impl.AbortIfNeeded(rc); + if (rc.IsFailure()) return rc.Miss(); + + return Result.Success; + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Shim/ErrorInfo.cs b/src/LibHac/Fs/Shim/ErrorInfo.cs new file mode 100644 index 00000000..7a951e54 --- /dev/null +++ b/src/LibHac/Fs/Shim/ErrorInfo.cs @@ -0,0 +1,23 @@ +using LibHac.Common; +using LibHac.FsSrv.Sf; + +namespace LibHac.Fs.Shim; + +/// +/// Contains functions for obtaining error information from the file system proxy service. +/// +/// Based on nnSdk 14.3.0 +public static class ErrorInfo +{ + public static Result GetAndClearFileSystemProxyErrorInfo(this FileSystemClient fs, + out FileSystemProxyErrorInfo outErrorInfo) + { + using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject(); + + Result rc = fileSystemProxy.Get.GetAndClearErrorInfo(out outErrorInfo); + fs.Impl.AbortIfNeeded(rc); + if (rc.IsFailure()) return rc.Miss(); + + return Result.Success; + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Shim/FsStackUsage.cs b/src/LibHac/Fs/Shim/FsStackUsage.cs new file mode 100644 index 00000000..cb8b25a2 --- /dev/null +++ b/src/LibHac/Fs/Shim/FsStackUsage.cs @@ -0,0 +1,21 @@ +using LibHac.Common; +using LibHac.Diag; +using LibHac.FsSrv.Sf; + +namespace LibHac.Fs.Shim; + +/// +/// Contains functions for getting the amount of stack space used by FS threads. +/// +/// Based on nnSdk 14.3.0 +public static class FsStackUsage +{ + public static uint GetFsStackUsage(this FileSystemClient fs, FsStackUsageThreadType threadType) + { + using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject(); + + Abort.DoAbortUnlessSuccess(fileSystemProxy.Get.GetFsStackUsage(out uint stackUsage, threadType)); + + return stackUsage; + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Shim/ImageDirectory.cs b/src/LibHac/Fs/Shim/ImageDirectory.cs new file mode 100644 index 00000000..213d357e --- /dev/null +++ b/src/LibHac/Fs/Shim/ImageDirectory.cs @@ -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; + +/// +/// Contains functions for mounting the directories where images and videos are saved. +/// +/// Based on nnSdk 14.3.0 +public static class ImageDirectory +{ + public static Result MountImageDirectory(this FileSystemClient fs, U8Span mountName, ImageDirectoryId directoryId) + { + Result rc; + Span 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 fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject(); + using var fileSystem = new SharedRef(); + + rc = fileSystemProxy.Get.OpenImageDirectoryFileSystem(ref fileSystem.Ref(), directoryId); + if (rc.IsFailure()) return rc.Miss(); + + using var fileSystemAdapter = + new UniqueRef(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; + } + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Shim/Logo.cs b/src/LibHac/Fs/Shim/Logo.cs new file mode 100644 index 00000000..03659567 --- /dev/null +++ b/src/LibHac/Fs/Shim/Logo.cs @@ -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; + +/// +/// Contains functions for opening the logo partitions of NCA files. +/// +/// Based on nnSdk 14.3.0 +public static class Logo +{ + public static Result MountLogo(this FileSystemClient fs, U8Span mountName, U8Span path, ProgramId programId) + { + Result rc; + Span 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 fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject(); + using var fileSystem = new SharedRef(); + + rc = fileSystemProxy.Get.OpenFileSystemWithId(ref fileSystem.Ref(), in sfPath, programId.Value, + FileSystemProxyType.Logo); + if (rc.IsFailure()) return rc.Miss(); + + using var fileSystemAdapter = + new UniqueRef(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; + } + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Shim/MemoryReportInfo.cs b/src/LibHac/Fs/Shim/MemoryReportInfo.cs new file mode 100644 index 00000000..8aa6fcb1 --- /dev/null +++ b/src/LibHac/Fs/Shim/MemoryReportInfo.cs @@ -0,0 +1,22 @@ +using LibHac.Common; +using LibHac.FsSrv.Sf; + +namespace LibHac.Fs.Shim; + +/// +/// Contains functions for obtaining reports on memory usage from the file system proxy service. +/// +/// Based on nnSdk 14.3.0 +public static class MemoryReportInfoShim +{ + public static Result GetAndClearMemoryReportInfo(this FileSystemClient fs, out MemoryReportInfo reportInfo) + { + using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject(); + + Result rc = fileSystemProxy.Get.GetAndClearMemoryReportInfo(out reportInfo); + fs.Impl.AbortIfNeeded(rc); + if (rc.IsFailure()) return rc.Miss(); + + return Result.Success; + } +} \ No newline at end of file diff --git a/src/LibHac/Fs/Shim/SpeedEmulation.cs b/src/LibHac/Fs/Shim/SpeedEmulation.cs new file mode 100644 index 00000000..a95fb0ae --- /dev/null +++ b/src/LibHac/Fs/Shim/SpeedEmulation.cs @@ -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(); + } + } +} \ No newline at end of file