mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Implement most of the remaining game card FS shim
This commit is contained in:
parent
81051907a4
commit
934e9af9a4
3 changed files with 523 additions and 9 deletions
|
@ -24,6 +24,18 @@ public static class GameCard
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum GameCardSize
|
||||||
|
{
|
||||||
|
// ReSharper disable InconsistentNaming
|
||||||
|
Size1GB = 1,
|
||||||
|
Size2GB = 2,
|
||||||
|
Size4GB = 4,
|
||||||
|
Size8GB = 8,
|
||||||
|
Size16GB = 16,
|
||||||
|
Size32GB = 32
|
||||||
|
// ReSharper restore InconsistentNaming
|
||||||
|
}
|
||||||
|
|
||||||
public enum GameCardSizeInternal : byte
|
public enum GameCardSizeInternal : byte
|
||||||
{
|
{
|
||||||
Size1Gb = 0xFA,
|
Size1Gb = 0xFA,
|
||||||
|
@ -84,3 +96,9 @@ public struct GameCardErrorReportInfo
|
||||||
public uint ReadCountFromAwaken;
|
public uint ReadCountFromAwaken;
|
||||||
public Array8<byte> Reserved38;
|
public Array8<byte> Reserved38;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct GameCardUpdatePartitionInfo
|
||||||
|
{
|
||||||
|
public uint CupVersion;
|
||||||
|
public ulong CupId;
|
||||||
|
}
|
|
@ -5,9 +5,14 @@ using LibHac.Diag;
|
||||||
using LibHac.Fs.Fsa;
|
using LibHac.Fs.Fsa;
|
||||||
using LibHac.Fs.Impl;
|
using LibHac.Fs.Impl;
|
||||||
using LibHac.FsSrv.Sf;
|
using LibHac.FsSrv.Sf;
|
||||||
|
using LibHac.Gc;
|
||||||
using LibHac.Os;
|
using LibHac.Os;
|
||||||
|
using LibHac.Sf;
|
||||||
using LibHac.Util;
|
using LibHac.Util;
|
||||||
|
|
||||||
using static LibHac.Fs.Impl.AccessLogStrings;
|
using static LibHac.Fs.Impl.AccessLogStrings;
|
||||||
|
using static LibHac.Gc.Values;
|
||||||
|
|
||||||
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
|
using IFileSystem = LibHac.Fs.Fsa.IFileSystem;
|
||||||
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
|
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
|
||||||
using IStorageSf = LibHac.FsSrv.Sf.IStorage;
|
using IStorageSf = LibHac.FsSrv.Sf.IStorage;
|
||||||
|
@ -81,7 +86,7 @@ public static class GameCard
|
||||||
|
|
||||||
Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||||
fs.Impl.AbortIfNeeded(rc);
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
rc = deviceOperator.Get.GetGameCardHandle(out GameCardHandle handle);
|
rc = deviceOperator.Get.GetGameCardHandle(out GameCardHandle handle);
|
||||||
fs.Impl.AbortIfNeeded(rc);
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
@ -107,7 +112,7 @@ public static class GameCard
|
||||||
var sb = new U8StringBuilder(logBuffer, true);
|
var sb = new U8StringBuilder(logBuffer, true);
|
||||||
|
|
||||||
sb.Append(LogName).Append(mountName).Append(LogQuote)
|
sb.Append(LogName).Append(mountName).Append(LogQuote)
|
||||||
.Append(LogGameCardHandle).AppendFormat(handle)
|
.Append(LogGameCardHandle).AppendFormat(handle, 'X')
|
||||||
.Append(LogGameCardPartition).Append(idString.ToString(partitionId));
|
.Append(LogGameCardPartition).Append(idString.ToString(partitionId));
|
||||||
|
|
||||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
|
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
|
||||||
|
@ -118,24 +123,23 @@ public static class GameCard
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.Impl.AbortIfNeeded(rc);
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System))
|
if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System))
|
||||||
fs.Impl.EnableFileSystemAccessorAccessLog(mountName);
|
fs.Impl.EnableFileSystemAccessorAccessLog(mountName);
|
||||||
|
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
|
|
||||||
static Result Mount(FileSystemClient fs, U8Span mountName, GameCardHandle handle,
|
static Result Mount(FileSystemClient fs, U8Span mountName, GameCardHandle handle, GameCardPartition partitionId)
|
||||||
GameCardPartition partitionId)
|
|
||||||
{
|
{
|
||||||
Result rc = fs.Impl.CheckMountNameAcceptingReservedMountName(mountName);
|
Result rc = fs.Impl.CheckMountNameAcceptingReservedMountName(mountName);
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||||
using var fileSystem = new SharedRef<IFileSystemSf>();
|
using var fileSystem = new SharedRef<IFileSystemSf>();
|
||||||
|
|
||||||
rc = fileSystemProxy.Get.OpenGameCardFileSystem(ref fileSystem.Ref(), handle, partitionId);
|
rc = fileSystemProxy.Get.OpenGameCardFileSystem(ref fileSystem.Ref(), handle, partitionId);
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
using var fileSystemAdapter =
|
using var fileSystemAdapter =
|
||||||
new UniqueRef<IFileSystem>(new FileSystemServiceObjectAdapter(ref fileSystem.Ref()));
|
new UniqueRef<IFileSystem>(new FileSystemServiceObjectAdapter(ref fileSystem.Ref()));
|
||||||
|
@ -149,7 +153,7 @@ public static class GameCard
|
||||||
if (!mountNameGenerator.HasValue)
|
if (!mountNameGenerator.HasValue)
|
||||||
return ResultFs.AllocationMemoryFailedInGameCardD.Log();
|
return ResultFs.AllocationMemoryFailedInGameCardD.Log();
|
||||||
|
|
||||||
return fs.Register(mountName, ref fileSystemAdapter.Ref(), ref mountNameGenerator.Ref());
|
return fs.Register(mountName, ref fileSystemAdapter.Ref(), ref mountNameGenerator.Ref()).Ret();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,7 +181,7 @@ public static class GameCard
|
||||||
|
|
||||||
Result rc = fileSystemProxy.Get.OpenGameCardStorage(ref storage.Ref(), handle, partitionType);
|
Result rc = fileSystemProxy.Get.OpenGameCardStorage(ref storage.Ref(), handle, partitionType);
|
||||||
fs.Impl.AbortIfNeeded(rc);
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
using var storageAdapter = new UniqueRef<IStorage>(new StorageServiceObjectAdapter(ref storage.Ref()));
|
using var storageAdapter = new UniqueRef<IStorage>(new StorageServiceObjectAdapter(ref storage.Ref()));
|
||||||
|
|
||||||
|
@ -187,4 +191,485 @@ public static class GameCard
|
||||||
outStorage.Set(ref storageAdapter.Ref());
|
outStorage.Set(ref storageAdapter.Ref());
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Result EraseGameCard(this FileSystemClient fs, GameCardSize cardSize, ulong romAreaStartPageAddress)
|
||||||
|
{
|
||||||
|
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||||
|
using var deviceOperator = new SharedRef<IDeviceOperator>();
|
||||||
|
|
||||||
|
Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
rc = deviceOperator.Get.EraseGameCard((uint)cardSize, romAreaStartPageAddress);
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result GetGameCardUpdatePartitionInfo(this FileSystemClient fs,
|
||||||
|
out GameCardUpdatePartitionInfo outPartitionInfo, GameCardHandle handle)
|
||||||
|
{
|
||||||
|
outPartitionInfo = default;
|
||||||
|
|
||||||
|
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||||
|
using var deviceOperator = new SharedRef<IDeviceOperator>();
|
||||||
|
|
||||||
|
Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
rc = deviceOperator.Get.GetGameCardUpdatePartitionInfo(out uint cupVersion, out ulong cupId, handle);
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
outPartitionInfo.CupVersion = cupVersion;
|
||||||
|
outPartitionInfo.CupId = cupId;
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void FinalizeGameCardDriver(this FileSystemClient fs)
|
||||||
|
{
|
||||||
|
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||||
|
using var deviceOperator = new SharedRef<IDeviceOperator>();
|
||||||
|
|
||||||
|
Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||||
|
fs.Impl.LogResultErrorMessage(rc);
|
||||||
|
Abort.DoAbortUnless(rc.IsSuccess());
|
||||||
|
|
||||||
|
rc = deviceOperator.Get.FinalizeGameCardDriver();
|
||||||
|
fs.Impl.LogResultErrorMessage(rc);
|
||||||
|
Abort.DoAbortUnless(rc.IsSuccess());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result GetGameCardAttribute(this FileSystemClient fs, out GameCardAttribute outAttribute,
|
||||||
|
GameCardHandle handle)
|
||||||
|
{
|
||||||
|
UnsafeHelpers.SkipParamInit(out outAttribute);
|
||||||
|
|
||||||
|
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||||
|
using var deviceOperator = new SharedRef<IDeviceOperator>();
|
||||||
|
|
||||||
|
Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
rc = deviceOperator.Get.GetGameCardAttribute(out byte gameCardAttribute, handle);
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
outAttribute = (GameCardAttribute)gameCardAttribute;
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result GetGameCardCompatibilityType(this FileSystemClient fs,
|
||||||
|
out GameCardCompatibilityType outCompatibilityType, GameCardHandle handle)
|
||||||
|
{
|
||||||
|
UnsafeHelpers.SkipParamInit(out outCompatibilityType);
|
||||||
|
|
||||||
|
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||||
|
using var deviceOperator = new SharedRef<IDeviceOperator>();
|
||||||
|
|
||||||
|
Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
rc = deviceOperator.Get.GetGameCardCompatibilityType(out byte gameCardCompatibilityType, handle);
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
outCompatibilityType = (GameCardCompatibilityType)gameCardCompatibilityType;
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result GetGameCardDeviceCertificate(this FileSystemClient fs, Span<byte> outBuffer,
|
||||||
|
GameCardHandle handle)
|
||||||
|
{
|
||||||
|
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||||
|
using var deviceOperator = new SharedRef<IDeviceOperator>();
|
||||||
|
|
||||||
|
Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
rc = deviceOperator.Get.GetGameCardDeviceCertificate(new OutBuffer(outBuffer), outBuffer.Length, handle);
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result ChallengeCardExistence(this FileSystemClient fs, Span<byte> responseBuffer,
|
||||||
|
ReadOnlySpan<byte> challengeSeedBuffer, ReadOnlySpan<byte> challengeValueBuffer, GameCardHandle handle)
|
||||||
|
{
|
||||||
|
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||||
|
using var deviceOperator = new SharedRef<IDeviceOperator>();
|
||||||
|
|
||||||
|
Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
rc = deviceOperator.Get.ChallengeCardExistence(new OutBuffer(responseBuffer), new InBuffer(challengeSeedBuffer),
|
||||||
|
new InBuffer(challengeValueBuffer), handle);
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result GetGameCardAsicInfo(this FileSystemClient fs, out RmaInformation outRmaInfo,
|
||||||
|
ReadOnlySpan<byte> asicFirmwareBuffer)
|
||||||
|
{
|
||||||
|
UnsafeHelpers.SkipParamInit(out outRmaInfo);
|
||||||
|
|
||||||
|
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||||
|
using var deviceOperator = new SharedRef<IDeviceOperator>();
|
||||||
|
|
||||||
|
Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
Unsafe.SkipInit(out RmaInformation rmaInformation);
|
||||||
|
|
||||||
|
rc = deviceOperator.Get.GetGameCardAsicInfo(OutBuffer.FromStruct(ref rmaInformation),
|
||||||
|
Unsafe.SizeOf<RmaInformation>(), new InBuffer(asicFirmwareBuffer), asicFirmwareBuffer.Length);
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
outRmaInfo = rmaInformation;
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result GetGameCardIdSet(this FileSystemClient fs, out GameCardIdSet outGcIdSet)
|
||||||
|
{
|
||||||
|
UnsafeHelpers.SkipParamInit(out outGcIdSet);
|
||||||
|
|
||||||
|
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||||
|
using var deviceOperator = new SharedRef<IDeviceOperator>();
|
||||||
|
|
||||||
|
Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
Unsafe.SkipInit(out GameCardIdSet gcIdSet);
|
||||||
|
|
||||||
|
rc = deviceOperator.Get.GetGameCardIdSet(OutBuffer.FromStruct(ref gcIdSet), Unsafe.SizeOf<GameCardIdSet>());
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
outGcIdSet = gcIdSet;
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result GetGameCardCid(this FileSystemClient fs, Span<byte> outCidBuffer)
|
||||||
|
{
|
||||||
|
Result rc;
|
||||||
|
|
||||||
|
if (outCidBuffer.Length < Unsafe.SizeOf<GameCardIdSet>())
|
||||||
|
{
|
||||||
|
rc = ResultFs.InvalidSize.Value;
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
return rc.Log();
|
||||||
|
}
|
||||||
|
|
||||||
|
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||||
|
using var deviceOperator = new SharedRef<IDeviceOperator>();
|
||||||
|
|
||||||
|
rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
Unsafe.SkipInit(out GameCardIdSet gcIdSet);
|
||||||
|
|
||||||
|
rc = deviceOperator.Get.GetGameCardIdSet(OutBuffer.FromStruct(ref gcIdSet), Unsafe.SizeOf<GameCardIdSet>());
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
SpanHelpers.AsByteSpan(ref gcIdSet).CopyTo(outCidBuffer);
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result WriteToGameCard(this FileSystemClient fs, long offset, Span<byte> buffer)
|
||||||
|
{
|
||||||
|
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||||
|
using var deviceOperator = new SharedRef<IDeviceOperator>();
|
||||||
|
|
||||||
|
Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
rc = deviceOperator.Get.WriteToGameCardDirectly(offset, new OutBuffer(buffer), buffer.Length);
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result SetVerifyWriteEnableFlag(this FileSystemClient fs, bool isEnabled)
|
||||||
|
{
|
||||||
|
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||||
|
using var deviceOperator = new SharedRef<IDeviceOperator>();
|
||||||
|
|
||||||
|
Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
rc = deviceOperator.Get.SetVerifyWriteEnableFlag(isEnabled);
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result GetGameCardImageHash(this FileSystemClient fs, Span<byte> outBuffer, GameCardHandle handle)
|
||||||
|
{
|
||||||
|
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||||
|
using var deviceOperator = new SharedRef<IDeviceOperator>();
|
||||||
|
|
||||||
|
Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
rc = deviceOperator.Get.GetGameCardImageHash(new OutBuffer(outBuffer), outBuffer.Length, handle);
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result GetGameCardDeviceIdForProdCard(this FileSystemClient fs, Span<byte> outIdBuffer,
|
||||||
|
ReadOnlySpan<byte> devHeaderBuffer)
|
||||||
|
{
|
||||||
|
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||||
|
using var deviceOperator = new SharedRef<IDeviceOperator>();
|
||||||
|
|
||||||
|
Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
rc = deviceOperator.Get.GetGameCardDeviceIdForProdCard(new OutBuffer(outIdBuffer), outIdBuffer.Length,
|
||||||
|
new InBuffer(devHeaderBuffer), devHeaderBuffer.Length);
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result EraseAndWriteParamDirectly(this FileSystemClient fs, ReadOnlySpan<byte> devParamBuffer)
|
||||||
|
{
|
||||||
|
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||||
|
using var deviceOperator = new SharedRef<IDeviceOperator>();
|
||||||
|
|
||||||
|
Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
rc = deviceOperator.Get.EraseAndWriteParamDirectly(new InBuffer(devParamBuffer), devParamBuffer.Length);
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result ReadParamDirectly(this FileSystemClient fs, Span<byte> outBuffer)
|
||||||
|
{
|
||||||
|
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||||
|
using var deviceOperator = new SharedRef<IDeviceOperator>();
|
||||||
|
|
||||||
|
Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
rc = deviceOperator.Get.ReadParamDirectly(new OutBuffer(outBuffer), outBuffer.Length);
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result ForceEraseGameCard(this FileSystemClient fs)
|
||||||
|
{
|
||||||
|
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||||
|
using var deviceOperator = new SharedRef<IDeviceOperator>();
|
||||||
|
|
||||||
|
Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
rc = deviceOperator.Get.ForceEraseGameCard();
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result GetGameCardErrorInfo(this FileSystemClient fs, out GameCardErrorInfo outErrorInfo)
|
||||||
|
{
|
||||||
|
UnsafeHelpers.SkipParamInit(out outErrorInfo);
|
||||||
|
|
||||||
|
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||||
|
using var deviceOperator = new SharedRef<IDeviceOperator>();
|
||||||
|
|
||||||
|
Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
rc = deviceOperator.Get.GetGameCardErrorInfo(out GameCardErrorInfo gameCardErrorInfo);
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
outErrorInfo = gameCardErrorInfo;
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result GetGameCardErrorReportInfo(this FileSystemClient fs, out GameCardErrorReportInfo outErrorInfo)
|
||||||
|
{
|
||||||
|
UnsafeHelpers.SkipParamInit(out outErrorInfo);
|
||||||
|
|
||||||
|
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||||
|
using var deviceOperator = new SharedRef<IDeviceOperator>();
|
||||||
|
|
||||||
|
Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
rc = deviceOperator.Get.GetGameCardErrorReportInfo(out GameCardErrorReportInfo gameCardErrorReportInfo);
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
outErrorInfo = gameCardErrorReportInfo;
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result CheckGameCardPartitionAvailability(this FileSystemClient fs, GameCardHandle handle,
|
||||||
|
GameCardPartition partitionId)
|
||||||
|
{
|
||||||
|
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||||
|
using var fileSystem = new SharedRef<IFileSystemSf>();
|
||||||
|
|
||||||
|
Result rc = fileSystemProxy.Get.OpenGameCardFileSystem(ref fileSystem.Ref(), handle, partitionId);
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result GetGameCardDeviceId(this FileSystemClient fs, Span<byte> outBuffer)
|
||||||
|
{
|
||||||
|
Result rc;
|
||||||
|
|
||||||
|
// Note: Nintendo checks for length 8 here rather than GcCardDeviceIdSize (0x10)
|
||||||
|
if (outBuffer.Length < GcCardDeviceIdSize)
|
||||||
|
{
|
||||||
|
rc = ResultFs.InvalidSize.Value;
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
return rc.Log();
|
||||||
|
}
|
||||||
|
|
||||||
|
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||||
|
using var deviceOperator = new SharedRef<IDeviceOperator>();
|
||||||
|
|
||||||
|
rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
Span<byte> buffer = stackalloc byte[GcCardDeviceIdSize];
|
||||||
|
|
||||||
|
rc = deviceOperator.Get.GetGameCardDeviceId(new OutBuffer(buffer), GcCardDeviceIdSize);
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
buffer.CopyTo(outBuffer);
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Result SetGameCardSimulationEventImpl(FileSystemClient fs,
|
||||||
|
SimulatingDeviceTargetOperation simulatedOperationType,
|
||||||
|
SimulatingDeviceAccessFailureEventType simulatedFailureType, Result failureResult, bool autoClearEvent)
|
||||||
|
{
|
||||||
|
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||||
|
using var deviceOperator = new SharedRef<IDeviceOperator>();
|
||||||
|
|
||||||
|
Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
rc = deviceOperator.Get.SetDeviceSimulationEvent((uint)SdmmcPort.GcAsic, (uint)simulatedOperationType,
|
||||||
|
(uint)simulatedFailureType, failureResult.Value, autoClearEvent);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result SimulateGameCardDetectionEvent(this FileSystemClient fs, SimulatingDeviceDetectionMode mode,
|
||||||
|
bool signalEvent)
|
||||||
|
{
|
||||||
|
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||||
|
|
||||||
|
Result rc = fileSystemProxy.Get.SimulateDeviceDetectionEvent(SdmmcPort.GcAsic, mode, signalEvent);
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result SetGameCardSimulationEvent(this FileSystemClient fs,
|
||||||
|
SimulatingDeviceTargetOperation simulatedOperationType,
|
||||||
|
SimulatingDeviceAccessFailureEventType simulatedFailureType)
|
||||||
|
{
|
||||||
|
Result rc = SetGameCardSimulationEventImpl(fs, simulatedOperationType, simulatedFailureType, Result.Success,
|
||||||
|
autoClearEvent: false);
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result SetGameCardSimulationEvent(this FileSystemClient fs,
|
||||||
|
SimulatingDeviceTargetOperation simulatedOperationType,
|
||||||
|
SimulatingDeviceAccessFailureEventType simulatedFailureType, bool autoClearEvent)
|
||||||
|
{
|
||||||
|
Result rc = SetGameCardSimulationEventImpl(fs, simulatedOperationType, simulatedFailureType, Result.Success,
|
||||||
|
autoClearEvent);
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result SetGameCardSimulationEvent(this FileSystemClient fs,
|
||||||
|
SimulatingDeviceTargetOperation simulatedOperationType, Result failureResult, bool autoClearEvent)
|
||||||
|
{
|
||||||
|
Result rc = SetGameCardSimulationEventImpl(fs, simulatedOperationType,
|
||||||
|
SimulatingDeviceAccessFailureEventType.AccessFailure, failureResult, autoClearEvent);
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result ClearGameCardSimulationEvent(this FileSystemClient fs)
|
||||||
|
{
|
||||||
|
using SharedRef<IFileSystemProxy> fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||||
|
using var deviceOperator = new SharedRef<IDeviceOperator>();
|
||||||
|
|
||||||
|
Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
rc = deviceOperator.Get.ClearDeviceSimulationEvent((uint)SdmmcPort.GcAsic);
|
||||||
|
fs.Impl.AbortIfNeeded(rc);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -492,6 +492,17 @@ public class TypeLayoutTests
|
||||||
Assert.Equal(0x38, GetOffset(in s, in s.Reserved38));
|
Assert.Equal(0x38, GetOffset(in s, in s.Reserved38));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public static void GameCardUpdatePartitionInfo_Layout()
|
||||||
|
{
|
||||||
|
var s = new GameCardUpdatePartitionInfo();
|
||||||
|
|
||||||
|
Assert.Equal(0x10, Unsafe.SizeOf<GameCardUpdatePartitionInfo>());
|
||||||
|
|
||||||
|
Assert.Equal(0, GetOffset(in s, in s.CupVersion));
|
||||||
|
Assert.Equal(8, GetOffset(in s, in s.CupId));
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public static void Int64_Layout()
|
public static void Int64_Layout()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue