mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Support reading the initial data/key area of xci files
This commit is contained in:
parent
1271a7e62d
commit
fe6f4422dd
16 changed files with 1103 additions and 226 deletions
|
@ -164,23 +164,28 @@ Module,DescriptionStart,DescriptionEnd,Flags,Namespace,Name,Summary
|
|||
2,2499,,,,PortSdCardUnexpected,
|
||||
|
||||
2,2500,2999,,,GameCardAccessFailed,
|
||||
2,2501,,,,GameCardUnknown,
|
||||
2,2502,,,,GameCardUnexpectedDeadCode,
|
||||
2,2503,,,,GameCardPreconditionViolation,
|
||||
2,2504,,,,GameCardNotImplemented,
|
||||
|
||||
2,2510,,,,GameCardNoAvailableLockers,
|
||||
2,2511,,,,GameCardLockerIndexOutOfRange,
|
||||
2,2510,,,,GameCardQueueFullFailure,
|
||||
2,2511,,,,GameCardLockerOutOfRange,
|
||||
2,2516,,,,GameCardFailedIoMappingForGpio,
|
||||
|
||||
2,2520,,,,GameCardCardNotInserted,
|
||||
2,2521,,,,InvalidGameCardIdInSpecificData,
|
||||
2,2521,,,,GameCardCardIdMismatch,
|
||||
2,2522,,,,GameCardCardNotActivated,
|
||||
2,2523,,,,InvalidCommandForDeactivatedGameCardAsic,
|
||||
2,2523,,,,GameCardNotAwakened,
|
||||
|
||||
2,2530,2559,,,GameCardCardAccessFailure,
|
||||
2,2531,,,,GameCardCardAccessTimeout,
|
||||
2,2532,,,,GameCardStatusFatalError,
|
||||
2,2533,,,,GameCardReadFailure,
|
||||
2,2536,,,,GameCardRetryLimitHit,
|
||||
2,2537,,,,GameCardStatusRefreshRequested,
|
||||
2,2538,,,,GameCardStatusCrcErrorAndRefreshRequested,
|
||||
2,2532,,,,GameCardCardFatal,
|
||||
2,2533,,,,GameCardCardNeedRetry,
|
||||
2,2534,,,,GameCardCardRetryFailure,
|
||||
2,2536,,,,GameCardRetryLimitOut,
|
||||
2,2537,2538,,,GameCardNeedRefresh,
|
||||
2,2538,,,,GameCardNeedRefreshAndCardNeedRetry,
|
||||
|
||||
2,2540,,,,GameCardInvalidSecureAccess,
|
||||
2,2541,,,,GameCardInvalidNormalAccess,
|
||||
|
@ -196,39 +201,48 @@ Module,DescriptionStart,DescriptionEnd,Flags,Namespace,Name,Summary
|
|||
2,2552,,,,GameCardCardReinitializeFailure,
|
||||
2,2553,,,,GameCardInvalidChallengeCardExistenceMode,
|
||||
2,2554,,,,GameCardInvalidCardHeader,
|
||||
2,2555,,,,GameCardInvalidCardCertificate,
|
||||
2,2555,,,,GameCardInvalidT1CardCertificate,
|
||||
|
||||
2,2557,,,,,
|
||||
2,2558,,,,,
|
||||
2,2557,,,,GameCardInvalidCa10Certificate,
|
||||
2,2558,,,,GameCardInvalidCa10CardHeader,
|
||||
|
||||
2,2565,2595,,,GameCardCommunicationFailure,
|
||||
2,2566,,,,GameCardFinishOperationFailed,
|
||||
|
||||
2,2599,,,,GameCardInvalidStateTransition,
|
||||
2,2600,,,,GameCardAsicInvalidTransitionToNormalMode,
|
||||
2,2601,,,,GameCardAsicInvalidTransitionToSecureMode,
|
||||
2,2602,,,,GameCardAsicInvalidTransitionToWriteMode,
|
||||
2,2597,2627,,,GameCardStateTransitionFailure,
|
||||
2,2598,,,,GameCardAlreadyTransitionedState,
|
||||
2,2599,,,,GameCardShouldTransitFromAsicInitialToSecure,
|
||||
2,2600,,,,GameCardShouldTransitFromInitialToNormal,
|
||||
2,2601,,,,GameCardShouldTransitFromNormalModeToSecure,
|
||||
2,2602,,,,GameCardShouldTransitFromNormalModeToDebug,
|
||||
|
||||
2,2629,,,,GameCardAsicInitializationFailureForWriterFirmware,
|
||||
2,2630,2669,,,GameCardAsicInitializationFailure,
|
||||
2,2631,,,,GameCardAsicGetDeviceStatusFailure,
|
||||
2,2632,,,,GameCardAsicActivationFailure,
|
||||
2,2634,,,,GameCardAsicSetUserAsicFirmwareFailure,
|
||||
2,2637,,,,GameCardAsicGetAsicCertFailure,
|
||||
2,2629,2669,,,GameCardInitializeAsicFailure,
|
||||
2,2630,,,,GameCardAlreadyInitializedAsic,
|
||||
2,2631,2632,,,GameCardActivateAsicFailure,
|
||||
2,2632,,,,GameCardAsicBootFailure,
|
||||
2,2634,,,,GameCardSendFirmwareFailure,
|
||||
|
||||
2,2636,2641,,,GameCardVerifyCertificateFailure,
|
||||
2,2637,,,,GameCardReceiveCertificateFailure,
|
||||
2,2638,,,,GameCardParseCertificateFailure,
|
||||
2,2639,,,,InvalidGameCardAsicCertificate,
|
||||
2,2640,,,,GameCardAsicSetEmmcEmbeddedSocCertificateFailure,
|
||||
2,2645,,,,GameCardAsicGetAsicEncryptedMessageFailure,
|
||||
2,2646,,,,GameCardAsicSetLibraryEncryptedMessageFailure,
|
||||
2,2639,,,,GameCardInvalidCertificate,
|
||||
2,2640,,,,GameCardSendSocCertificateFailure,
|
||||
|
||||
2,2651,,,,GameCardAsicGetAsicAuthenticationDataFailure,
|
||||
2,2652,,,,GameCardAsicSetAsicAuthenticationDataHashFailure,
|
||||
2,2653,,,,GameCardAsicSetLibraryAuthenticationDataFailure,
|
||||
2,2654,,,,GameCardAsicGetLibraryAuthenticationDataHashFailure,
|
||||
2,2655,,,,GameCardInvalidLibraryAuthenticationDataHash,
|
||||
2,2658,,,,GameCardAsicEnterSecureAsicModeFailure,
|
||||
2,2659,,,,GameCardAsicExchangeRandomValuesInSecureModeFailure,
|
||||
2,2644,2647,,,GameCardGenerateCommonKeyFailure,
|
||||
2,2645,,,,GameCardReceiveRandomValueFailure,
|
||||
2,2646,,,,GameCardSendRandomValueFailure,
|
||||
2,2647,,,,GameCardDecryptRandomValueFailure,
|
||||
|
||||
2,2650,2655,,,GameCardAuthenticateMutuallyFailure,
|
||||
2,2651,,,,GameCardReceiveDeviceChallengeFailure,
|
||||
2,2652,,,,GameCardRespondDeviceChallengeFailure,
|
||||
2,2653,,,,GameCardSendHostChallengeFailure,
|
||||
2,2654,,,,GameCardReceiveChallengeResponseFailure,
|
||||
2,2655,,,,GameCardChallengeAndResponseFailure,
|
||||
2,2658,,,,GameCardChangeModeToSecureFailure,
|
||||
2,2659,,,,GameCardExchangeRandomValuesFailure,
|
||||
2,2660,,,,GameCardAsicChallengeCardExistenceFailure,
|
||||
2,2663,,,,GameCardAsicActivationTimeout,
|
||||
2,2663,,,,GameCardInitializeAsicTimeOut,
|
||||
|
||||
2,2665,2669,,,GameCardSplFailure,
|
||||
2,2666,,,,GameCardSplDecryptAesKeyFailure,
|
||||
|
@ -236,33 +250,49 @@ Module,DescriptionStart,DescriptionEnd,Flags,Namespace,Name,Summary
|
|||
2,2668,,,,GameCardSplGenerateRandomBytesFailure,
|
||||
2,2669,,,,GameCardSplDecryptGcMessageFailure,
|
||||
|
||||
2,2671,,,,GameCardAsicReadAsicRegisterFailure,
|
||||
2,2672,,,,GameCardAsicWriteAsicRegisterFailure,
|
||||
2,2673,,,,GameCardAsicEnableCardBusFailure,
|
||||
2,2674,,,,GameCardAsicGetCardHeaderFailure,
|
||||
2,2671,,,,GameCardReadRegisterFailure,
|
||||
2,2672,,,,GameCardWriteRegisterFailure,
|
||||
2,2673,,,,GameCardEnableCardBusFailure,
|
||||
2,2674,,,,GameCardGetCardHeaderFailure,
|
||||
2,2675,,,,GameCardAsicStatusError,
|
||||
2,2676,,,,GameCardAsicGetCardKeyAreaFailure,
|
||||
2,2677,,,,GameCardAsicChangeDebugModeFailure,
|
||||
2,2678,,,,GameCardAsicGetRmaInformationFailure,
|
||||
2,2680,,,,GameCardAsicStatusBit22Set,
|
||||
2,2681,,,,GameCardSecureValuesNotInitialized,
|
||||
2,2692,,,,InvalidSecureGameCardCommand,
|
||||
2,2693,,,,InvalidWriteGameCardCommand,
|
||||
2,2676,,,,GameCardChangeGcModeToSecureFailure,
|
||||
2,2677,,,,GameCardChangeGcModeToDebugFailure,
|
||||
2,2678,,,,GameCardReadRmaInfoFailure,
|
||||
2,2680,2683,,,GameCardUpdateKeyFailure,
|
||||
2,2681,,,,GameCardKeySourceNotFound,
|
||||
|
||||
2,2690,2695,,,GameCardStateFailure,
|
||||
2,2691,,,,GameCardStateCardNormalModeRequired,
|
||||
2,2692,,,,GameCardStateCardSecureModeRequired,
|
||||
2,2693,,,,GameCardStateCardDebugModeRequired,
|
||||
2,2694,,,,GameCardStateAsicInitialRequired,
|
||||
2,2695,,,,GameCardStateAsicSecureRequired,
|
||||
|
||||
2,2700,2708,,,GameCardGeneralIoFailure,
|
||||
2,2701,,,,GameCardGeneralIoReleaseAsicResetFailure,
|
||||
2,2702,,,,GameCardGeneralIoHoldAsicResetFailure,
|
||||
2,2703,,,,GameCardSetVoltageFailure,
|
||||
|
||||
2,2710,2718,,,GameCardDataIoFailure,
|
||||
2,2711,,,,GameCardDataIoActivateFailure,
|
||||
|
||||
2,2730,2749,,,GameCardCardCommandFailure,
|
||||
2,2731,,,,GameCardCommandReadId1Failure,
|
||||
2,2732,,,,GameCardCommandReadId2Failure,
|
||||
2,2733,,,,GameCardCommandReadId3Failure,
|
||||
2,2735,,,,GameCardCommandReadPageFailure,
|
||||
2,2734,,,,GameCardSendCardReadUidFailure,
|
||||
2,2736,,,,GameCardCommandReadPageUnalignedFailure,
|
||||
2,2737,,,,GameCardCommandWritePageFailure,
|
||||
2,2738,,,,GameCardCommandRefreshFailure,
|
||||
2,2739,,,,GameCardCommandUpdateKeyFailure,
|
||||
2,2740,,,,GameCardSendCardSelfRefreshFailure,
|
||||
2,2741,,,,GameCardSendCardReadRefreshStatusFailure,
|
||||
2,2742,,,,GameCardCommandReadCrcFailure,
|
||||
2,2743,,,,GameCardCommandEraseFailure,
|
||||
2,2744,,,,GameCardCommandReadDevParamFailure,
|
||||
2,2745,,,,GameCardCommandWriteDevParamFailure,
|
||||
2,2746,,,,GameCardSendCardReadErrorCountFailure,
|
||||
|
||||
2,2900,2919,,,GameCardDevCardUnexpectedFailure,
|
||||
2,2901,,,,GameCardDebugParameterMismatch,
|
||||
|
@ -275,6 +305,7 @@ Module,DescriptionStart,DescriptionEnd,Flags,Namespace,Name,Summary
|
|||
2,2950,2998,,,GameCardFsFailure,
|
||||
2,2951,,,,GameCardFsGetHandleFailure,
|
||||
2,2952,,,,GameCardFsCheckHandleInReadFailure,
|
||||
2,2953,,,,GameCardFsCheckHandleInWriteFailure,
|
||||
2,2954,,,,GameCardFsCheckHandleInGetStatusFailure,
|
||||
2,2955,,,,GameCardFsCheckHandleInGetDeviceCertFailure,
|
||||
2,2956,,,,GameCardFsCheckHandleInGetCardImageHashFailure,
|
||||
|
@ -284,7 +315,7 @@ Module,DescriptionStart,DescriptionEnd,Flags,Namespace,Name,Summary
|
|||
2,2960,,,,GameCardFsCheckHandleInCreateReadOnlyFailure,
|
||||
2,2961,,,,GameCardFsCheckHandleInCreateSecureReadOnlyFailure,
|
||||
2,2962,,,,GameCardFsInvalidCompatibilityType,
|
||||
2,2963,,,,GameCardsNotSupportedOnDeviceModel,
|
||||
2,2963,,,,GameCardNotSupportedOnDeviceModel,
|
||||
|
||||
2,3000,7999,,,Internal,
|
||||
2,3001,,,,NotImplemented,
|
||||
|
|
|
31
src/LibHac/Common/FixedArrays/Array192.cs
Normal file
31
src/LibHac/Common/FixedArrays/Array192.cs
Normal file
|
@ -0,0 +1,31 @@
|
|||
#pragma warning disable CS0169, CS0649, IDE0051 // Field is never used, Field is never assigned to, Remove unused private members
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace LibHac.Common.FixedArrays;
|
||||
|
||||
public struct Array192<T>
|
||||
{
|
||||
public const int Length = 192;
|
||||
|
||||
private Array128<T> _0;
|
||||
private Array64<T> _128;
|
||||
|
||||
public ref T this[int i] => ref Items[i];
|
||||
|
||||
public Span<T> Items
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => SpanHelpers.CreateSpan(ref MemoryMarshal.GetReference(_0.Items), Length);
|
||||
}
|
||||
|
||||
public readonly ReadOnlySpan<T> ItemsRo
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => SpanHelpers.CreateSpan(ref MemoryMarshal.GetReference(_0.ItemsRo), Length);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator ReadOnlySpan<T>(in Array192<T> value) => value.ItemsRo;
|
||||
}
|
33
src/LibHac/Common/FixedArrays/Array452.cs
Normal file
33
src/LibHac/Common/FixedArrays/Array452.cs
Normal file
|
@ -0,0 +1,33 @@
|
|||
#pragma warning disable CS0169, CS0649, IDE0051 // Field is never used, Field is never assigned to, Remove unused private members
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace LibHac.Common.FixedArrays;
|
||||
|
||||
public struct Array452<T>
|
||||
{
|
||||
public const int Length = 452;
|
||||
|
||||
private Array256<T> _0;
|
||||
private Array128<T> _256;
|
||||
private Array64<T> _384;
|
||||
private Array4<T> _448;
|
||||
|
||||
public ref T this[int i] => ref Items[i];
|
||||
|
||||
public Span<T> Items
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => SpanHelpers.CreateSpan(ref MemoryMarshal.GetReference(_0.Items), Length);
|
||||
}
|
||||
|
||||
public readonly ReadOnlySpan<T> ItemsRo
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => SpanHelpers.CreateSpan(ref MemoryMarshal.GetReference(_0.ItemsRo), Length);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator ReadOnlySpan<T>(in Array452<T> value) => value.ItemsRo;
|
||||
}
|
33
src/LibHac/Common/FixedArrays/Array464.cs
Normal file
33
src/LibHac/Common/FixedArrays/Array464.cs
Normal file
|
@ -0,0 +1,33 @@
|
|||
#pragma warning disable CS0169, CS0649, IDE0051 // Field is never used, Field is never assigned to, Remove unused private members
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace LibHac.Common.FixedArrays;
|
||||
|
||||
public struct Array464<T>
|
||||
{
|
||||
public const int Length = 464;
|
||||
|
||||
private Array256<T> _0;
|
||||
private Array128<T> _256;
|
||||
private Array64<T> _384;
|
||||
private Array16<T> _448;
|
||||
|
||||
public ref T this[int i] => ref Items[i];
|
||||
|
||||
public Span<T> Items
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => SpanHelpers.CreateSpan(ref MemoryMarshal.GetReference(_0.Items), Length);
|
||||
}
|
||||
|
||||
public readonly ReadOnlySpan<T> ItemsRo
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => SpanHelpers.CreateSpan(ref MemoryMarshal.GetReference(_0.ItemsRo), Length);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator ReadOnlySpan<T>(in Array464<T> value) => value.ItemsRo;
|
||||
}
|
|
@ -167,6 +167,7 @@ internal static partial class DefaultKeySet
|
|||
keys.Add(new KeyInfo(264, Type.CommonSeed, "sd_card_custom_storage_key_source", (set, _) => set.SdCardKeySources[2]));
|
||||
|
||||
keys.Add(new KeyInfo(270, Type.CommonSeedDiff, "xci_header_key", (set, _) => set.XciHeaderKey));
|
||||
keys.Add(new KeyInfo(271, Type.CommonRoot, "xci_t1_titlekey_kek", 0, 0x10, (set, i) => set.GcTitleKeyKeks[i]));
|
||||
|
||||
keys.Add(new KeyInfo(280, Type.CommonRoot, "eticket_rsa_kek", (set, _) => set.ETicketRsaKek));
|
||||
keys.Add(new KeyInfo(281, Type.CommonRoot, "ssl_rsa_kek", (set, _) => set.SslRsaKek));
|
||||
|
|
|
@ -54,6 +54,7 @@ public class KeySet
|
|||
public Span<AesKey> TsecAuthSignatures => RootKeys.TsecAuthSignatures.Items;
|
||||
public Span<AesKey> TsecRootKeys => RootKeys.TsecRootKeys.Items;
|
||||
public Span<AesKey> MasterKekSources => _keys.KeySeeds.MasterKekSources.Items;
|
||||
public Span<AesKey> GcTitleKeyKeks => RootKeys.GcTitleKeyKeks.Items;
|
||||
|
||||
public Span<AesKey> MarikoMasterKekSources => _mode == Mode.Dev
|
||||
? _keys.KeySeeds.MarikoMasterKekSourcesDev.Items
|
||||
|
@ -293,6 +294,9 @@ public struct RootKeys
|
|||
|
||||
// Derived by TSEC. This is the first public root key for >= 6.2.0 Erista
|
||||
public Array32<AesKey> TsecRootKeys;
|
||||
|
||||
// Used to decrypt the title keys found in an XCI's initial data
|
||||
public Array16<AesKey> GcTitleKeyKeks;
|
||||
}
|
||||
|
||||
public struct KeySeeds
|
||||
|
|
|
@ -11,6 +11,7 @@ using LibHac.Fs.Fsa;
|
|||
using LibHac.Fs.Impl;
|
||||
using LibHac.Fs.Shim;
|
||||
using LibHac.FsSrv.Sf;
|
||||
using LibHac.Gc.Impl;
|
||||
using LibHac.Os;
|
||||
using LibHac.Sf;
|
||||
using static LibHac.Fs.Impl.AccessLogStrings;
|
||||
|
@ -158,7 +159,7 @@ namespace LibHac.Fs.Impl
|
|||
public static IdentifyAccessLogHandle MakeHandle(object handle) => new IdentifyAccessLogHandle(handle);
|
||||
}
|
||||
|
||||
internal struct IdString
|
||||
public struct IdString
|
||||
{
|
||||
private Buffer32 _buffer;
|
||||
|
||||
|
@ -296,6 +297,74 @@ namespace LibHac.Fs.Impl
|
|||
default: return ToValueString((int)value.Flags);
|
||||
}
|
||||
}
|
||||
|
||||
public ReadOnlySpan<byte> ToString(MemoryCapacity value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case MemoryCapacity.Capacity1GB: return new[] { (byte)'1', (byte)'G', (byte)'B' };
|
||||
case MemoryCapacity.Capacity2GB: return new[] { (byte)'2', (byte)'G', (byte)'B' };
|
||||
case MemoryCapacity.Capacity4GB: return new[] { (byte)'4', (byte)'G', (byte)'B' };
|
||||
case MemoryCapacity.Capacity8GB: return new[] { (byte)'8', (byte)'G', (byte)'B' };
|
||||
case MemoryCapacity.Capacity16GB: return new[] { (byte)'1', (byte)'6', (byte)'G', (byte)'B' };
|
||||
case MemoryCapacity.Capacity32GB: return new[] { (byte)'3', (byte)'2', (byte)'G', (byte)'B' };
|
||||
default: return ToValueString((int)value);
|
||||
}
|
||||
}
|
||||
|
||||
public ReadOnlySpan<byte> ToString(SelSec value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case SelSec.T1: return new[] { (byte)'T', (byte)'1' };
|
||||
case SelSec.T2: return new[] { (byte)'T', (byte)'2' };
|
||||
default: return ToValueString((int)value);
|
||||
}
|
||||
}
|
||||
|
||||
public ReadOnlySpan<byte> ToString(KekIndex value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case KekIndex.Version0: return new[] { (byte)'V', (byte)'e', (byte)'r', (byte)'s', (byte)'i', (byte)'o', (byte)'n', (byte)'0' };
|
||||
case KekIndex.ForDev: return new[] { (byte)'V', (byte)'e', (byte)'r', (byte)'s', (byte)'i', (byte)'o', (byte)'n', (byte)'F', (byte)'o', (byte)'r', (byte)'D', (byte)'e', (byte)'v' };
|
||||
default: return ToValueString((int)value);
|
||||
}
|
||||
}
|
||||
|
||||
public ReadOnlySpan<byte> ToString(AccessControl1ClockRate value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case AccessControl1ClockRate.ClockRate25MHz: return new[] { (byte)'2', (byte)'5', (byte)' ', (byte)'M', (byte)'H', (byte)'z' };
|
||||
case AccessControl1ClockRate.ClockRate50MHz: return new[] { (byte)'5', (byte)'0', (byte)' ', (byte)'M', (byte)'H', (byte)'z' };
|
||||
default: return ToValueString((int)value);
|
||||
}
|
||||
}
|
||||
|
||||
public ReadOnlySpan<byte> ToString(FwVersion value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case FwVersion.ForDev: return new[] { (byte)'F', (byte)'o', (byte)'r', (byte)'D', (byte)'e', (byte)'v' };
|
||||
case FwVersion.Since1_0_0: return new[] { (byte)'1', (byte)'.', (byte)'0', (byte)'.', (byte)'0' };
|
||||
case FwVersion.Since4_0_0: return new[] { (byte)'4', (byte)'.', (byte)'0', (byte)'.', (byte)'0' };
|
||||
case FwVersion.Since9_0_0: return new[] { (byte)'9', (byte)'.', (byte)'0', (byte)'.', (byte)'0' };
|
||||
case FwVersion.Since11_0_0: return new[] { (byte)'1', (byte)'1', (byte)'.', (byte)'0', (byte)'.', (byte)'0' };
|
||||
case FwVersion.Since12_0_0: return new[] { (byte)'1', (byte)'2', (byte)'.', (byte)'0', (byte)'.', (byte)'0' };
|
||||
default: return ToValueString((int)value);
|
||||
}
|
||||
}
|
||||
|
||||
public ReadOnlySpan<byte> ToString(GameCardCompatibilityType value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case GameCardCompatibilityType.Normal: return new[] { (byte)'N', (byte)'o', (byte)'r', (byte)'m', (byte)'a', (byte)'l' };
|
||||
case GameCardCompatibilityType.Terra: return new[] { (byte)'T', (byte)'e', (byte)'r', (byte)'r', (byte)'a' };
|
||||
default: return ToValueString((int)value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal delegate int AccessLogPrinterCallback(Span<byte> textBuffer);
|
||||
|
|
|
@ -40,7 +40,15 @@ public enum GameCardAttribute : byte
|
|||
HistoryEraseFlag = 1 << 1,
|
||||
RepairToolFlag = 1 << 2,
|
||||
DifferentRegionCupToTerraDeviceFlag = 1 << 3,
|
||||
DifferentRegionCupToGlobalDeviceFlag = 1 << 4
|
||||
DifferentRegionCupToGlobalDeviceFlag = 1 << 4,
|
||||
|
||||
HasCa10CertificateFlag = 1 << 7
|
||||
}
|
||||
|
||||
public enum GameCardCompatibilityType : byte
|
||||
{
|
||||
Normal = 0,
|
||||
Terra = 1
|
||||
}
|
||||
|
||||
public struct GameCardErrorInfo
|
||||
|
|
|
@ -240,123 +240,156 @@ public static class ResultFs
|
|||
|
||||
/// <summary>Error code: 2002-2500; Range: 2500-2999; Inner value: 0x138802</summary>
|
||||
public static Result.Base GameCardAccessFailed { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 2500, 2999); }
|
||||
/// <summary>Error code: 2002-2501; Inner value: 0x138a02</summary>
|
||||
public static Result.Base GameCardUnknown => new Result.Base(ModuleFs, 2501);
|
||||
/// <summary>Error code: 2002-2502; Inner value: 0x138c02</summary>
|
||||
public static Result.Base GameCardUnexpectedDeadCode => new Result.Base(ModuleFs, 2502);
|
||||
/// <summary>Error code: 2002-2503; Inner value: 0x138e02</summary>
|
||||
public static Result.Base GameCardPreconditionViolation => new Result.Base(ModuleFs, 2503);
|
||||
/// <summary>Error code: 2002-2504; Inner value: 0x139002</summary>
|
||||
public static Result.Base GameCardNotImplemented => new Result.Base(ModuleFs, 2504);
|
||||
/// <summary>Error code: 2002-2510; Inner value: 0x139c02</summary>
|
||||
public static Result.Base GameCardNoAvailableLockers => new Result.Base(ModuleFs, 2510);
|
||||
public static Result.Base GameCardQueueFullFailure => new Result.Base(ModuleFs, 2510);
|
||||
/// <summary>Error code: 2002-2511; Inner value: 0x139e02</summary>
|
||||
public static Result.Base GameCardLockerIndexOutOfRange => new Result.Base(ModuleFs, 2511);
|
||||
public static Result.Base GameCardLockerOutOfRange => new Result.Base(ModuleFs, 2511);
|
||||
/// <summary>Error code: 2002-2516; Inner value: 0x13a802</summary>
|
||||
public static Result.Base GameCardFailedIoMappingForGpio => new Result.Base(ModuleFs, 2516);
|
||||
/// <summary>Error code: 2002-2520; Inner value: 0x13b002</summary>
|
||||
public static Result.Base GameCardCardNotInserted => new Result.Base(ModuleFs, 2520);
|
||||
/// <summary>Error code: 2002-2521; Inner value: 0x13b202</summary>
|
||||
public static Result.Base InvalidGameCardIdInSpecificData => new Result.Base(ModuleFs, 2521);
|
||||
public static Result.Base GameCardCardIdMismatch => new Result.Base(ModuleFs, 2521);
|
||||
/// <summary>Error code: 2002-2522; Inner value: 0x13b402</summary>
|
||||
public static Result.Base GameCardCardNotActivated => new Result.Base(ModuleFs, 2522);
|
||||
/// <summary>Error code: 2002-2523; Inner value: 0x13b602</summary>
|
||||
public static Result.Base InvalidCommandForDeactivatedGameCardAsic => new Result.Base(ModuleFs, 2523);
|
||||
/// <summary>Error code: 2002-2531; Inner value: 0x13c602</summary>
|
||||
public static Result.Base GameCardCardAccessTimeout => new Result.Base(ModuleFs, 2531);
|
||||
/// <summary>Error code: 2002-2532; Inner value: 0x13c802</summary>
|
||||
public static Result.Base GameCardStatusFatalError => new Result.Base(ModuleFs, 2532);
|
||||
/// <summary>Error code: 2002-2533; Inner value: 0x13ca02</summary>
|
||||
public static Result.Base GameCardReadFailure => new Result.Base(ModuleFs, 2533);
|
||||
/// <summary>Error code: 2002-2536; Inner value: 0x13d002</summary>
|
||||
public static Result.Base GameCardRetryLimitHit => new Result.Base(ModuleFs, 2536);
|
||||
/// <summary>Error code: 2002-2537; Inner value: 0x13d202</summary>
|
||||
public static Result.Base GameCardStatusRefreshRequested => new Result.Base(ModuleFs, 2537);
|
||||
/// <summary>Error code: 2002-2538; Inner value: 0x13d402</summary>
|
||||
public static Result.Base GameCardStatusCrcErrorAndRefreshRequested => new Result.Base(ModuleFs, 2538);
|
||||
/// <summary>Error code: 2002-2540; Inner value: 0x13d802</summary>
|
||||
public static Result.Base GameCardInvalidSecureAccess => new Result.Base(ModuleFs, 2540);
|
||||
/// <summary>Error code: 2002-2541; Inner value: 0x13da02</summary>
|
||||
public static Result.Base GameCardInvalidNormalAccess => new Result.Base(ModuleFs, 2541);
|
||||
/// <summary>Error code: 2002-2542; Inner value: 0x13dc02</summary>
|
||||
public static Result.Base GameCardInvalidAccessAcrossMode => new Result.Base(ModuleFs, 2542);
|
||||
public static Result.Base GameCardNotAwakened => new Result.Base(ModuleFs, 2523);
|
||||
|
||||
/// <summary>Error code: 2002-2543; Range: 2543-2546; Inner value: 0x13de02</summary>
|
||||
public static Result.Base GameCardWrongCard { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 2543, 2546); }
|
||||
/// <summary>Error code: 2002-2544; Inner value: 0x13e002</summary>
|
||||
public static Result.Base GameCardInitialDataMismatch => new Result.Base(ModuleFs, 2544);
|
||||
/// <summary>Error code: 2002-2545; Inner value: 0x13e202</summary>
|
||||
public static Result.Base GameCardInitialNotFilledWithZero => new Result.Base(ModuleFs, 2545);
|
||||
/// <summary>Error code: 2002-2546; Inner value: 0x13e402</summary>
|
||||
public static Result.Base GameCardKekIndexMismatch => new Result.Base(ModuleFs, 2546);
|
||||
/// <summary>Error code: 2002-2530; Range: 2530-2559; Inner value: 0x13c402</summary>
|
||||
public static Result.Base GameCardCardAccessFailure { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 2530, 2559); }
|
||||
/// <summary>Error code: 2002-2531; Inner value: 0x13c602</summary>
|
||||
public static Result.Base GameCardCardAccessTimeout => new Result.Base(ModuleFs, 2531);
|
||||
/// <summary>Error code: 2002-2532; Inner value: 0x13c802</summary>
|
||||
public static Result.Base GameCardCardFatal => new Result.Base(ModuleFs, 2532);
|
||||
/// <summary>Error code: 2002-2533; Inner value: 0x13ca02</summary>
|
||||
public static Result.Base GameCardCardNeedRetry => new Result.Base(ModuleFs, 2533);
|
||||
/// <summary>Error code: 2002-2534; Inner value: 0x13cc02</summary>
|
||||
public static Result.Base GameCardCardRetryFailure => new Result.Base(ModuleFs, 2534);
|
||||
/// <summary>Error code: 2002-2536; Inner value: 0x13d002</summary>
|
||||
public static Result.Base GameCardRetryLimitOut => new Result.Base(ModuleFs, 2536);
|
||||
|
||||
/// <summary>Error code: 2002-2548; Inner value: 0x13e802</summary>
|
||||
public static Result.Base GameCardInvalidGetCardDeviceCertificate => new Result.Base(ModuleFs, 2548);
|
||||
/// <summary>Error code: 2002-2549; Inner value: 0x13ea02</summary>
|
||||
public static Result.Base GameCardUnregisteredCardSecureMethod => new Result.Base(ModuleFs, 2549);
|
||||
/// <summary>Error code: 2002-2550; Inner value: 0x13ec02</summary>
|
||||
public static Result.Base GameCardCardNeedRetryAfterAsicReinitialize => new Result.Base(ModuleFs, 2550);
|
||||
/// <summary>Error code: 2002-2551; Inner value: 0x13ee02</summary>
|
||||
public static Result.Base GameCardCardHeaderReadFailure => new Result.Base(ModuleFs, 2551);
|
||||
/// <summary>Error code: 2002-2552; Inner value: 0x13f002</summary>
|
||||
public static Result.Base GameCardCardReinitializeFailure => new Result.Base(ModuleFs, 2552);
|
||||
/// <summary>Error code: 2002-2553; Inner value: 0x13f202</summary>
|
||||
public static Result.Base GameCardInvalidChallengeCardExistenceMode => new Result.Base(ModuleFs, 2553);
|
||||
/// <summary>Error code: 2002-2554; Inner value: 0x13f402</summary>
|
||||
public static Result.Base GameCardInvalidCardHeader => new Result.Base(ModuleFs, 2554);
|
||||
/// <summary>Error code: 2002-2555; Inner value: 0x13f602</summary>
|
||||
public static Result.Base GameCardInvalidCardCertificate => new Result.Base(ModuleFs, 2555);
|
||||
/// <summary>Error code: 2002-2557; Inner value: 0x13fa02</summary>
|
||||
public static Result.Base Result2557 => new Result.Base(ModuleFs, 2557);
|
||||
/// <summary>Error code: 2002-2558; Inner value: 0x13fc02</summary>
|
||||
public static Result.Base Result2558 => new Result.Base(ModuleFs, 2558);
|
||||
/// <summary>Error code: 2002-2537; Range: 2537-2538; Inner value: 0x13d202</summary>
|
||||
public static Result.Base GameCardNeedRefresh { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 2537, 2538); }
|
||||
/// <summary>Error code: 2002-2538; Inner value: 0x13d402</summary>
|
||||
public static Result.Base GameCardNeedRefreshAndCardNeedRetry => new Result.Base(ModuleFs, 2538);
|
||||
|
||||
/// <summary>Error code: 2002-2540; Inner value: 0x13d802</summary>
|
||||
public static Result.Base GameCardInvalidSecureAccess => new Result.Base(ModuleFs, 2540);
|
||||
/// <summary>Error code: 2002-2541; Inner value: 0x13da02</summary>
|
||||
public static Result.Base GameCardInvalidNormalAccess => new Result.Base(ModuleFs, 2541);
|
||||
/// <summary>Error code: 2002-2542; Inner value: 0x13dc02</summary>
|
||||
public static Result.Base GameCardInvalidAccessAcrossMode => new Result.Base(ModuleFs, 2542);
|
||||
|
||||
/// <summary>Error code: 2002-2543; Range: 2543-2546; Inner value: 0x13de02</summary>
|
||||
public static Result.Base GameCardWrongCard { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 2543, 2546); }
|
||||
/// <summary>Error code: 2002-2544; Inner value: 0x13e002</summary>
|
||||
public static Result.Base GameCardInitialDataMismatch => new Result.Base(ModuleFs, 2544);
|
||||
/// <summary>Error code: 2002-2545; Inner value: 0x13e202</summary>
|
||||
public static Result.Base GameCardInitialNotFilledWithZero => new Result.Base(ModuleFs, 2545);
|
||||
/// <summary>Error code: 2002-2546; Inner value: 0x13e402</summary>
|
||||
public static Result.Base GameCardKekIndexMismatch => new Result.Base(ModuleFs, 2546);
|
||||
|
||||
/// <summary>Error code: 2002-2548; Inner value: 0x13e802</summary>
|
||||
public static Result.Base GameCardInvalidGetCardDeviceCertificate => new Result.Base(ModuleFs, 2548);
|
||||
/// <summary>Error code: 2002-2549; Inner value: 0x13ea02</summary>
|
||||
public static Result.Base GameCardUnregisteredCardSecureMethod => new Result.Base(ModuleFs, 2549);
|
||||
/// <summary>Error code: 2002-2550; Inner value: 0x13ec02</summary>
|
||||
public static Result.Base GameCardCardNeedRetryAfterAsicReinitialize => new Result.Base(ModuleFs, 2550);
|
||||
/// <summary>Error code: 2002-2551; Inner value: 0x13ee02</summary>
|
||||
public static Result.Base GameCardCardHeaderReadFailure => new Result.Base(ModuleFs, 2551);
|
||||
/// <summary>Error code: 2002-2552; Inner value: 0x13f002</summary>
|
||||
public static Result.Base GameCardCardReinitializeFailure => new Result.Base(ModuleFs, 2552);
|
||||
/// <summary>Error code: 2002-2553; Inner value: 0x13f202</summary>
|
||||
public static Result.Base GameCardInvalidChallengeCardExistenceMode => new Result.Base(ModuleFs, 2553);
|
||||
/// <summary>Error code: 2002-2554; Inner value: 0x13f402</summary>
|
||||
public static Result.Base GameCardInvalidCardHeader => new Result.Base(ModuleFs, 2554);
|
||||
/// <summary>Error code: 2002-2555; Inner value: 0x13f602</summary>
|
||||
public static Result.Base GameCardInvalidT1CardCertificate => new Result.Base(ModuleFs, 2555);
|
||||
/// <summary>Error code: 2002-2557; Inner value: 0x13fa02</summary>
|
||||
public static Result.Base GameCardInvalidCa10Certificate => new Result.Base(ModuleFs, 2557);
|
||||
/// <summary>Error code: 2002-2558; Inner value: 0x13fc02</summary>
|
||||
public static Result.Base GameCardInvalidCa10CardHeader => new Result.Base(ModuleFs, 2558);
|
||||
|
||||
/// <summary>Error code: 2002-2565; Range: 2565-2595; Inner value: 0x140a02</summary>
|
||||
public static Result.Base GameCardCommunicationFailure { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 2565, 2595); }
|
||||
/// <summary>Error code: 2002-2566; Inner value: 0x140c02</summary>
|
||||
public static Result.Base GameCardFinishOperationFailed => new Result.Base(ModuleFs, 2566);
|
||||
|
||||
/// <summary>Error code: 2002-2599; Inner value: 0x144e02</summary>
|
||||
public static Result.Base GameCardInvalidStateTransition => new Result.Base(ModuleFs, 2599);
|
||||
/// <summary>Error code: 2002-2600; Inner value: 0x145002</summary>
|
||||
public static Result.Base GameCardAsicInvalidTransitionToNormalMode => new Result.Base(ModuleFs, 2600);
|
||||
/// <summary>Error code: 2002-2601; Inner value: 0x145202</summary>
|
||||
public static Result.Base GameCardAsicInvalidTransitionToSecureMode => new Result.Base(ModuleFs, 2601);
|
||||
/// <summary>Error code: 2002-2602; Inner value: 0x145402</summary>
|
||||
public static Result.Base GameCardAsicInvalidTransitionToWriteMode => new Result.Base(ModuleFs, 2602);
|
||||
/// <summary>Error code: 2002-2629; Inner value: 0x148a02</summary>
|
||||
public static Result.Base GameCardAsicInitializationFailureForWriterFirmware => new Result.Base(ModuleFs, 2629);
|
||||
/// <summary>Error code: 2002-2597; Range: 2597-2627; Inner value: 0x144a02</summary>
|
||||
public static Result.Base GameCardStateTransitionFailure { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 2597, 2627); }
|
||||
/// <summary>Error code: 2002-2598; Inner value: 0x144c02</summary>
|
||||
public static Result.Base GameCardAlreadyTransitionedState => new Result.Base(ModuleFs, 2598);
|
||||
/// <summary>Error code: 2002-2599; Inner value: 0x144e02</summary>
|
||||
public static Result.Base GameCardShouldTransitFromAsicInitialToSecure => new Result.Base(ModuleFs, 2599);
|
||||
/// <summary>Error code: 2002-2600; Inner value: 0x145002</summary>
|
||||
public static Result.Base GameCardShouldTransitFromInitialToNormal => new Result.Base(ModuleFs, 2600);
|
||||
/// <summary>Error code: 2002-2601; Inner value: 0x145202</summary>
|
||||
public static Result.Base GameCardShouldTransitFromNormalModeToSecure => new Result.Base(ModuleFs, 2601);
|
||||
/// <summary>Error code: 2002-2602; Inner value: 0x145402</summary>
|
||||
public static Result.Base GameCardShouldTransitFromNormalModeToDebug => new Result.Base(ModuleFs, 2602);
|
||||
|
||||
/// <summary>Error code: 2002-2629; Range: 2629-2669; Inner value: 0x148a02</summary>
|
||||
public static Result.Base GameCardInitializeAsicFailure { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 2629, 2669); }
|
||||
/// <summary>Error code: 2002-2630; Inner value: 0x148c02</summary>
|
||||
public static Result.Base GameCardAlreadyInitializedAsic => new Result.Base(ModuleFs, 2630);
|
||||
|
||||
/// <summary>Error code: 2002-2631; Range: 2631-2632; Inner value: 0x148e02</summary>
|
||||
public static Result.Base GameCardActivateAsicFailure { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 2631, 2632); }
|
||||
/// <summary>Error code: 2002-2632; Inner value: 0x149002</summary>
|
||||
public static Result.Base GameCardAsicBootFailure => new Result.Base(ModuleFs, 2632);
|
||||
|
||||
/// <summary>Error code: 2002-2630; Range: 2630-2669; Inner value: 0x148c02</summary>
|
||||
public static Result.Base GameCardAsicInitializationFailure { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 2630, 2669); }
|
||||
/// <summary>Error code: 2002-2631; Inner value: 0x148e02</summary>
|
||||
public static Result.Base GameCardAsicGetDeviceStatusFailure => new Result.Base(ModuleFs, 2631);
|
||||
/// <summary>Error code: 2002-2632; Inner value: 0x149002</summary>
|
||||
public static Result.Base GameCardAsicActivationFailure => new Result.Base(ModuleFs, 2632);
|
||||
/// <summary>Error code: 2002-2634; Inner value: 0x149402</summary>
|
||||
public static Result.Base GameCardAsicSetUserAsicFirmwareFailure => new Result.Base(ModuleFs, 2634);
|
||||
/// <summary>Error code: 2002-2637; Inner value: 0x149a02</summary>
|
||||
public static Result.Base GameCardAsicGetAsicCertFailure => new Result.Base(ModuleFs, 2637);
|
||||
/// <summary>Error code: 2002-2638; Inner value: 0x149c02</summary>
|
||||
public static Result.Base GameCardParseCertificateFailure => new Result.Base(ModuleFs, 2638);
|
||||
/// <summary>Error code: 2002-2639; Inner value: 0x149e02</summary>
|
||||
public static Result.Base InvalidGameCardAsicCertificate => new Result.Base(ModuleFs, 2639);
|
||||
/// <summary>Error code: 2002-2640; Inner value: 0x14a002</summary>
|
||||
public static Result.Base GameCardAsicSetEmmcEmbeddedSocCertificateFailure => new Result.Base(ModuleFs, 2640);
|
||||
/// <summary>Error code: 2002-2645; Inner value: 0x14aa02</summary>
|
||||
public static Result.Base GameCardAsicGetAsicEncryptedMessageFailure => new Result.Base(ModuleFs, 2645);
|
||||
/// <summary>Error code: 2002-2646; Inner value: 0x14ac02</summary>
|
||||
public static Result.Base GameCardAsicSetLibraryEncryptedMessageFailure => new Result.Base(ModuleFs, 2646);
|
||||
/// <summary>Error code: 2002-2651; Inner value: 0x14b602</summary>
|
||||
public static Result.Base GameCardAsicGetAsicAuthenticationDataFailure => new Result.Base(ModuleFs, 2651);
|
||||
/// <summary>Error code: 2002-2652; Inner value: 0x14b802</summary>
|
||||
public static Result.Base GameCardAsicSetAsicAuthenticationDataHashFailure => new Result.Base(ModuleFs, 2652);
|
||||
/// <summary>Error code: 2002-2653; Inner value: 0x14ba02</summary>
|
||||
public static Result.Base GameCardAsicSetLibraryAuthenticationDataFailure => new Result.Base(ModuleFs, 2653);
|
||||
/// <summary>Error code: 2002-2654; Inner value: 0x14bc02</summary>
|
||||
public static Result.Base GameCardAsicGetLibraryAuthenticationDataHashFailure => new Result.Base(ModuleFs, 2654);
|
||||
/// <summary>Error code: 2002-2655; Inner value: 0x14be02</summary>
|
||||
public static Result.Base GameCardInvalidLibraryAuthenticationDataHash => new Result.Base(ModuleFs, 2655);
|
||||
public static Result.Base GameCardSendFirmwareFailure => new Result.Base(ModuleFs, 2634);
|
||||
|
||||
/// <summary>Error code: 2002-2636; Range: 2636-2641; Inner value: 0x149802</summary>
|
||||
public static Result.Base GameCardVerifyCertificateFailure { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 2636, 2641); }
|
||||
/// <summary>Error code: 2002-2637; Inner value: 0x149a02</summary>
|
||||
public static Result.Base GameCardReceiveCertificateFailure => new Result.Base(ModuleFs, 2637);
|
||||
/// <summary>Error code: 2002-2638; Inner value: 0x149c02</summary>
|
||||
public static Result.Base GameCardParseCertificateFailure => new Result.Base(ModuleFs, 2638);
|
||||
/// <summary>Error code: 2002-2639; Inner value: 0x149e02</summary>
|
||||
public static Result.Base GameCardInvalidCertificate => new Result.Base(ModuleFs, 2639);
|
||||
/// <summary>Error code: 2002-2640; Inner value: 0x14a002</summary>
|
||||
public static Result.Base GameCardSendSocCertificateFailure => new Result.Base(ModuleFs, 2640);
|
||||
|
||||
/// <summary>Error code: 2002-2644; Range: 2644-2647; Inner value: 0x14a802</summary>
|
||||
public static Result.Base GameCardGenerateCommonKeyFailure { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 2644, 2647); }
|
||||
/// <summary>Error code: 2002-2645; Inner value: 0x14aa02</summary>
|
||||
public static Result.Base GameCardReceiveRandomValueFailure => new Result.Base(ModuleFs, 2645);
|
||||
/// <summary>Error code: 2002-2646; Inner value: 0x14ac02</summary>
|
||||
public static Result.Base GameCardSendRandomValueFailure => new Result.Base(ModuleFs, 2646);
|
||||
/// <summary>Error code: 2002-2647; Inner value: 0x14ae02</summary>
|
||||
public static Result.Base GameCardDecryptRandomValueFailure => new Result.Base(ModuleFs, 2647);
|
||||
|
||||
/// <summary>Error code: 2002-2650; Range: 2650-2655; Inner value: 0x14b402</summary>
|
||||
public static Result.Base GameCardAuthenticateMutuallyFailure { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 2650, 2655); }
|
||||
/// <summary>Error code: 2002-2651; Inner value: 0x14b602</summary>
|
||||
public static Result.Base GameCardReceiveDeviceChallengeFailure => new Result.Base(ModuleFs, 2651);
|
||||
/// <summary>Error code: 2002-2652; Inner value: 0x14b802</summary>
|
||||
public static Result.Base GameCardRespondDeviceChallengeFailure => new Result.Base(ModuleFs, 2652);
|
||||
/// <summary>Error code: 2002-2653; Inner value: 0x14ba02</summary>
|
||||
public static Result.Base GameCardSendHostChallengeFailure => new Result.Base(ModuleFs, 2653);
|
||||
/// <summary>Error code: 2002-2654; Inner value: 0x14bc02</summary>
|
||||
public static Result.Base GameCardReceiveChallengeResponseFailure => new Result.Base(ModuleFs, 2654);
|
||||
/// <summary>Error code: 2002-2655; Inner value: 0x14be02</summary>
|
||||
public static Result.Base GameCardChallengeAndResponseFailure => new Result.Base(ModuleFs, 2655);
|
||||
|
||||
/// <summary>Error code: 2002-2658; Inner value: 0x14c402</summary>
|
||||
public static Result.Base GameCardAsicEnterSecureAsicModeFailure => new Result.Base(ModuleFs, 2658);
|
||||
public static Result.Base GameCardChangeModeToSecureFailure => new Result.Base(ModuleFs, 2658);
|
||||
/// <summary>Error code: 2002-2659; Inner value: 0x14c602</summary>
|
||||
public static Result.Base GameCardAsicExchangeRandomValuesInSecureModeFailure => new Result.Base(ModuleFs, 2659);
|
||||
public static Result.Base GameCardExchangeRandomValuesFailure => new Result.Base(ModuleFs, 2659);
|
||||
/// <summary>Error code: 2002-2660; Inner value: 0x14c802</summary>
|
||||
public static Result.Base GameCardAsicChallengeCardExistenceFailure => new Result.Base(ModuleFs, 2660);
|
||||
/// <summary>Error code: 2002-2663; Inner value: 0x14ce02</summary>
|
||||
public static Result.Base GameCardAsicActivationTimeout => new Result.Base(ModuleFs, 2663);
|
||||
public static Result.Base GameCardInitializeAsicTimeOut => new Result.Base(ModuleFs, 2663);
|
||||
|
||||
/// <summary>Error code: 2002-2665; Range: 2665-2669; Inner value: 0x14d202</summary>
|
||||
public static Result.Base GameCardSplFailure { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 2665, 2669); }
|
||||
|
@ -370,55 +403,88 @@ public static class ResultFs
|
|||
public static Result.Base GameCardSplDecryptGcMessageFailure => new Result.Base(ModuleFs, 2669);
|
||||
|
||||
/// <summary>Error code: 2002-2671; Inner value: 0x14de02</summary>
|
||||
public static Result.Base GameCardAsicReadAsicRegisterFailure => new Result.Base(ModuleFs, 2671);
|
||||
public static Result.Base GameCardReadRegisterFailure => new Result.Base(ModuleFs, 2671);
|
||||
/// <summary>Error code: 2002-2672; Inner value: 0x14e002</summary>
|
||||
public static Result.Base GameCardAsicWriteAsicRegisterFailure => new Result.Base(ModuleFs, 2672);
|
||||
public static Result.Base GameCardWriteRegisterFailure => new Result.Base(ModuleFs, 2672);
|
||||
/// <summary>Error code: 2002-2673; Inner value: 0x14e202</summary>
|
||||
public static Result.Base GameCardAsicEnableCardBusFailure => new Result.Base(ModuleFs, 2673);
|
||||
public static Result.Base GameCardEnableCardBusFailure => new Result.Base(ModuleFs, 2673);
|
||||
/// <summary>Error code: 2002-2674; Inner value: 0x14e402</summary>
|
||||
public static Result.Base GameCardAsicGetCardHeaderFailure => new Result.Base(ModuleFs, 2674);
|
||||
public static Result.Base GameCardGetCardHeaderFailure => new Result.Base(ModuleFs, 2674);
|
||||
/// <summary>Error code: 2002-2675; Inner value: 0x14e602</summary>
|
||||
public static Result.Base GameCardAsicStatusError => new Result.Base(ModuleFs, 2675);
|
||||
/// <summary>Error code: 2002-2676; Inner value: 0x14e802</summary>
|
||||
public static Result.Base GameCardAsicGetCardKeyAreaFailure => new Result.Base(ModuleFs, 2676);
|
||||
public static Result.Base GameCardChangeGcModeToSecureFailure => new Result.Base(ModuleFs, 2676);
|
||||
/// <summary>Error code: 2002-2677; Inner value: 0x14ea02</summary>
|
||||
public static Result.Base GameCardAsicChangeDebugModeFailure => new Result.Base(ModuleFs, 2677);
|
||||
public static Result.Base GameCardChangeGcModeToDebugFailure => new Result.Base(ModuleFs, 2677);
|
||||
/// <summary>Error code: 2002-2678; Inner value: 0x14ec02</summary>
|
||||
public static Result.Base GameCardAsicGetRmaInformationFailure => new Result.Base(ModuleFs, 2678);
|
||||
/// <summary>Error code: 2002-2680; Inner value: 0x14f002</summary>
|
||||
public static Result.Base GameCardAsicStatusBit22Set => new Result.Base(ModuleFs, 2680);
|
||||
/// <summary>Error code: 2002-2681; Inner value: 0x14f202</summary>
|
||||
public static Result.Base GameCardSecureValuesNotInitialized => new Result.Base(ModuleFs, 2681);
|
||||
/// <summary>Error code: 2002-2692; Inner value: 0x150802</summary>
|
||||
public static Result.Base InvalidSecureGameCardCommand => new Result.Base(ModuleFs, 2692);
|
||||
/// <summary>Error code: 2002-2693; Inner value: 0x150a02</summary>
|
||||
public static Result.Base InvalidWriteGameCardCommand => new Result.Base(ModuleFs, 2693);
|
||||
/// <summary>Error code: 2002-2703; Inner value: 0x151e02</summary>
|
||||
public static Result.Base GameCardSetVoltageFailure => new Result.Base(ModuleFs, 2703);
|
||||
/// <summary>Error code: 2002-2731; Inner value: 0x155602</summary>
|
||||
public static Result.Base GameCardCommandReadId1Failure => new Result.Base(ModuleFs, 2731);
|
||||
/// <summary>Error code: 2002-2732; Inner value: 0x155802</summary>
|
||||
public static Result.Base GameCardCommandReadId2Failure => new Result.Base(ModuleFs, 2732);
|
||||
/// <summary>Error code: 2002-2733; Inner value: 0x155a02</summary>
|
||||
public static Result.Base GameCardCommandReadId3Failure => new Result.Base(ModuleFs, 2733);
|
||||
/// <summary>Error code: 2002-2735; Inner value: 0x155e02</summary>
|
||||
public static Result.Base GameCardCommandReadPageFailure => new Result.Base(ModuleFs, 2735);
|
||||
/// <summary>Error code: 2002-2736; Inner value: 0x156002</summary>
|
||||
public static Result.Base GameCardCommandReadPageUnalignedFailure => new Result.Base(ModuleFs, 2736);
|
||||
/// <summary>Error code: 2002-2737; Inner value: 0x156202</summary>
|
||||
public static Result.Base GameCardCommandWritePageFailure => new Result.Base(ModuleFs, 2737);
|
||||
/// <summary>Error code: 2002-2738; Inner value: 0x156402</summary>
|
||||
public static Result.Base GameCardCommandRefreshFailure => new Result.Base(ModuleFs, 2738);
|
||||
/// <summary>Error code: 2002-2739; Inner value: 0x156602</summary>
|
||||
public static Result.Base GameCardCommandUpdateKeyFailure => new Result.Base(ModuleFs, 2739);
|
||||
/// <summary>Error code: 2002-2742; Inner value: 0x156c02</summary>
|
||||
public static Result.Base GameCardCommandReadCrcFailure => new Result.Base(ModuleFs, 2742);
|
||||
/// <summary>Error code: 2002-2743; Inner value: 0x156e02</summary>
|
||||
public static Result.Base GameCardCommandEraseFailure => new Result.Base(ModuleFs, 2743);
|
||||
/// <summary>Error code: 2002-2744; Inner value: 0x157002</summary>
|
||||
public static Result.Base GameCardCommandReadDevParamFailure => new Result.Base(ModuleFs, 2744);
|
||||
/// <summary>Error code: 2002-2745; Inner value: 0x157202</summary>
|
||||
public static Result.Base GameCardCommandWriteDevParamFailure => new Result.Base(ModuleFs, 2745);
|
||||
public static Result.Base GameCardReadRmaInfoFailure => new Result.Base(ModuleFs, 2678);
|
||||
|
||||
/// <summary>Error code: 2002-2680; Range: 2680-2683; Inner value: 0x14f002</summary>
|
||||
public static Result.Base GameCardUpdateKeyFailure { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 2680, 2683); }
|
||||
/// <summary>Error code: 2002-2681; Inner value: 0x14f202</summary>
|
||||
public static Result.Base GameCardKeySourceNotFound => new Result.Base(ModuleFs, 2681);
|
||||
|
||||
/// <summary>Error code: 2002-2690; Range: 2690-2695; Inner value: 0x150402</summary>
|
||||
public static Result.Base GameCardStateFailure { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 2690, 2695); }
|
||||
/// <summary>Error code: 2002-2691; Inner value: 0x150602</summary>
|
||||
public static Result.Base GameCardStateCardNormalModeRequired => new Result.Base(ModuleFs, 2691);
|
||||
/// <summary>Error code: 2002-2692; Inner value: 0x150802</summary>
|
||||
public static Result.Base GameCardStateCardSecureModeRequired => new Result.Base(ModuleFs, 2692);
|
||||
/// <summary>Error code: 2002-2693; Inner value: 0x150a02</summary>
|
||||
public static Result.Base GameCardStateCardDebugModeRequired => new Result.Base(ModuleFs, 2693);
|
||||
/// <summary>Error code: 2002-2694; Inner value: 0x150c02</summary>
|
||||
public static Result.Base GameCardStateAsicInitialRequired => new Result.Base(ModuleFs, 2694);
|
||||
/// <summary>Error code: 2002-2695; Inner value: 0x150e02</summary>
|
||||
public static Result.Base GameCardStateAsicSecureRequired => new Result.Base(ModuleFs, 2695);
|
||||
|
||||
/// <summary>Error code: 2002-2700; Range: 2700-2708; Inner value: 0x151802</summary>
|
||||
public static Result.Base GameCardGeneralIoFailure { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 2700, 2708); }
|
||||
/// <summary>Error code: 2002-2701; Inner value: 0x151a02</summary>
|
||||
public static Result.Base GameCardGeneralIoReleaseAsicResetFailure => new Result.Base(ModuleFs, 2701);
|
||||
/// <summary>Error code: 2002-2702; Inner value: 0x151c02</summary>
|
||||
public static Result.Base GameCardGeneralIoHoldAsicResetFailure => new Result.Base(ModuleFs, 2702);
|
||||
/// <summary>Error code: 2002-2703; Inner value: 0x151e02</summary>
|
||||
public static Result.Base GameCardSetVoltageFailure => new Result.Base(ModuleFs, 2703);
|
||||
|
||||
/// <summary>Error code: 2002-2710; Range: 2710-2718; Inner value: 0x152c02</summary>
|
||||
public static Result.Base GameCardDataIoFailure { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 2710, 2718); }
|
||||
/// <summary>Error code: 2002-2711; Inner value: 0x152e02</summary>
|
||||
public static Result.Base GameCardDataIoActivateFailure => new Result.Base(ModuleFs, 2711);
|
||||
|
||||
/// <summary>Error code: 2002-2730; Range: 2730-2749; Inner value: 0x155402</summary>
|
||||
public static Result.Base GameCardCardCommandFailure { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 2730, 2749); }
|
||||
/// <summary>Error code: 2002-2731; Inner value: 0x155602</summary>
|
||||
public static Result.Base GameCardCommandReadId1Failure => new Result.Base(ModuleFs, 2731);
|
||||
/// <summary>Error code: 2002-2732; Inner value: 0x155802</summary>
|
||||
public static Result.Base GameCardCommandReadId2Failure => new Result.Base(ModuleFs, 2732);
|
||||
/// <summary>Error code: 2002-2733; Inner value: 0x155a02</summary>
|
||||
public static Result.Base GameCardCommandReadId3Failure => new Result.Base(ModuleFs, 2733);
|
||||
/// <summary>Error code: 2002-2734; Inner value: 0x155c02</summary>
|
||||
public static Result.Base GameCardSendCardReadUidFailure => new Result.Base(ModuleFs, 2734);
|
||||
/// <summary>Error code: 2002-2735; Inner value: 0x155e02</summary>
|
||||
public static Result.Base GameCardCommandReadPageFailure => new Result.Base(ModuleFs, 2735);
|
||||
/// <summary>Error code: 2002-2736; Inner value: 0x156002</summary>
|
||||
public static Result.Base GameCardCommandReadPageUnalignedFailure => new Result.Base(ModuleFs, 2736);
|
||||
/// <summary>Error code: 2002-2737; Inner value: 0x156202</summary>
|
||||
public static Result.Base GameCardCommandWritePageFailure => new Result.Base(ModuleFs, 2737);
|
||||
/// <summary>Error code: 2002-2738; Inner value: 0x156402</summary>
|
||||
public static Result.Base GameCardCommandRefreshFailure => new Result.Base(ModuleFs, 2738);
|
||||
/// <summary>Error code: 2002-2739; Inner value: 0x156602</summary>
|
||||
public static Result.Base GameCardCommandUpdateKeyFailure => new Result.Base(ModuleFs, 2739);
|
||||
/// <summary>Error code: 2002-2740; Inner value: 0x156802</summary>
|
||||
public static Result.Base GameCardSendCardSelfRefreshFailure => new Result.Base(ModuleFs, 2740);
|
||||
/// <summary>Error code: 2002-2741; Inner value: 0x156a02</summary>
|
||||
public static Result.Base GameCardSendCardReadRefreshStatusFailure => new Result.Base(ModuleFs, 2741);
|
||||
/// <summary>Error code: 2002-2742; Inner value: 0x156c02</summary>
|
||||
public static Result.Base GameCardCommandReadCrcFailure => new Result.Base(ModuleFs, 2742);
|
||||
/// <summary>Error code: 2002-2743; Inner value: 0x156e02</summary>
|
||||
public static Result.Base GameCardCommandEraseFailure => new Result.Base(ModuleFs, 2743);
|
||||
/// <summary>Error code: 2002-2744; Inner value: 0x157002</summary>
|
||||
public static Result.Base GameCardCommandReadDevParamFailure => new Result.Base(ModuleFs, 2744);
|
||||
/// <summary>Error code: 2002-2745; Inner value: 0x157202</summary>
|
||||
public static Result.Base GameCardCommandWriteDevParamFailure => new Result.Base(ModuleFs, 2745);
|
||||
/// <summary>Error code: 2002-2746; Inner value: 0x157402</summary>
|
||||
public static Result.Base GameCardSendCardReadErrorCountFailure => new Result.Base(ModuleFs, 2746);
|
||||
|
||||
/// <summary>Error code: 2002-2900; Range: 2900-2919; Inner value: 0x16a802</summary>
|
||||
public static Result.Base GameCardDevCardUnexpectedFailure { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 2900, 2919); }
|
||||
|
@ -441,6 +507,8 @@ public static class ResultFs
|
|||
public static Result.Base GameCardFsGetHandleFailure => new Result.Base(ModuleFs, 2951);
|
||||
/// <summary>Error code: 2002-2952; Inner value: 0x171002</summary>
|
||||
public static Result.Base GameCardFsCheckHandleInReadFailure => new Result.Base(ModuleFs, 2952);
|
||||
/// <summary>Error code: 2002-2953; Inner value: 0x171202</summary>
|
||||
public static Result.Base GameCardFsCheckHandleInWriteFailure => new Result.Base(ModuleFs, 2953);
|
||||
/// <summary>Error code: 2002-2954; Inner value: 0x171402</summary>
|
||||
public static Result.Base GameCardFsCheckHandleInGetStatusFailure => new Result.Base(ModuleFs, 2954);
|
||||
/// <summary>Error code: 2002-2955; Inner value: 0x171602</summary>
|
||||
|
@ -460,7 +528,7 @@ public static class ResultFs
|
|||
/// <summary>Error code: 2002-2962; Inner value: 0x172402</summary>
|
||||
public static Result.Base GameCardFsInvalidCompatibilityType => new Result.Base(ModuleFs, 2962);
|
||||
/// <summary>Error code: 2002-2963; Inner value: 0x172602</summary>
|
||||
public static Result.Base GameCardsNotSupportedOnDeviceModel => new Result.Base(ModuleFs, 2963);
|
||||
public static Result.Base GameCardNotSupportedOnDeviceModel => new Result.Base(ModuleFs, 2963);
|
||||
|
||||
/// <summary>Error code: 2002-3000; Range: 3000-7999; Inner value: 0x177002</summary>
|
||||
public static Result.Base Internal { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 3000, 7999); }
|
||||
|
|
|
@ -39,10 +39,9 @@ public class EmulatedGameCard
|
|||
{
|
||||
RemoveGameCard();
|
||||
|
||||
CardImageStorage = cardImageStorage;
|
||||
|
||||
CardImage = new Xci(KeySet, cardImageStorage);
|
||||
CardHeader = CardImage.Header;
|
||||
CardImageStorage = CardImage.BaseStorage;
|
||||
}
|
||||
|
||||
public void RemoveGameCard()
|
||||
|
|
|
@ -22,6 +22,58 @@ public struct CardId3
|
|||
public Array4<byte> Reserved;
|
||||
}
|
||||
|
||||
public struct CardInitialDataPayload
|
||||
{
|
||||
public Array8<byte> PackageId;
|
||||
public Array8<byte> Reserved;
|
||||
public Array16<byte> AuthData;
|
||||
public Array16<byte> AuthMac;
|
||||
public Array12<byte> AuthNonce;
|
||||
}
|
||||
|
||||
public struct CardInitialData
|
||||
{
|
||||
public CardInitialDataPayload Payload;
|
||||
public Array452<byte> Padding;
|
||||
}
|
||||
|
||||
public enum FwVersion : byte
|
||||
{
|
||||
// ReSharper disable InconsistentNaming
|
||||
ForDev = 0,
|
||||
Since1_0_0 = 1,
|
||||
Since4_0_0 = 2,
|
||||
Since9_0_0 = 3,
|
||||
Since11_0_0 = 4,
|
||||
Since12_0_0 = 5
|
||||
// ReSharper restore InconsistentNaming
|
||||
}
|
||||
|
||||
public enum KekIndex : byte
|
||||
{
|
||||
Version0 = 0,
|
||||
ForDev = 1
|
||||
}
|
||||
|
||||
public struct CardHeaderEncryptedData
|
||||
{
|
||||
public Array2<uint> FwVersion;
|
||||
public uint AccCtrl1;
|
||||
public uint Wait1TimeRead;
|
||||
public uint Wait2TimeRead;
|
||||
public uint Wait1TimeWrite;
|
||||
public uint Wait2TimeWrite;
|
||||
public uint FwMode;
|
||||
public uint CupVersion;
|
||||
public byte CompatibilityType;
|
||||
public byte Reserved25;
|
||||
public byte Reserved26;
|
||||
public byte Reserved27;
|
||||
public Array8<byte> UppHash;
|
||||
public ulong CupId;
|
||||
public Array56<byte> Reserved38;
|
||||
}
|
||||
|
||||
public enum MemoryCapacity : byte
|
||||
{
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
@ -32,4 +84,72 @@ public enum MemoryCapacity : byte
|
|||
Capacity16GB = 0xE1,
|
||||
Capacity32GB = 0xE2
|
||||
// ReSharper restore InconsistentNaming
|
||||
}
|
||||
|
||||
public enum AccessControl1ClockRate
|
||||
{
|
||||
ClockRate25MHz = 0xA10011,
|
||||
ClockRate50MHz = 0xA10010
|
||||
}
|
||||
|
||||
public enum SelSec
|
||||
{
|
||||
T1 = 1,
|
||||
T2 = 2
|
||||
}
|
||||
|
||||
public struct CardHeader
|
||||
{
|
||||
public static uint HeaderMagic => 0x44414548; // HEAD
|
||||
|
||||
public uint Magic;
|
||||
public uint RomAreaStartPage;
|
||||
public uint BackupAreaStartPage;
|
||||
public byte KeyIndex;
|
||||
public byte RomSize;
|
||||
public byte Version;
|
||||
public byte Flags;
|
||||
public Array8<byte> PackageId;
|
||||
public uint ValidDataEndPage;
|
||||
public Array4<byte> Reserved11C;
|
||||
public Array16<byte> Iv;
|
||||
public ulong PartitionFsHeaderAddress;
|
||||
public ulong PartitionFsHeaderSize;
|
||||
public Array32<byte> PartitionFsHeaderHash;
|
||||
public Array32<byte> InitialDataHash;
|
||||
public uint SelSec;
|
||||
public uint SelT1Key;
|
||||
public uint SelKey;
|
||||
public uint LimAreaPage;
|
||||
public CardHeaderEncryptedData EncryptedData;
|
||||
}
|
||||
|
||||
public struct CardHeaderWithSignature
|
||||
{
|
||||
public Array256<byte> Signature;
|
||||
public CardHeader Data;
|
||||
}
|
||||
|
||||
public struct T1CardCertificate
|
||||
{
|
||||
public static uint CertMagic => 0x54524543; // CERT
|
||||
|
||||
public Array256<byte> Signature;
|
||||
public uint Magic;
|
||||
public uint Version;
|
||||
public byte KekIndex;
|
||||
public Array7<byte> Flags;
|
||||
public Array16<byte> T1CardDeviceId;
|
||||
public Array16<byte> Iv;
|
||||
public Array16<byte> HwKey;
|
||||
public Array192<byte> Reserved;
|
||||
public Array512<byte> Padding;
|
||||
}
|
||||
|
||||
public struct Ca10Certificate
|
||||
{
|
||||
public Array256<byte> Signature;
|
||||
public Array48<byte> Unk100;
|
||||
public Array256<byte> Modulus;
|
||||
public Array464<byte> Unk230;
|
||||
}
|
|
@ -11,7 +11,7 @@ public class Xci
|
|||
{
|
||||
public XciHeader Header { get; }
|
||||
|
||||
private IStorage BaseStorage { get; }
|
||||
internal IStorage BaseStorage { get; }
|
||||
private object InitLocker { get; } = new object();
|
||||
private XciPartition RootPartition { get; set; }
|
||||
|
||||
|
@ -19,6 +19,11 @@ public class Xci
|
|||
{
|
||||
BaseStorage = storage;
|
||||
Header = new XciHeader(keySet, storage.AsStream());
|
||||
|
||||
if (Header.HasInitialData)
|
||||
{
|
||||
BaseStorage = storage.Slice(0x1000);
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasPartition(XciPartitionType type)
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using LibHac.Common;
|
||||
using LibHac.Common.Keys;
|
||||
using LibHac.Crypto;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Gc.Impl;
|
||||
using LibHac.Tools.Crypto;
|
||||
using LibHac.Tools.FsSystem;
|
||||
using Aes = LibHac.Crypto.Aes;
|
||||
|
||||
namespace LibHac.Tools.Fs;
|
||||
|
||||
|
@ -13,7 +18,9 @@ public class XciHeader
|
|||
{
|
||||
private const int SignatureSize = 0x100;
|
||||
private const string HeaderMagic = "HEAD";
|
||||
private const uint HeaderMagicValue = 0x44414548; // HEAD
|
||||
private const int EncryptedHeaderSize = 0x70;
|
||||
private const int GcTitleKeyKekIndexMax = 0x10;
|
||||
|
||||
private static readonly byte[] XciHeaderPubk =
|
||||
{
|
||||
|
@ -56,6 +63,7 @@ public class XciHeader
|
|||
public int SelKey { get; set; }
|
||||
public int LimAreaPage { get; set; }
|
||||
|
||||
public bool IsHeaderDecrypted { get; set; }
|
||||
public ulong FwVersion { get; set; }
|
||||
public CardClockRate AccCtrl1 { get; set; }
|
||||
public int Wait1TimeRead { get; set; }
|
||||
|
@ -64,6 +72,7 @@ public class XciHeader
|
|||
public int Wait2TimeWrite { get; set; }
|
||||
public int FwMode { get; set; }
|
||||
public int UppVersion { get; set; }
|
||||
public byte CompatibilityType { get; set; }
|
||||
public byte[] UppHash { get; set; }
|
||||
public ulong UppId { get; set; }
|
||||
|
||||
|
@ -71,10 +80,38 @@ public class XciHeader
|
|||
|
||||
public Validity SignatureValidity { get; set; }
|
||||
public Validity PartitionFsHeaderValidity { get; set; }
|
||||
public Validity InitialDataValidity { get; set; }
|
||||
|
||||
public bool HasInitialData { get; set; }
|
||||
public byte[] InitialDataPackageId { get; set; }
|
||||
public byte[] InitialDataAuthData { get; set; }
|
||||
public byte[] InitialDataAuthMac { get; set; }
|
||||
public byte[] InitialDataAuthNonce { get; set; }
|
||||
public byte[] InitialData { get; set; }
|
||||
public byte[] DecryptedTitleKey { get; set; }
|
||||
|
||||
public XciHeader(KeySet keySet, Stream stream)
|
||||
{
|
||||
using (var reader = new BinaryReader(stream, Encoding.Default, true))
|
||||
DetermineXciSubStorages(out IStorage keyAreaStorage, out IStorage bodyStorage, stream.AsStorage())
|
||||
.ThrowIfFailure();
|
||||
|
||||
if (keyAreaStorage is not null)
|
||||
{
|
||||
using (var r = new BinaryReader(keyAreaStorage.AsStream(), Encoding.Default, true))
|
||||
{
|
||||
HasInitialData = true;
|
||||
InitialDataPackageId = r.ReadBytes(8);
|
||||
r.BaseStream.Position += 8;
|
||||
InitialDataAuthData = r.ReadBytes(0x10);
|
||||
InitialDataAuthMac = r.ReadBytes(0x10);
|
||||
InitialDataAuthNonce = r.ReadBytes(0xC);
|
||||
|
||||
r.BaseStream.Position = 0;
|
||||
InitialData = r.ReadBytes(Unsafe.SizeOf<CardInitialData>());
|
||||
}
|
||||
}
|
||||
|
||||
using (var reader = new BinaryReader(bodyStorage.AsStream(), Encoding.Default, true))
|
||||
{
|
||||
Signature = reader.ReadBytes(SignatureSize);
|
||||
Magic = reader.ReadAscii(4);
|
||||
|
@ -112,6 +149,8 @@ public class XciHeader
|
|||
|
||||
if (keySet != null && !keySet.XciHeaderKey.IsZeros())
|
||||
{
|
||||
IsHeaderDecrypted = true;
|
||||
|
||||
byte[] encHeader = reader.ReadBytes(EncryptedHeaderSize);
|
||||
byte[] decHeader = new byte[EncryptedHeaderSize];
|
||||
Aes.DecryptCbc128(encHeader, decHeader, keySet.XciHeaderKey, AesCbcIv);
|
||||
|
@ -126,7 +165,8 @@ public class XciHeader
|
|||
Wait2TimeWrite = decReader.ReadInt32();
|
||||
FwMode = decReader.ReadInt32();
|
||||
UppVersion = decReader.ReadInt32();
|
||||
decReader.BaseStream.Position += 4;
|
||||
CompatibilityType = decReader.ReadByte();
|
||||
decReader.BaseStream.Position += 3;
|
||||
UppHash = decReader.ReadBytes(8);
|
||||
UppId = decReader.ReadUInt64();
|
||||
}
|
||||
|
@ -142,14 +182,103 @@ public class XciHeader
|
|||
Sha256.GenerateSha256Hash(headerBytes, actualHeaderHash);
|
||||
|
||||
PartitionFsHeaderValidity = Utilities.SpansEqual(RootPartitionHeaderHash, actualHeaderHash) ? Validity.Valid : Validity.Invalid;
|
||||
|
||||
if (HasInitialData)
|
||||
{
|
||||
Span<byte> actualInitialDataHash = stackalloc byte[Sha256.DigestSize];
|
||||
Sha256.GenerateSha256Hash(InitialData, actualInitialDataHash);
|
||||
|
||||
InitialDataValidity = Utilities.SpansEqual(InitialDataHash, actualInitialDataHash)
|
||||
? Validity.Valid
|
||||
: Validity.Invalid;
|
||||
}
|
||||
|
||||
Span<byte> key = stackalloc byte[0x10];
|
||||
Result rc = DecryptCardInitialData(key, InitialData, KekIndex, keySet);
|
||||
if (rc.IsSuccess())
|
||||
{
|
||||
DecryptedTitleKey = key.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Result DecryptCardInitialData(Span<byte> dest, ReadOnlySpan<byte> initialData, int kekIndex, KeySet keySet)
|
||||
{
|
||||
if (initialData.Length != Unsafe.SizeOf<CardInitialData>())
|
||||
return ResultFs.GameCardPreconditionViolation.Log();
|
||||
|
||||
if (kekIndex >= GcTitleKeyKekIndexMax)
|
||||
return ResultFs.GameCardPreconditionViolation.Log();
|
||||
|
||||
// Verify the kek is preset.
|
||||
if (keySet.GcTitleKeyKeks[kekIndex].IsZeros())
|
||||
return ResultFs.GameCardPreconditionViolation.Log();
|
||||
|
||||
// Generate the key.
|
||||
Span<byte> key = stackalloc byte[0x10];
|
||||
Aes.DecryptEcb128(initialData.Slice(0, 0x10), key, keySet.GcTitleKeyKeks[kekIndex]);
|
||||
|
||||
ref readonly CardInitialData data = ref SpanHelpers.AsReadOnlyStruct<CardInitialData>(initialData);
|
||||
|
||||
if (dest.Length != data.Payload.AuthData.ItemsRo.Length)
|
||||
return ResultFs.GameCardPreconditionViolation.Log();
|
||||
|
||||
// Verify padding is all-zero.
|
||||
bool anyNonZero = false;
|
||||
for (int i = 0; i < data.Padding.ItemsRo.Length; i++)
|
||||
{
|
||||
anyNonZero |= data.Padding.ItemsRo[i] != 0;
|
||||
}
|
||||
|
||||
if (anyNonZero)
|
||||
return ResultFs.GameCardInitialNotFilledWithZero.Log();
|
||||
|
||||
using (var decryptor = new AesCcm(key))
|
||||
{
|
||||
try
|
||||
{
|
||||
decryptor.Decrypt(data.Payload.AuthNonce, data.Payload.AuthData, data.Payload.AuthMac, dest);
|
||||
}
|
||||
catch (CryptographicException)
|
||||
{
|
||||
return ResultFs.GameCardKekIndexMismatch.Log();
|
||||
}
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private Result DetermineXciSubStorages(out IStorage keyAreaStorage, out IStorage bodyStorage, IStorage baseStorage)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out keyAreaStorage, out bodyStorage);
|
||||
|
||||
Result rc = baseStorage.GetSize(out long storageSize);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
if (storageSize >= 0x1104)
|
||||
{
|
||||
uint magic = 0;
|
||||
rc = baseStorage.Read(0x1100, SpanHelpers.AsByteSpan(ref magic));
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
if (magic == HeaderMagicValue)
|
||||
{
|
||||
keyAreaStorage = new SubStorage(baseStorage, 0, 0x1000);
|
||||
bodyStorage = new SubStorage(baseStorage, 0x1000, storageSize - 0x1000);
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
keyAreaStorage = null;
|
||||
bodyStorage = baseStorage;
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
public enum CardClockRate
|
||||
{
|
||||
ClockRate25 = 10551312,
|
||||
ClockRate50
|
||||
ClockRate25 = 0xA10011,
|
||||
ClockRate50 = 0xA10010
|
||||
}
|
||||
|
||||
public enum XciPartitionType
|
||||
|
|
173
src/hactoolnet/IndentingStringBuilder.cs
Normal file
173
src/hactoolnet/IndentingStringBuilder.cs
Normal file
|
@ -0,0 +1,173 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace hactoolnet;
|
||||
|
||||
public struct ScopedIndentation : IDisposable
|
||||
{
|
||||
private IndentingStringBuilder Builder;
|
||||
|
||||
public ScopedIndentation(IndentingStringBuilder builder)
|
||||
{
|
||||
builder.IncreaseLevel();
|
||||
Builder = builder;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Builder.DecreaseLevel();
|
||||
}
|
||||
}
|
||||
|
||||
public class IndentingStringBuilder
|
||||
{
|
||||
public int LevelSize { get; set; } = 4;
|
||||
public int Level { get; private set; }
|
||||
|
||||
private StringBuilder _sb = new StringBuilder();
|
||||
private string _indentation = string.Empty;
|
||||
private bool _hasIndentedCurrentLine;
|
||||
private bool _lastLineWasEmpty;
|
||||
private int _columnLength;
|
||||
private int _paddingSize;
|
||||
|
||||
public IndentingStringBuilder(int columnLength)
|
||||
{
|
||||
_columnLength = columnLength;
|
||||
_paddingSize = columnLength;
|
||||
}
|
||||
|
||||
public IndentingStringBuilder(int levelSize, int columnLength)
|
||||
{
|
||||
LevelSize = levelSize;
|
||||
_columnLength = columnLength;
|
||||
_paddingSize = columnLength;
|
||||
}
|
||||
|
||||
public void SetLevel(int level)
|
||||
{
|
||||
Level = Math.Max(level, 0);
|
||||
_indentation = new string(' ', Level * LevelSize);
|
||||
_paddingSize = _columnLength - Level * LevelSize;
|
||||
}
|
||||
|
||||
public void IncreaseLevel() => SetLevel(Level + 1);
|
||||
public void DecreaseLevel() => SetLevel(Level - 1);
|
||||
|
||||
public IndentingStringBuilder AppendLine()
|
||||
{
|
||||
_sb.AppendLine();
|
||||
_hasIndentedCurrentLine = false;
|
||||
_lastLineWasEmpty = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IndentingStringBuilder AppendSpacerLine()
|
||||
{
|
||||
if (!_lastLineWasEmpty)
|
||||
{
|
||||
_sb.AppendLine();
|
||||
_hasIndentedCurrentLine = false;
|
||||
_lastLineWasEmpty = true;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public IndentingStringBuilder AppendLine(string value)
|
||||
{
|
||||
IndentIfNeeded();
|
||||
_sb.AppendLine(value);
|
||||
_hasIndentedCurrentLine = false;
|
||||
_lastLineWasEmpty = string.IsNullOrWhiteSpace(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public IndentingStringBuilder Append(string value)
|
||||
{
|
||||
IndentIfNeeded();
|
||||
_sb.Append(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public IndentingStringBuilder Append(char value, int repeatCount)
|
||||
{
|
||||
IndentIfNeeded();
|
||||
_sb.Append(value, repeatCount);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ScopedIndentation AppendHeader(string value)
|
||||
{
|
||||
AppendLine(value);
|
||||
return new ScopedIndentation(this);
|
||||
}
|
||||
|
||||
public void PrintItem(string prefix, object data)
|
||||
{
|
||||
if (data is byte[] byteData)
|
||||
{
|
||||
AppendBytes(prefix.PadRight(_paddingSize), byteData);
|
||||
}
|
||||
else
|
||||
{
|
||||
AppendLine(prefix.PadRight(_paddingSize) + data);
|
||||
}
|
||||
}
|
||||
|
||||
public IndentingStringBuilder AppendLineAndIncrease(string value)
|
||||
{
|
||||
AppendLine(value);
|
||||
IncreaseLevel();
|
||||
return this;
|
||||
}
|
||||
|
||||
public IndentingStringBuilder DecreaseAndAppendLine(string value)
|
||||
{
|
||||
DecreaseLevel();
|
||||
AppendLine(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
private void IndentIfNeeded()
|
||||
{
|
||||
if (!_hasIndentedCurrentLine)
|
||||
{
|
||||
_sb.Append(_indentation);
|
||||
_hasIndentedCurrentLine = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void AppendBytes(string prefix, byte[] data)
|
||||
{
|
||||
int max = 32;
|
||||
int remaining = data.Length;
|
||||
bool first = true;
|
||||
int offset = 0;
|
||||
|
||||
while (remaining > 0)
|
||||
{
|
||||
max = Math.Min(max, remaining);
|
||||
|
||||
if (first)
|
||||
{
|
||||
Append(prefix);
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Append(' ', prefix.Length);
|
||||
}
|
||||
|
||||
for (int i = 0; i < max; i++)
|
||||
{
|
||||
Append($"{data[offset++]:X2}");
|
||||
}
|
||||
|
||||
AppendLine();
|
||||
remaining -= max;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString() => _sb.ToString();
|
||||
}
|
|
@ -1,13 +1,14 @@
|
|||
using System.IO;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Impl;
|
||||
using LibHac.FsSystem;
|
||||
using LibHac.Gc.Impl;
|
||||
using LibHac.Tools.Fs;
|
||||
using LibHac.Tools.FsSystem;
|
||||
using LibHac.Tools.FsSystem.NcaUtils;
|
||||
using static hactoolnet.Print;
|
||||
|
||||
namespace hactoolnet;
|
||||
|
||||
|
@ -140,19 +141,86 @@ internal static class ProcessXci
|
|||
|
||||
private static string Print(this Xci xci)
|
||||
{
|
||||
const int colLen = 36;
|
||||
const int colLen = 52;
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine();
|
||||
var sb = new IndentingStringBuilder(colLen);
|
||||
|
||||
sb.AppendLine("XCI:");
|
||||
if (!xci.Header.HasInitialData)
|
||||
{
|
||||
sb.AppendLine("Warning: Game card is missing key area/initial data header. Re-dump?");
|
||||
}
|
||||
|
||||
PrintItem(sb, colLen, "Magic:", xci.Header.Magic);
|
||||
PrintItem(sb, colLen, $"Header Signature{xci.Header.SignatureValidity.GetValidityString()}:", xci.Header.Signature);
|
||||
PrintItem(sb, colLen, $"Header Hash{xci.Header.PartitionFsHeaderValidity.GetValidityString()}:", xci.Header.RootPartitionHeaderHash);
|
||||
PrintItem(sb, colLen, "Cartridge Type:", GetCartridgeType(xci.Header.GameCardSize));
|
||||
PrintItem(sb, colLen, "Cartridge Size:", $"0x{Utilities.MediaToReal(xci.Header.ValidDataEndPage + 1):x12}");
|
||||
PrintItem(sb, colLen, "Header IV:", xci.Header.AesCbcIv);
|
||||
using ScopedIndentation xciScope = sb.AppendHeader("XCI:");
|
||||
|
||||
if (xci.Header.HasInitialData)
|
||||
{
|
||||
using ScopedIndentation initialDataScope = sb.AppendHeader("Initial Data:");
|
||||
|
||||
sb.PrintItem("Package Id:", xci.Header.InitialDataPackageId);
|
||||
sb.PrintItem("Encrypted Title Key:", xci.Header.InitialDataAuthData);
|
||||
|
||||
if (xci.Header.DecryptedTitleKey is not null)
|
||||
{
|
||||
sb.PrintItem("Decrypted Title Key:", xci.Header.DecryptedTitleKey);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.PrintItem("Initial Data:", "Missing/Not Dumped");
|
||||
}
|
||||
|
||||
using (sb.AppendHeader("Main Header:"))
|
||||
{
|
||||
sb.PrintItem("Magic:", xci.Header.Magic);
|
||||
sb.PrintItem($"Signature{xci.Header.SignatureValidity.GetValidityString()}:",
|
||||
xci.Header.Signature);
|
||||
sb.PrintItem("Package Id:", BitConverter.GetBytes(xci.Header.PackageId));
|
||||
|
||||
sb.PrintItem("Memory Capacity:", new U8Span(new IdString().ToString((MemoryCapacity)xci.Header.GameCardSize)).ToString());
|
||||
sb.PrintItem("Rom Area Start:", $"0x{Utilities.MediaToReal(xci.Header.RomAreaStartPage):X12}");
|
||||
sb.PrintItem("Backup Area Start:", $"0x{Utilities.MediaToReal((uint)xci.Header.BackupAreaStartPage):X12}");
|
||||
sb.PrintItem("Valid Data End:", $"0x{Utilities.MediaToReal(xci.Header.ValidDataEndPage):X12}");
|
||||
sb.PrintItem("Limit Area:", $"0x{Utilities.MediaToReal(xci.Header.LimAreaPage):X12}");
|
||||
sb.PrintItem("Kek Index:", new U8Span(new IdString().ToString((KekIndex)xci.Header.KekIndex)).ToString());
|
||||
sb.PrintItem("Title Key Dec Index:", xci.Header.TitleKeyDecIndex);
|
||||
|
||||
using (sb.AppendHeader("Flags:"))
|
||||
{
|
||||
sb.PrintItem("Auto Boot:", xci.Header.Flags.HasFlag(GameCardAttribute.AutoBootFlag) ? 1 : 0);
|
||||
sb.PrintItem("History Erase:", xci.Header.Flags.HasFlag(GameCardAttribute.HistoryEraseFlag) ? 1 : 0);
|
||||
sb.PrintItem("Repair Tool:", xci.Header.Flags.HasFlag(GameCardAttribute.RepairToolFlag) ? 1 : 0);
|
||||
sb.PrintItem("Different Region Cup to Terra Device:", xci.Header.Flags.HasFlag(GameCardAttribute.DifferentRegionCupToTerraDeviceFlag) ? 1 : 0);
|
||||
sb.PrintItem("Different Region Cup to Global Device:", xci.Header.Flags.HasFlag(GameCardAttribute.DifferentRegionCupToGlobalDeviceFlag) ? 1 : 0);
|
||||
sb.PrintItem("Has Ca10 Certificate:", xci.Header.Flags.HasFlag(GameCardAttribute.HasCa10CertificateFlag) ? 1 : 0);
|
||||
}
|
||||
|
||||
sb.PrintItem("Sel Sec:", new U8Span(new IdString().ToString((SelSec)xci.Header.SelSec)).ToString());
|
||||
sb.PrintItem("Sel T1 Key:", xci.Header.SelT1Key);
|
||||
sb.PrintItem("Sel Key:", xci.Header.SelKey);
|
||||
|
||||
sb.PrintItem($"Initial Data Hash{xci.Header.InitialDataValidity.GetValidityString()}:", xci.Header.InitialDataHash);
|
||||
sb.PrintItem($"Partition Header Hash{xci.Header.PartitionFsHeaderValidity.GetValidityString()}:", xci.Header.RootPartitionHeaderHash);
|
||||
sb.PrintItem("Encrypted Data Iv:", xci.Header.AesCbcIv.Reverse().ToArray());
|
||||
|
||||
if (xci.Header.IsHeaderDecrypted)
|
||||
{
|
||||
using ScopedIndentation infoScope = sb.AppendHeader("Card Info:");
|
||||
|
||||
sb.PrintItem("Card Fw Version:", new U8Span(new IdString().ToString((FwVersion)xci.Header.FwVersion)).ToString());
|
||||
sb.PrintItem("Clock Rate:", new U8Span(new IdString().ToString((AccessControl1ClockRate)xci.Header.AccCtrl1)).ToString());
|
||||
sb.PrintItem("Wait1 Time Read:", xci.Header.Wait1TimeRead);
|
||||
sb.PrintItem("Wait2 Time Read:", xci.Header.Wait2TimeRead);
|
||||
sb.PrintItem("Wait1 Time Write:", xci.Header.Wait1TimeWrite);
|
||||
sb.PrintItem("Wait2 Time Write:", xci.Header.Wait2TimeWrite);
|
||||
sb.PrintItem("Fw Mode:", $"0x{xci.Header.FwMode:X8}");
|
||||
sb.PrintItem("Compatibility Type:", new U8Span(new IdString().ToString((GameCardCompatibilityType)xci.Header.CompatibilityType)).ToString());
|
||||
|
||||
int cv = xci.Header.UppVersion;
|
||||
sb.PrintItem("Cup Version:", $"{(cv >> 26) & 0x3F}.{(cv >> 20) & 0x3F}.{(cv >> 16) & 0xF}.{(cv >> 0) & 0xFFFF} ({cv})");
|
||||
sb.PrintItem("Cup Id:", $"{xci.Header.UppId:X16}");
|
||||
sb.PrintItem("Upp Hash:", xci.Header.UppHash);
|
||||
}
|
||||
}
|
||||
|
||||
PrintPartition(sb, colLen, xci.OpenPartition(XciPartitionType.Root), XciPartitionType.Root);
|
||||
|
||||
|
@ -168,14 +236,13 @@ internal static class ProcessXci
|
|||
return sb.ToString();
|
||||
}
|
||||
|
||||
private static void PrintPartition(StringBuilder sb, int colLen, XciPartition partition, XciPartitionType type)
|
||||
private static void PrintPartition(IndentingStringBuilder sb, int colLen, XciPartition partition, XciPartitionType type)
|
||||
{
|
||||
const int fileNameLen = 57;
|
||||
using ScopedIndentation mainHeader =
|
||||
sb.AppendHeader($"{type.Print()} Partition:{partition.HashValidity.GetValidityString()}");
|
||||
|
||||
sb.AppendLine($"{type.Print()} Partition:{partition.HashValidity.GetValidityString()}");
|
||||
PrintItem(sb, colLen, " Magic:", partition.Header.Magic);
|
||||
PrintItem(sb, colLen, " Offset:", $"{partition.Offset:x12}");
|
||||
PrintItem(sb, colLen, " Number of files:", partition.Files.Length);
|
||||
sb.PrintItem("Magic:", partition.Header.Magic);
|
||||
sb.PrintItem("Number of files:", partition.Files.Length);
|
||||
|
||||
string name = type.GetFileName();
|
||||
|
||||
|
@ -185,26 +252,11 @@ internal static class ProcessXci
|
|||
{
|
||||
PartitionFileEntry file = partition.Files[i];
|
||||
|
||||
string label = i == 0 ? " Files:" : "";
|
||||
string offsets = $"{file.Offset:x12}-{file.Offset + file.Size:x12}{file.HashValidity.GetValidityString()}";
|
||||
string data = $"{name}:/{file.Name}".PadRight(fileNameLen) + offsets;
|
||||
string label = i == 0 ? "Files:" : "";
|
||||
string data = $"{name}:/{file.Name}";
|
||||
|
||||
PrintItem(sb, colLen, label, data);
|
||||
sb.PrintItem(label, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetCartridgeType(GameCardSizeInternal size)
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case GameCardSizeInternal.Size1Gb: return "1GB";
|
||||
case GameCardSizeInternal.Size2Gb: return "2GB";
|
||||
case GameCardSizeInternal.Size4Gb: return "4GB";
|
||||
case GameCardSizeInternal.Size8Gb: return "8GB";
|
||||
case GameCardSizeInternal.Size16Gb: return "16GB";
|
||||
case GameCardSizeInternal.Size32Gb: return "32GB";
|
||||
default: return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -86,4 +86,125 @@ public class TypeLayoutTests
|
|||
|
||||
Assert.Equal(0, GetOffset(in s, in s.Reserved));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void CardInitialDataPayload_Layout()
|
||||
{
|
||||
var s = new CardInitialDataPayload();
|
||||
|
||||
Assert.Equal(0x3C, Unsafe.SizeOf<CardInitialDataPayload>());
|
||||
|
||||
Assert.Equal(0x00, GetOffset(in s, in s.PackageId));
|
||||
Assert.Equal(0x08, GetOffset(in s, in s.Reserved));
|
||||
Assert.Equal(0x10, GetOffset(in s, in s.AuthData));
|
||||
Assert.Equal(0x20, GetOffset(in s, in s.AuthMac));
|
||||
Assert.Equal(0x30, GetOffset(in s, in s.AuthNonce));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void CardInitialData_Layout()
|
||||
{
|
||||
var s = new CardInitialData();
|
||||
|
||||
Assert.Equal(0x200, Unsafe.SizeOf<CardInitialData>());
|
||||
|
||||
Assert.Equal(0x00, GetOffset(in s, in s.Payload));
|
||||
Assert.Equal(0x3C, GetOffset(in s, in s.Padding));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void CardHeaderEncryptedData_Layout()
|
||||
{
|
||||
var s = new CardHeaderEncryptedData();
|
||||
|
||||
Assert.Equal(0x70, Unsafe.SizeOf<CardHeaderEncryptedData>());
|
||||
|
||||
Assert.Equal(0x00, GetOffset(in s, in s.FwVersion));
|
||||
Assert.Equal(0x08, GetOffset(in s, in s.AccCtrl1));
|
||||
Assert.Equal(0x0C, GetOffset(in s, in s.Wait1TimeRead));
|
||||
Assert.Equal(0x10, GetOffset(in s, in s.Wait2TimeRead));
|
||||
Assert.Equal(0x14, GetOffset(in s, in s.Wait1TimeWrite));
|
||||
Assert.Equal(0x18, GetOffset(in s, in s.Wait2TimeWrite));
|
||||
Assert.Equal(0x1C, GetOffset(in s, in s.FwMode));
|
||||
Assert.Equal(0x20, GetOffset(in s, in s.CupVersion));
|
||||
Assert.Equal(0x24, GetOffset(in s, in s.CompatibilityType));
|
||||
Assert.Equal(0x25, GetOffset(in s, in s.Reserved25));
|
||||
Assert.Equal(0x26, GetOffset(in s, in s.Reserved26));
|
||||
Assert.Equal(0x27, GetOffset(in s, in s.Reserved27));
|
||||
Assert.Equal(0x28, GetOffset(in s, in s.UppHash));
|
||||
Assert.Equal(0x30, GetOffset(in s, in s.CupId));
|
||||
Assert.Equal(0x38, GetOffset(in s, in s.Reserved38));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void CardHeader_Layout()
|
||||
{
|
||||
var s = new CardHeader();
|
||||
|
||||
Assert.Equal(0x100, Unsafe.SizeOf<CardHeader>());
|
||||
|
||||
Assert.Equal(0x00, GetOffset(in s, in s.Magic));
|
||||
Assert.Equal(0x04, GetOffset(in s, in s.RomAreaStartPage));
|
||||
Assert.Equal(0x08, GetOffset(in s, in s.BackupAreaStartPage));
|
||||
Assert.Equal(0x0C, GetOffset(in s, in s.KeyIndex));
|
||||
Assert.Equal(0x0D, GetOffset(in s, in s.RomSize));
|
||||
Assert.Equal(0x0E, GetOffset(in s, in s.Version));
|
||||
Assert.Equal(0x0F, GetOffset(in s, in s.Flags));
|
||||
Assert.Equal(0x10, GetOffset(in s, in s.PackageId));
|
||||
Assert.Equal(0x18, GetOffset(in s, in s.ValidDataEndPage));
|
||||
Assert.Equal(0x1C, GetOffset(in s, in s.Reserved11C));
|
||||
Assert.Equal(0x20, GetOffset(in s, in s.Iv));
|
||||
Assert.Equal(0x30, GetOffset(in s, in s.PartitionFsHeaderAddress));
|
||||
Assert.Equal(0x38, GetOffset(in s, in s.PartitionFsHeaderSize));
|
||||
Assert.Equal(0x40, GetOffset(in s, in s.PartitionFsHeaderHash));
|
||||
Assert.Equal(0x60, GetOffset(in s, in s.InitialDataHash));
|
||||
Assert.Equal(0x80, GetOffset(in s, in s.SelSec));
|
||||
Assert.Equal(0x84, GetOffset(in s, in s.SelT1Key));
|
||||
Assert.Equal(0x88, GetOffset(in s, in s.SelKey));
|
||||
Assert.Equal(0x8C, GetOffset(in s, in s.LimAreaPage));
|
||||
Assert.Equal(0x90, GetOffset(in s, in s.EncryptedData));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void CardHeaderWithSignature_Layout()
|
||||
{
|
||||
var s = new CardHeaderWithSignature();
|
||||
|
||||
Assert.Equal(0x200, Unsafe.SizeOf<CardHeaderWithSignature>());
|
||||
|
||||
Assert.Equal(0x000, GetOffset(in s, in s.Signature));
|
||||
Assert.Equal(0x100, GetOffset(in s, in s.Data));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void T1CardCertificate_Layout()
|
||||
{
|
||||
var s = new T1CardCertificate();
|
||||
|
||||
Assert.Equal(0x400, Unsafe.SizeOf<T1CardCertificate>());
|
||||
|
||||
Assert.Equal(0x000, GetOffset(in s, in s.Signature));
|
||||
Assert.Equal(0x100, GetOffset(in s, in s.Magic));
|
||||
Assert.Equal(0x104, GetOffset(in s, in s.Version));
|
||||
Assert.Equal(0x108, GetOffset(in s, in s.KekIndex));
|
||||
Assert.Equal(0x109, GetOffset(in s, in s.Flags));
|
||||
Assert.Equal(0x110, GetOffset(in s, in s.T1CardDeviceId));
|
||||
Assert.Equal(0x120, GetOffset(in s, in s.Iv));
|
||||
Assert.Equal(0x130, GetOffset(in s, in s.HwKey));
|
||||
Assert.Equal(0x140, GetOffset(in s, in s.Reserved));
|
||||
Assert.Equal(0x200, GetOffset(in s, in s.Padding));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void Ca10Certificate_Layout()
|
||||
{
|
||||
var s = new Ca10Certificate();
|
||||
|
||||
Assert.Equal(0x400, Unsafe.SizeOf<Ca10Certificate>());
|
||||
|
||||
Assert.Equal(0x000, GetOffset(in s, in s.Signature));
|
||||
Assert.Equal(0x100, GetOffset(in s, in s.Unk100));
|
||||
Assert.Equal(0x130, GetOffset(in s, in s.Modulus));
|
||||
Assert.Equal(0x230, GetOffset(in s, in s.Unk230));
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue