Move initialization code out of FileSystemServer

This commit is contained in:
Alex Barney 2021-02-07 00:26:20 -07:00
parent a94bb81c54
commit e50078d939
8 changed files with 303 additions and 261 deletions

View file

@ -0,0 +1,7 @@
namespace LibHac.Fs
{
public static class SaveData
{
public const ulong SaveIndexerId = 0x8000000000000000;
}
}

View file

@ -1,24 +1,12 @@
using System; using LibHac.FsSrv.Impl;
using LibHac.Fs.Impl;
using LibHac.Fs.Shim;
using LibHac.FsSrv.Creators;
using LibHac.FsSrv.Impl;
using LibHac.FsSrv.Sf;
using LibHac.FsSrv.Storage; using LibHac.FsSrv.Storage;
using LibHac.Sm;
namespace LibHac.FsSrv namespace LibHac.FsSrv
{ {
public class FileSystemServer public class FileSystemServer
{ {
internal const ulong SaveIndexerId = 0x8000000000000000;
private const ulong SpeedEmulationProgramIdMinimum = 0x100000000000000;
private const ulong SpeedEmulationProgramIdMaximum = 0x100000000001FFF;
internal FileSystemServerGlobals Globals; internal FileSystemServerGlobals Globals;
private HorizonClient Hos => Globals.Hos;
public FileSystemServerImpl Impl => new FileSystemServerImpl(this); public FileSystemServerImpl Impl => new FileSystemServerImpl(this);
public StorageService Storage => new StorageService(this); public StorageService Storage => new StorageService(this);
@ -26,236 +14,11 @@ namespace LibHac.FsSrv
/// Creates a new <see cref="FileSystemServer"/> and registers its services using the provided HOS client. /// Creates a new <see cref="FileSystemServer"/> and registers its services using the provided HOS client.
/// </summary> /// </summary>
/// <param name="horizonClient">The <see cref="HorizonClient"/> that will be used by this server.</param> /// <param name="horizonClient">The <see cref="HorizonClient"/> that will be used by this server.</param>
/// <param name="config">The configuration for the created <see cref="FileSystemServer"/>.</param> public FileSystemServer(HorizonClient horizonClient)
public FileSystemServer(HorizonClient horizonClient, FileSystemServerConfig config)
{ {
if (config.FsCreators == null)
throw new ArgumentException("FsCreators must not be null");
if (config.DeviceOperator == null)
throw new ArgumentException("DeviceOperator must not be null");
Globals.Hos = horizonClient; Globals.Hos = horizonClient;
Globals.InitMutex = new object(); Globals.InitMutex = new object();
FileSystemProxyConfiguration fspConfig = InitializeFileSystemProxyConfiguration(config);
this.InitializeFileSystemProxy(fspConfig);
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = Impl.GetFileSystemProxyServiceObject();
ulong processId = Hos.Os.GetCurrentProcessId().Value;
fsProxy.Target.SetCurrentProcess(processId).IgnoreResult();
Hos.Fs.InitializeDfcFileSystemProxyServiceObject(fsProxy);
var saveService = new SaveDataFileSystemService(fspConfig.SaveDataFileSystemService, processId);
saveService.CleanUpTemporaryStorage().IgnoreResult();
saveService.CleanUpSaveData().IgnoreResult();
saveService.CompleteSaveDataExtension().IgnoreResult();
saveService.FixSaveData().IgnoreResult();
saveService.RecoverMultiCommit().IgnoreResult();
Hos.Sm.RegisterService(new FileSystemProxyService(this), "fsp-srv").IgnoreResult();
Hos.Sm.RegisterService(new FileSystemProxyForLoaderService(this), "fsp-ldr").IgnoreResult();
Hos.Sm.RegisterService(new ProgramRegistryService(this), "fsp-pr").IgnoreResult();
// NS usually takes care of this
if (Hos.Fs.IsSdCardInserted())
Hos.Fs.SetSdCardAccessibility(true);
} }
private FileSystemProxyConfiguration InitializeFileSystemProxyConfiguration(FileSystemServerConfig config)
{
var saveDataIndexerManager = new SaveDataIndexerManager(Hos.Fs, SaveIndexerId,
new ArrayPoolMemoryResource(), new SdHandleManager(), false);
var programRegistryService = new ProgramRegistryServiceImpl(this);
this.InitializeProgramRegistryImpl(programRegistryService);
var baseStorageConfig = new BaseStorageServiceImpl.Configuration();
baseStorageConfig.BisStorageCreator = config.FsCreators.BuiltInStorageCreator;
baseStorageConfig.GameCardStorageCreator = config.FsCreators.GameCardStorageCreator;
baseStorageConfig.FsServer = this;
baseStorageConfig.DeviceOperator = new ReferenceCountedDisposable<IDeviceOperator>(config.DeviceOperator);
var baseStorageService = new BaseStorageServiceImpl(in baseStorageConfig);
var timeService = new TimeServiceImpl(this);
var baseFsServiceConfig = new BaseFileSystemServiceImpl.Configuration();
baseFsServiceConfig.BisFileSystemCreator = config.FsCreators.BuiltInStorageFileSystemCreator;
baseFsServiceConfig.GameCardFileSystemCreator = config.FsCreators.GameCardFileSystemCreator;
baseFsServiceConfig.SdCardFileSystemCreator = config.FsCreators.SdCardFileSystemCreator;
baseFsServiceConfig.BisWiperCreator = BisWiper.CreateWiper;
baseFsServiceConfig.FsServer = this;
var baseFsService = new BaseFileSystemServiceImpl(in baseFsServiceConfig);
var accessFailureManagementServiceConfig = new AccessFailureManagementServiceImpl.Configuration();
accessFailureManagementServiceConfig.FsServer = this;
var accessFailureManagementService =
new AccessFailureManagementServiceImpl(in accessFailureManagementServiceConfig);
var speedEmulationRange =
new InternalProgramIdRangeForSpeedEmulation(SpeedEmulationProgramIdMinimum,
SpeedEmulationProgramIdMaximum);
var ncaFsServiceConfig = new NcaFileSystemServiceImpl.Configuration();
ncaFsServiceConfig.BaseFsService = baseFsService;
ncaFsServiceConfig.HostFsCreator = config.FsCreators.HostFileSystemCreator;
ncaFsServiceConfig.TargetManagerFsCreator = config.FsCreators.TargetManagerFileSystemCreator;
ncaFsServiceConfig.PartitionFsCreator = config.FsCreators.PartitionFileSystemCreator;
ncaFsServiceConfig.RomFsCreator = config.FsCreators.RomFileSystemCreator;
ncaFsServiceConfig.StorageOnNcaCreator = config.FsCreators.StorageOnNcaCreator;
ncaFsServiceConfig.SubDirectoryFsCreator = config.FsCreators.SubDirectoryFileSystemCreator;
ncaFsServiceConfig.EncryptedFsCreator = config.FsCreators.EncryptedFileSystemCreator;
ncaFsServiceConfig.ProgramRegistryService = programRegistryService;
ncaFsServiceConfig.AccessFailureManagementService = accessFailureManagementService;
ncaFsServiceConfig.SpeedEmulationRange = speedEmulationRange;
ncaFsServiceConfig.FsServer = this;
var ncaFsService = new NcaFileSystemServiceImpl(in ncaFsServiceConfig, config.ExternalKeySet);
var saveFsServiceConfig = new SaveDataFileSystemServiceImpl.Configuration();
saveFsServiceConfig.BaseFsService = baseFsService;
saveFsServiceConfig.HostFsCreator = config.FsCreators.HostFileSystemCreator;
saveFsServiceConfig.TargetManagerFsCreator = config.FsCreators.TargetManagerFileSystemCreator;
saveFsServiceConfig.SaveFsCreator = config.FsCreators.SaveDataFileSystemCreator;
saveFsServiceConfig.EncryptedFsCreator = config.FsCreators.EncryptedFileSystemCreator;
saveFsServiceConfig.ProgramRegistryService = programRegistryService;
saveFsServiceConfig.ShouldCreateDirectorySaveData = () => true;
saveFsServiceConfig.SaveIndexerManager = saveDataIndexerManager;
saveFsServiceConfig.FsServer = this;
var saveFsService = new SaveDataFileSystemServiceImpl(in saveFsServiceConfig);
var statusReportServiceConfig = new StatusReportServiceImpl.Configuration();
statusReportServiceConfig.NcaFsServiceImpl = ncaFsService;
statusReportServiceConfig.SaveFsServiceImpl = saveFsService;
statusReportServiceConfig.BufferManagerMemoryReport = null;
statusReportServiceConfig.ExpHeapMemoryReport = null;
statusReportServiceConfig.BufferPoolMemoryReport = null;
statusReportServiceConfig.GetPatrolAllocateCounts = null;
statusReportServiceConfig.MainThreadStackUsageReporter = new DummyStackUsageReporter();
statusReportServiceConfig.IpcWorkerThreadStackUsageReporter = new DummyStackUsageReporter();
statusReportServiceConfig.PipeLineWorkerThreadStackUsageReporter = new DummyStackUsageReporter();
statusReportServiceConfig.FsServer = this;
var statusReportService = new StatusReportServiceImpl(in statusReportServiceConfig);
var accessLogServiceConfig = new AccessLogServiceImpl.Configuration();
accessLogServiceConfig.MinimumProgramIdForSdCardLog = 0x0100000000003000;
accessLogServiceConfig.FsServer = this;
var accessLogService = new AccessLogServiceImpl(in accessLogServiceConfig);
var fspConfig = new FileSystemProxyConfiguration
{
FsCreatorInterfaces = config.FsCreators,
BaseStorageService = baseStorageService,
BaseFileSystemService = baseFsService,
NcaFileSystemService = ncaFsService,
SaveDataFileSystemService = saveFsService,
AccessFailureManagementService = accessFailureManagementService,
TimeService = timeService,
StatusReportService = statusReportService,
ProgramRegistryService = programRegistryService,
AccessLogService = accessLogService
};
return fspConfig;
}
private class FileSystemProxyService : IServiceObject
{
private readonly FileSystemServer _server;
public FileSystemProxyService(FileSystemServer server)
{
_server = server;
}
public Result GetServiceObject(out object serviceObject)
{
serviceObject = _server.Impl.GetFileSystemProxyServiceObject();
return Result.Success;
}
}
private class FileSystemProxyForLoaderService : IServiceObject
{
private readonly FileSystemServer _server;
public FileSystemProxyForLoaderService(FileSystemServer server)
{
_server = server;
}
public Result GetServiceObject(out object serviceObject)
{
serviceObject = _server.Impl.GetFileSystemProxyForLoaderServiceObject();
return Result.Success;
}
}
private class ProgramRegistryService : IServiceObject
{
private readonly FileSystemServer _server;
public ProgramRegistryService(FileSystemServer server)
{
_server = server;
}
public Result GetServiceObject(out object serviceObject)
{
serviceObject = _server.Impl.GetProgramRegistryServiceObject();
return Result.Success;
}
}
private class DummyStackUsageReporter : IStackUsageReporter
{
public uint GetStackUsage() => 0;
}
}
/// <summary>
/// Contains the configuration for creating a new <see cref="FileSystemServer"/>.
/// </summary>
public class FileSystemServerConfig
{
/// <summary>
/// The <see cref="FileSystemCreatorInterfaces"/> used for creating filesystems.
/// </summary>
public FileSystemCreatorInterfaces FsCreators { get; set; }
/// <summary>
/// An <see cref="IDeviceOperator"/> for managing the gamecard and SD card.
/// </summary>
public IDeviceOperator DeviceOperator { get; set; }
/// <summary>
/// A keyset containing rights IDs and title keys.
/// If null, an empty set will be created.
/// </summary>
public ExternalKeySet ExternalKeySet { get; set; }
}
public readonly struct StorageService
{
internal readonly FileSystemServer FsSrv;
internal StorageService(FileSystemServer parentServer) => FsSrv = parentServer;
}
// Functions in the nn::fssrv::detail namespace use this struct.
// Possibly move this to the main class if the separation doesn't seem necessary.
public readonly struct FileSystemServerImpl
{
internal readonly FileSystemServer FsSrv;
public FileSystemServerImpl(FileSystemServer parentServer) => FsSrv = parentServer;
} }
internal struct FileSystemServerGlobals internal struct FileSystemServerGlobals
@ -268,4 +31,20 @@ namespace LibHac.FsSrv
public AccessControlGlobals AccessControl; public AccessControlGlobals AccessControl;
public StorageDeviceManagerFactoryGlobals StorageDeviceManagerFactory; public StorageDeviceManagerFactoryGlobals StorageDeviceManagerFactory;
} }
// Functions in the nn::fssrv::storage namespace use this struct.
public readonly struct StorageService
{
internal readonly FileSystemServer FsSrv;
internal StorageService(FileSystemServer parentServer) => FsSrv = parentServer;
}
// Functions in the nn::fssrv::detail namespace use this struct.
public readonly struct FileSystemServerImpl
{
internal readonly FileSystemServer FsSrv;
public FileSystemServerImpl(FileSystemServer parentServer) => FsSrv = parentServer;
}
} }

