mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2025-02-09 13:14:46 +01:00
Begin implementing StorageDeviceManagerFactory and GameCardManager
This commit is contained in:
parent
dfd37d314f
commit
43d63086bf
@ -310,8 +310,8 @@ Module,DescriptionStart,DescriptionEnd,Flags,Namespace,Name,Summary
|
||||
2,2955,,,,GameCardFsCheckHandleInGetDeviceCertFailure,
|
||||
2,2956,,,,GameCardFsCheckHandleInGetCardImageHashFailure,
|
||||
2,2957,,,,GameCardFsCheckHandleInChallengeCardExistence,
|
||||
2,2958,,,,GameCardFsCheckHandleInOnAcquireLock,
|
||||
2,2959,,,,GameCardFsCheckModeInOnAcquireSecureLock,
|
||||
2,2958,,,,GameCardFsCheckHandleInAcquireReadLock,
|
||||
2,2959,,,,GameCardFsCheckModeInAcquireSecureLock,
|
||||
2,2960,,,,GameCardFsCheckHandleInCreateReadOnlyFailure,
|
||||
2,2961,,,,GameCardFsCheckHandleInCreateSecureReadOnlyFailure,
|
||||
2,2962,,,,GameCardFsInvalidCompatibilityType,
|
||||
|
|
@ -45,6 +45,12 @@ public enum GameCardSizeInternal : byte
|
||||
Size32Gb = 0xE2
|
||||
}
|
||||
|
||||
public enum GameCardClockRate
|
||||
{
|
||||
ClockRate25 = 25,
|
||||
ClockRate50 = 50
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum GameCardAttribute : byte
|
||||
{
|
||||
|
@ -518,9 +518,9 @@ public static class ResultFs
|
||||
/// <summary>Error code: 2002-2957; Inner value: 0x171a02</summary>
|
||||
public static Result.Base GameCardFsCheckHandleInChallengeCardExistence => new Result.Base(ModuleFs, 2957);
|
||||
/// <summary>Error code: 2002-2958; Inner value: 0x171c02</summary>
|
||||
public static Result.Base GameCardFsCheckHandleInOnAcquireLock => new Result.Base(ModuleFs, 2958);
|
||||
public static Result.Base GameCardFsCheckHandleInAcquireReadLock => new Result.Base(ModuleFs, 2958);
|
||||
/// <summary>Error code: 2002-2959; Inner value: 0x171e02</summary>
|
||||
public static Result.Base GameCardFsCheckModeInOnAcquireSecureLock => new Result.Base(ModuleFs, 2959);
|
||||
public static Result.Base GameCardFsCheckModeInAcquireSecureLock => new Result.Base(ModuleFs, 2959);
|
||||
/// <summary>Error code: 2002-2960; Inner value: 0x172002</summary>
|
||||
public static Result.Base GameCardFsCheckHandleInCreateReadOnlyFailure => new Result.Base(ModuleFs, 2960);
|
||||
/// <summary>Error code: 2002-2961; Inner value: 0x172202</summary>
|
||||
|
@ -136,8 +136,11 @@ public readonly struct BaseStorageService
|
||||
Result res = GetProgramInfo(out ProgramInfo programInfo);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
res = _serviceImpl.OpenDeviceOperator(ref outDeviceOperator, programInfo.AccessControl);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
using var deviceOperator =
|
||||
new SharedRef<IDeviceOperator>(new DeviceOperator(_serviceImpl.FsServer, programInfo.AccessControl,
|
||||
_processId));
|
||||
|
||||
outDeviceOperator.SetByMove(ref deviceOperator.Ref);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
@ -180,13 +183,11 @@ public class BaseStorageServiceImpl
|
||||
{
|
||||
private Configuration _config;
|
||||
|
||||
// LibHac addition
|
||||
private SharedRef<IDeviceOperator> _deviceOperator;
|
||||
internal FileSystemServer FsServer => _config.FsServer;
|
||||
|
||||
public BaseStorageServiceImpl(in Configuration configuration)
|
||||
{
|
||||
_config = configuration;
|
||||
_deviceOperator = new SharedRef<IDeviceOperator>(configuration.DeviceOperator);
|
||||
}
|
||||
|
||||
public struct Configuration
|
||||
@ -196,8 +197,6 @@ public class BaseStorageServiceImpl
|
||||
|
||||
// LibHac additions
|
||||
public FileSystemServer FsServer;
|
||||
// Todo: The DeviceOperator in FS uses mostly global state. Decide how to handle this.
|
||||
public IDeviceOperator DeviceOperator;
|
||||
}
|
||||
|
||||
internal Result GetProgramInfo(out ProgramInfo programInfo, ulong processId)
|
||||
@ -231,12 +230,4 @@ public class BaseStorageServiceImpl
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
}
|
||||
|
||||
// LibHac addition
|
||||
internal Result OpenDeviceOperator(ref SharedRef<IDeviceOperator> outDeviceOperator,
|
||||
AccessControl accessControl)
|
||||
{
|
||||
outDeviceOperator.SetByCopy(in _deviceOperator);
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
using LibHac.Common;
|
||||
using LibHac.Common.Keys;
|
||||
using LibHac.FsSrv.FsCreator;
|
||||
using LibHac.FsSrv.Sf;
|
||||
using LibHac.FsSrv.Storage;
|
||||
using LibHac.FsSystem;
|
||||
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
|
||||
|
||||
@ -10,9 +10,9 @@ namespace LibHac.FsSrv;
|
||||
public class DefaultFsServerObjects
|
||||
{
|
||||
public FileSystemCreatorInterfaces FsCreators { get; set; }
|
||||
public IDeviceOperator DeviceOperator { get; set; }
|
||||
public EmulatedGameCard GameCard { get; set; }
|
||||
public EmulatedSdCard SdCard { get; set; }
|
||||
public EmulatedStorageDeviceManagerFactory StorageDeviceManagerFactory { get; set; }
|
||||
|
||||
public static DefaultFsServerObjects GetDefaultEmulatedCreators(IFileSystem rootFileSystem, KeySet keySet,
|
||||
FileSystemServer fsServer, RandomDataGenerator randomGenerator)
|
||||
@ -39,14 +39,14 @@ public class DefaultFsServerObjects
|
||||
creators.BuiltInStorageFileSystemCreator = new EmulatedBisFileSystemCreator(ref sharedRootFileSystem.Ref);
|
||||
creators.SdCardFileSystemCreator = new EmulatedSdCardFileSystemCreator(sdCard, ref sharedRootFileSystemCopy.Ref);
|
||||
|
||||
var deviceOperator = new EmulatedDeviceOperator(gameCard, sdCard);
|
||||
var storageDeviceManagerFactory = new EmulatedStorageDeviceManagerFactory(fsServer, true);
|
||||
|
||||
return new DefaultFsServerObjects
|
||||
{
|
||||
FsCreators = creators,
|
||||
DeviceOperator = deviceOperator,
|
||||
GameCard = gameCard,
|
||||
SdCard = sdCard
|
||||
SdCard = sdCard,
|
||||
StorageDeviceManagerFactory = storageDeviceManagerFactory
|
||||
};
|
||||
}
|
||||
}
|
@ -31,11 +31,11 @@ public static class FileSystemServerInitializer
|
||||
if (config.FsCreators == null)
|
||||
throw new ArgumentException("FsCreators must not be null");
|
||||
|
||||
if (config.DeviceOperator == null)
|
||||
throw new ArgumentException("DeviceOperator must not be null");
|
||||
if (config.StorageDeviceManagerFactory == null)
|
||||
throw new ArgumentException("StorageDeviceManagerFactory must not be null");
|
||||
|
||||
server.SetDebugFlagEnabled(false);
|
||||
server.Storage.InitializeStorageDeviceManagerFactory(null);
|
||||
server.Storage.InitializeStorageDeviceManagerFactory(config.StorageDeviceManagerFactory);
|
||||
|
||||
FileSystemProxyConfiguration fspConfig = InitializeFileSystemProxy(server, config);
|
||||
|
||||
@ -55,6 +55,9 @@ public static class FileSystemServerInitializer
|
||||
saveService.FixSaveData().IgnoreResult();
|
||||
saveService.RecoverMultiCommit().IgnoreResult();
|
||||
|
||||
config.StorageDeviceManagerFactory.SetReady(StorageDevicePortId.SdCard, null);
|
||||
config.StorageDeviceManagerFactory.SetReady(StorageDevicePortId.GameCard, null);
|
||||
|
||||
// NS usually takes care of this
|
||||
if (client.Fs.IsSdCardInserted())
|
||||
client.Fs.SetSdCardAccessibility(true);
|
||||
@ -86,7 +89,6 @@ public static class FileSystemServerInitializer
|
||||
baseStorageConfig.BisStorageCreator = config.FsCreators.BuiltInStorageCreator;
|
||||
baseStorageConfig.GameCardStorageCreator = config.FsCreators.GameCardStorageCreator;
|
||||
baseStorageConfig.FsServer = server;
|
||||
baseStorageConfig.DeviceOperator = config.DeviceOperator;
|
||||
var baseStorageService = new BaseStorageServiceImpl(in baseStorageConfig);
|
||||
|
||||
var timeService = new TimeServiceImpl(server);
|
||||
@ -263,9 +265,9 @@ public class FileSystemServerConfig
|
||||
public FileSystemCreatorInterfaces FsCreators { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// An <see cref="IDeviceOperator"/> for managing the gamecard and SD card.
|
||||
/// An <see cref="IStorageDeviceManagerFactory"/> for managing the gamecard and SD card.
|
||||
/// </summary>
|
||||
public IDeviceOperator DeviceOperator { get; set; }
|
||||
public IStorageDeviceManagerFactory StorageDeviceManagerFactory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A keyset containing rights IDs and title keys.
|
||||
|
150
src/LibHac/FsSrv/Storage/EmulatedStorageDeviceManagerFactory.cs
Normal file
150
src/LibHac/FsSrv/Storage/EmulatedStorageDeviceManagerFactory.cs
Normal file
@ -0,0 +1,150 @@
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.FsSrv.Storage.Sf;
|
||||
using LibHac.GcSrv;
|
||||
using LibHac.Os;
|
||||
using LibHac.SdmmcSrv;
|
||||
using LibHac.Sf;
|
||||
|
||||
namespace LibHac.FsSrv.Storage;
|
||||
|
||||
public class EmulatedStorageDeviceManagerFactory : IStorageDeviceManagerFactory
|
||||
{
|
||||
private SdkMutexType _gameCardDeviceMutex;
|
||||
private SdkMutexType _sdCardDeviceMutex;
|
||||
private SdkMutexType _mmcDeviceMutex;
|
||||
|
||||
private SharedRef<SdCardManager> _sdCardDeviceManager;
|
||||
private SharedRef<DummyGameCardManager> _dummyGameCardDeviceManager;
|
||||
private SharedRef<GameCardManager> _gameCardDeviceManager;
|
||||
private SharedRef<MmcManager> _mmcDeviceManager;
|
||||
|
||||
private readonly bool _hasGameCard;
|
||||
|
||||
private readonly FileSystemServer _fsServer;
|
||||
|
||||
public EmulatedStorageDeviceManagerFactory(FileSystemServer fsServer, bool hasGameCard)
|
||||
{
|
||||
_fsServer = fsServer;
|
||||
_hasGameCard = hasGameCard;
|
||||
|
||||
_gameCardDeviceMutex = new SdkMutexType();
|
||||
_sdCardDeviceMutex = new SdkMutexType();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_sdCardDeviceManager.Destroy();
|
||||
_dummyGameCardDeviceManager.Destroy();
|
||||
_gameCardDeviceManager.Destroy();
|
||||
_mmcDeviceManager.Destroy();
|
||||
}
|
||||
|
||||
public Result Create(ref SharedRef<IStorageDeviceManager> outDeviceManager, StorageDevicePortId portId)
|
||||
{
|
||||
switch (portId)
|
||||
{
|
||||
case StorageDevicePortId.Mmc:
|
||||
EnsureMmcReady();
|
||||
outDeviceManager.SetByCopy(in _mmcDeviceManager);
|
||||
break;
|
||||
case StorageDevicePortId.SdCard:
|
||||
{
|
||||
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _sdCardDeviceMutex);
|
||||
|
||||
if (!_sdCardDeviceManager.HasValue)
|
||||
return ResultFs.StorageDeviceNotReady.Log();
|
||||
|
||||
outDeviceManager.SetByCopy(in _sdCardDeviceManager);
|
||||
break;
|
||||
}
|
||||
case StorageDevicePortId.GameCard:
|
||||
{
|
||||
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _gameCardDeviceMutex);
|
||||
|
||||
if (!_dummyGameCardDeviceManager.HasValue && !_gameCardDeviceManager.HasValue)
|
||||
return ResultFs.StorageDeviceNotReady.Log();
|
||||
|
||||
if (_hasGameCard)
|
||||
{
|
||||
outDeviceManager.SetByCopy(in _gameCardDeviceManager);
|
||||
}
|
||||
else
|
||||
{
|
||||
outDeviceManager.SetByCopy(in _dummyGameCardDeviceManager);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return ResultFs.StorageDeviceInvalidOperation.Log();
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result SetReady(StorageDevicePortId portId, NativeHandle handle)
|
||||
{
|
||||
switch (portId)
|
||||
{
|
||||
case StorageDevicePortId.Mmc:
|
||||
EnsureMmcReady();
|
||||
break;
|
||||
case StorageDevicePortId.SdCard:
|
||||
EnsureSdCardReady();
|
||||
break;
|
||||
case StorageDevicePortId.GameCard:
|
||||
EnsureGameCardReady();
|
||||
break;
|
||||
default:
|
||||
return ResultFs.StorageDeviceInvalidOperation.Log();
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result UnsetReady(StorageDevicePortId portId)
|
||||
{
|
||||
return ResultFs.StorageDeviceInvalidOperation.Log();
|
||||
}
|
||||
|
||||
private void EnsureMmcReady()
|
||||
{
|
||||
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _mmcDeviceMutex);
|
||||
|
||||
if (!_mmcDeviceManager.HasValue)
|
||||
{
|
||||
_mmcDeviceManager.Reset(new MmcManager());
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureSdCardReady()
|
||||
{
|
||||
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _sdCardDeviceMutex);
|
||||
|
||||
if (!_sdCardDeviceManager.HasValue)
|
||||
{
|
||||
_sdCardDeviceManager.Reset(new SdCardManager());
|
||||
|
||||
// Todo: BuiltInStorageFileSystemCreator::SetSdCardPortReady
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureGameCardReady()
|
||||
{
|
||||
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _gameCardDeviceMutex);
|
||||
|
||||
if (!_dummyGameCardDeviceManager.HasValue && !_gameCardDeviceManager.HasValue)
|
||||
{
|
||||
if (_hasGameCard)
|
||||
{
|
||||
using SharedRef<GameCardManager> manger = GameCardManager.CreateShared(_fsServer);
|
||||
_gameCardDeviceManager.SetByMove(ref manger.Ref);
|
||||
}
|
||||
else
|
||||
{
|
||||
_dummyGameCardDeviceManager.Reset(new DummyGameCardManager());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -8,8 +8,8 @@ namespace LibHac.FsSrv.Storage.Sf;
|
||||
public interface IStorageDeviceManager : IDisposable
|
||||
{
|
||||
Result IsInserted(out bool isInserted);
|
||||
Result IsHandleValid(out bool isValid, uint handle);
|
||||
Result OpenDetectionEvent(ref SharedRef<IEventNotifier> outEventNotifier);
|
||||
Result IsHandleValid(out bool isValid, GameCardHandle handle);
|
||||
Result OpenDetectionEvent(ref SharedRef<IEventNotifier> outDetectionEvent);
|
||||
Result OpenOperator(ref SharedRef<IStorageDeviceOperator> outDeviceOperator);
|
||||
Result OpenDevice(ref SharedRef<IStorageDevice> outStorageDevice, ulong attribute);
|
||||
Result OpenStorage(ref SharedRef<IStorageSf> outStorage, ulong attribute);
|
||||
|
@ -33,7 +33,7 @@ internal static class StorageDeviceManagerFactory
|
||||
IStorageDeviceManagerFactory factory = storage.GetStorageDeviceManagerFactory(null);
|
||||
Assert.SdkNotNull(factory);
|
||||
|
||||
return factory.Create(ref outDeviceManager, portId);
|
||||
return factory.Create(ref outDeviceManager, portId).Ret();
|
||||
}
|
||||
|
||||
public static IStorageDeviceManagerFactory GetStorageDeviceManagerFactory(this StorageService storage,
|
||||
|
76
src/LibHac/FsSystem/CardDeviceDetectionEvent.cs
Normal file
76
src/LibHac/FsSystem/CardDeviceDetectionEvent.cs
Normal file
@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using LibHac.Common;
|
||||
using LibHac.FsSrv.Sf;
|
||||
using LibHac.Os;
|
||||
using LibHac.Sf;
|
||||
|
||||
namespace LibHac.FsSystem;
|
||||
|
||||
internal class CardDeviceDetectionEventManager : IDisposable
|
||||
{
|
||||
private LinkedList<CardDeviceDetectionEvent> _events;
|
||||
private SdkMutex _mutex;
|
||||
protected CallbackArguments CallbackArgs;
|
||||
|
||||
protected class CallbackArguments
|
||||
{
|
||||
public CardDeviceDetectionEventManager EventManager;
|
||||
public SdkMutex Mutex;
|
||||
public Sdmmc.Port Port;
|
||||
}
|
||||
|
||||
public CardDeviceDetectionEventManager()
|
||||
{
|
||||
_events = new LinkedList<CardDeviceDetectionEvent>();
|
||||
_mutex = new SdkMutex();
|
||||
|
||||
CallbackArgs = new CallbackArguments { EventManager = this, Mutex = _mutex };
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result CreateDetectionEvent(ref SharedRef<IEventNotifier> outDetectionEvent)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Unlink(CardDeviceDetectionEvent detectionEvent)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SignalAll()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected static void DetectionEventCallback(object args)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
internal class CardDeviceDetectionEvent : IEventNotifier
|
||||
{
|
||||
private CardDeviceDetectionEventManager _eventManager;
|
||||
// Todo: SystemEvent
|
||||
|
||||
public CardDeviceDetectionEvent(CardDeviceDetectionEventManager eventManager)
|
||||
{
|
||||
_eventManager = eventManager;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result GetEventHandle(out NativeHandle handle)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
200
src/LibHac/Gc/GameCardDummy.cs
Normal file
200
src/LibHac/Gc/GameCardDummy.cs
Normal file
@ -0,0 +1,200 @@
|
||||
using System;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Gc.Impl;
|
||||
using LibHac.Gc.Writer;
|
||||
|
||||
namespace LibHac.Gc;
|
||||
|
||||
public class GameCardDummy
|
||||
{
|
||||
public GameCardWriter Writer => new GameCardWriter();
|
||||
|
||||
public readonly struct GameCardWriter
|
||||
{
|
||||
public GameCardWriter()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void ChangeMode(AsicMode mode)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result ActivateForWriter()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result EraseAndWriteParameter(MemorySize size, uint romAreaStartPageIndex)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result Write(ReadOnlySpan<byte> source, uint pageIndex, uint pageCount)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result GetCardAvailableRawSize(out long outSize)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SetVerifyEnableFlag(bool isEnabled)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SetUserAsicFirmwareBuffer(ReadOnlySpan<byte> firmwareBuffer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result GetRmaInformation(out RmaInformation outRmaInformation)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result WriteDevCardParam(in DevCardParameter devCardParam)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result ReadDevCardParam(out DevCardParameter outDevCardParam)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result ForceErase()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public void PresetInternalKeys(ReadOnlySpan<byte> gameCardKey, ReadOnlySpan<byte> gameCardCertificate)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Initialize(Memory<byte> workBuffer, ulong deviceBufferAddress)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void FinalizeGc()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void PowerOffGameCard()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void RegisterDeviceVirtualAddress(Memory<byte> buffer, ulong deviceBufferAddress)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void UnregisterDeviceVirtualAddress(Memory<byte> buffer, ulong deviceBufferAddress)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result GetInitializationResult()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result Activate()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Deactivate()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result SetCardToSecureMode()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result Read(Span<byte> destination, uint pageIndex, uint pageCount)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void PutToSleep()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Awaken()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsCardInserted()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsCardActivationValid()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result GetCardStatus(out GameCardStatus outStatus)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result GetCardDeviceId(Span<byte> destBuffer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result GetCardDeviceCertificate(Span<byte> destBuffer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result ChallengeCardExistence(Span<byte> responseBuffer, ReadOnlySpan<byte> challengeSeedBuffer,
|
||||
ReadOnlySpan<byte> challengeValueBuffer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result GetCardImageHash(Span<byte> destBuffer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result GetGameCardIdSet(out GameCardIdSet outGcIdSet)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void RegisterDetectionEventCallback(Action<object> function, object args)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void UnregisterDetectionEventCallback()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result GetCardHeader(Span<byte> destBuffer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result GetErrorInfo(out GameCardErrorReportInfo outErrorReportInfo)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
@ -22,6 +22,11 @@ public struct CardId3
|
||||
public Array4<byte> Reserved;
|
||||
}
|
||||
|
||||
public struct DevCardParameter
|
||||
{
|
||||
public Array512<byte> Data;
|
||||
}
|
||||
|
||||
public struct CardInitialDataPayload
|
||||
{
|
||||
public Array8<byte> PackageId;
|
||||
|
19
src/LibHac/Gc/Writer/WriterTypes.cs
Normal file
19
src/LibHac/Gc/Writer/WriterTypes.cs
Normal file
@ -0,0 +1,19 @@
|
||||
namespace LibHac.Gc.Writer;
|
||||
|
||||
public enum AsicMode : byte
|
||||
{
|
||||
Read = 0,
|
||||
Write = 1
|
||||
}
|
||||
|
||||
public enum MemorySize
|
||||
{
|
||||
// ReSharper disable InconsistentNaming
|
||||
Size1GB = 1,
|
||||
Size2GB = 2,
|
||||
Size4GB = 4,
|
||||
Size8GB = 8,
|
||||
Size16GB = 16,
|
||||
Size32GB = 32
|
||||
// ReSharper restore InconsistentNaming
|
||||
}
|
189
src/LibHac/GcSrv/DummyGameCardManager.cs
Normal file
189
src/LibHac/GcSrv/DummyGameCardManager.cs
Normal file
@ -0,0 +1,189 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.FsSrv.Sf;
|
||||
using LibHac.FsSrv.Storage.Sf;
|
||||
using LibHac.Sf;
|
||||
using IStorageSf = LibHac.FsSrv.Sf.IStorage;
|
||||
|
||||
namespace LibHac.GcSrv;
|
||||
|
||||
public class DummyGameCardManager : IStorageDeviceManager, IStorageDeviceOperator
|
||||
{
|
||||
public DummyGameCardManager()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result IsInserted(out bool isInserted)
|
||||
{
|
||||
isInserted = false;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result IsHandleValid(out bool isValid, uint handle)
|
||||
{
|
||||
isValid = false;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenDetectionEvent(ref SharedRef<IEventNotifier> outDetectionEvent)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result OpenOperator(ref SharedRef<IStorageDeviceOperator> outDeviceOperator)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result OpenDevice(ref SharedRef<IStorageDevice> outStorageDevice, ulong attribute)
|
||||
{
|
||||
return ResultFs.GameCardCardNotInserted.Log();
|
||||
}
|
||||
|
||||
public Result OpenStorage(ref SharedRef<IStorageSf> outStorage, ulong attribute)
|
||||
{
|
||||
return ResultFs.GameCardCardNotInserted.Log();
|
||||
}
|
||||
|
||||
public Result Invalidate()
|
||||
{
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result Operate(int operationId)
|
||||
{
|
||||
var operation = (GameCardManagerOperationIdValue)operationId;
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case GameCardManagerOperationIdValue.Finalize:
|
||||
return Result.Success;
|
||||
|
||||
case GameCardManagerOperationIdValue.GetInitializationResult:
|
||||
return Result.Success;
|
||||
|
||||
case GameCardManagerOperationIdValue.ForceErase:
|
||||
return ResultFs.GameCardCardNotInserted.Log();
|
||||
|
||||
case GameCardManagerOperationIdValue.SimulateDetectionEventSignaled:
|
||||
return ResultFs.GameCardNotSupportedOnDeviceModel.Log();
|
||||
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
}
|
||||
|
||||
public Result OperateIn(InBuffer buffer, long offset, long size, int operationId)
|
||||
{
|
||||
var operation = (GameCardManagerOperationIdValue)operationId;
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case GameCardManagerOperationIdValue.SetVerifyEnableFlag:
|
||||
return Result.Success;
|
||||
|
||||
case GameCardManagerOperationIdValue.EraseAndWriteParamDirectly:
|
||||
return ResultFs.GameCardCardNotInserted.Log();
|
||||
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
}
|
||||
|
||||
public Result OperateOut(out long bytesWritten, OutBuffer buffer, int operationId)
|
||||
{
|
||||
var operation = (GameCardManagerOperationIdValue)operationId;
|
||||
bytesWritten = 0;
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case GameCardManagerOperationIdValue.GetHandle:
|
||||
{
|
||||
return ResultFs.GameCardCardNotInserted.Log();
|
||||
}
|
||||
case GameCardManagerOperationIdValue.GetGameCardErrorInfo:
|
||||
{
|
||||
if (buffer.Size < Unsafe.SizeOf<GameCardErrorInfo>())
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
buffer.As<GameCardErrorInfo>() = default;
|
||||
bytesWritten = Unsafe.SizeOf<GameCardErrorInfo>();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
case GameCardManagerOperationIdValue.GetGameCardErrorReportInfo:
|
||||
{
|
||||
if (buffer.Size < Unsafe.SizeOf<GameCardErrorReportInfo>())
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
buffer.As<GameCardErrorReportInfo>() = default;
|
||||
bytesWritten = Unsafe.SizeOf<GameCardErrorReportInfo>();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
case GameCardManagerOperationIdValue.ReadParamDirectly:
|
||||
{
|
||||
return ResultFs.GameCardCardNotInserted.Log();
|
||||
}
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
}
|
||||
|
||||
public Result OperateOut2(out long bytesWrittenBuffer1, OutBuffer buffer1, out long bytesWrittenBuffer2,
|
||||
OutBuffer buffer2, int operationId)
|
||||
{
|
||||
bytesWrittenBuffer1 = 0;
|
||||
bytesWrittenBuffer2 = 0;
|
||||
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
public Result OperateInOut(out long bytesWritten, OutBuffer outBuffer, InBuffer inBuffer, long offset, long size,
|
||||
int operationId)
|
||||
{
|
||||
var operation = (GameCardManagerOperationIdValue)operationId;
|
||||
bytesWritten = 0;
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case GameCardManagerOperationIdValue.IsGameCardActivationValid:
|
||||
{
|
||||
if (outBuffer.Size < Unsafe.SizeOf<bool>())
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
outBuffer.As<bool>() = false;
|
||||
bytesWritten = sizeof(bool);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
case GameCardManagerOperationIdValue.GetGameCardAsicInfo:
|
||||
return ResultFs.GameCardAccessFailed.Log();
|
||||
|
||||
case GameCardManagerOperationIdValue.GetGameCardDeviceIdForProdCard:
|
||||
return ResultFs.GameCardCardNotInserted.Log();
|
||||
|
||||
case GameCardManagerOperationIdValue.WriteToGameCardDirectly:
|
||||
return ResultFs.GameCardCardNotInserted.Log();
|
||||
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
}
|
||||
|
||||
public Result OperateIn2Out(out long bytesWritten, OutBuffer outBuffer, InBuffer inBuffer1, InBuffer inBuffer2,
|
||||
long offset, long size, int operationId)
|
||||
{
|
||||
bytesWritten = 0;
|
||||
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
}
|
17
src/LibHac/GcSrv/GameCardDeviceDetectionEventManager.cs
Normal file
17
src/LibHac/GcSrv/GameCardDeviceDetectionEventManager.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using LibHac.FsSystem;
|
||||
|
||||
namespace LibHac.GcSrv;
|
||||
|
||||
internal class GameCardDeviceDetectionEventManager : CardDeviceDetectionEventManager
|
||||
{
|
||||
public GameCardDeviceDetectionEventManager()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
897
src/LibHac/GcSrv/GameCardManager.cs
Normal file
897
src/LibHac/GcSrv/GameCardManager.cs
Normal file
@ -0,0 +1,897 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Diag;
|
||||
using LibHac.Fs;
|
||||
using LibHac.FsSrv;
|
||||
using LibHac.FsSrv.Sf;
|
||||
using LibHac.FsSrv.Storage.Sf;
|
||||
using LibHac.FsSystem;
|
||||
using LibHac.Gc;
|
||||
using LibHac.Gc.Impl;
|
||||
using LibHac.Gc.Writer;
|
||||
using LibHac.Os;
|
||||
using LibHac.Sf;
|
||||
using IStorage = LibHac.FsSrv.Sf.IStorage;
|
||||
|
||||
namespace LibHac.GcSrv;
|
||||
|
||||
public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IGameCardDeviceManager
|
||||
{
|
||||
private enum CardState
|
||||
{
|
||||
Initial = 0,
|
||||
Normal = 1,
|
||||
Secure = 2,
|
||||
Write = 3
|
||||
}
|
||||
|
||||
private ReaderWriterLock _rwLock;
|
||||
private bool _isInitialized;
|
||||
private bool _isFinalized;
|
||||
private CardState _state;
|
||||
private GameCardHandle _currentHandle;
|
||||
private GameCardDeviceDetectionEventManager _detectionEventManager;
|
||||
|
||||
// LibHac additions
|
||||
private WeakRef<GameCardManager> _selfReference;
|
||||
private readonly FileSystemServer _fsServer;
|
||||
private readonly GameCardDummy _gc;
|
||||
|
||||
private GameCardManager(FileSystemServer fsServer)
|
||||
{
|
||||
_rwLock = new ReaderWriterLock(fsServer.Hos.Os);
|
||||
|
||||
_fsServer = fsServer;
|
||||
}
|
||||
|
||||
public static SharedRef<GameCardManager> CreateShared(FileSystemServer fsServer)
|
||||
{
|
||||
var manager = new GameCardManager(fsServer);
|
||||
|
||||
using var sharedManager = new SharedRef<GameCardManager>(manager);
|
||||
manager._selfReference.Set(in sharedManager);
|
||||
|
||||
return SharedRef<GameCardManager>.CreateMove(ref sharedManager.Ref);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_detectionEventManager?.Dispose();
|
||||
_detectionEventManager = null;
|
||||
|
||||
_rwLock?.Dispose();
|
||||
_rwLock = null;
|
||||
}
|
||||
|
||||
private uint BytesToPages(long byteCount)
|
||||
{
|
||||
return (uint)((ulong)byteCount / (ulong)Values.GcPageSize);
|
||||
}
|
||||
|
||||
private void DeactivateAndChangeState()
|
||||
{
|
||||
_gc.Deactivate();
|
||||
_currentHandle++;
|
||||
_state = CardState.Initial;
|
||||
}
|
||||
|
||||
private void CheckGameCardAndDeactivate()
|
||||
{
|
||||
if (_state != CardState.Initial && !_gc.IsCardActivationValid())
|
||||
{
|
||||
DeactivateAndChangeState();
|
||||
}
|
||||
}
|
||||
|
||||
private Result ActivateGameCard()
|
||||
{
|
||||
Result res = HandleGameCardAccessResult(_gc.Activate());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private Result ActivateGameCardForWriter()
|
||||
{
|
||||
return HandleGameCardAccessResult(_gc.Writer.ActivateForWriter());
|
||||
}
|
||||
|
||||
private Result SetGameCardToSecureMode()
|
||||
{
|
||||
return HandleGameCardAccessResult(_gc.SetCardToSecureMode());
|
||||
}
|
||||
|
||||
public Result IsInserted(out bool isInserted)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out isInserted);
|
||||
|
||||
Result res = InitializeGcLibrary();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
isInserted = _gc.IsCardInserted();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result InitializeGcLibrary()
|
||||
{
|
||||
using var writeLock = new UniqueLock<ReaderWriterLock>(_rwLock);
|
||||
|
||||
if (_isFinalized)
|
||||
return ResultFs.PreconditionViolation.Log();
|
||||
|
||||
if (_isInitialized)
|
||||
return Result.Success;
|
||||
|
||||
// Missing: Wait on settings-ready event
|
||||
// Missing: Allocate work buffer and pass it to nn::gc::Initialize
|
||||
_gc.Initialize(default, default);
|
||||
// Missing: Register the device buffer
|
||||
|
||||
_detectionEventManager = new GameCardDeviceDetectionEventManager();
|
||||
_isInitialized = true;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private Result EnsureGameCardNormalMode(out GameCardHandle outNewHandle)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out outNewHandle);
|
||||
|
||||
if (_state == CardState.Normal)
|
||||
CheckGameCardAndDeactivate();
|
||||
|
||||
switch (_state)
|
||||
{
|
||||
case CardState.Initial:
|
||||
{
|
||||
// Initial -> Normal
|
||||
Result res = ActivateGameCard();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
_state = CardState.Normal;
|
||||
|
||||
break;
|
||||
}
|
||||
case CardState.Normal:
|
||||
{
|
||||
outNewHandle = _currentHandle;
|
||||
return Result.Success;
|
||||
}
|
||||
case CardState.Secure:
|
||||
{
|
||||
// Secure -> Initial -> Normal
|
||||
DeactivateAndChangeState();
|
||||
|
||||
Result res = ActivateGameCard();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
_state = CardState.Normal;
|
||||
|
||||
break;
|
||||
}
|
||||
case CardState.Write:
|
||||
{
|
||||
// Write -> Initial -> Normal
|
||||
DeactivateAndChangeState();
|
||||
_gc.Writer.ChangeMode(AsicMode.Read);
|
||||
|
||||
Result res = ActivateGameCard();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
_state = CardState.Normal;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Abort.UnexpectedDefault();
|
||||
break;
|
||||
}
|
||||
|
||||
outNewHandle = _currentHandle;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private Result EnsureGameCardSecureMode(out GameCardHandle outNewHandle)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out outNewHandle);
|
||||
|
||||
if (_state == CardState.Secure)
|
||||
CheckGameCardAndDeactivate();
|
||||
|
||||
switch (_state)
|
||||
{
|
||||
case CardState.Initial:
|
||||
{
|
||||
// Initial -> Normal -> Secure
|
||||
Result res = ActivateGameCard();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
_state = CardState.Normal;
|
||||
|
||||
res = SetGameCardToSecureMode();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
_state = CardState.Secure;
|
||||
|
||||
break;
|
||||
}
|
||||
case CardState.Normal:
|
||||
{
|
||||
// Normal -> Secure
|
||||
Result res = SetGameCardToSecureMode();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
_state = CardState.Secure;
|
||||
|
||||
break;
|
||||
}
|
||||
case CardState.Secure:
|
||||
{
|
||||
outNewHandle = _currentHandle;
|
||||
return Result.Success;
|
||||
}
|
||||
case CardState.Write:
|
||||
{
|
||||
// Write -> Initial -> Normal -> Secure
|
||||
DeactivateAndChangeState();
|
||||
_gc.Writer.ChangeMode(AsicMode.Read);
|
||||
|
||||
Result res = ActivateGameCard();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
_state = CardState.Normal;
|
||||
|
||||
res = SetGameCardToSecureMode();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
_state = CardState.Secure;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Abort.UnexpectedDefault();
|
||||
break;
|
||||
}
|
||||
|
||||
outNewHandle = _currentHandle;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private Result EnsureGameCardWriteMode(out GameCardHandle outNewHandle)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out outNewHandle);
|
||||
|
||||
switch (_state)
|
||||
{
|
||||
case CardState.Initial:
|
||||
{
|
||||
// Initial -> Write
|
||||
_gc.Writer.ChangeMode(AsicMode.Write);
|
||||
Result res = ActivateGameCardForWriter();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
_state = CardState.Write;
|
||||
|
||||
break;
|
||||
}
|
||||
case CardState.Normal:
|
||||
case CardState.Secure:
|
||||
{
|
||||
// Normal/Secure -> Initial -> Write
|
||||
DeactivateAndChangeState();
|
||||
|
||||
_gc.Writer.ChangeMode(AsicMode.Write);
|
||||
Result res = ActivateGameCardForWriter();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
_state = CardState.Write;
|
||||
|
||||
break;
|
||||
}
|
||||
case CardState.Write:
|
||||
{
|
||||
outNewHandle = _currentHandle;
|
||||
return Result.Success;
|
||||
}
|
||||
default:
|
||||
Abort.UnexpectedDefault();
|
||||
break;
|
||||
}
|
||||
|
||||
outNewHandle = _currentHandle;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result IsHandleValid(out bool isValid, GameCardHandle handle)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out isValid);
|
||||
|
||||
Result res = InitializeGcLibrary();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
using var readLock = new SharedLock<ReaderWriterLock>();
|
||||
isValid = AcquireReadLock(ref readLock.Ref(), handle).IsSuccess();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenDetectionEvent(ref SharedRef<IEventNotifier> outDetectionEvent)
|
||||
{
|
||||
Result res = InitializeGcLibrary();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
res = _detectionEventManager.CreateDetectionEvent(ref outDetectionEvent);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenOperator(ref SharedRef<IStorageDeviceOperator> outDeviceOperator)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result OpenDevice(ref SharedRef<IStorageDevice> outStorageDevice, ulong attribute)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result OpenStorage(ref SharedRef<IStorage> outStorage, ulong attribute)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result PutToSleep()
|
||||
{
|
||||
using var writeLock = new UniqueLock<ReaderWriterLock>(_rwLock);
|
||||
_gc.PutToSleep();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result Awaken()
|
||||
{
|
||||
using var writeLock = new UniqueLock<ReaderWriterLock>(_rwLock);
|
||||
_gc.Awaken();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result Shutdown()
|
||||
{
|
||||
using var writeLock = new UniqueLock<ReaderWriterLock>(_rwLock);
|
||||
_gc.PutToSleep();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result Invalidate()
|
||||
{
|
||||
using var writeLock = new UniqueLock<ReaderWriterLock>(_rwLock);
|
||||
DeactivateAndChangeState();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result Operate(int operationId)
|
||||
{
|
||||
var operation = (GameCardManagerOperationIdValue)operationId;
|
||||
|
||||
Result res = InitializeGcLibrary();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case GameCardManagerOperationIdValue.Finalize:
|
||||
FinalizeGcLibrary();
|
||||
return Result.Success;
|
||||
|
||||
case GameCardManagerOperationIdValue.GetInitializationResult:
|
||||
return GetInitializationResult().Ret();
|
||||
|
||||
case GameCardManagerOperationIdValue.ForceErase:
|
||||
return ForceEraseGameCard().Ret();
|
||||
|
||||
case GameCardManagerOperationIdValue.SimulateDetectionEventSignaled:
|
||||
_detectionEventManager.SignalAll();
|
||||
return Result.Success;
|
||||
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
}
|
||||
|
||||
public Result OperateIn(InBuffer buffer, long offset, long size, int operationId)
|
||||
{
|
||||
var operation = (GameCardManagerOperationIdValue)operationId;
|
||||
|
||||
Result res = InitializeGcLibrary();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
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();
|
||||
|
||||
res = EraseAndWriteParamDirectly(buffer.Buffer);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
return Result.Success;
|
||||
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
}
|
||||
|
||||
public Result OperateOut(out long bytesWritten, OutBuffer buffer, int operationId)
|
||||
{
|
||||
var operation = (GameCardManagerOperationIdValue)operationId;
|
||||
bytesWritten = 0;
|
||||
|
||||
Result res = InitializeGcLibrary();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case GameCardManagerOperationIdValue.GetHandle:
|
||||
{
|
||||
using var writeLock = new UniqueLock<ReaderWriterLock>(_rwLock);
|
||||
|
||||
if (buffer.Size < sizeof(GameCardHandle))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
res = GetHandle(out buffer.As<GameCardHandle>());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
bytesWritten = sizeof(GameCardHandle);
|
||||
return Result.Success;
|
||||
}
|
||||
case GameCardManagerOperationIdValue.GetGameCardErrorInfo:
|
||||
if (buffer.Size < Unsafe.SizeOf<GameCardErrorInfo>())
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
res = GetGameCardErrorInfo(out buffer.As<GameCardErrorInfo>());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
bytesWritten = Unsafe.SizeOf<GameCardErrorInfo>();
|
||||
return Result.Success;
|
||||
|
||||
case GameCardManagerOperationIdValue.GetGameCardErrorReportInfo:
|
||||
if (buffer.Size < Unsafe.SizeOf<GameCardErrorReportInfo>())
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
res = GetGameCardErrorReportInfo(out buffer.As<GameCardErrorReportInfo>());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
bytesWritten = Unsafe.SizeOf<GameCardErrorReportInfo>();
|
||||
return Result.Success;
|
||||
|
||||
case GameCardManagerOperationIdValue.ReadParamDirectly:
|
||||
if (buffer.Size < Unsafe.SizeOf<DevCardParameter>())
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
res = ReadParamDirectly(buffer.Buffer);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
bytesWritten = Unsafe.SizeOf<DevCardParameter>();
|
||||
return Result.Success;
|
||||
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
var operation = (GameCardManagerOperationIdValue)operationId;
|
||||
bytesWritten = 0;
|
||||
|
||||
Result res = InitializeGcLibrary();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case GameCardManagerOperationIdValue.IsGameCardActivationValid:
|
||||
if (inBuffer.Size != sizeof(GameCardHandle))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
if (outBuffer.Size < sizeof(bool))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
outBuffer.As<bool>() = IsGameCardActivationValid(inBuffer.As<GameCardHandle>());
|
||||
bytesWritten = sizeof(bool);
|
||||
|
||||
return Result.Success;
|
||||
|
||||
case GameCardManagerOperationIdValue.GetGameCardAsicInfo:
|
||||
if (inBuffer.Size != Values.GcAsicFirmwareSize)
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
if (outBuffer.Size < Unsafe.SizeOf<RmaInformation>())
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
res = GetGameCardAsicInfo(out RmaInformation rmaInfo, inBuffer.Buffer);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
SpanHelpers.AsReadOnlyByteSpan(in rmaInfo).CopyTo(outBuffer.Buffer);
|
||||
bytesWritten = Unsafe.SizeOf<RmaInformation>();
|
||||
|
||||
return Result.Success;
|
||||
|
||||
case GameCardManagerOperationIdValue.GetGameCardDeviceIdForProdCard:
|
||||
if (inBuffer.Size < Values.GcPageSize)
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
if (outBuffer.Size < Values.GcPageSize)
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
res = GetGameCardDeviceIdForProdCard(outBuffer.Buffer, inBuffer.Buffer);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
bytesWritten = Values.GcPageSize;
|
||||
|
||||
return Result.Success;
|
||||
|
||||
case GameCardManagerOperationIdValue.WriteToGameCardDirectly:
|
||||
return WriteToGameCardDirectly(offset, outBuffer.Buffer.Slice(0, (int)size)).Ret();
|
||||
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
}
|
||||
|
||||
public Result OperateIn2Out(out long bytesWritten, OutBuffer outBuffer, InBuffer inBuffer1, InBuffer inBuffer2,
|
||||
long offset, long size, int operationId)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out bytesWritten);
|
||||
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
private void FinalizeGcLibrary()
|
||||
{
|
||||
using var writeLock = new UniqueLock<ReaderWriterLock>(_rwLock);
|
||||
|
||||
if (_isInitialized)
|
||||
{
|
||||
_gc.UnregisterDetectionEventCallback();
|
||||
_isFinalized = true;
|
||||
_gc.FinalizeGc();
|
||||
// nn::gc::UnregisterDeviceVirtualAddress
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsGameCardActivationValid(GameCardHandle handle)
|
||||
{
|
||||
using var writeLock = new UniqueLock<ReaderWriterLock>(_rwLock);
|
||||
|
||||
return handle == _currentHandle && _gc.IsCardActivationValid();
|
||||
}
|
||||
|
||||
private Result GetInitializationResult()
|
||||
{
|
||||
return _gc.GetInitializationResult();
|
||||
}
|
||||
|
||||
private Result GetGameCardErrorInfo(out GameCardErrorInfo outErrorInfo)
|
||||
{
|
||||
outErrorInfo = default;
|
||||
|
||||
Result res = _gc.GetErrorInfo(out GameCardErrorReportInfo errorInfo);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
outErrorInfo.GameCardCrcErrorCount = errorInfo.ErrorInfo.GameCardCrcErrorCount;
|
||||
outErrorInfo.AsicCrcErrorCount = errorInfo.ErrorInfo.AsicCrcErrorCount;
|
||||
outErrorInfo.RefreshCount = errorInfo.ErrorInfo.RefreshCount;
|
||||
outErrorInfo.TimeoutRetryErrorCount = errorInfo.ErrorInfo.TimeoutRetryErrorCount;
|
||||
outErrorInfo.ReadRetryCount = errorInfo.ErrorInfo.ReadRetryCount;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private Result GetGameCardErrorReportInfo(out GameCardErrorReportInfo outErrorInfo)
|
||||
{
|
||||
Result res = _gc.GetErrorInfo(out outErrorInfo);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private void SetVerifyEnableFlag(bool isEnabled)
|
||||
{
|
||||
_gc.Writer.SetVerifyEnableFlag(isEnabled);
|
||||
}
|
||||
|
||||
private Result GetGameCardAsicInfo(out RmaInformation outRmaInfo, ReadOnlySpan<byte> asicFirmwareBuffer)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out outRmaInfo);
|
||||
|
||||
Assert.SdkRequiresEqual(asicFirmwareBuffer.Length, Values.GcAsicFirmwareSize);
|
||||
|
||||
_gc.Writer.SetUserAsicFirmwareBuffer(asicFirmwareBuffer);
|
||||
_gc.Writer.ChangeMode(AsicMode.Write);
|
||||
|
||||
Result res = _gc.Writer.GetRmaInformation(out RmaInformation rmaInfo);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
outRmaInfo = rmaInfo;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private Result GetGameCardDeviceIdForProdCard(Span<byte> outBuffer, ReadOnlySpan<byte> devHeaderBuffer)
|
||||
{
|
||||
Assert.SdkRequiresGreaterEqual(outBuffer.Length, Values.GcPageSize);
|
||||
Assert.SdkRequiresGreaterEqual(devHeaderBuffer.Length, Values.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);
|
||||
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();
|
||||
|
||||
_gc.GetCardHeader(pooledBuffer.GetBuffer());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
pooledBuffer.GetBuffer().CopyTo(tmpBuffer);
|
||||
|
||||
// Write the provided card header
|
||||
_gc.Writer.ChangeMode(AsicMode.Write);
|
||||
res = HandleGameCardAccessResult(_gc.Writer.ActivateForWriter());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
devHeaderBuffer.CopyTo(pooledBuffer.GetBuffer());
|
||||
res = _gc.Writer.Write(pooledBuffer.GetBuffer(), 8, 1);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
// Read the cert area
|
||||
_gc.Writer.ChangeMode(AsicMode.Read);
|
||||
res = _gc.Activate();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
res = _gc.Read(pooledBuffer.GetBuffer(), 0x38, 1);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
Span<byte> deviceCert = stackalloc byte[writeSize];
|
||||
pooledBuffer.GetBuffer().CopyTo(deviceCert);
|
||||
|
||||
// Restore the original card header
|
||||
_gc.Writer.ChangeMode(AsicMode.Write);
|
||||
res = HandleGameCardAccessResult(_gc.Writer.ActivateForWriter());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
tmpBuffer.CopyTo(pooledBuffer.GetBuffer());
|
||||
res = _gc.Writer.Write(pooledBuffer.GetBuffer(), 8, 1);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
deviceCert.CopyTo(outBuffer);
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private Result EraseAndWriteParamDirectly(ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
Assert.SdkRequires(inBuffer.Length >= Unsafe.SizeOf<DevCardParameter>());
|
||||
|
||||
Result res = InitializeGcLibrary();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
using var writeLock = new UniqueLock<ReaderWriterLock>(_rwLock);
|
||||
|
||||
var devCardParam = SpanHelpers.AsReadOnlyStruct<DevCardParameter>(inBuffer);
|
||||
return _gc.Writer.WriteDevCardParam(in devCardParam).Ret();
|
||||
}
|
||||
|
||||
private Result ReadParamDirectly(Span<byte> outBuffer)
|
||||
{
|
||||
Result res = InitializeGcLibrary();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
using var writeLock = new UniqueLock<ReaderWriterLock>(_rwLock);
|
||||
|
||||
res = _gc.Writer.ReadDevCardParam(out DevCardParameter devCardParam);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
SpanHelpers.AsReadOnlyByteSpan(in devCardParam).CopyTo(outBuffer);
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private Result WriteToGameCardDirectly(long offset, Span<byte> buffer)
|
||||
{
|
||||
Result res;
|
||||
|
||||
using (new SharedLock<ReaderWriterLock>(_rwLock))
|
||||
{
|
||||
if (buffer.Length == 0)
|
||||
return Result.Success;
|
||||
|
||||
res = _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;
|
||||
}
|
||||
|
||||
private Result ForceEraseGameCard()
|
||||
{
|
||||
Result res = InitializeGcLibrary();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
using var writeLock = new UniqueLock<ReaderWriterLock>(_rwLock);
|
||||
|
||||
_gc.Writer.ChangeMode(AsicMode.Write);
|
||||
res = _gc.Writer.ForceErase();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result AcquireReadLock(ref SharedLock<ReaderWriterLock> outLock, GameCardHandle handle)
|
||||
{
|
||||
using var readLock = new SharedLock<ReaderWriterLock>(_rwLock);
|
||||
|
||||
if (_state != CardState.Initial && !_gc.IsCardActivationValid())
|
||||
{
|
||||
readLock.Unlock();
|
||||
Invalidate().IgnoreResult();
|
||||
|
||||
return ResultFs.GameCardFsCheckHandleInAcquireReadLock.Log();
|
||||
}
|
||||
|
||||
if (_currentHandle != handle)
|
||||
return ResultFs.GameCardFsCheckHandleInAcquireReadLock.Log();
|
||||
|
||||
outLock.Set(ref readLock.Ref());
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result AcquireSecureLock(ref SharedLock<ReaderWriterLock> outLock, ref GameCardHandle handle,
|
||||
ReadOnlySpan<byte> cardDeviceId, ReadOnlySpan<byte> cardImageHash)
|
||||
{
|
||||
using (var readLock = new SharedLock<ReaderWriterLock>(_rwLock))
|
||||
{
|
||||
if (!IsSecureMode())
|
||||
{
|
||||
return ResultFs.GameCardFsCheckModeInAcquireSecureLock.Log();
|
||||
}
|
||||
|
||||
if (_state != CardState.Initial && !_gc.IsCardActivationValid())
|
||||
{
|
||||
readLock.Unlock();
|
||||
Invalidate().IgnoreResult();
|
||||
}
|
||||
else if (_currentHandle == handle)
|
||||
{
|
||||
outLock.Set(ref readLock.Ref());
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
GameCardHandle newHandle;
|
||||
|
||||
using (new UniqueLock<ReaderWriterLock>(_rwLock))
|
||||
{
|
||||
if (!IsSecureMode())
|
||||
{
|
||||
return ResultFs.GameCardFsCheckModeInAcquireSecureLock.Log();
|
||||
}
|
||||
|
||||
Span<byte> currentCardDeviceId = stackalloc byte[Values.GcCardDeviceIdSize];
|
||||
Span<byte> currentCardImageHash = stackalloc byte[Values.GcCardImageHashSize];
|
||||
|
||||
Result res = HandleGameCardAccessResult(_gc.GetCardDeviceId(currentCardDeviceId));
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
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))
|
||||
return ResultFs.GameCardFsCheckModeInAcquireSecureLock.Log();
|
||||
|
||||
res = GetHandle(out newHandle);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
}
|
||||
|
||||
using (var readLock = new SharedLock<ReaderWriterLock>())
|
||||
{
|
||||
Result res = AcquireReadLock(ref readLock.Ref(), newHandle);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
handle = newHandle;
|
||||
outLock.Set(ref readLock.Ref());
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
public Result AcquireWriteLock(ref UniqueLock<ReaderWriterLock> outLock)
|
||||
{
|
||||
Result res = InitializeGcLibrary();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
using var writeLock = new UniqueLock<ReaderWriterLock>(_rwLock);
|
||||
outLock.Set(ref writeLock.Ref());
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result HandleGameCardAccessResult(Result result)
|
||||
{
|
||||
if (result.IsFailure())
|
||||
{
|
||||
DeactivateAndChangeState();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Result GetHandle(out GameCardHandle outHandle)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out outHandle);
|
||||
|
||||
if (_state == CardState.Normal || _state == CardState.Secure)
|
||||
{
|
||||
CheckGameCardAndDeactivate();
|
||||
}
|
||||
|
||||
switch (_state)
|
||||
{
|
||||
case CardState.Initial:
|
||||
{
|
||||
Result res = ActivateGameCard();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
break;
|
||||
}
|
||||
case CardState.Normal:
|
||||
case CardState.Secure:
|
||||
break;
|
||||
case CardState.Write:
|
||||
{
|
||||
DeactivateAndChangeState();
|
||||
_gc.Writer.ChangeMode(AsicMode.Read);
|
||||
|
||||
Result res = ActivateGameCard();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
_state = CardState.Normal;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Abort.UnexpectedDefault();
|
||||
break;
|
||||
}
|
||||
|
||||
outHandle = _currentHandle;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public bool IsSecureMode()
|
||||
{
|
||||
return _state == CardState.Secure;
|
||||
}
|
||||
}
|
@ -1,14 +1,14 @@
|
||||
using System;
|
||||
using LibHac.Fs.Impl;
|
||||
using LibHac.Os;
|
||||
|
||||
namespace LibHac.GcSrv;
|
||||
|
||||
internal interface IGameCardDeviceManager
|
||||
{
|
||||
Result AcquireReadLock(out UniqueLock locker, uint handle);
|
||||
Result AcquireReadLockSecureMode(out UniqueLock locker, ref uint handle, ReadOnlySpan<byte> cardDeviceId, ReadOnlySpan<byte> cardImageHash);
|
||||
Result AcquireWriteLock(out SharedLock locker);
|
||||
Result AcquireReadLock(ref SharedLock<ReaderWriterLock> outLock, GameCardHandle handle);
|
||||
Result AcquireSecureLock(ref SharedLock<ReaderWriterLock> outLock, ref GameCardHandle handle, ReadOnlySpan<byte> cardDeviceId, ReadOnlySpan<byte> cardImageHash);
|
||||
Result AcquireWriteLock(ref UniqueLock<ReaderWriterLock> outLock);
|
||||
Result HandleGameCardAccessResult(Result result);
|
||||
Result GetHandle(out uint handle);
|
||||
Result GetHandle(out GameCardHandle outHandle);
|
||||
bool IsSecureMode();
|
||||
}
|
@ -24,9 +24,9 @@ public static class HorizonFactory
|
||||
|
||||
var fsServerConfig = new FileSystemServerConfig
|
||||
{
|
||||
DeviceOperator = defaultObjects.DeviceOperator,
|
||||
ExternalKeySet = keySet.ExternalKeySet,
|
||||
FsCreators = defaultObjects.FsCreators,
|
||||
StorageDeviceManagerFactory = defaultObjects.StorageDeviceManagerFactory,
|
||||
RandomGenerator = randomGenerator
|
||||
};
|
||||
|
||||
|
54
src/LibHac/SdmmcSrv/MmcManager.cs
Normal file
54
src/LibHac/SdmmcSrv/MmcManager.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.FsSrv.Sf;
|
||||
using LibHac.FsSrv.Storage.Sf;
|
||||
|
||||
namespace LibHac.SdmmcSrv;
|
||||
|
||||
public class MmcManager : IStorageDeviceManager
|
||||
{
|
||||
public MmcManager()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result IsInserted(out bool isInserted)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result IsHandleValid(out bool isValid, uint handle)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result OpenDetectionEvent(ref SharedRef<IEventNotifier> outDetectionEvent)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result OpenOperator(ref SharedRef<IStorageDeviceOperator> outDeviceOperator)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result OpenDevice(ref SharedRef<IStorageDevice> outStorageDevice, ulong attribute)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result OpenStorage(ref SharedRef<IStorage> outStorage, ulong attribute)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result Invalidate()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
19
src/LibHac/SdmmcSrv/SdCardDeviceDetectionEvent.cs
Normal file
19
src/LibHac/SdmmcSrv/SdCardDeviceDetectionEvent.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using LibHac.FsSystem;
|
||||
|
||||
namespace LibHac.SdmmcSrv;
|
||||
|
||||
internal class SdCardDeviceDetectionEventManager : CardDeviceDetectionEventManager
|
||||
{
|
||||
public SdCardDeviceDetectionEventManager(Sdmmc.Port port)
|
||||
{
|
||||
CallbackArgs.Port = port;
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
54
src/LibHac/SdmmcSrv/SdCardManager.cs
Normal file
54
src/LibHac/SdmmcSrv/SdCardManager.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.FsSrv.Sf;
|
||||
using LibHac.FsSrv.Storage.Sf;
|
||||
|
||||
namespace LibHac.SdmmcSrv;
|
||||
|
||||
public class SdCardManager : IStorageDeviceManager
|
||||
{
|
||||
public SdCardManager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result IsInserted(out bool isInserted)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result IsHandleValid(out bool isValid, uint handle)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result OpenDetectionEvent(ref SharedRef<IEventNotifier> outDetectionEvent)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result OpenOperator(ref SharedRef<IStorageDeviceOperator> outDeviceOperator)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result OpenDevice(ref SharedRef<IStorageDevice> outStorageDevice, ulong attribute)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result OpenStorage(ref SharedRef<IStorage> outStorage, ulong attribute)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result Invalidate()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
@ -17,6 +17,11 @@ public readonly ref struct InBuffer
|
||||
_buffer = buffer;
|
||||
}
|
||||
|
||||
public ref readonly T As<T>() where T : unmanaged
|
||||
{
|
||||
return ref SpanHelpers.AsReadOnlyStruct<T>(_buffer);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static InBuffer FromSpan<T>(ReadOnlySpan<T> buffer) where T : unmanaged
|
||||
{
|
||||
@ -42,6 +47,11 @@ public readonly ref struct OutBuffer
|
||||
_buffer = buffer;
|
||||
}
|
||||
|
||||
public ref T As<T>() where T : unmanaged
|
||||
{
|
||||
return ref SpanHelpers.AsStruct<T>(_buffer);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static OutBuffer FromSpan<T>(Span<T> buffer) where T : unmanaged
|
||||
{
|
||||
|
@ -46,7 +46,7 @@ public static class FileSystemServerFactory
|
||||
|
||||
var config = new FileSystemServerConfig();
|
||||
config.FsCreators = defaultObjects.FsCreators;
|
||||
config.DeviceOperator = defaultObjects.DeviceOperator;
|
||||
config.StorageDeviceManagerFactory = defaultObjects.StorageDeviceManagerFactory;
|
||||
config.ExternalKeySet = new ExternalKeySet();
|
||||
config.RandomGenerator = randomGenerator;
|
||||
|
||||
|
@ -26,7 +26,7 @@ public static class HorizonFactory
|
||||
|
||||
var config = new FileSystemServerConfig();
|
||||
config.FsCreators = defaultObjects.FsCreators;
|
||||
config.DeviceOperator = defaultObjects.DeviceOperator;
|
||||
config.StorageDeviceManagerFactory = defaultObjects.StorageDeviceManagerFactory;
|
||||
config.ExternalKeySet = new ExternalKeySet();
|
||||
config.RandomGenerator = randomGenerator;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user