mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Implement the remaining gcsrv functions
This commit is contained in:
parent
e18f6a9daf
commit
56765598a7
9 changed files with 401 additions and 31 deletions
|
@ -3,6 +3,7 @@ using LibHac.Common.Keys;
|
||||||
using LibHac.FsSrv.FsCreator;
|
using LibHac.FsSrv.FsCreator;
|
||||||
using LibHac.FsSrv.Storage;
|
using LibHac.FsSrv.Storage;
|
||||||
using LibHac.FsSystem;
|
using LibHac.FsSystem;
|
||||||
|
using LibHac.Gc;
|
||||||
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
|
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
|
||||||
|
|
||||||
namespace LibHac.FsSrv;
|
namespace LibHac.FsSrv;
|
||||||
|
@ -12,6 +13,7 @@ public class DefaultFsServerObjects
|
||||||
public FileSystemCreatorInterfaces FsCreators { get; set; }
|
public FileSystemCreatorInterfaces FsCreators { get; set; }
|
||||||
public EmulatedGameCard GameCard { get; set; }
|
public EmulatedGameCard GameCard { get; set; }
|
||||||
public EmulatedSdCard SdCard { get; set; }
|
public EmulatedSdCard SdCard { get; set; }
|
||||||
|
public GameCardDummy GameCardNew { get; set; }
|
||||||
public EmulatedStorageDeviceManagerFactory StorageDeviceManagerFactory { get; set; }
|
public EmulatedStorageDeviceManagerFactory StorageDeviceManagerFactory { get; set; }
|
||||||
|
|
||||||
public static DefaultFsServerObjects GetDefaultEmulatedCreators(IFileSystem rootFileSystem, KeySet keySet,
|
public static DefaultFsServerObjects GetDefaultEmulatedCreators(IFileSystem rootFileSystem, KeySet keySet,
|
||||||
|
@ -21,6 +23,8 @@ public class DefaultFsServerObjects
|
||||||
var gameCard = new EmulatedGameCard(keySet);
|
var gameCard = new EmulatedGameCard(keySet);
|
||||||
var sdCard = new EmulatedSdCard();
|
var sdCard = new EmulatedSdCard();
|
||||||
|
|
||||||
|
var gameCardNew = new GameCardDummy();
|
||||||
|
|
||||||
var gcStorageCreator = new EmulatedGameCardStorageCreator(gameCard);
|
var gcStorageCreator = new EmulatedGameCardStorageCreator(gameCard);
|
||||||
|
|
||||||
using var sharedRootFileSystem = new SharedRef<IFileSystem>(rootFileSystem);
|
using var sharedRootFileSystem = new SharedRef<IFileSystem>(rootFileSystem);
|
||||||
|
@ -39,13 +43,14 @@ public class DefaultFsServerObjects
|
||||||
creators.BuiltInStorageFileSystemCreator = new EmulatedBisFileSystemCreator(ref sharedRootFileSystem.Ref);
|
creators.BuiltInStorageFileSystemCreator = new EmulatedBisFileSystemCreator(ref sharedRootFileSystem.Ref);
|
||||||
creators.SdCardFileSystemCreator = new EmulatedSdCardFileSystemCreator(sdCard, ref sharedRootFileSystemCopy.Ref);
|
creators.SdCardFileSystemCreator = new EmulatedSdCardFileSystemCreator(sdCard, ref sharedRootFileSystemCopy.Ref);
|
||||||
|
|
||||||
var storageDeviceManagerFactory = new EmulatedStorageDeviceManagerFactory(fsServer, true);
|
var storageDeviceManagerFactory = new EmulatedStorageDeviceManagerFactory(fsServer, gameCardNew, hasGameCard: true);
|
||||||
|
|
||||||
return new DefaultFsServerObjects
|
return new DefaultFsServerObjects
|
||||||
{
|
{
|
||||||
FsCreators = creators,
|
FsCreators = creators,
|
||||||
GameCard = gameCard,
|
GameCard = gameCard,
|
||||||
SdCard = sdCard,
|
SdCard = sdCard,
|
||||||
|
GameCardNew = gameCardNew,
|
||||||
StorageDeviceManagerFactory = storageDeviceManagerFactory
|
StorageDeviceManagerFactory = storageDeviceManagerFactory
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,9 +25,10 @@ public class EmulatedStorageDeviceManagerFactory : IStorageDeviceManagerFactory
|
||||||
private readonly FileSystemServer _fsServer;
|
private readonly FileSystemServer _fsServer;
|
||||||
private readonly GameCardDummy _gc;
|
private readonly GameCardDummy _gc;
|
||||||
|
|
||||||
public EmulatedStorageDeviceManagerFactory(FileSystemServer fsServer, bool hasGameCard)
|
public EmulatedStorageDeviceManagerFactory(FileSystemServer fsServer, GameCardDummy gc, bool hasGameCard)
|
||||||
{
|
{
|
||||||
_fsServer = fsServer;
|
_fsServer = fsServer;
|
||||||
|
_gc = gc;
|
||||||
_hasGameCard = hasGameCard;
|
_hasGameCard = hasGameCard;
|
||||||
|
|
||||||
_gameCardDeviceMutex = new SdkMutexType();
|
_gameCardDeviceMutex = new SdkMutexType();
|
||||||
|
@ -110,12 +111,80 @@ public class EmulatedStorageDeviceManagerFactory : IStorageDeviceManagerFactory
|
||||||
return ResultFs.StorageDeviceInvalidOperation.Log();
|
return ResultFs.StorageDeviceInvalidOperation.Log();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AwakenAll()
|
||||||
|
{
|
||||||
|
EnsureMmcReady();
|
||||||
|
_mmcDeviceManager.Get.Awaken().IgnoreResult();
|
||||||
|
|
||||||
|
using (ScopedLock.Lock(ref _sdCardDeviceMutex))
|
||||||
|
{
|
||||||
|
if (_sdCardDeviceManager.HasValue)
|
||||||
|
{
|
||||||
|
_sdCardDeviceManager.Get.Awaken().IgnoreResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using (ScopedLock.Lock(ref _gameCardDeviceMutex))
|
||||||
|
{
|
||||||
|
if (_gameCardDeviceManager.HasValue)
|
||||||
|
{
|
||||||
|
_gameCardDeviceManager.Get.Awaken().IgnoreResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PutAllToSleep()
|
||||||
|
{
|
||||||
|
using (ScopedLock.Lock(ref _gameCardDeviceMutex))
|
||||||
|
{
|
||||||
|
if (_gameCardDeviceManager.HasValue)
|
||||||
|
{
|
||||||
|
_gameCardDeviceManager.Get.PutToSleep().IgnoreResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using (ScopedLock.Lock(ref _sdCardDeviceMutex))
|
||||||
|
{
|
||||||
|
if (_sdCardDeviceManager.HasValue)
|
||||||
|
{
|
||||||
|
_sdCardDeviceManager.Get.PutToSleep().IgnoreResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsureMmcReady();
|
||||||
|
_mmcDeviceManager.Get.PutToSleep().IgnoreResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShutdownAll()
|
||||||
|
{
|
||||||
|
using (ScopedLock.Lock(ref _gameCardDeviceMutex))
|
||||||
|
{
|
||||||
|
if (_gameCardDeviceManager.HasValue)
|
||||||
|
{
|
||||||
|
_gameCardDeviceManager.Get.Shutdown().IgnoreResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using (ScopedLock.Lock(ref _sdCardDeviceMutex))
|
||||||
|
{
|
||||||
|
if (_sdCardDeviceManager.HasValue)
|
||||||
|
{
|
||||||
|
_sdCardDeviceManager.Get.Shutdown().IgnoreResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsureMmcReady();
|
||||||
|
_mmcDeviceManager.Get.Shutdown().IgnoreResult();
|
||||||
|
}
|
||||||
|
|
||||||
private void EnsureMmcReady()
|
private void EnsureMmcReady()
|
||||||
{
|
{
|
||||||
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _mmcDeviceMutex);
|
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _mmcDeviceMutex);
|
||||||
|
|
||||||
if (!_mmcDeviceManager.HasValue)
|
if (!_mmcDeviceManager.HasValue)
|
||||||
{
|
{
|
||||||
|
// Missing: Register device address space
|
||||||
|
|
||||||
_mmcDeviceManager.Reset(new MmcManager());
|
_mmcDeviceManager.Reset(new MmcManager());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,18 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using LibHac.Common;
|
using LibHac.Common;
|
||||||
|
using LibHac.Diag;
|
||||||
|
using LibHac.Fs;
|
||||||
using LibHac.FsSrv.Sf;
|
using LibHac.FsSrv.Sf;
|
||||||
using LibHac.Os;
|
using LibHac.Os;
|
||||||
using LibHac.Sf;
|
using LibHac.Sf;
|
||||||
|
|
||||||
namespace LibHac.FsSystem;
|
namespace LibHac.FsSystem;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Base class for classes that manage registering events and signaling them when a card device is inserted or removed.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Based on nnSdk 14.3.0 (FS 14.1.0)</remarks>
|
||||||
internal class CardDeviceDetectionEventManager : IDisposable
|
internal class CardDeviceDetectionEventManager : IDisposable
|
||||||
{
|
{
|
||||||
private LinkedList<CardDeviceDetectionEvent> _events;
|
private LinkedList<CardDeviceDetectionEvent> _events;
|
||||||
|
@ -28,29 +34,55 @@ internal class CardDeviceDetectionEventManager : IDisposable
|
||||||
CallbackArgs = new CallbackArguments { EventManager = this, Mutex = _mutex };
|
CallbackArgs = new CallbackArguments { EventManager = this, Mutex = _mutex };
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Dispose()
|
public virtual void Dispose() { }
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Result CreateDetectionEvent(ref SharedRef<IEventNotifier> outDetectionEvent)
|
public Result CreateDetectionEvent(ref SharedRef<IEventNotifier> outDetectionEvent)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
using ScopedLock<SdkMutex> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||||
|
|
||||||
|
var detectionEventImpl = new CardDeviceDetectionEvent(this);
|
||||||
|
using var detectionEvent = new SharedRef<IEventNotifier>(detectionEventImpl);
|
||||||
|
|
||||||
|
if (!detectionEvent.HasValue)
|
||||||
|
return ResultFs.AllocationMemoryFailedInDeviceDetectionEventManagerA.Log();
|
||||||
|
|
||||||
|
_events.AddLast(detectionEventImpl);
|
||||||
|
outDetectionEvent.SetByMove(ref detectionEvent.Ref );
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Unlink(CardDeviceDetectionEvent detectionEvent)
|
public void Unlink(CardDeviceDetectionEvent detectionEvent)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
using ScopedLock<SdkMutex> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||||
|
|
||||||
|
_events.Remove(detectionEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SignalAll()
|
public void SignalAll()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
using ScopedLock<SdkMutex> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||||
|
|
||||||
|
// ReSharper disable once UnusedVariable
|
||||||
|
foreach (CardDeviceDetectionEvent detectionEvent in _events)
|
||||||
|
{
|
||||||
|
// Todo: Signal event
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static void DetectionEventCallback(object args)
|
protected static void DetectionEventCallback(object args)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
Abort.DoAbortUnless(args is CallbackArguments, "Invalid device detection callback arguments type.");
|
||||||
|
|
||||||
|
var callbackArgs = (CallbackArguments)args;
|
||||||
|
|
||||||
|
using ScopedLock<SdkMutex> scopedLock = ScopedLock.Lock(ref callbackArgs.Mutex);
|
||||||
|
|
||||||
|
// ReSharper disable once UnusedVariable
|
||||||
|
foreach (CardDeviceDetectionEvent detectionEvent in callbackArgs.EventManager._events)
|
||||||
|
{
|
||||||
|
// Todo: Signal event
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +98,8 @@ internal class CardDeviceDetectionEvent : IEventNotifier
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
_eventManager?.Unlink(this);
|
||||||
|
_eventManager = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Result GetEventHandle(out NativeHandle handle)
|
public Result GetEventHandle(out NativeHandle handle)
|
||||||
|
|
|
@ -1,17 +1,27 @@
|
||||||
using System;
|
using LibHac.FsSystem;
|
||||||
using LibHac.FsSystem;
|
using LibHac.Gc;
|
||||||
|
|
||||||
namespace LibHac.GcSrv;
|
namespace LibHac.GcSrv;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Manages registering events and signaling them when a game card is inserted or removed.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Based on nnSdk 14.3.0 (FS 14.1.0)</remarks>
|
||||||
internal class GameCardDetectionEventManager : CardDeviceDetectionEventManager
|
internal class GameCardDetectionEventManager : CardDeviceDetectionEventManager
|
||||||
{
|
{
|
||||||
public GameCardDetectionEventManager()
|
private GameCardDummy _gc;
|
||||||
|
|
||||||
|
public GameCardDetectionEventManager(GameCardDummy gc)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
_gc = gc;
|
||||||
|
|
||||||
|
gc.RegisterDetectionEventCallback(DetectionEventCallback, CallbackArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Dispose()
|
public override void Dispose()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
_gc.UnregisterDetectionEventCallback();
|
||||||
|
|
||||||
|
base.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -14,7 +14,8 @@ using LibHac.Os;
|
||||||
using LibHac.Sf;
|
using LibHac.Sf;
|
||||||
using static LibHac.Gc.Values;
|
using static LibHac.Gc.Values;
|
||||||
using static LibHac.GcSrv.GameCardDeviceOperator;
|
using static LibHac.GcSrv.GameCardDeviceOperator;
|
||||||
using IStorage = LibHac.FsSrv.Sf.IStorage;
|
using IStorage = LibHac.Fs.IStorage;
|
||||||
|
using IStorageSf = LibHac.FsSrv.Sf.IStorage;
|
||||||
|
|
||||||
namespace LibHac.GcSrv;
|
namespace LibHac.GcSrv;
|
||||||
|
|
||||||
|
@ -124,7 +125,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Result InitializeGcLibrary()
|
private Result InitializeGcLibrary()
|
||||||
{
|
{
|
||||||
using var writeLock = new UniqueLock<ReaderWriterLock>(_rwLock);
|
using var writeLock = new UniqueLock<ReaderWriterLock>(_rwLock);
|
||||||
|
|
||||||
|
@ -139,7 +140,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
||||||
_gc.Initialize(default, default);
|
_gc.Initialize(default, default);
|
||||||
// Missing: Register the device buffer
|
// Missing: Register the device buffer
|
||||||
|
|
||||||
_detectionEventManager = new GameCardDetectionEventManager();
|
_detectionEventManager = new GameCardDetectionEventManager(_gc);
|
||||||
_isInitialized = true;
|
_isInitialized = true;
|
||||||
|
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
|
@ -358,7 +359,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Result OpenStorage(ref SharedRef<IStorage> outStorage, ulong attribute)
|
public Result OpenStorage(ref SharedRef<IStorageSf> outStorage, ulong attribute)
|
||||||
{
|
{
|
||||||
Result res = InitializeGcLibrary();
|
Result res = InitializeGcLibrary();
|
||||||
if (res.IsFailure()) return res.Miss();
|
if (res.IsFailure()) return res.Miss();
|
||||||
|
@ -375,7 +376,208 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
||||||
|
|
||||||
private Result OpenDeviceImpl(ref SharedRef<IStorageDevice> outStorageDevice, OpenGameCardAttribute attribute)
|
private Result OpenDeviceImpl(ref SharedRef<IStorageDevice> outStorageDevice, OpenGameCardAttribute attribute)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
Result res;
|
||||||
|
using var writeLock = new UniqueLock<ReaderWriterLock>(_rwLock);
|
||||||
|
|
||||||
|
using var storageDevice = new SharedRef<IStorageDevice>();
|
||||||
|
using var baseStorage = new SharedRef<IStorage>();
|
||||||
|
|
||||||
|
switch (attribute)
|
||||||
|
{
|
||||||
|
case OpenGameCardAttribute.ReadOnly:
|
||||||
|
res = OpenDeviceReadOnly(ref baseStorage.Ref, ref storageDevice.Ref);
|
||||||
|
if (res.IsFailure()) return res.Miss();
|
||||||
|
break;
|
||||||
|
case OpenGameCardAttribute.SecureReadOnly:
|
||||||
|
res = OpenDeviceSecureReadOnly(ref baseStorage.Ref, ref storageDevice.Ref);
|
||||||
|
if (res.IsFailure()) return res.Miss();
|
||||||
|
break;
|
||||||
|
case OpenGameCardAttribute.WriteOnly:
|
||||||
|
res = OpenDeviceWriteOnly(ref baseStorage.Ref, ref storageDevice.Ref);
|
||||||
|
if (res.IsFailure()) return res.Miss();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return ResultFs.InvalidArgument.Log();
|
||||||
|
}
|
||||||
|
|
||||||
|
outStorageDevice.SetByMove(ref storageDevice.Ref);
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Result OpenDeviceReadOnly(ref SharedRef<IStorage> outStorage,
|
||||||
|
ref SharedRef<IStorageDevice> outStorageDevice)
|
||||||
|
{
|
||||||
|
Result res = EnsureGameCardNormalMode(out GameCardHandle handle);
|
||||||
|
if (res.IsFailure()) return res.Miss();
|
||||||
|
|
||||||
|
res = CreateReadOnlyStorage(ref outStorage);
|
||||||
|
if (res.IsFailure()) return res.Miss();
|
||||||
|
|
||||||
|
if (!outStorage.HasValue)
|
||||||
|
return ResultFs.AllocationMemoryFailedInGameCardManagerB.Log();
|
||||||
|
|
||||||
|
using SharedRef<IStorageDevice> storageDevice = CreateStorageDeviceNonSecure(in outStorage, handle);
|
||||||
|
if (!storageDevice.HasValue)
|
||||||
|
return ResultFs.AllocationMemoryFailedInGameCardManagerB.Log();
|
||||||
|
|
||||||
|
outStorageDevice.SetByMove(ref storageDevice.Ref);
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Result OpenDeviceSecureReadOnly(ref SharedRef<IStorage> outStorage,
|
||||||
|
ref SharedRef<IStorageDevice> outStorageDevice)
|
||||||
|
{
|
||||||
|
Result res = EnsureGameCardSecureMode(out GameCardHandle handle);
|
||||||
|
if (res.IsFailure()) return res.Miss();
|
||||||
|
|
||||||
|
Span<byte> currentCardDeviceId = stackalloc byte[GcCardDeviceIdSize];
|
||||||
|
Span<byte> currentCardImageHash = stackalloc byte[GcCardImageHashSize];
|
||||||
|
|
||||||
|
res = HandleGameCardAccessResult(_gc.GetCardDeviceId(currentCardDeviceId));
|
||||||
|
if (res.IsFailure()) return res.Miss();
|
||||||
|
|
||||||
|
res = HandleGameCardAccessResult(_gc.GetCardImageHash(currentCardImageHash));
|
||||||
|
if (res.IsFailure()) return res.Miss();
|
||||||
|
|
||||||
|
res = CreateSecureReadOnlyStorage(ref outStorage);
|
||||||
|
if (res.IsFailure()) return res.Miss();
|
||||||
|
|
||||||
|
if (!outStorage.HasValue)
|
||||||
|
return ResultFs.AllocationMemoryFailedInGameCardManagerC.Log();
|
||||||
|
|
||||||
|
using SharedRef<IStorageDevice> storageDevice =
|
||||||
|
CreateStorageDeviceSecure(in outStorage, handle, currentCardDeviceId, currentCardImageHash);
|
||||||
|
|
||||||
|
if (!storageDevice.HasValue)
|
||||||
|
return ResultFs.AllocationMemoryFailedInGameCardManagerD.Log();
|
||||||
|
|
||||||
|
outStorageDevice.SetByMove(ref storageDevice.Ref);
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Result OpenDeviceWriteOnly(ref SharedRef<IStorage> outStorage,
|
||||||
|
ref SharedRef<IStorageDevice> outStorageDevice)
|
||||||
|
{
|
||||||
|
Result res = EnsureGameCardWriteMode(out GameCardHandle handle);
|
||||||
|
if (res.IsFailure()) return res.Miss();
|
||||||
|
|
||||||
|
res = CreateWriteOnlyStorage(ref outStorage);
|
||||||
|
if (res.IsFailure()) return res.Miss();
|
||||||
|
|
||||||
|
if (!outStorage.HasValue)
|
||||||
|
return ResultFs.AllocationMemoryFailedInGameCardManagerE.Log();
|
||||||
|
|
||||||
|
using SharedRef<IStorageDevice> storageDevice = CreateStorageDeviceNonSecure(in outStorage, handle);
|
||||||
|
if (!storageDevice.HasValue)
|
||||||
|
return ResultFs.AllocationMemoryFailedInGameCardManagerF.Log();
|
||||||
|
|
||||||
|
outStorageDevice.SetByMove(ref storageDevice.Ref);
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DelegatedSubStorage : SubStorage
|
||||||
|
{
|
||||||
|
private SharedRef<IStorage> _baseStorageShared;
|
||||||
|
|
||||||
|
public DelegatedSubStorage(ref UniqueRef<IStorage> baseStorage, long offset, long size)
|
||||||
|
: base(baseStorage.Get, offset, size)
|
||||||
|
{
|
||||||
|
_baseStorageShared = SharedRef<IStorage>.Create(ref baseStorage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
_baseStorageShared.Destroy();
|
||||||
|
|
||||||
|
base.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Result CreateReadOnlyStorage(ref SharedRef<IStorage> outStorage)
|
||||||
|
{
|
||||||
|
using var storage = new UniqueRef<IStorage>(MakeReadOnlyGameCardStorage());
|
||||||
|
if (!storage.HasValue)
|
||||||
|
return ResultFs.AllocationMemoryFailedInGameCardManagerA.Log();
|
||||||
|
|
||||||
|
Result res = HandleGameCardAccessResult(_gc.GetCardStatus(out GameCardStatus cardStatus));
|
||||||
|
if (res.IsFailure()) return res.Miss();
|
||||||
|
|
||||||
|
long size = cardStatus.SecureAreaOffset;
|
||||||
|
|
||||||
|
outStorage.Reset(new DelegatedSubStorage(ref storage.Ref, 0, size));
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Result CreateSecureReadOnlyStorage(ref SharedRef<IStorage> outStorage)
|
||||||
|
{
|
||||||
|
using var storage = new UniqueRef<IStorage>(MakeReadOnlyGameCardStorage());
|
||||||
|
if (!storage.HasValue)
|
||||||
|
return ResultFs.AllocationMemoryFailedInGameCardManagerC.Log();
|
||||||
|
|
||||||
|
Result res = HandleGameCardAccessResult(_gc.GetCardStatus(out GameCardStatus cardStatus));
|
||||||
|
if (res.IsFailure()) return res.Miss();
|
||||||
|
|
||||||
|
long offset = cardStatus.SecureAreaOffset;
|
||||||
|
long size = cardStatus.SecureAreaSize;
|
||||||
|
|
||||||
|
outStorage.Reset(new DelegatedSubStorage(ref storage.Ref, offset, size));
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Result CreateWriteOnlyStorage(ref SharedRef<IStorage> outStorage)
|
||||||
|
{
|
||||||
|
using var storage = new UniqueRef<IStorage>(MakeWriteOnlyGameCardStorage());
|
||||||
|
if (!storage.HasValue)
|
||||||
|
return ResultFs.AllocationMemoryFailedInGameCardManagerE.Log();
|
||||||
|
|
||||||
|
Result res = storage.Get.GetSize(out long size);
|
||||||
|
if (res.IsFailure()) return res.Miss();
|
||||||
|
|
||||||
|
outStorage.Reset(new DelegatedSubStorage(ref storage.Ref, 0, size));
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ReadOnlyGameCardStorage MakeReadOnlyGameCardStorage()
|
||||||
|
{
|
||||||
|
using SharedRef<IGameCardManager> manager = SharedRef<IGameCardManager>.Create(in _selfReference);
|
||||||
|
|
||||||
|
return new ReadOnlyGameCardStorage(ref manager.Ref, _gc);
|
||||||
|
}
|
||||||
|
|
||||||
|
private WriteOnlyGameCardStorage MakeWriteOnlyGameCardStorage()
|
||||||
|
{
|
||||||
|
using SharedRef<IGameCardManager> manager = SharedRef<IGameCardManager>.Create(in _selfReference);
|
||||||
|
|
||||||
|
return new WriteOnlyGameCardStorage(ref manager.Ref, _gc);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SharedRef<IStorageDevice> CreateStorageDeviceNonSecure(in SharedRef<IStorage> baseStorage,
|
||||||
|
GameCardHandle handle)
|
||||||
|
{
|
||||||
|
using SharedRef<IGameCardManager> manager = SharedRef<IGameCardManager>.Create(in _selfReference);
|
||||||
|
|
||||||
|
using SharedRef<GameCardStorageDevice> storageDevice =
|
||||||
|
GameCardStorageDevice.CreateShared(_gc, ref manager.Ref, in baseStorage, handle);
|
||||||
|
|
||||||
|
return SharedRef<IStorageDevice>.CreateMove(ref storageDevice.Ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SharedRef<IStorageDevice> CreateStorageDeviceSecure(in SharedRef<IStorage> baseStorage,
|
||||||
|
GameCardHandle handle, ReadOnlySpan<byte> cardDeviceId, ReadOnlySpan<byte> cardImageHash)
|
||||||
|
{
|
||||||
|
using SharedRef<IGameCardManager> manager = SharedRef<IGameCardManager>.Create(in _selfReference);
|
||||||
|
|
||||||
|
using SharedRef<GameCardStorageDevice> storageDevice = GameCardStorageDevice.CreateShared(
|
||||||
|
_gc, ref manager.Ref, in baseStorage, handle, isSecure: true, cardDeviceId, cardImageHash);
|
||||||
|
|
||||||
|
return SharedRef<IStorageDevice>.CreateMove(ref storageDevice.Ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Result PutToSleep()
|
public Result PutToSleep()
|
||||||
|
@ -956,6 +1158,15 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
||||||
|
|
||||||
public void PresetInternalKeys(ReadOnlySpan<byte> gameCardKey, ReadOnlySpan<byte> gameCardCertificate)
|
public void PresetInternalKeys(ReadOnlySpan<byte> gameCardKey, ReadOnlySpan<byte> gameCardCertificate)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
if (gameCardKey.IsEmpty || gameCardCertificate.IsEmpty)
|
||||||
|
{
|
||||||
|
_fsServer.Hos.Diag.Impl.LogImpl(Log.EmptyModuleName, LogSeverity.Info, "[fs] Warning: skipped nn::gc::PresetInternalKeys\n"u8);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_gc.PresetInternalKeys(gameCardKey, gameCardCertificate);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Missing: Signal settings-ready event
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -11,6 +11,10 @@ using IStorageSf = LibHac.FsSrv.Sf.IStorage;
|
||||||
|
|
||||||
namespace LibHac.GcSrv;
|
namespace LibHac.GcSrv;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides an <see cref="IStorage"/> interface for reading from the game card.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Based on nnSdk 14.3.0 (FS 14.1.0)</remarks>
|
||||||
internal class ReadOnlyGameCardStorage : IStorage
|
internal class ReadOnlyGameCardStorage : IStorage
|
||||||
{
|
{
|
||||||
private SharedRef<IGameCardManager> _deviceManager;
|
private SharedRef<IGameCardManager> _deviceManager;
|
||||||
|
@ -90,6 +94,10 @@ internal class ReadOnlyGameCardStorage : IStorage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides an <see cref="IStorage"/> interface for writing to the game card.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Based on nnSdk 14.3.0 (FS 14.1.0)</remarks>
|
||||||
internal class WriteOnlyGameCardStorage : IStorage
|
internal class WriteOnlyGameCardStorage : IStorage
|
||||||
{
|
{
|
||||||
private SharedRef<IGameCardManager> _deviceManager;
|
private SharedRef<IGameCardManager> _deviceManager;
|
||||||
|
@ -156,13 +164,17 @@ internal class WriteOnlyGameCardStorage : IStorage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An adapter that provides an <see cref="IStorageSf"/> interface for a <see cref="IStorage"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Based on nnSdk 14.3.0 (FS 14.1.0)</remarks>
|
||||||
internal abstract class GameCardStorageInterfaceAdapter : IStorageSf
|
internal abstract class GameCardStorageInterfaceAdapter : IStorageSf
|
||||||
{
|
{
|
||||||
private SharedRef<IStorage> _baseStorage;
|
private SharedRef<IStorage> _baseStorage;
|
||||||
|
|
||||||
protected GameCardStorageInterfaceAdapter(ref SharedRef<IStorage> baseStorage)
|
protected GameCardStorageInterfaceAdapter(in SharedRef<IStorage> baseStorage)
|
||||||
{
|
{
|
||||||
_baseStorage = SharedRef<IStorage>.CreateMove(ref baseStorage);
|
_baseStorage = SharedRef<IStorage>.CreateCopy(in baseStorage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Dispose()
|
public virtual void Dispose()
|
||||||
|
|
|
@ -23,7 +23,7 @@ internal class GameCardStorageDevice : GameCardStorageInterfaceAdapter, IStorage
|
||||||
private readonly GameCardDummy _gc;
|
private readonly GameCardDummy _gc;
|
||||||
|
|
||||||
private GameCardStorageDevice(GameCardDummy gc, ref SharedRef<IGameCardManager> manager,
|
private GameCardStorageDevice(GameCardDummy gc, ref SharedRef<IGameCardManager> manager,
|
||||||
ref SharedRef<IStorage> baseStorage, GameCardHandle handle) : base(ref baseStorage)
|
in SharedRef<IStorage> baseStorage, GameCardHandle handle) : base(in baseStorage)
|
||||||
{
|
{
|
||||||
_manager = SharedRef<IGameCardManager>.CreateMove(ref manager);
|
_manager = SharedRef<IGameCardManager>.CreateMove(ref manager);
|
||||||
_handle = handle;
|
_handle = handle;
|
||||||
|
@ -33,9 +33,9 @@ internal class GameCardStorageDevice : GameCardStorageInterfaceAdapter, IStorage
|
||||||
}
|
}
|
||||||
|
|
||||||
private GameCardStorageDevice(GameCardDummy gc, ref SharedRef<IGameCardManager> manager,
|
private GameCardStorageDevice(GameCardDummy gc, ref SharedRef<IGameCardManager> manager,
|
||||||
ref SharedRef<IStorage> baseStorage, GameCardHandle handle, bool isSecure, ReadOnlySpan<byte> cardDeviceId,
|
in SharedRef<IStorage> baseStorage, GameCardHandle handle, bool isSecure, ReadOnlySpan<byte> cardDeviceId,
|
||||||
ReadOnlySpan<byte> cardImageHash)
|
ReadOnlySpan<byte> cardImageHash)
|
||||||
: base(ref baseStorage)
|
: base(in baseStorage)
|
||||||
{
|
{
|
||||||
Assert.SdkRequiresEqual(cardDeviceId.Length, Values.GcCardDeviceIdSize);
|
Assert.SdkRequiresEqual(cardDeviceId.Length, Values.GcCardDeviceIdSize);
|
||||||
Assert.SdkRequiresEqual(cardImageHash.Length, Values.GcCardImageHashSize);
|
Assert.SdkRequiresEqual(cardImageHash.Length, Values.GcCardImageHashSize);
|
||||||
|
@ -51,9 +51,9 @@ internal class GameCardStorageDevice : GameCardStorageInterfaceAdapter, IStorage
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SharedRef<GameCardStorageDevice> CreateShared(GameCardDummy gc,
|
public static SharedRef<GameCardStorageDevice> CreateShared(GameCardDummy gc,
|
||||||
ref SharedRef<IGameCardManager> manager, ref SharedRef<IStorage> baseStorage, GameCardHandle handle)
|
ref SharedRef<IGameCardManager> manager, in SharedRef<IStorage> baseStorage, GameCardHandle handle)
|
||||||
{
|
{
|
||||||
var storageDevice = new GameCardStorageDevice(gc, ref manager, ref baseStorage, handle);
|
var storageDevice = new GameCardStorageDevice(gc, ref manager, in baseStorage, handle);
|
||||||
|
|
||||||
using var sharedStorageDevice = new SharedRef<GameCardStorageDevice>(storageDevice);
|
using var sharedStorageDevice = new SharedRef<GameCardStorageDevice>(storageDevice);
|
||||||
storageDevice._selfReference.Set(in sharedStorageDevice);
|
storageDevice._selfReference.Set(in sharedStorageDevice);
|
||||||
|
@ -62,10 +62,10 @@ internal class GameCardStorageDevice : GameCardStorageInterfaceAdapter, IStorage
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SharedRef<GameCardStorageDevice> CreateShared(GameCardDummy gc,
|
public static SharedRef<GameCardStorageDevice> CreateShared(GameCardDummy gc,
|
||||||
ref SharedRef<IGameCardManager> manager, ref SharedRef<IStorage> baseStorage, GameCardHandle handle,
|
ref SharedRef<IGameCardManager> manager, in SharedRef<IStorage> baseStorage, GameCardHandle handle,
|
||||||
bool isSecure, ReadOnlySpan<byte> cardDeviceId, ReadOnlySpan<byte> cardImageHash)
|
bool isSecure, ReadOnlySpan<byte> cardDeviceId, ReadOnlySpan<byte> cardImageHash)
|
||||||
{
|
{
|
||||||
var storageDevice = new GameCardStorageDevice(gc, ref manager, ref baseStorage, handle, isSecure, cardDeviceId,
|
var storageDevice = new GameCardStorageDevice(gc, ref manager, in baseStorage, handle, isSecure, cardDeviceId,
|
||||||
cardImageHash);
|
cardImageHash);
|
||||||
|
|
||||||
using var sharedStorageDevice = new SharedRef<GameCardStorageDevice>(storageDevice);
|
using var sharedStorageDevice = new SharedRef<GameCardStorageDevice>(storageDevice);
|
||||||
|
|
|
@ -47,6 +47,21 @@ public class MmcManager : IStorageDeviceManager
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Result PutToSleep()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result Awaken()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result Shutdown()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
public Result Invalidate()
|
public Result Invalidate()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
|
|
|
@ -47,6 +47,21 @@ public class SdCardManager : IStorageDeviceManager
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Result PutToSleep()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result Awaken()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result Shutdown()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
public Result Invalidate()
|
public Result Invalidate()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
|
|
Loading…
Reference in a new issue