diff --git a/src/LibHac/Fs/FsEnums.cs b/src/LibHac/Fs/FsEnums.cs index ef661f74..6939c687 100644 --- a/src/LibHac/Fs/FsEnums.cs +++ b/src/LibHac/Fs/FsEnums.cs @@ -190,4 +190,11 @@ namespace LibHac.Fs None = 0, PseudoCaseSensitive = 1 } + + public enum SimulatingDeviceDetectionMode + { + None = 0, + Inserted = 1, + NotInserted = 2 + } } diff --git a/src/LibHac/FsSrv/BaseStorageService.cs b/src/LibHac/FsSrv/BaseStorageService.cs new file mode 100644 index 00000000..23690d15 --- /dev/null +++ b/src/LibHac/FsSrv/BaseStorageService.cs @@ -0,0 +1,238 @@ +using System; +using System.Runtime.CompilerServices; +using LibHac.Fs; +using LibHac.FsSrv.Creators; +using LibHac.FsSrv.Impl; +using LibHac.FsSrv.Sf; +using LibHac.FsSystem; + +namespace LibHac.FsSrv +{ + public readonly struct BaseStorageService + { + private readonly BaseStorageServiceImpl _serviceImpl; + private readonly ulong _processId; + + public BaseStorageService(BaseStorageServiceImpl serviceImpl, ulong processId) + { + _serviceImpl = serviceImpl; + _processId = processId; + } + + public Result OpenBisStorage(out ReferenceCountedDisposable storage, BisPartitionId id) + { + storage = default; + + var storageFlag = StorageType.Bis; + using var scopedLayoutType = new ScopedStorageLayoutTypeSetter(storageFlag); + + Result rc = GetProgramInfo(out ProgramInfo programInfo); + if (rc.IsFailure()) return rc; + + rc = GetAccessibilityForOpenBisPartition(out Accessibility accessibility, programInfo, id); + if (rc.IsFailure()) return rc; + + bool canAccess = accessibility.CanRead && accessibility.CanWrite; + + if (!canAccess) + return ResultFs.PermissionDenied.Log(); + + ReferenceCountedDisposable tempStorage = null; + try + { + rc = _serviceImpl.OpenBisStorage(out tempStorage, id); + if (rc.IsFailure()) return rc; + + tempStorage = StorageLayoutTypeSetStorage.CreateShared(ref tempStorage, storageFlag); + + // Todo: Async storage + + storage = StorageInterfaceAdapter.CreateShared(ref tempStorage); + return Result.Success; + + } + finally + { + tempStorage?.Dispose(); + } + } + + public Result InvalidateBisCache() + { + Result rc = GetProgramInfo(out ProgramInfo programInfo); + if (rc.IsFailure()) return rc; + + if (!programInfo.AccessControl.CanCall(OperationType.InvalidateBisCache)) + return ResultFs.PermissionDenied.Log(); + + return _serviceImpl.InvalidateBisCache(); + } + + public Result OpenGameCardStorage(out ReferenceCountedDisposable storage, GameCardHandle handle, + GameCardPartitionRaw partitionId) + { + storage = default; + + Result rc = GetProgramInfo(out ProgramInfo programInfo); + if (rc.IsFailure()) return rc; + + Accessibility accessibility = + programInfo.AccessControl.GetAccessibilityFor(AccessibilityType.OpenGameCardStorage); + + bool canAccess = accessibility.CanRead && accessibility.CanWrite; + + if (!canAccess) + return ResultFs.PermissionDenied.Log(); + + ReferenceCountedDisposable tempStorage = null; + try + { + rc = _serviceImpl.OpenGameCardPartition(out tempStorage, handle, partitionId); + if (rc.IsFailure()) return rc; + + // Todo: Async storage + + storage = StorageInterfaceAdapter.CreateShared(ref tempStorage); + return Result.Success; + } + finally + { + tempStorage?.Dispose(); + } + } + + public Result OpenDeviceOperator(out ReferenceCountedDisposable deviceOperator) + { + deviceOperator = _serviceImpl.Config.DeviceOperator.AddReference(); + return Result.Success; + } + + public Result OpenSdCardDetectionEventNotifier(out ReferenceCountedDisposable eventNotifier) + { + eventNotifier = default; + + Result rc = GetProgramInfo(out ProgramInfo programInfo); + if (rc.IsFailure()) return rc; + + if (!programInfo.AccessControl.CanCall(OperationType.OpenSdCardDetectionEventNotifier)) + return ResultFs.PermissionDenied.Log(); + + throw new NotImplementedException(); + } + + public Result OpenGameCardDetectionEventNotifier(out ReferenceCountedDisposable eventNotifier) + { + eventNotifier = default; + + Result rc = GetProgramInfo(out ProgramInfo programInfo); + if (rc.IsFailure()) return rc; + + if (!programInfo.AccessControl.CanCall(OperationType.OpenGameCardDetectionEventNotifier)) + return ResultFs.PermissionDenied.Log(); + + throw new NotImplementedException(); + } + + public Result SimulateDeviceDetectionEvent(SdmmcPort port, SimulatingDeviceDetectionMode mode, bool signalEvent) + { + Result rc = GetProgramInfo(out ProgramInfo programInfo); + if (rc.IsFailure()) return rc; + + if (!programInfo.AccessControl.CanCall(OperationType.SimulateDevice)) + return ResultFs.PermissionDenied.Log(); + + throw new NotImplementedException(); + } + + private Result GetProgramInfo(out ProgramInfo programInfo) + { + return _serviceImpl.GetProgramInfo(out programInfo, _processId); + } + + private Result GetAccessibilityForOpenBisPartition(out Accessibility accessibility, ProgramInfo programInfo, + BisPartitionId partitionId) + { + Unsafe.SkipInit(out accessibility); + + AccessibilityType type = partitionId switch + { + BisPartitionId.BootPartition1Root => AccessibilityType.OpenBisPartitionBootPartition1Root, + BisPartitionId.BootPartition2Root => AccessibilityType.OpenBisPartitionBootPartition2Root, + BisPartitionId.UserDataRoot => AccessibilityType.OpenBisPartitionUserDataRoot, + BisPartitionId.BootConfigAndPackage2Part1 => AccessibilityType.OpenBisPartitionBootConfigAndPackage2Part1, + BisPartitionId.BootConfigAndPackage2Part2 => AccessibilityType.OpenBisPartitionBootConfigAndPackage2Part2, + BisPartitionId.BootConfigAndPackage2Part3 => AccessibilityType.OpenBisPartitionBootConfigAndPackage2Part3, + BisPartitionId.BootConfigAndPackage2Part4 => AccessibilityType.OpenBisPartitionBootConfigAndPackage2Part4, + BisPartitionId.BootConfigAndPackage2Part5 => AccessibilityType.OpenBisPartitionBootConfigAndPackage2Part5, + BisPartitionId.BootConfigAndPackage2Part6 => AccessibilityType.OpenBisPartitionBootConfigAndPackage2Part6, + BisPartitionId.CalibrationBinary => AccessibilityType.OpenBisPartitionCalibrationBinary, + BisPartitionId.CalibrationFile => AccessibilityType.OpenBisPartitionCalibrationFile, + BisPartitionId.SafeMode => AccessibilityType.OpenBisPartitionSafeMode, + BisPartitionId.User => AccessibilityType.OpenBisPartitionUser, + BisPartitionId.System => AccessibilityType.OpenBisPartitionSystem, + BisPartitionId.SystemProperEncryption => AccessibilityType.OpenBisPartitionSystemProperEncryption, + BisPartitionId.SystemProperPartition => AccessibilityType.OpenBisPartitionSystemProperPartition, + _ => (AccessibilityType)(-1) + }; + + if (type == (AccessibilityType)(-1)) + return ResultFs.InvalidArgument.Log(); + + accessibility = programInfo.AccessControl.GetAccessibilityFor(type); + return Result.Success; + } + } + + public class BaseStorageServiceImpl + { + internal Configuration Config; + + public BaseStorageServiceImpl(in Configuration configuration) + { + Config = configuration; + } + + public struct Configuration + { + public IBuiltInStorageCreator BisStorageCreator; + public IGameCardStorageCreator GameCardStorageCreator; + + // LibHac additions + public ProgramRegistryImpl ProgramRegistry; + // Todo: The DeviceOperator in FS uses mostly global state. Decide how to handle this. + public ReferenceCountedDisposable DeviceOperator; + } + + public Result OpenBisStorage(out ReferenceCountedDisposable storage, BisPartitionId partitionId) + { + return Config.BisStorageCreator.Create(out storage, partitionId); + } + + public Result InvalidateBisCache() + { + return Config.BisStorageCreator.InvalidateCache(); + } + + public Result OpenGameCardPartition(out ReferenceCountedDisposable storage, GameCardHandle handle, + GameCardPartitionRaw partitionId) + { + switch (partitionId) + { + case GameCardPartitionRaw.NormalReadOnly: + return Config.GameCardStorageCreator.CreateReadOnly(handle, out storage); + case GameCardPartitionRaw.SecureReadOnly: + return Config.GameCardStorageCreator.CreateSecureReadOnly(handle, out storage); + case GameCardPartitionRaw.RootWriteOnly: + return Config.GameCardStorageCreator.CreateWriteOnly(handle, out storage); + default: + storage = default; + return ResultFs.InvalidArgument.Log(); + } + } + + internal Result GetProgramInfo(out ProgramInfo programInfo, ulong processId) + { + return Config.ProgramRegistry.GetProgramInfo(out programInfo, processId); + } + } +} diff --git a/src/LibHac/FsSrv/Creators/EmulatedGameCardStorageCreator.cs b/src/LibHac/FsSrv/Creators/EmulatedGameCardStorageCreator.cs index 7e246bea..65daa55d 100644 --- a/src/LibHac/FsSrv/Creators/EmulatedGameCardStorageCreator.cs +++ b/src/LibHac/FsSrv/Creators/EmulatedGameCardStorageCreator.cs @@ -12,7 +12,7 @@ namespace LibHac.FsSrv.Creators GameCard = gameCard; } - public Result CreateNormal(GameCardHandle handle, out IStorage storage) + public Result CreateReadOnly(GameCardHandle handle, out ReferenceCountedDisposable storage) { storage = default; @@ -21,16 +21,17 @@ namespace LibHac.FsSrv.Creators return ResultFs.InvalidGameCardHandleOnOpenNormalPartition.Log(); } - var baseStorage = new ReadOnlyGameCardStorage(GameCard, handle); + var baseStorage = new ReferenceCountedDisposable(new ReadOnlyGameCardStorage(GameCard, handle)); Result rc = GameCard.GetCardInfo(out GameCardInfo cardInfo, handle); if (rc.IsFailure()) return rc; - storage = new SubStorage(baseStorage, 0, cardInfo.SecureAreaOffset); + storage = new ReferenceCountedDisposable( + new SubStorage(baseStorage, 0, cardInfo.SecureAreaOffset)); return Result.Success; } - public Result CreateSecure(GameCardHandle handle, out IStorage storage) + public Result CreateSecureReadOnly(GameCardHandle handle, out ReferenceCountedDisposable storage) { storage = default; @@ -48,16 +49,19 @@ namespace LibHac.FsSrv.Creators rc = GameCard.GetGameCardImageHash(imageHash); if (rc.IsFailure()) return rc; - var baseStorage = new ReadOnlyGameCardStorage(GameCard, handle, deviceId, imageHash); + var baseStorage = + new ReferenceCountedDisposable(new ReadOnlyGameCardStorage(GameCard, handle, deviceId, + imageHash)); rc = GameCard.GetCardInfo(out GameCardInfo cardInfo, handle); if (rc.IsFailure()) return rc; - storage = new SubStorage(baseStorage, cardInfo.SecureAreaOffset, cardInfo.SecureAreaSize); + storage = new ReferenceCountedDisposable(new SubStorage(baseStorage, cardInfo.SecureAreaOffset, + cardInfo.SecureAreaSize)); return Result.Success; } - public Result CreateWritable(GameCardHandle handle, out IStorage storage) + public Result CreateWriteOnly(GameCardHandle handle, out ReferenceCountedDisposable storage) { throw new NotImplementedException(); } diff --git a/src/LibHac/FsSrv/Creators/IBuiltInStorageCreator.cs b/src/LibHac/FsSrv/Creators/IBuiltInStorageCreator.cs index 47dc7756..2b58c738 100644 --- a/src/LibHac/FsSrv/Creators/IBuiltInStorageCreator.cs +++ b/src/LibHac/FsSrv/Creators/IBuiltInStorageCreator.cs @@ -4,6 +4,7 @@ namespace LibHac.FsSrv.Creators { public interface IBuiltInStorageCreator { - Result Create(out IStorage storage, BisPartitionId partitionId); + Result Create(out ReferenceCountedDisposable storage, BisPartitionId partitionId); + Result InvalidateCache(); } } diff --git a/src/LibHac/FsSrv/Creators/IGameCardStorageCreator.cs b/src/LibHac/FsSrv/Creators/IGameCardStorageCreator.cs index 2da142fd..a6874e41 100644 --- a/src/LibHac/FsSrv/Creators/IGameCardStorageCreator.cs +++ b/src/LibHac/FsSrv/Creators/IGameCardStorageCreator.cs @@ -4,8 +4,8 @@ namespace LibHac.FsSrv.Creators { public interface IGameCardStorageCreator { - Result CreateNormal(GameCardHandle handle, out IStorage storage); - Result CreateSecure(GameCardHandle handle, out IStorage storage); - Result CreateWritable(GameCardHandle handle, out IStorage storage); + Result CreateReadOnly(GameCardHandle handle, out ReferenceCountedDisposable storage); + Result CreateSecureReadOnly(GameCardHandle handle, out ReferenceCountedDisposable storage); + Result CreateWriteOnly(GameCardHandle handle, out ReferenceCountedDisposable storage); } } \ No newline at end of file diff --git a/src/LibHac/FsSrv/DefaultFsServerObjects.cs b/src/LibHac/FsSrv/DefaultFsServerObjects.cs index d764f4f2..ddfbcbca 100644 --- a/src/LibHac/FsSrv/DefaultFsServerObjects.cs +++ b/src/LibHac/FsSrv/DefaultFsServerObjects.cs @@ -1,6 +1,7 @@ using LibHac.Common.Keys; using LibHac.Fs.Fsa; using LibHac.FsSrv.Creators; +using LibHac.FsSrv.Sf; namespace LibHac.FsSrv { diff --git a/src/LibHac/FsSrv/EmulatedDeviceOperator.cs b/src/LibHac/FsSrv/EmulatedDeviceOperator.cs index ed206964..1870e2eb 100644 --- a/src/LibHac/FsSrv/EmulatedDeviceOperator.cs +++ b/src/LibHac/FsSrv/EmulatedDeviceOperator.cs @@ -1,4 +1,5 @@ using LibHac.Fs; +using LibHac.FsSrv.Sf; namespace LibHac.FsSrv { diff --git a/src/LibHac/FsSrv/FileSystemProxyConfiguration.cs b/src/LibHac/FsSrv/FileSystemProxyConfiguration.cs index 73dac42c..d7de11da 100644 --- a/src/LibHac/FsSrv/FileSystemProxyConfiguration.cs +++ b/src/LibHac/FsSrv/FileSystemProxyConfiguration.cs @@ -5,6 +5,7 @@ namespace LibHac.FsSrv public class FileSystemProxyConfiguration { public FileSystemCreators FsCreatorInterfaces { get; set; } + public BaseStorageServiceImpl BaseStorageService { get; set; } public BaseFileSystemServiceImpl BaseFileSystemService { get; set; } public NcaFileSystemServiceImpl NcaFileSystemService { get; set; } public SaveDataFileSystemServiceImpl SaveDataFileSystemService { get; set; } diff --git a/src/LibHac/FsSrv/FileSystemProxyCoreImpl.cs b/src/LibHac/FsSrv/FileSystemProxyCoreImpl.cs index 45e632d5..ea962aa5 100644 --- a/src/LibHac/FsSrv/FileSystemProxyCoreImpl.cs +++ b/src/LibHac/FsSrv/FileSystemProxyCoreImpl.cs @@ -4,8 +4,6 @@ using LibHac.Fs; using LibHac.Fs.Fsa; using LibHac.Fs.Shim; using LibHac.FsSrv.Creators; -using LibHac.FsSrv.Impl; -using LibHac.FsSrv.Sf; namespace LibHac.FsSrv { @@ -15,67 +13,14 @@ namespace LibHac.FsSrv private FileSystemCreators FsCreators => Config.FsCreatorInterfaces; internal ProgramRegistryImpl ProgramRegistry { get; } - private ReferenceCountedDisposable DeviceOperator { get; } - private byte[] SdEncryptionSeed { get; } = new byte[0x10]; private const string NintendoDirectoryName = "Nintendo"; - private GlobalAccessLogMode LogMode { get; set; } - - internal ISaveDataIndexerManager SaveDataIndexerManager { get; private set; } - - public FileSystemProxyCoreImpl(FileSystemProxyConfiguration config, IDeviceOperator deviceOperator) + public FileSystemProxyCoreImpl(FileSystemProxyConfiguration config) { Config = config; ProgramRegistry = new ProgramRegistryImpl(Config.ProgramRegistryService); - DeviceOperator = new ReferenceCountedDisposable(deviceOperator); - } - - public Result OpenGameCardStorage(out ReferenceCountedDisposable storage, GameCardHandle handle, - GameCardPartitionRaw partitionId) - { - storage = default; - - Result rc; - IStorage gcStorage = null; - ReferenceCountedDisposable sharedGcStorage = null; - try - { - switch (partitionId) - { - case GameCardPartitionRaw.NormalReadOnly: - rc = FsCreators.GameCardStorageCreator.CreateNormal(handle, out gcStorage); - break; - case GameCardPartitionRaw.SecureReadOnly: - rc = FsCreators.GameCardStorageCreator.CreateSecure(handle, out gcStorage); - break; - case GameCardPartitionRaw.RootWriteOnly: - rc = FsCreators.GameCardStorageCreator.CreateWritable(handle, out gcStorage); - break; - default: - throw new ArgumentOutOfRangeException(nameof(partitionId), partitionId, null); - } - - if (rc.IsFailure()) return rc; - - sharedGcStorage = new ReferenceCountedDisposable(gcStorage); - gcStorage = null; - - storage = StorageInterfaceAdapter.CreateShared(ref sharedGcStorage); - return Result.Success; - } - finally - { - gcStorage?.Dispose(); - sharedGcStorage?.Dispose(); - } - } - - public Result OpenDeviceOperator(out ReferenceCountedDisposable deviceOperator) - { - deviceOperator = DeviceOperator.AddReference(); - return Result.Success; } public Result OpenCustomStorageFileSystem(out ReferenceCountedDisposable fileSystem, @@ -177,29 +122,7 @@ namespace LibHac.FsSrv public Result SetSdCardEncryptionSeed(in EncryptionSeed seed) { seed.Value.CopyTo(SdEncryptionSeed); - // todo: FsCreators.SaveDataFileSystemCreator.SetSdCardEncryptionSeed(seed); - - SaveDataIndexerManager.InvalidateIndexer(SaveDataSpaceId.SdSystem); - SaveDataIndexerManager.InvalidateIndexer(SaveDataSpaceId.SdCache); - return Result.Success; } - - public Result SetGlobalAccessLogMode(GlobalAccessLogMode mode) - { - LogMode = mode; - return Result.Success; - } - - public Result GetGlobalAccessLogMode(out GlobalAccessLogMode mode) - { - mode = LogMode; - return Result.Success; - } - - internal void SetSaveDataIndexerManager(ISaveDataIndexerManager manager) - { - SaveDataIndexerManager = manager; - } } } diff --git a/src/LibHac/FsSrv/FileSystemProxyImpl.cs b/src/LibHac/FsSrv/FileSystemProxyImpl.cs index 2dfe1b74..da486f2d 100644 --- a/src/LibHac/FsSrv/FileSystemProxyImpl.cs +++ b/src/LibHac/FsSrv/FileSystemProxyImpl.cs @@ -386,12 +386,12 @@ namespace LibHac.FsSrv public Result OpenBisStorage(out ReferenceCountedDisposable storage, BisPartitionId partitionId) { - throw new NotImplementedException(); + return GetBaseStorageService().OpenBisStorage(out storage, partitionId); } public Result InvalidateBisCache() { - throw new NotImplementedException(); + return GetBaseStorageService().InvalidateBisCache(); } public Result OpenHostFileSystem(out ReferenceCountedDisposable fileSystem, in FspPath path) @@ -457,26 +457,27 @@ namespace LibHac.FsSrv public Result OpenGameCardStorage(out ReferenceCountedDisposable storage, GameCardHandle handle, GameCardPartitionRaw partitionId) { - // Missing permission check and StorageInterfaceAdapter - - return FsProxyCore.OpenGameCardStorage(out storage, handle, partitionId); + return GetBaseStorageService().OpenGameCardStorage(out storage, handle, partitionId); } public Result OpenDeviceOperator(out ReferenceCountedDisposable deviceOperator) { - // Missing permission check - - return FsProxyCore.OpenDeviceOperator(out deviceOperator); + return GetBaseStorageService().OpenDeviceOperator(out deviceOperator); } public Result OpenSdCardDetectionEventNotifier(out ReferenceCountedDisposable eventNotifier) { - throw new NotImplementedException(); + return GetBaseStorageService().OpenSdCardDetectionEventNotifier(out eventNotifier); } public Result OpenGameCardDetectionEventNotifier(out ReferenceCountedDisposable eventNotifier) { - throw new NotImplementedException(); + return GetBaseStorageService().OpenGameCardDetectionEventNotifier(out eventNotifier); + } + + public Result SimulateDeviceDetectionEvent(SdmmcPort port, SimulatingDeviceDetectionMode mode, bool signalEvent) + { + return GetBaseStorageService().SimulateDeviceDetectionEvent(port, mode, signalEvent); } public Result OpenSystemDataUpdateEventNotifier(out ReferenceCountedDisposable eventNotifier) @@ -713,6 +714,9 @@ namespace LibHac.FsSrv ReferenceCountedDisposable customFs = null; try { + rc = FsProxyCore.OpenCustomStorageFileSystem(out customFs, storageId); + if (rc.IsFailure()) return rc; + customFs = StorageLayoutTypeSetFileSystem.CreateShared(ref customFs, storageFlag); customFs = AsynchronousAccessFileSystem.CreateShared(ref customFs); fileSystem = FileSystemInterfaceAdapter.CreateShared(ref customFs); @@ -971,11 +975,6 @@ namespace LibHac.FsSrv return FsProxyCore.ProgramRegistry.GetProgramInfo(out programInfo, CurrentProcess); } - private BaseFileSystemService GetBaseFileSystemService() - { - return new BaseFileSystemService(FsProxyCore.Config.BaseFileSystemService, CurrentProcess); - } - private Result GetNcaFileSystemService(out NcaFileSystemService ncaFsService) { if (NcaFsService is null) @@ -1000,6 +999,16 @@ namespace LibHac.FsSrv return Result.Success; } + private BaseStorageService GetBaseStorageService() + { + return new BaseStorageService(FsProxyCore.Config.BaseStorageService, CurrentProcess); + } + + private BaseFileSystemService GetBaseFileSystemService() + { + return new BaseFileSystemService(FsProxyCore.Config.BaseFileSystemService, CurrentProcess); + } + private TimeService GetTimeService() { return new TimeService(FsProxyCore.Config.TimeService, CurrentProcess); diff --git a/src/LibHac/FsSrv/FileSystemServer.cs b/src/LibHac/FsSrv/FileSystemServer.cs index 8bab0b16..3ac30b7d 100644 --- a/src/LibHac/FsSrv/FileSystemServer.cs +++ b/src/LibHac/FsSrv/FileSystemServer.cs @@ -4,6 +4,7 @@ using LibHac.Fs.Impl; using LibHac.Fs.Shim; using LibHac.FsSrv.Creators; using LibHac.FsSrv.Impl; +using LibHac.FsSrv.Sf; using LibHac.Sm; namespace LibHac.FsSrv @@ -44,10 +45,7 @@ namespace LibHac.FsSrv FileSystemProxyConfiguration fspConfig = InitializeFileSystemProxyConfiguration(config); - FsProxyCore = new FileSystemProxyCoreImpl(fspConfig, config.DeviceOperator); - - FsProxyCore.SetSaveDataIndexerManager(new SaveDataIndexerManager(Hos.Fs, SaveIndexerId, - new ArrayPoolMemoryResource(), new SdHandleManager(), false)); + FsProxyCore = new FileSystemProxyCoreImpl(fspConfig); FileSystemProxyImpl fsProxy = GetFileSystemProxyServiceObject(); ulong processId = Hos.Os.GetCurrentProcessId().Value; @@ -96,6 +94,13 @@ namespace LibHac.FsSrv var programRegistryService = new ProgramRegistryServiceImpl(this); var programRegistry = new ProgramRegistryImpl(programRegistryService); + var baseStorageConfig = new BaseStorageServiceImpl.Configuration(); + baseStorageConfig.BisStorageCreator = config.FsCreators.BuiltInStorageCreator; + baseStorageConfig.GameCardStorageCreator = config.FsCreators.GameCardStorageCreator; + baseStorageConfig.ProgramRegistry = programRegistry; + baseStorageConfig.DeviceOperator = new ReferenceCountedDisposable(config.DeviceOperator); + var baseStorageService = new BaseStorageServiceImpl(in baseStorageConfig); + var timeServiceConfig = new TimeServiceImpl.Configuration(); timeServiceConfig.HorizonClient = Hos; timeServiceConfig.ProgramRegistry = programRegistry; @@ -150,6 +155,7 @@ namespace LibHac.FsSrv var fspConfig = new FileSystemProxyConfiguration { FsCreatorInterfaces = config.FsCreators, + BaseStorageService = baseStorageService, BaseFileSystemService = baseFsService, NcaFileSystemService = ncaFsService, SaveDataFileSystemService = saveFsService, diff --git a/src/LibHac/FsSrv/IFileSystemProxy.cs b/src/LibHac/FsSrv/IFileSystemProxy.cs index 935eb73d..1d6eb2ca 100644 --- a/src/LibHac/FsSrv/IFileSystemProxy.cs +++ b/src/LibHac/FsSrv/IFileSystemProxy.cs @@ -1,9 +1,5 @@ -using System; -using LibHac.Common; -using LibHac.Fs; -using LibHac.Fs.Fsa; +using LibHac.Fs; using LibHac.FsSrv.Sf; -using LibHac.FsSystem; using LibHac.Ncm; using LibHac.Sf; using LibHac.Spl; @@ -75,6 +71,7 @@ namespace LibHac.FsSrv Result OpenGameCardDetectionEventNotifier(out ReferenceCountedDisposable eventNotifier); Result OpenSystemDataUpdateEventNotifier(out ReferenceCountedDisposable eventNotifier); Result NotifySystemDataUpdateEvent(); + Result SimulateDeviceDetectionEvent(SdmmcPort port, SimulatingDeviceDetectionMode mode, bool signalEvent); Result QuerySaveDataTotalSize(out long totalSize, long dataSize, long journalSize); Result VerifySaveDataFileSystem(ulong saveDataId, OutBuffer readBuffer); diff --git a/src/LibHac/FsSrv/IDeviceOperator.cs b/src/LibHac/FsSrv/Sf/IDeviceOperator.cs similarity index 90% rename from src/LibHac/FsSrv/IDeviceOperator.cs rename to src/LibHac/FsSrv/Sf/IDeviceOperator.cs index 0b605385..f8185a1c 100644 --- a/src/LibHac/FsSrv/IDeviceOperator.cs +++ b/src/LibHac/FsSrv/Sf/IDeviceOperator.cs @@ -1,6 +1,6 @@ using System; -namespace LibHac.FsSrv +namespace LibHac.FsSrv.Sf { public interface IDeviceOperator : IDisposable { diff --git a/src/LibHac/FsSystem/StorageLayoutTypeSetFileSystem.cs b/src/LibHac/FsSystem/StorageLayoutTypeSetFileSystem.cs index 89b1b747..fb089897 100644 --- a/src/LibHac/FsSystem/StorageLayoutTypeSetFileSystem.cs +++ b/src/LibHac/FsSystem/StorageLayoutTypeSetFileSystem.cs @@ -42,6 +42,7 @@ namespace LibHac.FsSystem { if (disposing) { + using var scopedLayoutType = new ScopedStorageLayoutTypeSetter(StorageFlag); BaseFileSystem?.Dispose(); } diff --git a/src/LibHac/FsSystem/StorageLayoutTypeSetStorage.cs b/src/LibHac/FsSystem/StorageLayoutTypeSetStorage.cs new file mode 100644 index 00000000..8d82a4dc --- /dev/null +++ b/src/LibHac/FsSystem/StorageLayoutTypeSetStorage.cs @@ -0,0 +1,67 @@ +using System; +using LibHac.Common; +using LibHac.Fs; + +namespace LibHac.FsSystem +{ + internal class StorageLayoutTypeSetStorage : IStorage + { + private ReferenceCountedDisposable BaseStorage { get; } + private StorageType StorageFlag { get; } + + protected StorageLayoutTypeSetStorage(ref ReferenceCountedDisposable baseStorage, + StorageType storageFlag) + { + BaseStorage = Shared.Move(ref baseStorage); + StorageFlag = storageFlag; + } + + public static ReferenceCountedDisposable CreateShared( + ref ReferenceCountedDisposable baseStorage, StorageType storageFlag) + { + return new ReferenceCountedDisposable( + new StorageLayoutTypeSetStorage(ref baseStorage, storageFlag)); + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + using var scopedLayoutType = new ScopedStorageLayoutTypeSetter(StorageFlag); + BaseStorage?.Dispose(); + } + + base.Dispose(disposing); + } + + protected override Result DoRead(long offset, Span destination) + { + using var scopedLayoutType = new ScopedStorageLayoutTypeSetter(StorageFlag); + return BaseStorage.Target.Read(offset, destination); + } + + protected override Result DoWrite(long offset, ReadOnlySpan source) + { + using var scopedLayoutType = new ScopedStorageLayoutTypeSetter(StorageFlag); + return BaseStorage.Target.Write(offset, source); + } + + protected override Result DoFlush() + { + using var scopedLayoutType = new ScopedStorageLayoutTypeSetter(StorageFlag); + return BaseStorage.Target.Flush(); + } + + protected override Result DoSetSize(long size) + { + using var scopedLayoutType = new ScopedStorageLayoutTypeSetter(StorageFlag); + return BaseStorage.Target.SetSize(size); + } + + protected override Result DoGetSize(out long size) + { + using var scopedLayoutType = new ScopedStorageLayoutTypeSetter(StorageFlag); + return BaseStorage.Target.GetSize(out size); + } + } +}