View file

@ -0,0 +1,243 @@
using System;
using LibHac.Fs.Impl;
using LibHac.Fs.Shim;
using LibHac.FsSrv.Creators;
using LibHac.FsSrv.Impl;
using LibHac.FsSrv.Sf;
using LibHac.FsSrv.Storage;
using LibHac.Sm;
namespace LibHac.FsSrv
{
public static class FileSystemServerInitializer
{
private const ulong SpeedEmulationProgramIdMinimum = 0x100000000000000;
private const ulong SpeedEmulationProgramIdMaximum = 0x100000000001FFF;
/// <summary>
/// Initializes a <see cref="FileSystemServer"/> with the provided <see cref="FileSystemServerConfig"/>.
/// </summary>
/// <param name="client">The <see cref="HorizonClient"/> that <paramref name="server"/> was created with.</param>
/// <param name="server">The <see cref="FileSystemServer"/> to initialize.</param>
/// <param name="config">The config for initializing <paramref name="server"/>.</param>
public static void InitializeWithConfig(HorizonClient client, FileSystemServer server, FileSystemServerConfig config)
{
if (config.FsCreators == null)
throw new ArgumentException("FsCreators must not be null");
if (config.DeviceOperator == null)
throw new ArgumentException("DeviceOperator must not be null");
server.SetDebugFlagEnabled(false);
server.Storage.InitializeStorageDeviceManagerFactory(null);
FileSystemProxyConfiguration fspConfig = InitializeFileSystemProxy(server, config);
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = server.Impl.GetFileSystemProxyServiceObject();
ulong processId = client.Os.GetCurrentProcessId().Value;
fsProxy.Target.SetCurrentProcess(processId).IgnoreResult();
client.Fs.InitializeDfcFileSystemProxyServiceObject(fsProxy);
InitializeFileSystemProxyServer(client, server);
var saveService = new SaveDataFileSystemService(fspConfig.SaveDataFileSystemService, processId);
saveService.CleanUpTemporaryStorage().IgnoreResult();
saveService.CleanUpSaveData().IgnoreResult();
saveService.CompleteSaveDataExtension().IgnoreResult();
saveService.FixSaveData().IgnoreResult();
saveService.RecoverMultiCommit().IgnoreResult();
// NS usually takes care of this
if (client.Fs.IsSdCardInserted())
client.Fs.SetSdCardAccessibility(true);
}
private static FileSystemProxyConfiguration InitializeFileSystemProxy(FileSystemServer server,
FileSystemServerConfig config)
{
var saveDataIndexerManager = new SaveDataIndexerManager(server.Globals.Hos.Fs, Fs.SaveData.SaveIndexerId,
new ArrayPoolMemoryResource(), new SdHandleManager(), false);
var programRegistryService = new ProgramRegistryServiceImpl(server);
server.InitializeProgramRegistryImpl(programRegistryService);
var baseStorageConfig = new BaseStorageServiceImpl.Configuration();
baseStorageConfig.BisStorageCreator = config.FsCreators.BuiltInStorageCreator;
baseStorageConfig.GameCardStorageCreator = config.FsCreators.GameCardStorageCreator;
baseStorageConfig.FsServer = server;
baseStorageConfig.DeviceOperator = new ReferenceCountedDisposable<IDeviceOperator>(config.DeviceOperator);
var baseStorageService = new BaseStorageServiceImpl(in baseStorageConfig);
var timeService = new TimeServiceImpl(server);
var baseFsServiceConfig = new BaseFileSystemServiceImpl.Configuration();
baseFsServiceConfig.BisFileSystemCreator = config.FsCreators.BuiltInStorageFileSystemCreator;
baseFsServiceConfig.GameCardFileSystemCreator = config.FsCreators.GameCardFileSystemCreator;
baseFsServiceConfig.SdCardFileSystemCreator = config.FsCreators.SdCardFileSystemCreator;
baseFsServiceConfig.BisWiperCreator = BisWiper.CreateWiper;
baseFsServiceConfig.FsServer = server;
var baseFsService = new BaseFileSystemServiceImpl(in baseFsServiceConfig);
var accessFailureManagementServiceConfig = new AccessFailureManagementServiceImpl.Configuration();
accessFailureManagementServiceConfig.FsServer = server;
var accessFailureManagementService =
new AccessFailureManagementServiceImpl(in accessFailureManagementServiceConfig);
var speedEmulationRange =
new InternalProgramIdRangeForSpeedEmulation(SpeedEmulationProgramIdMinimum,
SpeedEmulationProgramIdMaximum);
var ncaFsServiceConfig = new NcaFileSystemServiceImpl.Configuration();
ncaFsServiceConfig.BaseFsService = baseFsService;
ncaFsServiceConfig.HostFsCreator = config.FsCreators.HostFileSystemCreator;
ncaFsServiceConfig.TargetManagerFsCreator = config.FsCreators.TargetManagerFileSystemCreator;
ncaFsServiceConfig.PartitionFsCreator = config.FsCreators.PartitionFileSystemCreator;
ncaFsServiceConfig.RomFsCreator = config.FsCreators.RomFileSystemCreator;
ncaFsServiceConfig.StorageOnNcaCreator = config.FsCreators.StorageOnNcaCreator;
ncaFsServiceConfig.SubDirectoryFsCreator = config.FsCreators.SubDirectoryFileSystemCreator;
ncaFsServiceConfig.EncryptedFsCreator = config.FsCreators.EncryptedFileSystemCreator;
ncaFsServiceConfig.ProgramRegistryService = programRegistryService;
ncaFsServiceConfig.AccessFailureManagementService = accessFailureManagementService;
ncaFsServiceConfig.SpeedEmulationRange = speedEmulationRange;
ncaFsServiceConfig.FsServer = server;
var ncaFsService = new NcaFileSystemServiceImpl(in ncaFsServiceConfig, config.ExternalKeySet);
var saveFsServiceConfig = new SaveDataFileSystemServiceImpl.Configuration();
saveFsServiceConfig.BaseFsService = baseFsService;
saveFsServiceConfig.HostFsCreator = config.FsCreators.HostFileSystemCreator;
saveFsServiceConfig.TargetManagerFsCreator = config.FsCreators.TargetManagerFileSystemCreator;
saveFsServiceConfig.SaveFsCreator = config.FsCreators.SaveDataFileSystemCreator;
saveFsServiceConfig.EncryptedFsCreator = config.FsCreators.EncryptedFileSystemCreator;
saveFsServiceConfig.ProgramRegistryService = programRegistryService;
saveFsServiceConfig.ShouldCreateDirectorySaveData = () => true;
saveFsServiceConfig.SaveIndexerManager = saveDataIndexerManager;
saveFsServiceConfig.FsServer = server;
var saveFsService = new SaveDataFileSystemServiceImpl(in saveFsServiceConfig);
var statusReportServiceConfig = new StatusReportServiceImpl.Configuration();
statusReportServiceConfig.NcaFsServiceImpl = ncaFsService;
statusReportServiceConfig.SaveFsServiceImpl = saveFsService;
statusReportServiceConfig.BufferManagerMemoryReport = null;
statusReportServiceConfig.ExpHeapMemoryReport = null;
statusReportServiceConfig.BufferPoolMemoryReport = null;
statusReportServiceConfig.GetPatrolAllocateCounts = null;
statusReportServiceConfig.MainThreadStackUsageReporter = new DummyStackUsageReporter();
statusReportServiceConfig.IpcWorkerThreadStackUsageReporter = new DummyStackUsageReporter();
statusReportServiceConfig.PipeLineWorkerThreadStackUsageReporter = new DummyStackUsageReporter();
statusReportServiceConfig.FsServer = server;
var statusReportService = new StatusReportServiceImpl(in statusReportServiceConfig);
var accessLogServiceConfig = new AccessLogServiceImpl.Configuration();
accessLogServiceConfig.MinimumProgramIdForSdCardLog = 0x0100000000003000;
accessLogServiceConfig.FsServer = server;
var accessLogService = new AccessLogServiceImpl(in accessLogServiceConfig);
var fspConfig = new FileSystemProxyConfiguration
{
FsCreatorInterfaces = config.FsCreators,
BaseStorageService = baseStorageService,
BaseFileSystemService = baseFsService,
NcaFileSystemService = ncaFsService,
SaveDataFileSystemService = saveFsService,
AccessFailureManagementService = accessFailureManagementService,
TimeService = timeService,
StatusReportService = statusReportService,
ProgramRegistryService = programRegistryService,
AccessLogService = accessLogService
};
server.InitializeFileSystemProxy(fspConfig);
return fspConfig;
}
private static void InitializeFileSystemProxyServer(HorizonClient client, FileSystemServer server)
{
client.Sm.RegisterService(new FileSystemProxyService(server), "fsp-srv").IgnoreResult();
client.Sm.RegisterService(new FileSystemProxyForLoaderService(server), "fsp-ldr").IgnoreResult();
client.Sm.RegisterService(new ProgramRegistryService(server), "fsp-pr").IgnoreResult();
}
private class FileSystemProxyService : IServiceObject
{
private readonly FileSystemServer _server;
public FileSystemProxyService(FileSystemServer server)
{
_server = server;
}
public Result GetServiceObject(out object serviceObject)
{
serviceObject = _server.Impl.GetFileSystemProxyServiceObject();
return Result.Success;
}
}
private class FileSystemProxyForLoaderService : IServiceObject
{
private readonly FileSystemServer _server;
public FileSystemProxyForLoaderService(FileSystemServer server)
{
_server = server;
}
public Result GetServiceObject(out object serviceObject)
{
serviceObject = _server.Impl.GetFileSystemProxyForLoaderServiceObject();
return Result.Success;
}
}
private class ProgramRegistryService : IServiceObject
{
private readonly FileSystemServer _server;
public ProgramRegistryService(FileSystemServer server)
{
_server = server;
}
public Result GetServiceObject(out object serviceObject)
{
serviceObject = _server.Impl.GetProgramRegistryServiceObject();
return Result.Success;
}
}
private class DummyStackUsageReporter : IStackUsageReporter
{
public uint GetStackUsage() => 0;
}
}
/// <summary>
/// Contains the configuration for creating a new <see cref="FileSystemServer"/>.
/// </summary>
public class FileSystemServerConfig
{
/// <summary>
/// The <see cref="FileSystemCreatorInterfaces"/> used for creating filesystems.
/// </summary>
public FileSystemCreatorInterfaces FsCreators { get; set; }
/// <summary>
/// An <see cref="IDeviceOperator"/> for managing the gamecard and SD card.
/// </summary>
public IDeviceOperator DeviceOperator { get; set; }
/// <summary>
/// A keyset containing rights IDs and title keys.
/// If null, an empty set will be created.
/// </summary>
public ExternalKeySet ExternalKeySet { get; set; }
}
}

View file

@ -403,7 +403,7 @@ namespace LibHac.FsSrv
private Result DeleteSaveDataFileSystemBySaveDataSpaceIdCore(SaveDataSpaceId spaceId, ulong saveDataId) private Result DeleteSaveDataFileSystemBySaveDataSpaceIdCore(SaveDataSpaceId spaceId, ulong saveDataId)
{ {
if (saveDataId != FileSystemServer.SaveIndexerId) if (saveDataId != SaveData.SaveIndexerId)
{ {
SaveDataIndexerAccessor accessor = null; SaveDataIndexerAccessor accessor = null;
try try
@ -449,7 +449,7 @@ namespace LibHac.FsSrv
SaveDataSpaceId actualSpaceId; SaveDataSpaceId actualSpaceId;
// Only the FS process may delete the save indexer's save data. // Only the FS process may delete the save indexer's save data.
if (saveDataId == FileSystemServer.SaveIndexerId) if (saveDataId == SaveData.SaveIndexerId)
{ {
if (!IsCurrentProcess(ProcessId)) if (!IsCurrentProcess(ProcessId))
return ResultFs.PermissionDenied.Log(); return ResultFs.PermissionDenied.Log();
@ -499,7 +499,7 @@ namespace LibHac.FsSrv
// Remove the save data from the indexer. // Remove the save data from the indexer.
// The indexer doesn't track itself, so skip if deleting its save data. // The indexer doesn't track itself, so skip if deleting its save data.
if (saveDataId != FileSystemServer.SaveIndexerId) if (saveDataId != SaveData.SaveIndexerId)
{ {
// accessor will never be null at this point // accessor will never be null at this point
rc = accessor!.Indexer.Delete(saveDataId); rc = accessor!.Indexer.Delete(saveDataId);
@ -590,7 +590,7 @@ namespace LibHac.FsSrv
// ReSharper disable once UnusedParameter.Global // ReSharper disable once UnusedParameter.Global
public Result UpdateSaveDataMacForDebug(SaveDataSpaceId spaceId, ulong saveDataId) public Result UpdateSaveDataMacForDebug(SaveDataSpaceId spaceId, ulong saveDataId)
{ {
if (saveDataId == FileSystemServer.SaveIndexerId) if (saveDataId == SaveData.SaveIndexerId)
return ResultFs.InvalidArgument.Log(); return ResultFs.InvalidArgument.Log();
return ResultFs.NotImplemented.Log(); return ResultFs.NotImplemented.Log();
@ -630,10 +630,10 @@ namespace LibHac.FsSrv
try try
{ {
// Add the new save data to the save indexer // Add the new save data to the save indexer
if (attribute.StaticSaveDataId == FileSystemServer.SaveIndexerId) if (attribute.StaticSaveDataId == SaveData.SaveIndexerId)
{ {
// The save indexer doesn't index itself // The save indexer doesn't index itself
saveDataId = FileSystemServer.SaveIndexerId; saveDataId = SaveData.SaveIndexerId;
rc = ServiceImpl.DoesSaveDataEntityExist(out bool saveExists, creationInfo.SpaceId, saveDataId); rc = ServiceImpl.DoesSaveDataEntityExist(out bool saveExists, creationInfo.SpaceId, saveDataId);
if (rc.IsSuccess() && saveExists) if (rc.IsSuccess() && saveExists)
@ -755,7 +755,7 @@ namespace LibHac.FsSrv
} }
// The indexer's save data isn't tracked, so we don't need to update its state. // The indexer's save data isn't tracked, so we don't need to update its state.
if (attribute.StaticSaveDataId != FileSystemServer.SaveIndexerId) if (attribute.StaticSaveDataId != SaveData.SaveIndexerId)
{ {
// accessor shouldn't ever be null, but checking makes the analyzers happy // accessor shouldn't ever be null, but checking makes the analyzers happy
Abort.DoAbortUnless(accessor != null); Abort.DoAbortUnless(accessor != null);
@ -778,7 +778,7 @@ namespace LibHac.FsSrv
{ {
DeleteSaveDataFileSystemCore(creationInfo.SpaceId, saveDataId, false).IgnoreResult(); DeleteSaveDataFileSystemCore(creationInfo.SpaceId, saveDataId, false).IgnoreResult();
if (accessor != null && saveDataId != FileSystemServer.SaveIndexerId) if (accessor != null && saveDataId != SaveData.SaveIndexerId)
{ {
rc = accessor.Indexer.GetValue(out SaveDataIndexerValue value, saveDataId); rc = accessor.Indexer.GetValue(out SaveDataIndexerValue value, saveDataId);
@ -994,7 +994,7 @@ namespace LibHac.FsSrv
Result RemoveSaveIndexerEntry() Result RemoveSaveIndexerEntry()
{ {
if (tempSaveDataId == FileSystemServer.SaveIndexerId) if (tempSaveDataId == SaveData.SaveIndexerId)
return Result.Success; return Result.Success;
if (isStaticSaveDataId) if (isStaticSaveDataId)

View file

@ -1,10 +1,8 @@
using System.Diagnostics; using System.Diagnostics;
using System.Threading; using System.Threading;
using LibHac.Bcat;
using LibHac.Common; using LibHac.Common;
using LibHac.Diag; using LibHac.Diag;
using LibHac.Fs.Shim; using LibHac.Fs.Shim;
using LibHac.FsSrv;
using LibHac.FsSrv.Impl; using LibHac.FsSrv.Impl;
using LibHac.Ncm; using LibHac.Ncm;
using LibHac.Os; using LibHac.Os;
@ -20,14 +18,11 @@ namespace LibHac
internal ServiceManager ServiceManager { get; } internal ServiceManager ServiceManager { get; }
private HorizonClient LoaderClient { get; } private HorizonClient LoaderClient { get; }
// long instead of ulong because the ulong Interlocked.Increment overload
// wasn't added until .NET 5
private ulong _currentInitialProcessId; private ulong _currentInitialProcessId;
private ulong _currentProcessId; private ulong _currentProcessId;
// Todo: Initialize with a configuration object // Todo: Initialize with a configuration object
public Horizon(ITimeSpanGenerator timer, FileSystemServerConfig fsServerConfig) public Horizon(ITimeSpanGenerator timer)
{ {
_currentProcessId = InitialProcessCountMax; _currentProcessId = InitialProcessCountMax;
@ -35,11 +30,6 @@ namespace LibHac
StartTick = Stopwatch.GetTimestamp(); StartTick = Stopwatch.GetTimestamp();
ServiceManager = new ServiceManager(); ServiceManager = new ServiceManager();
// ReSharper disable ObjectCreationAsStatement
new FileSystemServer(CreatePrivilegedHorizonClient(), fsServerConfig);
new BcatServer(CreateHorizonClient());
// ReSharper restore ObjectCreationAsStatement
LoaderClient = CreatePrivilegedHorizonClient(); LoaderClient = CreatePrivilegedHorizonClient();
} }

View file

@ -0,0 +1,23 @@
using LibHac.Bcat;
using LibHac.FsSrv;
namespace LibHac
{
public static class HorizonFactory
{
public static Horizon CreateWithFsConfig(ITimeSpanGenerator timer, FileSystemServerConfig fsServerConfig)
{
var horizon = new Horizon(timer);
HorizonClient fsServerClient = horizon.CreatePrivilegedHorizonClient();
var fsServer = new FileSystemServer(fsServerClient);
FileSystemServerInitializer.InitializeWithConfig(fsServerClient, fsServer, fsServerConfig);
HorizonClient bcatServerClient = horizon.CreateHorizonClient();
_ = new BcatServer(bcatServerClient);
return horizon;
}
}
}

View file

@ -20,7 +20,7 @@ namespace LibHac.Tests.Fs.FileSystemClientTests
config.DeviceOperator = defaultObjects.DeviceOperator; config.DeviceOperator = defaultObjects.DeviceOperator;
config.ExternalKeySet = new ExternalKeySet(); config.ExternalKeySet = new ExternalKeySet();
var horizon = new Horizon(new StopWatchTimeSpanGenerator(), config); Horizon horizon = LibHac.HorizonFactory.CreateWithFsConfig(new StopWatchTimeSpanGenerator(), config);
HorizonClient horizonClient = horizon.CreatePrivilegedHorizonClient(); HorizonClient horizonClient = horizon.CreatePrivilegedHorizonClient();

View file

@ -18,7 +18,7 @@ namespace LibHac.Tests
config.DeviceOperator = defaultObjects.DeviceOperator; config.DeviceOperator = defaultObjects.DeviceOperator;
config.ExternalKeySet = new ExternalKeySet(); config.ExternalKeySet = new ExternalKeySet();
var horizon = new Horizon(new StopWatchTimeSpanGenerator(), config); Horizon horizon = LibHac.HorizonFactory.CreateWithFsConfig(new StopWatchTimeSpanGenerator(), config);
return horizon; return horizon;
} }