mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Add GameCardDeviceOperator
This commit is contained in:
parent
f4c59771cb
commit
e18f6a9daf
10 changed files with 474 additions and 155 deletions
|
@ -1,6 +1,7 @@
|
|||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.FsSrv.Storage.Sf;
|
||||
using LibHac.Gc;
|
||||
using LibHac.GcSrv;
|
||||
using LibHac.Os;
|
||||
using LibHac.SdmmcSrv;
|
||||
|
@ -22,6 +23,7 @@ public class EmulatedStorageDeviceManagerFactory : IStorageDeviceManagerFactory
|
|||
private readonly bool _hasGameCard;
|
||||
|
||||
private readonly FileSystemServer _fsServer;
|
||||
private readonly GameCardDummy _gc;
|
||||
|
||||
public EmulatedStorageDeviceManagerFactory(FileSystemServer fsServer, bool hasGameCard)
|
||||
{
|
||||
|
@ -138,12 +140,13 @@ public class EmulatedStorageDeviceManagerFactory : IStorageDeviceManagerFactory
|
|||
{
|
||||
if (_hasGameCard)
|
||||
{
|
||||
using SharedRef<GameCardManager> manger = GameCardManager.CreateShared(_fsServer);
|
||||
_gameCardDeviceManager.SetByMove(ref manger.Ref);
|
||||
using SharedRef<GameCardManager> manager = GameCardManager.CreateShared(_gc, _fsServer);
|
||||
_gameCardDeviceManager.SetByMove(ref manager.Ref);
|
||||
}
|
||||
else
|
||||
{
|
||||
_dummyGameCardDeviceManager.Reset(new DummyGameCardManager());
|
||||
using SharedRef<DummyGameCardManager> manager = DummyGameCardManager.CreateShared();
|
||||
_dummyGameCardDeviceManager.SetByMove(ref manager.Ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,10 +2,26 @@
|
|||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsSrv.Sf;
|
||||
using LibHac.Os;
|
||||
using LibHac.Sf;
|
||||
using IDirectory = LibHac.Fs.Fsa.IDirectory;
|
||||
using IFile = LibHac.Fs.Fsa.IFile;
|
||||
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
|
||||
using Path = LibHac.Fs.Path;
|
||||
|
||||
namespace LibHac.FsSystem;
|
||||
|
||||
public class DummyEventNotifier : IEventNotifier
|
||||
{
|
||||
public void Dispose() { }
|
||||
|
||||
public Result GetEventHandle(out NativeHandle handle)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Various utility functions used by the <see cref="LibHac.FsSystem"/> namespace.
|
||||
/// </summary>
|
||||
|
|
|
@ -9,4 +9,6 @@ public static class Values
|
|||
public static int GcCardImageHashSize => 0x20;
|
||||
public static int GcDeviceCertificateSize => 0x200;
|
||||
public static int GcCardKeyAreaSize => 0x1000;
|
||||
public static int GcCardKeyAreaPageCount => 8;
|
||||
public static int GcCertAreaStartPageAddress => 56;
|
||||
}
|
|
@ -4,21 +4,38 @@ using LibHac.Common;
|
|||
using LibHac.Fs;
|
||||
using LibHac.FsSrv.Sf;
|
||||
using LibHac.FsSrv.Storage.Sf;
|
||||
using LibHac.FsSystem;
|
||||
using LibHac.Sf;
|
||||
using IStorageSf = LibHac.FsSrv.Sf.IStorage;
|
||||
|
||||
namespace LibHac.GcSrv;
|
||||
|
||||
public class DummyGameCardManager : IStorageDeviceManager, IStorageDeviceOperator
|
||||
public class DummyGameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IGameCardKeyManager
|
||||
{
|
||||
public DummyGameCardManager()
|
||||
private SharedRef<DummyEventNotifier> _eventNotifier;
|
||||
|
||||
// LibHac additions
|
||||
private WeakRef<DummyGameCardManager> _selfReference;
|
||||
|
||||
private DummyGameCardManager()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_eventNotifier = new SharedRef<DummyEventNotifier>(new DummyEventNotifier());
|
||||
}
|
||||
|
||||
public static SharedRef<DummyGameCardManager> CreateShared()
|
||||
{
|
||||
var manager = new DummyGameCardManager();
|
||||
|
||||
using var sharedManager = new SharedRef<DummyGameCardManager>(manager);
|
||||
manager._selfReference.Set(in sharedManager);
|
||||
|
||||
return SharedRef<DummyGameCardManager>.CreateMove(ref sharedManager.Ref);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_eventNotifier.Destroy();
|
||||
_selfReference.Destroy();
|
||||
}
|
||||
|
||||
public Result IsInserted(out bool isInserted)
|
||||
|
@ -35,12 +52,20 @@ public class DummyGameCardManager : IStorageDeviceManager, IStorageDeviceOperato
|
|||
|
||||
public Result OpenDetectionEvent(ref SharedRef<IEventNotifier> outDetectionEvent)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
outDetectionEvent.SetByCopy(in _eventNotifier);
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenOperator(ref SharedRef<IStorageDeviceOperator> outDeviceOperator)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using SharedRef<DummyGameCardManager> deviceOperator = SharedRef<DummyGameCardManager>.Create(in _selfReference);
|
||||
|
||||
if (!deviceOperator.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInGameCardManagerG.Log();
|
||||
|
||||
outDeviceOperator.SetByMove(ref deviceOperator.Ref);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenDevice(ref SharedRef<IStorageDevice> outStorageDevice, ulong attribute)
|
||||
|
@ -157,7 +182,7 @@ public class DummyGameCardManager : IStorageDeviceManager, IStorageDeviceOperato
|
|||
{
|
||||
case GameCardManagerOperationIdValue.IsGameCardActivationValid:
|
||||
{
|
||||
if (outBuffer.Size < Unsafe.SizeOf<bool>())
|
||||
if (outBuffer.Size < sizeof(bool))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
outBuffer.As<bool>() = false;
|
||||
|
@ -186,4 +211,9 @@ public class DummyGameCardManager : IStorageDeviceManager, IStorageDeviceOperato
|
|||
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
public void PresetInternalKeys(ReadOnlySpan<byte> gameCardKey, ReadOnlySpan<byte> gameCardCertificate)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
}
|
|
@ -3,9 +3,9 @@ using LibHac.FsSystem;
|
|||
|
||||
namespace LibHac.GcSrv;
|
||||
|
||||
internal class GameCardDeviceDetectionEventManager : CardDeviceDetectionEventManager
|
||||
internal class GameCardDetectionEventManager : CardDeviceDetectionEventManager
|
||||
{
|
||||
public GameCardDeviceDetectionEventManager()
|
||||
public GameCardDetectionEventManager()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
196
src/LibHac/GcSrv/GameCardDeviceOperator.cs
Normal file
196
src/LibHac/GcSrv/GameCardDeviceOperator.cs
Normal file
|
@ -0,0 +1,196 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.FsSrv.Storage.Sf;
|
||||
using LibHac.Gc;
|
||||
using LibHac.Gc.Writer;
|
||||
using LibHac.Os;
|
||||
using LibHac.Sf;
|
||||
using static LibHac.Gc.Values;
|
||||
|
||||
namespace LibHac.GcSrv;
|
||||
|
||||
internal class GameCardDeviceOperator : IStorageDeviceOperator
|
||||
{
|
||||
private SharedRef<GameCardStorageDevice> _storageDevice;
|
||||
|
||||
// LibHac additions
|
||||
private readonly GameCardDummy _gc;
|
||||
|
||||
public static uint BytesToPages(long byteCount)
|
||||
{
|
||||
return (uint)((ulong)byteCount / (ulong)GcPageSize);
|
||||
}
|
||||
|
||||
public GameCardDeviceOperator(ref SharedRef<GameCardStorageDevice> storageDevice, GameCardDummy gc)
|
||||
{
|
||||
_storageDevice = SharedRef<GameCardStorageDevice>.CreateMove(ref storageDevice);
|
||||
_gc = gc;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_storageDevice.Destroy();
|
||||
}
|
||||
|
||||
public Result Operate(int operationId)
|
||||
{
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
public Result OperateIn(InBuffer buffer, long offset, long size, int operationId)
|
||||
{
|
||||
Result result;
|
||||
var operation = (GameCardOperationIdValue)operationId;
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case GameCardOperationIdValue.EraseGameCard:
|
||||
{
|
||||
using var readLock = new SharedLock<ReaderWriterLock>();
|
||||
Result res = _storageDevice.Get.AcquireReadLock(ref readLock.Ref());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
if (buffer.Size != sizeof(long))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
result = _gc.Writer.EraseAndWriteParameter((MemorySize)size, BytesToPages(buffer.As<long>()));
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
|
||||
return _storageDevice.Get.HandleGameCardAccessResult(result).Ret();
|
||||
}
|
||||
|
||||
public Result OperateOut(out long bytesWritten, OutBuffer buffer, int operationId)
|
||||
{
|
||||
Result result;
|
||||
bytesWritten = 0;
|
||||
var operation = (GameCardOperationIdValue)operationId;
|
||||
|
||||
using (var readLock = new SharedLock<ReaderWriterLock>())
|
||||
{
|
||||
switch (operation)
|
||||
{
|
||||
case GameCardOperationIdValue.GetGameCardIdSet:
|
||||
{
|
||||
Result res = _storageDevice.Get.AcquireReadLock(ref readLock.Ref());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
if (buffer.Size < Unsafe.SizeOf<GameCardIdSet>())
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
result = _gc.GetGameCardIdSet(out buffer.As<GameCardIdSet>());
|
||||
bytesWritten = Unsafe.SizeOf<GameCardIdSet>();
|
||||
|
||||
break;
|
||||
}
|
||||
case GameCardOperationIdValue.GetGameCardDeviceId:
|
||||
{
|
||||
Result res = _storageDevice.Get.AcquireReadLock(ref readLock.Ref());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
if (buffer.Size < GcCardDeviceIdSize)
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
result = _gc.GetCardDeviceId(buffer.Buffer);
|
||||
bytesWritten = GcCardDeviceIdSize;
|
||||
|
||||
break;
|
||||
}
|
||||
case GameCardOperationIdValue.GetGameCardImageHash:
|
||||
{
|
||||
Result res = _storageDevice.Get.AcquireReadLock(ref readLock.Ref());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
if (buffer.Size < GcCardImageHashSize)
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
result = _gc.GetCardImageHash(buffer.Buffer);
|
||||
bytesWritten = GcCardImageHashSize;
|
||||
|
||||
break;
|
||||
}
|
||||
case GameCardOperationIdValue.GetGameCardDeviceCertificate:
|
||||
{
|
||||
Result res = _storageDevice.Get.AcquireReadLock(ref readLock.Ref());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
if (buffer.Size < GcDeviceCertificateSize)
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
result = _gc.GetCardDeviceCertificate(buffer.Buffer);
|
||||
bytesWritten = GcDeviceCertificateSize;
|
||||
|
||||
break;
|
||||
}
|
||||
case GameCardOperationIdValue.GetGameCardStatus:
|
||||
{
|
||||
Result res = _storageDevice.Get.AcquireReadLock(ref readLock.Ref());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
if (buffer.Size < Unsafe.SizeOf<GameCardStatus>())
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
result = _gc.GetCardStatus(out buffer.As<GameCardStatus>());
|
||||
bytesWritten = Unsafe.SizeOf<GameCardStatus>();
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
}
|
||||
|
||||
return _storageDevice.Get.HandleGameCardAccessResult(result).Ret();
|
||||
}
|
||||
|
||||
public Result OperateOut2(out long bytesWrittenBuffer1, OutBuffer buffer1, out long bytesWrittenBuffer2,
|
||||
OutBuffer buffer2, int operationId)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out bytesWrittenBuffer1, out bytesWrittenBuffer2);
|
||||
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
public Result OperateInOut(out long bytesWritten, OutBuffer outBuffer, InBuffer inBuffer, long offset, long size,
|
||||
int operationId)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out bytesWritten);
|
||||
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
public Result OperateIn2Out(out long bytesWritten, OutBuffer outBuffer, InBuffer inBuffer1, InBuffer inBuffer2,
|
||||
long offset, long size, int operationId)
|
||||
{
|
||||
Result result;
|
||||
bytesWritten = 0;
|
||||
var operation = (GameCardOperationIdValue)operationId;
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case GameCardOperationIdValue.ChallengeCardExistence:
|
||||
{
|
||||
using var readLock = new SharedLock<ReaderWriterLock>();
|
||||
Result res = _storageDevice.Get.AcquireReadLock(ref readLock.Ref());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
if (outBuffer.Size < GcCardExistenceResponseDataSize)
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
result = _gc.ChallengeCardExistence(outBuffer.Buffer, inBuffer1.Buffer, inBuffer2.Buffer);
|
||||
bytesWritten = GcCardExistenceResponseDataSize;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
|
||||
return _storageDevice.Get.HandleGameCardAccessResult(result).Ret();
|
||||
}
|
||||
}
|
|
@ -12,6 +12,8 @@ using LibHac.Gc.Impl;
|
|||
using LibHac.Gc.Writer;
|
||||
using LibHac.Os;
|
||||
using LibHac.Sf;
|
||||
using static LibHac.Gc.Values;
|
||||
using static LibHac.GcSrv.GameCardDeviceOperator;
|
||||
using IStorage = LibHac.FsSrv.Sf.IStorage;
|
||||
|
||||
namespace LibHac.GcSrv;
|
||||
|
@ -31,23 +33,24 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
private bool _isFinalized;
|
||||
private CardState _state;
|
||||
private GameCardHandle _currentHandle;
|
||||
private GameCardDeviceDetectionEventManager _detectionEventManager;
|
||||
private GameCardDetectionEventManager _detectionEventManager;
|
||||
|
||||
// LibHac additions
|
||||
private WeakRef<GameCardManager> _selfReference;
|
||||
private readonly FileSystemServer _fsServer;
|
||||
private readonly GameCardDummy _gc;
|
||||
|
||||
private GameCardManager(FileSystemServer fsServer)
|
||||
private GameCardManager(GameCardDummy gc, FileSystemServer fsServer)
|
||||
{
|
||||
_rwLock = new ReaderWriterLock(fsServer.Hos.Os);
|
||||
|
||||
_fsServer = fsServer;
|
||||
_gc = gc;
|
||||
}
|
||||
|
||||
public static SharedRef<GameCardManager> CreateShared(FileSystemServer fsServer)
|
||||
public static SharedRef<GameCardManager> CreateShared(GameCardDummy gc, FileSystemServer fsServer)
|
||||
{
|
||||
var manager = new GameCardManager(fsServer);
|
||||
var manager = new GameCardManager(gc, fsServer);
|
||||
|
||||
using var sharedManager = new SharedRef<GameCardManager>(manager);
|
||||
manager._selfReference.Set(in sharedManager);
|
||||
|
@ -62,11 +65,8 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
|
||||
_rwLock?.Dispose();
|
||||
_rwLock = null;
|
||||
}
|
||||
|
||||
public static uint BytesToPages(long byteCount)
|
||||
{
|
||||
return (uint)((ulong)byteCount / (ulong)Values.GcPageSize);
|
||||
_selfReference.Destroy();
|
||||
}
|
||||
|
||||
private void DeactivateAndChangeState()
|
||||
|
@ -102,6 +102,16 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
return HandleGameCardAccessResult(_gc.SetCardToSecureMode());
|
||||
}
|
||||
|
||||
private Result LockAndHandleGameCardAccessResult(Result result)
|
||||
{
|
||||
if (result.IsSuccess())
|
||||
return Result.Success;
|
||||
|
||||
using var writeLock = new UniqueLock<ReaderWriterLock>(_rwLock);
|
||||
|
||||
return HandleGameCardAccessResult(result).Ret();
|
||||
}
|
||||
|
||||
public Result IsInserted(out bool isInserted)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out isInserted);
|
||||
|
@ -129,7 +139,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
_gc.Initialize(default, default);
|
||||
// Missing: Register the device buffer
|
||||
|
||||
_detectionEventManager = new GameCardDeviceDetectionEventManager();
|
||||
_detectionEventManager = new GameCardDetectionEventManager();
|
||||
_isInitialized = true;
|
||||
|
||||
return Result.Success;
|
||||
|
@ -371,7 +381,9 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
public Result PutToSleep()
|
||||
{
|
||||
using var writeLock = new UniqueLock<ReaderWriterLock>(_rwLock);
|
||||
_gc.PutToSleep();
|
||||
|
||||
if (_isInitialized)
|
||||
_gc.PutToSleep();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
@ -379,7 +391,9 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
public Result Awaken()
|
||||
{
|
||||
using var writeLock = new UniqueLock<ReaderWriterLock>(_rwLock);
|
||||
_gc.Awaken();
|
||||
|
||||
if (_isInitialized)
|
||||
_gc.Awaken();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
@ -387,7 +401,9 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
public Result Shutdown()
|
||||
{
|
||||
using var writeLock = new UniqueLock<ReaderWriterLock>(_rwLock);
|
||||
_gc.PutToSleep();
|
||||
|
||||
if (_isInitialized)
|
||||
_gc.PutToSleep();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
@ -438,13 +454,15 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
switch (operation)
|
||||
{
|
||||
case GameCardManagerOperationIdValue.SetVerifyEnableFlag:
|
||||
{
|
||||
if (buffer.Size < sizeof(bool))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
SetVerifyEnableFlag(buffer.As<bool>());
|
||||
return Result.Success;
|
||||
|
||||
}
|
||||
case GameCardManagerOperationIdValue.EraseAndWriteParamDirectly:
|
||||
{
|
||||
if (buffer.Size < Unsafe.SizeOf<DevCardParameter>())
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
|
@ -452,6 +470,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
@ -482,6 +501,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
return Result.Success;
|
||||
}
|
||||
case GameCardManagerOperationIdValue.GetGameCardErrorInfo:
|
||||
{
|
||||
if (buffer.Size < Unsafe.SizeOf<GameCardErrorInfo>())
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
|
@ -490,8 +510,9 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
|
||||
bytesWritten = Unsafe.SizeOf<GameCardErrorInfo>();
|
||||
return Result.Success;
|
||||
|
||||
}
|
||||
case GameCardManagerOperationIdValue.GetGameCardErrorReportInfo:
|
||||
{
|
||||
if (buffer.Size < Unsafe.SizeOf<GameCardErrorReportInfo>())
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
|
@ -500,8 +521,9 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
|
||||
bytesWritten = Unsafe.SizeOf<GameCardErrorReportInfo>();
|
||||
return Result.Success;
|
||||
|
||||
}
|
||||
case GameCardManagerOperationIdValue.ReadParamDirectly:
|
||||
{
|
||||
if (buffer.Size < Unsafe.SizeOf<DevCardParameter>())
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
|
@ -510,6 +532,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
|
||||
bytesWritten = Unsafe.SizeOf<DevCardParameter>();
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
@ -536,6 +559,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
switch (operation)
|
||||
{
|
||||
case GameCardManagerOperationIdValue.IsGameCardActivationValid:
|
||||
{
|
||||
if (inBuffer.Size != sizeof(GameCardHandle))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
|
@ -546,9 +570,10 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
bytesWritten = sizeof(bool);
|
||||
|
||||
return Result.Success;
|
||||
|
||||
}
|
||||
case GameCardManagerOperationIdValue.GetGameCardAsicInfo:
|
||||
if (inBuffer.Size != Values.GcAsicFirmwareSize)
|
||||
{
|
||||
if (inBuffer.Size != GcAsicFirmwareSize)
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
if (outBuffer.Size < Unsafe.SizeOf<RmaInformation>())
|
||||
|
@ -561,20 +586,22 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
bytesWritten = Unsafe.SizeOf<RmaInformation>();
|
||||
|
||||
return Result.Success;
|
||||
|
||||
}
|
||||
case GameCardManagerOperationIdValue.GetGameCardDeviceIdForProdCard:
|
||||
if (inBuffer.Size < Values.GcPageSize)
|
||||
{
|
||||
if (inBuffer.Size < GcPageSize)
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
if (outBuffer.Size < Values.GcPageSize)
|
||||
if (outBuffer.Size < GcPageSize)
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
res = GetGameCardDeviceIdForProdCard(outBuffer.Buffer, inBuffer.Buffer);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
bytesWritten = Values.GcPageSize;
|
||||
bytesWritten = GcPageSize;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
case GameCardManagerOperationIdValue.WriteToGameCardDirectly:
|
||||
return WriteToGameCardDirectly(offset, outBuffer.Buffer.Slice(0, (int)size)).Ret();
|
||||
|
@ -601,6 +628,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
_gc.UnregisterDetectionEventCallback();
|
||||
_isFinalized = true;
|
||||
_gc.FinalizeGc();
|
||||
// nn::fssystem::PooledBuffer::Deallocate
|
||||
// nn::gc::UnregisterDeviceVirtualAddress
|
||||
}
|
||||
}
|
||||
|
@ -650,7 +678,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
{
|
||||
UnsafeHelpers.SkipParamInit(out outRmaInfo);
|
||||
|
||||
Assert.SdkRequiresEqual(asicFirmwareBuffer.Length, Values.GcAsicFirmwareSize);
|
||||
Assert.SdkRequiresEqual(asicFirmwareBuffer.Length, GcAsicFirmwareSize);
|
||||
|
||||
_gc.Writer.SetUserAsicFirmwareBuffer(asicFirmwareBuffer);
|
||||
_gc.Writer.ChangeMode(AsicMode.Write);
|
||||
|
@ -664,36 +692,36 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
|
||||
private Result GetGameCardDeviceIdForProdCard(Span<byte> outBuffer, ReadOnlySpan<byte> devHeaderBuffer)
|
||||
{
|
||||
Assert.SdkRequiresGreaterEqual(outBuffer.Length, Values.GcPageSize);
|
||||
Assert.SdkRequiresGreaterEqual(devHeaderBuffer.Length, Values.GcPageSize);
|
||||
Assert.SdkRequiresGreaterEqual(outBuffer.Length, GcPageSize);
|
||||
Assert.SdkRequiresGreaterEqual(devHeaderBuffer.Length, GcPageSize);
|
||||
|
||||
Result res = InitializeGcLibrary();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
using var writeLock = new UniqueLock<ReaderWriterLock>(_rwLock);
|
||||
|
||||
int writeSize = Values.GcPageSize;
|
||||
var pooledBuffer = new PooledBuffer(writeSize, writeSize);
|
||||
int writeSize = GcPageSize;
|
||||
using var pooledBuffer = new PooledBuffer(writeSize, writeSize);
|
||||
Assert.SdkGreaterEqual(pooledBuffer.GetSize(), writeSize);
|
||||
|
||||
// Read the current card header into a temporary buffer
|
||||
_gc.Writer.ChangeMode(AsicMode.Read);
|
||||
|
||||
Span<byte> tmpBuffer = stackalloc byte[writeSize];
|
||||
tmpBuffer.Clear();
|
||||
Span<byte> originalHeaderBuffer = stackalloc byte[writeSize];
|
||||
originalHeaderBuffer.Clear();
|
||||
|
||||
_gc.GetCardHeader(pooledBuffer.GetBuffer());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
pooledBuffer.GetBuffer().CopyTo(tmpBuffer);
|
||||
pooledBuffer.GetBuffer().CopyTo(originalHeaderBuffer);
|
||||
|
||||
// Write the provided card header
|
||||
_gc.Writer.ChangeMode(AsicMode.Write);
|
||||
res = HandleGameCardAccessResult(_gc.Writer.ActivateForWriter());
|
||||
res = ActivateGameCardForWriter();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
devHeaderBuffer.CopyTo(pooledBuffer.GetBuffer());
|
||||
res = _gc.Writer.Write(pooledBuffer.GetBuffer(), 8, 1);
|
||||
res = _gc.Writer.Write(pooledBuffer.GetBuffer(), (uint)GcCardKeyAreaPageCount, 1);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
// Read the cert area
|
||||
|
@ -701,7 +729,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
res = _gc.Activate();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
res = _gc.Read(pooledBuffer.GetBuffer(), 0x38, 1);
|
||||
res = _gc.Read(pooledBuffer.GetBuffer(), (uint)GcCertAreaStartPageAddress, 1);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
Span<byte> deviceCert = stackalloc byte[writeSize];
|
||||
|
@ -709,11 +737,11 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
|
||||
// Restore the original card header
|
||||
_gc.Writer.ChangeMode(AsicMode.Write);
|
||||
res = HandleGameCardAccessResult(_gc.Writer.ActivateForWriter());
|
||||
res = ActivateGameCardForWriter();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
tmpBuffer.CopyTo(pooledBuffer.GetBuffer());
|
||||
res = _gc.Writer.Write(pooledBuffer.GetBuffer(), 8, 1);
|
||||
originalHeaderBuffer.CopyTo(pooledBuffer.GetBuffer());
|
||||
res = _gc.Writer.Write(pooledBuffer.GetBuffer(), (uint)GcCardKeyAreaPageCount, 1);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
deviceCert.CopyTo(outBuffer);
|
||||
|
@ -749,25 +777,17 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
|
||||
private Result WriteToGameCardDirectly(long offset, Span<byte> buffer)
|
||||
{
|
||||
Result res;
|
||||
Result result;
|
||||
|
||||
using (new SharedLock<ReaderWriterLock>(_rwLock))
|
||||
{
|
||||
if (buffer.Length == 0)
|
||||
return Result.Success;
|
||||
|
||||
res = _gc.Writer.Write(buffer, BytesToPages(offset), BytesToPages(buffer.Length));
|
||||
result = _gc.Writer.Write(buffer, BytesToPages(offset), BytesToPages(buffer.Length));
|
||||
}
|
||||
|
||||
if (res != Result.Success)
|
||||
{
|
||||
using var writeLock = new UniqueLock<ReaderWriterLock>(_rwLock);
|
||||
res = HandleGameCardAccessResult(res);
|
||||
}
|
||||
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
return Result.Success;
|
||||
return LockAndHandleGameCardAccessResult(result).Ret();
|
||||
}
|
||||
|
||||
private Result ForceEraseGameCard()
|
||||
|
@ -786,24 +806,26 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
|
||||
public Result AcquireReadLock(ref SharedLock<ReaderWriterLock> outLock, GameCardHandle handle)
|
||||
{
|
||||
using var readLock = new SharedLock<ReaderWriterLock>(_rwLock);
|
||||
|
||||
if (_state != CardState.Initial && !_gc.IsCardActivationValid())
|
||||
using (var readLock = new SharedLock<ReaderWriterLock>(_rwLock))
|
||||
{
|
||||
readLock.Unlock();
|
||||
Invalidate().IgnoreResult();
|
||||
if (_state == CardState.Initial || _gc.IsCardActivationValid())
|
||||
{
|
||||
if (_currentHandle == handle)
|
||||
{
|
||||
outLock.Set(ref readLock.Ref());
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
return ResultFs.GameCardFsCheckHandleInAcquireReadLock.Log();
|
||||
return ResultFs.GameCardFsCheckHandleInAcquireReadLock.Log();
|
||||
}
|
||||
}
|
||||
|
||||
if (_currentHandle != handle)
|
||||
return ResultFs.GameCardFsCheckHandleInAcquireReadLock.Log();
|
||||
Invalidate().IgnoreResult();
|
||||
|
||||
outLock.Set(ref readLock.Ref());
|
||||
return Result.Success;
|
||||
return ResultFs.GameCardFsCheckHandleInAcquireReadLock.Log();
|
||||
}
|
||||
|
||||
public Result AcquireSecureLock(ref SharedLock<ReaderWriterLock> outLock, ref GameCardHandle handle,
|
||||
public Result AcquireSecureLock(ref SharedLock<ReaderWriterLock> outLock, ref GameCardHandle inOutHandle,
|
||||
ReadOnlySpan<byte> cardDeviceId, ReadOnlySpan<byte> cardImageHash)
|
||||
{
|
||||
using (var readLock = new SharedLock<ReaderWriterLock>(_rwLock))
|
||||
|
@ -818,7 +840,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
readLock.Unlock();
|
||||
Invalidate().IgnoreResult();
|
||||
}
|
||||
else if (_currentHandle == handle)
|
||||
else if (_currentHandle == inOutHandle)
|
||||
{
|
||||
outLock.Set(ref readLock.Ref());
|
||||
return Result.Success;
|
||||
|
@ -834,8 +856,8 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
return ResultFs.GameCardFsCheckModeInAcquireSecureLock.Log();
|
||||
}
|
||||
|
||||
Span<byte> currentCardDeviceId = stackalloc byte[Values.GcCardDeviceIdSize];
|
||||
Span<byte> currentCardImageHash = stackalloc byte[Values.GcCardImageHashSize];
|
||||
Span<byte> currentCardDeviceId = stackalloc byte[GcCardDeviceIdSize];
|
||||
Span<byte> currentCardImageHash = stackalloc byte[GcCardImageHashSize];
|
||||
|
||||
Result res = HandleGameCardAccessResult(_gc.GetCardDeviceId(currentCardDeviceId));
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
@ -843,8 +865,8 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
res = HandleGameCardAccessResult(_gc.GetCardImageHash(currentCardImageHash));
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
if (!Crypto.CryptoUtil.IsSameBytes(currentCardDeviceId, cardDeviceId, Values.GcCardDeviceIdSize) ||
|
||||
!Crypto.CryptoUtil.IsSameBytes(currentCardImageHash, cardImageHash, Values.GcCardImageHashSize))
|
||||
if (!Crypto.CryptoUtil.IsSameBytes(currentCardDeviceId, cardDeviceId, GcCardDeviceIdSize) ||
|
||||
!Crypto.CryptoUtil.IsSameBytes(currentCardImageHash, cardImageHash, GcCardImageHashSize))
|
||||
return ResultFs.GameCardFsCheckModeInAcquireSecureLock.Log();
|
||||
|
||||
res = GetHandle(out newHandle);
|
||||
|
@ -856,7 +878,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
Result res = AcquireReadLock(ref readLock.Ref(), newHandle);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
handle = newHandle;
|
||||
inOutHandle = newHandle;
|
||||
outLock.Set(ref readLock.Ref());
|
||||
|
||||
return Result.Success;
|
||||
|
@ -876,6 +898,8 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
|
|||
|
||||
public Result HandleGameCardAccessResult(Result result)
|
||||
{
|
||||
Assert.SdkRequires(_rwLock.IsWriteLockHeldByCurrentThread());
|
||||
|
||||
if (result.IsFailure())
|
||||
{
|
||||
DeactivateAndChangeState();
|
||||
|
|
|
@ -4,7 +4,10 @@ using LibHac.Common;
|
|||
using LibHac.Diag;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Gc;
|
||||
using LibHac.Sf;
|
||||
using static LibHac.Gc.Values;
|
||||
using static LibHac.GcSrv.GameCardDeviceOperator;
|
||||
using IStorageSf = LibHac.FsSrv.Sf.IStorage;
|
||||
|
||||
namespace LibHac.GcSrv;
|
||||
|
||||
|
@ -38,8 +41,7 @@ internal class ReadOnlyGameCardStorage : IStorage
|
|||
|
||||
// Missing: Allocate a device buffer if the destination buffer is not one
|
||||
|
||||
return _gc.Read(destination, GameCardManager.BytesToPages(offset),
|
||||
GameCardManager.BytesToPages(destination.Length)).Ret();
|
||||
return _gc.Read(destination, BytesToPages(offset), BytesToPages(destination.Length)).Ret();
|
||||
}
|
||||
|
||||
public override Result Write(long offset, ReadOnlySpan<byte> source)
|
||||
|
@ -123,8 +125,7 @@ internal class WriteOnlyGameCardStorage : IStorage
|
|||
|
||||
// Missing: Allocate a device buffer if the destination buffer is not one
|
||||
|
||||
return _gc.Writer.Write(source, GameCardManager.BytesToPages(offset),
|
||||
GameCardManager.BytesToPages(source.Length)).Ret();
|
||||
return _gc.Writer.Write(source, BytesToPages(offset), BytesToPages(source.Length)).Ret();
|
||||
}
|
||||
|
||||
public override Result Flush()
|
||||
|
@ -154,3 +155,51 @@ internal class WriteOnlyGameCardStorage : IStorage
|
|||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract class GameCardStorageInterfaceAdapter : IStorageSf
|
||||
{
|
||||
private SharedRef<IStorage> _baseStorage;
|
||||
|
||||
protected GameCardStorageInterfaceAdapter(ref SharedRef<IStorage> baseStorage)
|
||||
{
|
||||
_baseStorage = SharedRef<IStorage>.CreateMove(ref baseStorage);
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
_baseStorage.Destroy();
|
||||
}
|
||||
|
||||
public virtual Result Read(long offset, OutBuffer destination, long size)
|
||||
{
|
||||
return _baseStorage.Get.Read(offset, destination.Buffer.Slice(0, (int)size)).Ret();
|
||||
}
|
||||
|
||||
public virtual Result Write(long offset, InBuffer source, long size)
|
||||
{
|
||||
return _baseStorage.Get.Write(offset, source.Buffer.Slice(0, (int)size)).Ret();
|
||||
}
|
||||
|
||||
public virtual Result Flush()
|
||||
{
|
||||
return _baseStorage.Get.Flush().Ret();
|
||||
}
|
||||
|
||||
public virtual Result SetSize(long size)
|
||||
{
|
||||
return _baseStorage.Get.SetSize(size).Ret();
|
||||
}
|
||||
|
||||
public virtual Result GetSize(out long size)
|
||||
{
|
||||
return _baseStorage.Get.GetSize(out size).Ret();
|
||||
}
|
||||
|
||||
public virtual Result OperateRange(out QueryRangeInfo rangeInfo, int operationId, long offset, long size)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out rangeInfo);
|
||||
|
||||
return _baseStorage.Get.OperateRange(SpanHelpers.AsByteSpan(ref rangeInfo), (OperationId)operationId, offset,
|
||||
size, ReadOnlySpan<byte>.Empty).Ret();
|
||||
}
|
||||
}
|
|
@ -7,58 +7,9 @@ using LibHac.FsSrv.Storage.Sf;
|
|||
using LibHac.Gc;
|
||||
using LibHac.Os;
|
||||
using LibHac.Sf;
|
||||
using IStorageSf = LibHac.FsSrv.Sf.IStorage;
|
||||
|
||||
namespace LibHac.GcSrv;
|
||||
|
||||
internal abstract class GameCardStorageInterfaceAdapter : IStorageSf
|
||||
{
|
||||
private SharedRef<IStorage> _baseStorage;
|
||||
|
||||
protected GameCardStorageInterfaceAdapter(ref SharedRef<IStorage> baseStorage)
|
||||
{
|
||||
_baseStorage = SharedRef<IStorage>.CreateMove(ref baseStorage);
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
_baseStorage.Destroy();
|
||||
}
|
||||
|
||||
public virtual Result Read(long offset, OutBuffer destination, long size)
|
||||
{
|
||||
return _baseStorage.Get.Read(offset, destination.Buffer.Slice(0, (int)size)).Ret();
|
||||
}
|
||||
|
||||
public virtual Result Write(long offset, InBuffer source, long size)
|
||||
{
|
||||
return _baseStorage.Get.Write(offset, source.Buffer.Slice(0, (int)size)).Ret();
|
||||
}
|
||||
|
||||
public virtual Result Flush()
|
||||
{
|
||||
return _baseStorage.Get.Flush().Ret();
|
||||
}
|
||||
|
||||
public virtual Result SetSize(long size)
|
||||
{
|
||||
return _baseStorage.Get.SetSize(size).Ret();
|
||||
}
|
||||
|
||||
public virtual Result GetSize(out long size)
|
||||
{
|
||||
return _baseStorage.Get.GetSize(out size).Ret();
|
||||
}
|
||||
|
||||
public virtual Result OperateRange(out QueryRangeInfo rangeInfo, int operationId, long offset, long size)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out rangeInfo);
|
||||
|
||||
return _baseStorage.Get.OperateRange(SpanHelpers.AsByteSpan(ref rangeInfo), (OperationId)operationId, offset,
|
||||
size, ReadOnlySpan<byte>.Empty).Ret();
|
||||
}
|
||||
}
|
||||
|
||||
internal class GameCardStorageDevice : GameCardStorageInterfaceAdapter, IStorageDevice
|
||||
{
|
||||
private SharedRef<IGameCardManager> _manager;
|
||||
|
@ -67,16 +18,23 @@ internal class GameCardStorageDevice : GameCardStorageInterfaceAdapter, IStorage
|
|||
private Array16<byte> _cardDeviceId;
|
||||
private Array32<byte> _cardImageHash;
|
||||
|
||||
public GameCardStorageDevice(ref SharedRef<IGameCardManager> manager, ref SharedRef<IStorage> baseStorage,
|
||||
GameCardHandle handle) : base(ref baseStorage)
|
||||
// LibHac additions
|
||||
private WeakRef<GameCardStorageDevice> _selfReference;
|
||||
private readonly GameCardDummy _gc;
|
||||
|
||||
private GameCardStorageDevice(GameCardDummy gc, ref SharedRef<IGameCardManager> manager,
|
||||
ref SharedRef<IStorage> baseStorage, GameCardHandle handle) : base(ref baseStorage)
|
||||
{
|
||||
_manager = SharedRef<IGameCardManager>.CreateMove(ref manager);
|
||||
_handle = handle;
|
||||
_isSecure = false;
|
||||
|
||||
_gc = gc;
|
||||
}
|
||||
|
||||
public GameCardStorageDevice(ref SharedRef<IGameCardManager> manager, ref SharedRef<IStorage> baseStorage,
|
||||
GameCardHandle handle, bool isSecure, ReadOnlySpan<byte> cardDeviceId, ReadOnlySpan<byte> cardImageHash)
|
||||
private GameCardStorageDevice(GameCardDummy gc, ref SharedRef<IGameCardManager> manager,
|
||||
ref SharedRef<IStorage> baseStorage, GameCardHandle handle, bool isSecure, ReadOnlySpan<byte> cardDeviceId,
|
||||
ReadOnlySpan<byte> cardImageHash)
|
||||
: base(ref baseStorage)
|
||||
{
|
||||
Assert.SdkRequiresEqual(cardDeviceId.Length, Values.GcCardDeviceIdSize);
|
||||
|
@ -88,27 +46,49 @@ internal class GameCardStorageDevice : GameCardStorageInterfaceAdapter, IStorage
|
|||
|
||||
cardDeviceId.CopyTo(_cardDeviceId.Items);
|
||||
cardImageHash.CopyTo(_cardImageHash.Items);
|
||||
|
||||
_gc = gc;
|
||||
}
|
||||
|
||||
public static SharedRef<GameCardStorageDevice> CreateShared(GameCardDummy gc,
|
||||
ref SharedRef<IGameCardManager> manager, ref SharedRef<IStorage> baseStorage, GameCardHandle handle)
|
||||
{
|
||||
var storageDevice = new GameCardStorageDevice(gc, ref manager, ref baseStorage, handle);
|
||||
|
||||
using var sharedStorageDevice = new SharedRef<GameCardStorageDevice>(storageDevice);
|
||||
storageDevice._selfReference.Set(in sharedStorageDevice);
|
||||
|
||||
return SharedRef<GameCardStorageDevice>.CreateMove(ref sharedStorageDevice.Ref);
|
||||
}
|
||||
|
||||
public static SharedRef<GameCardStorageDevice> CreateShared(GameCardDummy gc,
|
||||
ref SharedRef<IGameCardManager> manager, ref SharedRef<IStorage> baseStorage, GameCardHandle handle,
|
||||
bool isSecure, ReadOnlySpan<byte> cardDeviceId, ReadOnlySpan<byte> cardImageHash)
|
||||
{
|
||||
var storageDevice = new GameCardStorageDevice(gc, ref manager, ref baseStorage, handle, isSecure, cardDeviceId,
|
||||
cardImageHash);
|
||||
|
||||
using var sharedStorageDevice = new SharedRef<GameCardStorageDevice>(storageDevice);
|
||||
storageDevice._selfReference.Set(in sharedStorageDevice);
|
||||
|
||||
return SharedRef<GameCardStorageDevice>.CreateMove(ref sharedStorageDevice.Ref);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
_manager.Destroy();
|
||||
_selfReference.Destroy();
|
||||
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
public Result AcquireReadLock(ref SharedLock<ReaderWriterLock> outLock)
|
||||
{
|
||||
if (_isSecure)
|
||||
{
|
||||
Result res = _manager.Get.AcquireSecureLock(ref outLock, ref _handle, _cardDeviceId, _cardImageHash);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
}
|
||||
else
|
||||
{
|
||||
Result res = _manager.Get.AcquireReadLock(ref outLock, _handle);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
}
|
||||
Result res = _isSecure
|
||||
? _manager.Get.AcquireSecureLock(ref outLock, ref _handle, _cardDeviceId, _cardImageHash)
|
||||
: _manager.Get.AcquireReadLock(ref outLock, _handle);
|
||||
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
@ -118,11 +98,23 @@ internal class GameCardStorageDevice : GameCardStorageInterfaceAdapter, IStorage
|
|||
return _manager.Get.AcquireWriteLock(ref outLock).Ret();
|
||||
}
|
||||
|
||||
public Result HandleGameCardAccessResult(Result result)
|
||||
private Result HandleGameCardAccessResultImpl(Result result)
|
||||
{
|
||||
return _manager.Get.HandleGameCardAccessResult(result);
|
||||
}
|
||||
|
||||
public Result HandleGameCardAccessResult(Result result)
|
||||
{
|
||||
if (result.IsSuccess())
|
||||
return Result.Success;
|
||||
|
||||
using var writeLock = new UniqueLock<ReaderWriterLock>();
|
||||
Result res = AcquireWriteLock(ref writeLock.Ref());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
return HandleGameCardAccessResultImpl(result).Ret();
|
||||
}
|
||||
|
||||
public Result GetHandle(out GameCardHandle handle)
|
||||
{
|
||||
handle = _handle;
|
||||
|
@ -140,7 +132,23 @@ internal class GameCardStorageDevice : GameCardStorageInterfaceAdapter, IStorage
|
|||
|
||||
public Result OpenOperator(ref SharedRef<IStorageDeviceOperator> outDeviceOperator)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using var readLock = new SharedLock<ReaderWriterLock>();
|
||||
|
||||
Result res = AcquireReadLock(ref readLock.Ref());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
using SharedRef<GameCardStorageDevice> storageDevice =
|
||||
SharedRef<GameCardStorageDevice>.Create(in _selfReference);
|
||||
|
||||
using var deviceOperator =
|
||||
new SharedRef<GameCardDeviceOperator>(new GameCardDeviceOperator(ref storageDevice.Ref, _gc));
|
||||
|
||||
if (!deviceOperator.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInGameCardManagerG.Log();
|
||||
|
||||
outDeviceOperator.SetByMove(ref deviceOperator.Ref);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public override Result Read(long offset, OutBuffer destination, long size)
|
||||
|
@ -182,15 +190,6 @@ internal class GameCardStorageDevice : GameCardStorageInterfaceAdapter, IStorage
|
|||
resultGetSize = base.GetSize(out size);
|
||||
}
|
||||
|
||||
if (resultGetSize.IsSuccess())
|
||||
return Result.Success;
|
||||
|
||||
using (var writeLock = new UniqueLock<ReaderWriterLock>())
|
||||
{
|
||||
Result res = AcquireWriteLock(ref writeLock.Ref());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
return HandleGameCardAccessResult(resultGetSize).Ret();
|
||||
}
|
||||
return HandleGameCardAccessResult(resultGetSize).Ret();
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ namespace LibHac.GcSrv;
|
|||
internal interface IGameCardManager : IDisposable
|
||||
{
|
||||
Result AcquireReadLock(ref SharedLock<ReaderWriterLock> outLock, GameCardHandle handle);
|
||||
Result AcquireSecureLock(ref SharedLock<ReaderWriterLock> outLock, ref GameCardHandle handle, ReadOnlySpan<byte> cardDeviceId, ReadOnlySpan<byte> cardImageHash);
|
||||
Result AcquireSecureLock(ref SharedLock<ReaderWriterLock> outLock, ref GameCardHandle inOutHandle, ReadOnlySpan<byte> cardDeviceId, ReadOnlySpan<byte> cardImageHash);
|
||||
Result AcquireWriteLock(ref UniqueLock<ReaderWriterLock> outLock);
|
||||
Result HandleGameCardAccessResult(Result result);
|
||||
Result GetHandle(out GameCardHandle outHandle);
|
||||
|
|
Loading…
Reference in a new issue