Implement the remaining gcsrv functions

This commit is contained in:
Alex Barney 2022-05-24 16:35:30 -07:00
parent e18f6a9daf
commit 56765598a7
9 changed files with 401 additions and 31 deletions

View file

@ -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
}; };
} }

View file

@ -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());
} }
} }

View file

@ -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)

View file

@ -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();
} }
} }

View file

@ -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
} }
} }

View file

@ -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()

View file

@ -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);

View file

@ -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();

View file

@ -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();