diff --git a/src/LibHac/Common/FixedArrays/Array68.cs b/src/LibHac/Common/FixedArrays/Array68.cs new file mode 100644 index 00000000..2b4b9f43 --- /dev/null +++ b/src/LibHac/Common/FixedArrays/Array68.cs @@ -0,0 +1,31 @@ +#pragma warning disable CS0169, CS0649, IDE0051 // Field is never used, Field is never assigned to, Remove unused private members +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace LibHac.Common.FixedArrays; + +public struct Array68 +{ + public const int Length = 68; + + private Array64 _0; + private Array4 _64; + + public ref T this[int i] => ref Items[i]; + + public Span Items + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => SpanHelpers.CreateSpan(ref MemoryMarshal.GetReference(_0.Items), Length); + } + + public readonly ReadOnlySpan ItemsRo + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => SpanHelpers.CreateSpan(ref MemoryMarshal.GetReference(_0.ItemsRo), Length); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator ReadOnlySpan(in Array68 value) => value.ItemsRo; +} \ No newline at end of file diff --git a/src/LibHac/Fat/FatReport.cs b/src/LibHac/Fat/FatReport.cs new file mode 100644 index 00000000..216a056b --- /dev/null +++ b/src/LibHac/Fat/FatReport.cs @@ -0,0 +1,15 @@ +namespace LibHac.Fat; + +public struct FatReport +{ + public ushort FileCurrentOpenCount; + public ushort FilePeakOpenCount; + public ushort DirectoryCurrentOpenCount; + public ushort DirectoryPeakOpenCount; +} + +public struct FatReportInfo +{ + public ushort FilePeakOpenCount; + public ushort DirectoryPeakOpenCount; +} \ No newline at end of file diff --git a/src/LibHac/Fs/ErrorInfo.cs b/src/LibHac/Fs/ErrorInfo.cs index b3ef2385..3ca56178 100644 --- a/src/LibHac/Fs/ErrorInfo.cs +++ b/src/LibHac/Fs/ErrorInfo.cs @@ -10,7 +10,10 @@ public struct FileSystemProxyErrorInfo public FatError FatFsError; public int RecoveredByInvalidateCacheCount; public int SaveDataIndexCount; - public Array80 Reserved; + public FatReportInfo BisSystemFatReportInfo; + public FatReportInfo BisUserFatReport; + public FatReportInfo SdCardFatReport; + public Array68 Reserved; } public struct StorageErrorInfo diff --git a/src/LibHac/FsSrv/FsCreator/FatFileSystemCreator.cs b/src/LibHac/FsSrv/FsCreator/FatFileSystemCreator.cs new file mode 100644 index 00000000..c717f3bd --- /dev/null +++ b/src/LibHac/FsSrv/FsCreator/FatFileSystemCreator.cs @@ -0,0 +1,73 @@ +using System; +using LibHac.Common; +using LibHac.Fat; +using LibHac.Fs; +using LibHac.Fs.Fsa; +using LibHac.Os; + +namespace LibHac.FsSrv.FsCreator; + +/// +/// Handles creating FAT file systems. +/// +/// Based on FS 14.1.0 (nnSdk 14.3.0) +public class FatFileSystemCreator : IFatFileSystemCreator +{ + // ReSharper disable once NotAccessedField.Local + private MemoryResource _allocator; + private FatError _fatFsError; + private SdkMutexType _fatErrorMutex; + private FatReport _bisSystemReport; + private FatReport _bisUserReport; + private FatReport _sdCardReport; + private SdkMutexType _fatReportMutex; + + public FatFileSystemCreator(MemoryResource allocator) + { + _fatErrorMutex = new SdkMutexType(); + _fatReportMutex = new SdkMutexType(); + _allocator = allocator; + + // Missing: Call nn::fat::SetMemoryResource + } + + public Result Create(ref SharedRef outFileSystem, ref SharedRef baseStorage, + FatAttribute attribute, int driveId, Result invalidFatFormatResult, Result usableSpaceNotEnoughResult) + { + throw new NotImplementedException(); + } + + public Result Format(ref SharedRef partitionStorage, FatAttribute attribute, FatFormatParam formatParam, + int driveId, Result invalidFatFormatResult, Result usableSpaceNotEnoughResult) + { + throw new NotImplementedException(); + } + + public void GetAndClearFatFsError(out FatError outFatError) + { + using var scopedLock = new ScopedLock(ref _fatErrorMutex); + + outFatError = _fatFsError; + _fatFsError = default; + } + + public void GetAndClearFatReportInfo(out FatReportInfo outBisSystemFatReportInfo, + out FatReportInfo outBisUserFatReportInfo, out FatReportInfo outSdCardFatReportInfo) + { + using var scopedLock = new ScopedLock(ref _fatReportMutex); + + outBisSystemFatReportInfo.FilePeakOpenCount = _bisSystemReport.FilePeakOpenCount; + outBisSystemFatReportInfo.DirectoryPeakOpenCount = _bisSystemReport.DirectoryPeakOpenCount; + outBisUserFatReportInfo.FilePeakOpenCount = _bisUserReport.FilePeakOpenCount; + outBisUserFatReportInfo.DirectoryPeakOpenCount = _bisUserReport.DirectoryPeakOpenCount; + outSdCardFatReportInfo.FilePeakOpenCount = _sdCardReport.FilePeakOpenCount; + outSdCardFatReportInfo.DirectoryPeakOpenCount = _sdCardReport.DirectoryPeakOpenCount; + + _bisSystemReport.FilePeakOpenCount = _bisSystemReport.FileCurrentOpenCount; + _bisSystemReport.DirectoryPeakOpenCount = _bisSystemReport.DirectoryCurrentOpenCount; + _bisUserReport.FilePeakOpenCount = _bisUserReport.FileCurrentOpenCount; + _bisUserReport.DirectoryPeakOpenCount = _bisUserReport.DirectoryCurrentOpenCount; + _sdCardReport.FilePeakOpenCount = _sdCardReport.FileCurrentOpenCount; + _sdCardReport.DirectoryPeakOpenCount = _sdCardReport.DirectoryCurrentOpenCount; + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/StatusReportService.cs b/src/LibHac/FsSrv/StatusReportService.cs index 4e6ccb0e..623ebc39 100644 --- a/src/LibHac/FsSrv/StatusReportService.cs +++ b/src/LibHac/FsSrv/StatusReportService.cs @@ -1,5 +1,6 @@ using LibHac.Diag; using LibHac.Fs; +using LibHac.FsSrv.FsCreator; using LibHac.FsSystem; using LibHac.Os; @@ -10,7 +11,7 @@ namespace LibHac.FsSrv; /// /// This struct handles forwarding calls to the object. /// No permissions are needed to call any of this struct's functions. -/// Based on FS 13.1.0 (nnSdk 13.4.0) +/// Based on FS 14.1.0 (nnSdk 14.3.0) public readonly struct StatusReportService { private readonly StatusReportServiceImpl _serviceImpl; @@ -40,7 +41,7 @@ public readonly struct StatusReportService /// /// Manages getting and resetting various status reports and statistics about parts of the FS service. /// -/// Based on FS 13.1.0 (nnSdk 13.4.0) +/// Based on FS 14.1.0 (nnSdk 14.3.0) public class StatusReportServiceImpl { private Configuration _config; @@ -56,7 +57,7 @@ public class StatusReportServiceImpl { public NcaFileSystemServiceImpl NcaFileSystemServiceImpl; public SaveDataFileSystemServiceImpl SaveDataFileSystemServiceImpl; - // Missing: FatFileSystemCreator (Not an IFatFileSystemCreator) + public FatFileSystemCreator FatFileSystemCreator; public MemoryReport BufferManagerMemoryReport; public MemoryReport ExpHeapMemoryReport; public MemoryReport BufferPoolMemoryReport; @@ -79,7 +80,12 @@ public class StatusReportServiceImpl out errorInfo.UnrecoverableDataCorruptionByRemountCount, out errorInfo.RecoveredByInvalidateCacheCount); - // Missing: GetFatInfo + if (_config.FatFileSystemCreator is not null) + { + _config.FatFileSystemCreator.GetAndClearFatFsError(out errorInfo.FatFsError); + _config.FatFileSystemCreator.GetAndClearFatReportInfo(out errorInfo.BisSystemFatReportInfo, + out errorInfo.BisUserFatReport, out errorInfo.SdCardFatReport); + } Assert.SdkRequiresNotNull(_config.SaveDataFileSystemServiceImpl); diff --git a/tests/LibHac.Tests/Fs/TypeLayoutTests.cs b/tests/LibHac.Tests/Fs/TypeLayoutTests.cs index 8035c0c6..4a6ef886 100644 --- a/tests/LibHac.Tests/Fs/TypeLayoutTests.cs +++ b/tests/LibHac.Tests/Fs/TypeLayoutTests.cs @@ -213,7 +213,10 @@ public class TypeLayoutTests Assert.Equal(0x08, GetOffset(in s, in s.FatFsError)); Assert.Equal(0x28, GetOffset(in s, in s.RecoveredByInvalidateCacheCount)); Assert.Equal(0x2C, GetOffset(in s, in s.SaveDataIndexCount)); - Assert.Equal(0x30, GetOffset(in s, in s.Reserved)); + Assert.Equal(0x30, GetOffset(in s, in s.BisSystemFatReportInfo)); + Assert.Equal(0x34, GetOffset(in s, in s.BisUserFatReport)); + Assert.Equal(0x38, GetOffset(in s, in s.SdCardFatReport)); + Assert.Equal(0x3C, GetOffset(in s, in s.Reserved)); } [Fact]