diff --git a/build/CodeGen/Stage1/ResultCodegen.cs b/build/CodeGen/Stage1/ResultCodegen.cs index 998974eb..56f29a67 100644 --- a/build/CodeGen/Stage1/ResultCodegen.cs +++ b/build/CodeGen/Stage1/ResultCodegen.cs @@ -471,7 +471,7 @@ public static class ResultCodeGen { for (int i = prevResult + 1; i < result.DescriptionStart; i++) { - int innerValue = 2 & 0x1ff | ((i & 0x7ffff) << 9); + int innerValue = module.Id & 0x1ff | ((i & 0x7ffff) << 9); string unknownResultLine = $"Result_{result.ModuleId}_{i} = {innerValue},"; sb.AppendLine(unknownResultLine); } @@ -488,7 +488,7 @@ public static class ResultCodeGen { for (int i = prevResult + 1; i < 8192; i++) { - int innerValue = 2 & 0x1ff | ((i & 0x7ffff) << 9); + int innerValue = module.Id & 0x1ff | ((i & 0x7ffff) << 9); string unknownResultLine = $"Result_{module.Id}_{i} = {innerValue},"; sb.AppendLine(unknownResultLine); } diff --git a/build/CodeGen/result_modules.csv b/build/CodeGen/result_modules.csv index 43d72ee0..b668ad86 100644 --- a/build/CodeGen/result_modules.csv +++ b/build/CodeGen/result_modules.csv @@ -42,6 +42,7 @@ Id,Name,Default Namespace 168,CReport, 183,Debug, 189,Pwm, +192,Regulator, 198,Powctl, 202,Hid, 204,Cs, diff --git a/build/CodeGen/results.csv b/build/CodeGen/results.csv index 4fb9abc7..6634e2c9 100644 --- a/build/CodeGen/results.csv +++ b/build/CodeGen/results.csv @@ -204,7 +204,7 @@ Module,DescriptionStart,DescriptionEnd,Flags,Namespace,Name,Summary 2,2555,,,,GameCardInvalidT1CardCertificate, 2,2557,,,,GameCardInvalidCa10Certificate, -2,2558,,,,GameCardInvalidCa10CardHeader, +2,2558,,,,GameCardInvalidResponseVerificationValue, 2,2565,2595,,,GameCardCommunicationFailure, 2,2566,,,,GameCardFinishOperationFailed, @@ -241,7 +241,7 @@ Module,DescriptionStart,DescriptionEnd,Flags,Namespace,Name,Summary 2,2655,,,,GameCardChallengeAndResponseFailure, 2,2658,,,,GameCardChangeModeToSecureFailure, 2,2659,,,,GameCardExchangeRandomValuesFailure, -2,2660,,,,GameCardAsicChallengeCardExistenceFailure, +2,2660,,,,GameCardChallengeCardExistenceFailure, 2,2663,,,,GameCardInitializeAsicTimeOut, 2,2665,2669,,,GameCardSplFailure, diff --git a/src/LibHac/Common/FixedArrays/Arrays.cs b/src/LibHac/Common/FixedArrays/Arrays.cs index 990a6fd4..6d567e84 100644 --- a/src/LibHac/Common/FixedArrays/Arrays.cs +++ b/src/LibHac/Common/FixedArrays/Arrays.cs @@ -10,6 +10,7 @@ namespace LibHac.Common.FixedArrays; [InlineArray(6)] public struct Array6 { public readonly int Length => 6; private T _0; } [InlineArray(7)] public struct Array7 { public readonly int Length => 7; private T _0; } [InlineArray(8)] public struct Array8 { public readonly int Length => 8; private T _0; } +[InlineArray(9)] public struct Array9 { public readonly int Length => 9; private T _0; } [InlineArray(11)] public struct Array11 { public readonly int Length => 11; private T _0; } [InlineArray(12)] public struct Array12 { public readonly int Length => 12; private T _0; } [InlineArray(14)] public struct Array14 { public readonly int Length => 14; private T _0; } diff --git a/src/LibHac/Common/SpanHelpers.cs b/src/LibHac/Common/SpanHelpers.cs index 46631143..cc5631f5 100644 --- a/src/LibHac/Common/SpanHelpers.cs +++ b/src/LibHac/Common/SpanHelpers.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -33,19 +34,19 @@ public static class SpanExtensions public static class SpanHelpers { - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining), DebuggerStepThrough] public static Span CreateSpan(ref T reference, int length) { return MemoryMarshal.CreateSpan(ref reference, length); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining), DebuggerStepThrough] public static Span AsSpan(ref T reference) where T : unmanaged { return new Span(ref reference); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining), DebuggerStepThrough] public static Span AsSpan(ref TStruct reference) where TStruct : unmanaged where TSpan : unmanaged { @@ -53,25 +54,25 @@ public static class SpanHelpers Unsafe.SizeOf() / Unsafe.SizeOf()); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining), DebuggerStepThrough] public static Span AsByteSpan(ref T reference) where T : unmanaged { return CreateSpan(ref Unsafe.As(ref reference), Unsafe.SizeOf()); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining), DebuggerStepThrough] public static ReadOnlySpan CreateReadOnlySpan(ref readonly T reference, int length) { return MemoryMarshal.CreateReadOnlySpan(ref Unsafe.AsRef(in reference), length); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining), DebuggerStepThrough] public static ReadOnlySpan AsReadOnlySpan(ref readonly T reference) where T : unmanaged { return new ReadOnlySpan(in reference); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining), DebuggerStepThrough] public static ReadOnlySpan AsReadOnlySpan(ref readonly TStruct reference) where TStruct : unmanaged where TSpan : unmanaged { @@ -79,26 +80,26 @@ public static class SpanHelpers Unsafe.SizeOf() / Unsafe.SizeOf()); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining), DebuggerStepThrough] public static ReadOnlySpan AsReadOnlyByteSpan(ref readonly T reference) where T : unmanaged { return CreateReadOnlySpan(in Unsafe.As(ref Unsafe.AsRef(in reference)), Unsafe.SizeOf()); } // All AsStruct methods do bounds checks on the input - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining), DebuggerStepThrough] public static ref T AsStruct(Span span) where T : unmanaged { return ref MemoryMarshal.Cast(span)[0]; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining), DebuggerStepThrough] public static ref readonly T AsReadOnlyStruct(ReadOnlySpan span) where T : unmanaged { return ref MemoryMarshal.Cast(span)[0]; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining), DebuggerStepThrough] public static ref TTo AsStruct(Span span) where TFrom : unmanaged where TTo : unmanaged @@ -106,7 +107,7 @@ public static class SpanHelpers return ref MemoryMarshal.Cast(span)[0]; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining), DebuggerStepThrough] public static ref readonly TTo AsStruct(ReadOnlySpan span) where TFrom : unmanaged where TTo : unmanaged diff --git a/src/LibHac/Fs/MemoryStorage.cs b/src/LibHac/Fs/MemoryStorage.cs index 6e72b0cd..0df7b325 100644 --- a/src/LibHac/Fs/MemoryStorage.cs +++ b/src/LibHac/Fs/MemoryStorage.cs @@ -25,6 +25,7 @@ public class MemoryStorage : IStorage Assert.SdkRequiresNotNull(buffer); Assert.SdkRequiresInRange(size, 0, buffer.Length); + // ReSharper disable once ConditionIsAlwaysTrueOrFalse Abort.DoAbortUnless(buffer is null || 0 <= size && size < buffer.Length); _buffer = buffer; diff --git a/src/LibHac/Fs/ResultFs.cs b/src/LibHac/Fs/ResultFs.cs index 81fc7d1f..9e5ebdb2 100644 --- a/src/LibHac/Fs/ResultFs.cs +++ b/src/LibHac/Fs/ResultFs.cs @@ -316,7 +316,7 @@ public static class ResultFs /// Error code: 2002-2557; Inner value: 0x13fa02 public static Result.Base GameCardInvalidCa10Certificate => new Result.Base(ModuleFs, 2557); /// Error code: 2002-2558; Inner value: 0x13fc02 - public static Result.Base GameCardInvalidCa10CardHeader => new Result.Base(ModuleFs, 2558); + public static Result.Base GameCardInvalidResponseVerificationValue => new Result.Base(ModuleFs, 2558); /// Error code: 2002-2565; Range: 2565-2595; Inner value: 0x140a02 public static Result.Base GameCardCommunicationFailure { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 2565, 2595); } @@ -387,7 +387,7 @@ public static class ResultFs /// Error code: 2002-2659; Inner value: 0x14c602 public static Result.Base GameCardExchangeRandomValuesFailure => new Result.Base(ModuleFs, 2659); /// Error code: 2002-2660; Inner value: 0x14c802 - public static Result.Base GameCardAsicChallengeCardExistenceFailure => new Result.Base(ModuleFs, 2660); + public static Result.Base GameCardChallengeCardExistenceFailure => new Result.Base(ModuleFs, 2660); /// Error code: 2002-2663; Inner value: 0x14ce02 public static Result.Base GameCardInitializeAsicTimeOut => new Result.Base(ModuleFs, 2663); diff --git a/src/LibHac/Gc/GameCardTypes.cs b/src/LibHac/Gc/GameCardTypes.cs index a63fbb11..ada071e0 100644 --- a/src/LibHac/Gc/GameCardTypes.cs +++ b/src/LibHac/Gc/GameCardTypes.cs @@ -6,7 +6,7 @@ namespace LibHac.Gc; public struct GameCardStatus { public Array32 PartitionFsHeaderHash; - public Array8 PackageId; + public Array8 PackageId; public long CardSize; public long PartitionFsHeaderAddress; public long PartitionFsHeaderSize; diff --git a/src/LibHac/Gc/Impl/GameCardImplTypes.cs b/src/LibHac/Gc/Impl/GameCardImplTypes.cs index 175c64cc..12f650a4 100644 --- a/src/LibHac/Gc/Impl/GameCardImplTypes.cs +++ b/src/LibHac/Gc/Impl/GameCardImplTypes.cs @@ -1,28 +1,108 @@ -using System.Runtime.InteropServices; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using LibHac.Common.FixedArrays; namespace LibHac.Gc.Impl; -public struct CardId1 +public enum MakerCodeForCardId1 : byte { - public byte MakerCode; - public MemoryCapacity MemoryCapacity; - public byte Reserved; - public byte MemoryType; + MegaChips = 0xC2, + Lapis = 0xAE } +public enum MemoryCapacity : byte +{ + // ReSharper disable InconsistentNaming + Capacity1GB = 0xFA, + Capacity2GB = 0xF8, + Capacity4GB = 0xF0, + Capacity8GB = 0xE0, + Capacity16GB = 0xE1, + Capacity32GB = 0xE2 + // ReSharper restore InconsistentNaming +} + +public enum MemoryType : byte +{ + T1RomFast = 0x01, + T2RomFast = 0x02, + T1NandFast = 0x09, + T2NandFast = 0x0A, + T1RomLate = 0x21, + T2RomLate = 0x22, + T1NandLate = 0x29, + T2NandLate = 0x2A +} + +public enum CardSecurityNumber : byte +{ + Number0 = 0, + Number1 = 1, + Number2 = 2, + Number3 = 3, + Number4 = 4 +} + +public enum CardType : byte +{ + Rom = 0, + WritableDevT1 = 1, + WritableProdT1 = 2, + WritableDevT2 = 3, + WritableProdT2 = 4 +} + +[StructLayout(LayoutKind.Sequential)] +public struct CardId1 +{ + public MakerCodeForCardId1 MakerCode; + public MemoryCapacity MemoryCapacity; + public byte Reserved; + public MemoryType MemoryType; +} + +[StructLayout(LayoutKind.Sequential)] public struct CardId2 { - public byte CardSecurityNumber; - public byte CardType; + public CardSecurityNumber CardSecurityNumber; + public CardType CardType; public Array2 Reserved; } +[StructLayout(LayoutKind.Sequential)] public struct CardId3 { public Array4 Reserved; } +public enum MakerCodeForCardUid : byte +{ + Maker0 = 0, + Maker1 = 1, + Maker2 = 2, +} + +public enum CardTypeForUid : byte +{ + WritableDev = 0xFE, + WritableProd = 0xFF +} + +[StructLayout(LayoutKind.Sequential)] +public struct CardUid +{ + public MakerCodeForCardUid MakerCode; + public byte Version; + public CardTypeForUid CardType; + public Array9 UniqueData; + public uint Random; + public byte PlatformFlag; + public Array11 Reserved; + public CardId1 CardId1; + public Array32 Mac; +} + public enum DevCardRomSize : byte { // ReSharper disable InconsistentNaming @@ -79,6 +159,7 @@ public struct DevCardParameter public Array436 Reserved; } +[StructLayout(LayoutKind.Sequential)] public struct CardInitialDataPayload { public Array8 PackageId; @@ -88,12 +169,25 @@ public struct CardInitialDataPayload public Array12 AuthNonce; } +[StructLayout(LayoutKind.Sequential)] public struct CardInitialData { public CardInitialDataPayload Payload; public Array452 Padding; } +[StructLayout(LayoutKind.Sequential)] +public struct CardSpecificData +{ + public uint AsicSecurityMode; + public uint AsicStatus; + public CardId1 CardId1; + public CardId2 CardId2; + public Array64 CardUid; + public Array400 Reserved; + public Array32 Mac; +} + public enum FwVersion : byte { // ReSharper disable InconsistentNaming @@ -112,6 +206,7 @@ public enum KekIndex : byte ForDev = 1 } +[StructLayout(LayoutKind.Sequential)] public struct CardHeaderEncryptedData { public Array2 FwVersion; @@ -131,18 +226,6 @@ public struct CardHeaderEncryptedData public Array56 Reserved38; } -public enum MemoryCapacity : byte -{ - // ReSharper disable InconsistentNaming - Capacity1GB = 0xFA, - Capacity2GB = 0xF8, - Capacity4GB = 0xF0, - Capacity8GB = 0xE0, - Capacity16GB = 0xE1, - Capacity32GB = 0xE2 - // ReSharper restore InconsistentNaming -} - public enum AccessControl1ClockRate { ClockRate25MHz = 0xA10011, @@ -155,6 +238,15 @@ public enum SelSec T2 = 2 } +public enum BusPower +{ + // ReSharper disable InconsistentNaming + Power_3_1V = 0, + Power_1_8V = 1 + // ReSharper restore InconsistentNaming +} + +[StructLayout(LayoutKind.Sequential)] public struct CardHeader { public static uint HeaderMagic => 0x44414548; // HEAD @@ -179,14 +271,19 @@ public struct CardHeader public uint SelKey; public uint LimAreaPage; public CardHeaderEncryptedData EncryptedData; + + public KekIndex KekIndex => (KekIndex)(KeyIndex & 0xF); + public byte TitleKeyDecIndex => (byte)(KeyIndex >> 4); } +[StructLayout(LayoutKind.Sequential)] public struct CardHeaderWithSignature { public Array256 Signature; public CardHeader Data; } +[StructLayout(LayoutKind.Sequential)] public struct T1CardCertificate { public static uint CertMagic => 0x54524543; // CERT @@ -203,10 +300,79 @@ public struct T1CardCertificate public Array512 Padding; } +[StructLayout(LayoutKind.Sequential)] public struct Ca10Certificate { public Array256 Signature; public Array48 Unk100; public Array256 Modulus; public Array464 Unk230; +} + +[StructLayout(LayoutKind.Sequential)] +public struct CardInitReceiveData +{ + public uint CupVersion; + public CardId1 CardId1; +} + +[StructLayout(LayoutKind.Sequential)] +public struct CardSecurityInformation +{ + public uint MemoryInterfaceMode; + public uint AsicStatus; + public CardId1 Id1; + public CardId2 Id2; + public CardUid Uid; + public Array400 Reserved; + public Array32 Mac; + public Array1024 CardCertificate; + public CardInitialData InitialData; + + [UnscopedRef] + public ref T1CardCertificate T1Certificate => + ref Unsafe.As(ref MemoryMarshal.GetReference(CardCertificate[..])); +} + +public enum AsicFirmwareType : byte +{ + Read = 0, + Write = 1 +} + +public enum AsicState : byte +{ + Initial = 0, + Secure = 1 +} + +public enum GameCardMode : byte +{ + Initial = 0, + Normal = 1, + Secure = 2, + Debug = 3 +} + +[StructLayout(LayoutKind.Sequential)] +public struct TotalAsicInfo +{ + public uint InitializeCount; + public uint AwakenCount; + public ushort AwakenFailureCount; + public Array2 Reserved; +} + +[StructLayout(LayoutKind.Sequential)] +public struct CardAccessInternalInfo +{ + public ushort RetryLimitOutNum; + public ushort AsicReinitializeCount; + public ushort AsicReinitializeFailureNum; + public ushort RefreshSuccessCount; + public uint LastReadErrorPageAddress; + public uint LastReadErrorPageCount; + public uint ReadCountFromInsert; + public uint ReadCountFromAwaken; + public Result LastAsicReinitializeFailureResult; } \ No newline at end of file diff --git a/src/LibHac/GcSrv/GameCardManager.cs b/src/LibHac/GcSrv/GameCardManager.cs index 42b97a93..a0e97b9a 100644 --- a/src/LibHac/GcSrv/GameCardManager.cs +++ b/src/LibHac/GcSrv/GameCardManager.cs @@ -22,7 +22,7 @@ namespace LibHac.GcSrv; /// /// Provides access to the game card and game card ASIC. /// -/// he manager keeps track of the state of the ASIC and uses a handle system to control access to the +/// The manager keeps track of the state of the ASIC and uses a handle system to control access to the /// storage device. When a consumer wants to access the device, they are given a handle that will be used to make sure /// they're accessing the same device that they originally opened. The manager's internal handle is incremented every /// time the game card is deactivated. This ensures the consumer doesn't do things like accidentally continue reading @@ -980,7 +980,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG if (res.IsFailure()) return res.Miss(); devHeaderBuffer.CopyTo(pooledBuffer.GetBuffer()); - res = _gc.Writer.Write(pooledBuffer.GetBuffer(), GcCardKeyAreaPageCount, 1); + res = _gc.Writer.Write(pooledBuffer.GetBuffer(), GcCardKeyAreaPageCount, GcDeviceCertificatePageCount); if (res.IsFailure()) return res.Miss(); // Read the cert area @@ -988,7 +988,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG res = _gc.Activate(); if (res.IsFailure()) return res.Miss(); - res = _gc.Read(pooledBuffer.GetBuffer(), GcCertAreaPageAddress, 1); + res = _gc.Read(pooledBuffer.GetBuffer(), GcCertAreaPageAddress, GcDeviceCertificatePageCount); if (res.IsFailure()) return res.Miss(); Span deviceCert = stackalloc byte[writeSize]; @@ -1000,7 +1000,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG if (res.IsFailure()) return res.Miss(); originalHeaderBuffer.CopyTo(pooledBuffer.GetBuffer()); - res = _gc.Writer.Write(pooledBuffer.GetBuffer(), GcCardKeyAreaPageCount, 1); + res = _gc.Writer.Write(pooledBuffer.GetBuffer(), GcCardKeyAreaPageCount, GcDeviceCertificatePageCount); if (res.IsFailure()) return res.Miss(); deviceCert.CopyTo(outBuffer); diff --git a/src/LibHac/Sdmmc/Common.cs b/src/LibHac/Sdmmc/Common.cs index f7a5f12f..408ea2d6 100644 --- a/src/LibHac/Sdmmc/Common.cs +++ b/src/LibHac/Sdmmc/Common.cs @@ -76,7 +76,7 @@ public partial class SdmmcApi public void Initialize(Port port) { - throw new NotImplementedException(); + // Todo: Implement } public void Finalize(Port port) diff --git a/src/LibHac/SdmmcSrv/SdCardManager.cs b/src/LibHac/SdmmcSrv/SdCardManager.cs index fd2ff3eb..c13d5a8d 100644 --- a/src/LibHac/SdmmcSrv/SdCardManager.cs +++ b/src/LibHac/SdmmcSrv/SdCardManager.cs @@ -94,6 +94,8 @@ public class SdCardManager : IStorageDeviceManager, IStorageDeviceOperator, ISdm if (_isInitialized) return; + _sdmmc.Initialize(_port); + // Missing: Work buffer management if (_detectionEventManager.HasValue) diff --git a/src/LibHac/Sf/NativeHandle.cs b/src/LibHac/Sf/NativeHandle.cs index d17ebdd3..f5e7924f 100644 --- a/src/LibHac/Sf/NativeHandle.cs +++ b/src/LibHac/Sf/NativeHandle.cs @@ -21,10 +21,18 @@ public class NativeHandle : IDisposable Handle = handle; IsManaged = isManaged; } + + public OsNativeHandle GetOsHandle() => throw new NotImplementedException(); public void Dispose() { if (IsManaged) Os.CloseNativeHandle(Handle.Object); } + + public void Detach() + { + IsManaged = false; + Handle = new Handle(); + } } \ No newline at end of file diff --git a/tests/LibHac.Tests/Gc/TypeLayoutTests.cs b/tests/LibHac.Tests/Gc/TypeLayoutTests.cs index 58820055..391a88fc 100644 --- a/tests/LibHac.Tests/Gc/TypeLayoutTests.cs +++ b/tests/LibHac.Tests/Gc/TypeLayoutTests.cs @@ -105,6 +105,24 @@ public class TypeLayoutTests Assert.Equal(Values.GcRsaPublicExponentLength, s.PublicKeyExponent.Length); } + [Fact] + public static void CardUid_Layout() + { + var s = new CardUid(); + + Assert.Equal(0x40, Unsafe.SizeOf()); + + Assert.Equal(0x00, GetOffset(in s, in s.MakerCode)); + Assert.Equal(0x01, GetOffset(in s, in s.Version)); + Assert.Equal(0x02, GetOffset(in s, in s.CardType)); + Assert.Equal(0x03, GetOffset(in s, in s.UniqueData)); + Assert.Equal(0x0C, GetOffset(in s, in s.Random)); + Assert.Equal(0x10, GetOffset(in s, in s.PlatformFlag)); + Assert.Equal(0x11, GetOffset(in s, in s.Reserved)); + Assert.Equal(0x1C, GetOffset(in s, in s.CardId1)); + Assert.Equal(0x20, GetOffset(in s, in s.Mac)); + } + [Fact] public static void CardInitialDataPayload_Layout() { @@ -264,4 +282,64 @@ public class TypeLayoutTests Assert.Equal(0x130, GetOffset(in s, in s.Modulus)); Assert.Equal(0x230, GetOffset(in s, in s.Unk230)); } + + [Fact] + public static void CardInitReceiveData_Layout() + { + var s = new CardInitReceiveData(); + + Assert.Equal(8, Unsafe.SizeOf()); + + Assert.Equal(0, GetOffset(in s, in s.CupVersion)); + Assert.Equal(4, GetOffset(in s, in s.CardId1)); + } + + [Fact] + public static void CardSecurityInformation_Layout() + { + var s = new CardSecurityInformation(); + + Assert.Equal(0x800, Unsafe.SizeOf()); + + Assert.Equal(0x000, GetOffset(in s, in s.MemoryInterfaceMode)); + Assert.Equal(0x004, GetOffset(in s, in s.AsicStatus)); + Assert.Equal(0x008, GetOffset(in s, in s.Id1)); + Assert.Equal(0x00C, GetOffset(in s, in s.Id2)); + Assert.Equal(0x010, GetOffset(in s, in s.Uid)); + Assert.Equal(0x050, GetOffset(in s, in s.Reserved)); + Assert.Equal(0x1E0, GetOffset(in s, in s.Mac)); + Assert.Equal(0x200, GetOffset(in s, in s.CardCertificate)); + Assert.Equal(0x600, GetOffset(in s, in s.InitialData)); + } + + [Fact] + public static void TotalAsicInfo_Layout() + { + var s = new TotalAsicInfo(); + + Assert.Equal(0xC, Unsafe.SizeOf()); + + Assert.Equal(0x0, GetOffset(in s, in s.InitializeCount)); + Assert.Equal(0x4, GetOffset(in s, in s.AwakenCount)); + Assert.Equal(0x8, GetOffset(in s, in s.AwakenFailureCount)); + Assert.Equal(0xA, GetOffset(in s, in s.Reserved)); + } + + [Fact] + public static void CardAccessInternalInfo_Layout() + { + var s = new CardAccessInternalInfo(); + + Assert.Equal(0x1C, Unsafe.SizeOf()); + + Assert.Equal(0x00, GetOffset(in s, in s.RetryLimitOutNum)); + Assert.Equal(0x02, GetOffset(in s, in s.AsicReinitializeCount)); + Assert.Equal(0x04, GetOffset(in s, in s.AsicReinitializeFailureNum)); + Assert.Equal(0x06, GetOffset(in s, in s.RefreshSuccessCount)); + Assert.Equal(0x08, GetOffset(in s, in s.LastReadErrorPageAddress)); + Assert.Equal(0x0C, GetOffset(in s, in s.LastReadErrorPageCount)); + Assert.Equal(0x10, GetOffset(in s, in s.ReadCountFromInsert)); + Assert.Equal(0x14, GetOffset(in s, in s.ReadCountFromAwaken)); + Assert.Equal(0x18, GetOffset(in s, in s.LastAsicReinitializeFailureResult)); + } } \ No newline at end of file