Difference between revisions of "Lotus3"
(28 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
− | + | Lotus3 is the Gamecard ASIC, which is a separate chip on the motherboard responsible for communicating with the [[Gamecard]]. | |
It is the Tegra's SDMMC2 device on the Switch and [[Filesystem_services|FS]] communicates with it using a custom protocol based on vendor specific MMC commands. | It is the Tegra's SDMMC2 device on the Switch and [[Filesystem_services|FS]] communicates with it using a custom protocol based on vendor specific MMC commands. | ||
Line 15: | Line 15: | ||
|- | |- | ||
| 61 | | 61 | ||
− | | [[# | + | | [[#FinishOperation]] |
|- | |- | ||
| 62 | | 62 | ||
− | | [[# | + | | [[#Sleep]] |
|- | |- | ||
| 63 | | 63 | ||
− | | [[# | + | | [[#UpdateKey]] |
|} | |} | ||
== WriteOperation == | == WriteOperation == | ||
− | Submits a Gamecard ASIC [[#ASIC commands|operation]] using a 0x40 byte sized | + | Submits a Gamecard ASIC [[#ASIC commands|operation]] using a 0x40 byte sized [[#OperationBuffer|OperationBuffer]]. |
=== OperationBuffer === | === OperationBuffer === | ||
Line 47: | Line 47: | ||
|} | |} | ||
− | == | + | == FinishOperation == |
Returns the status of a completed operation. | Returns the status of a completed operation. | ||
− | == | + | == Sleep == |
Puts the Gamecard ASIC in sleep mode. | Puts the Gamecard ASIC in sleep mode. | ||
− | == | + | == UpdateKey == |
Tells the Gamecard ASIC to generate new random key data. | Tells the Gamecard ASIC to generate new random key data. | ||
= ASIC commands = | = ASIC commands = | ||
− | The Gamecard ASIC supports a total of | + | The Gamecard ASIC supports a total of 20 operation commands. These commands are passed to the ASIC using the [[#WriteOperation]] MMC command. |
Additional data buffers are then read/written using standard MMC read/write commands. | Additional data buffers are then read/written using standard MMC read/write commands. | ||
Line 67: | Line 67: | ||
|- | |- | ||
| 0x01 | | 0x01 | ||
− | | [[# | + | | [[#SendFirmware]] |
|- | |- | ||
| 0x02 | | 0x02 | ||
− | | [[# | + | | [[#ReceiveCertificate]] |
|- | |- | ||
| 0x03 | | 0x03 | ||
− | | [[# | + | | [[#SendSocCertificate]] |
|- | |- | ||
| 0x04 | | 0x04 | ||
− | | [[# | + | | [[#ReceiveRandomValue]] |
|- | |- | ||
| 0x05 | | 0x05 | ||
− | | [[# | + | | [[#SendRandomValue]] |
|- | |- | ||
| 0x06 | | 0x06 | ||
− | | [[# | + | | [[#ReceiveDeviceChallenge]] |
|- | |- | ||
| 0x07 | | 0x07 | ||
− | | [[# | + | | [[#RespondDeviceChallenge]] |
|- | |- | ||
| 0x08 | | 0x08 | ||
− | | [[# | + | | [[#SendHostChallenge]] |
|- | |- | ||
| 0x09 | | 0x09 | ||
− | | [[# | + | | [[#ReceiveChallengeResponse]] |
|- | |- | ||
| 0x0A | | 0x0A | ||
− | | [[# | + | | [[#ChangeModeToSecure]] |
|- | |- | ||
| 0x0B | | 0x0B | ||
− | | [[# | + | | [[#WriteRegister]] |
|- | |- | ||
| 0x0C | | 0x0C | ||
− | | [[# | + | | [[#ReadRegister]] |
|- | |- | ||
| 0x0D | | 0x0D | ||
− | | [[# | + | | [[#ChangeGcModeToDebug]] |
|- | |- | ||
| 0x0E | | 0x0E | ||
Line 109: | Line 109: | ||
|- | |- | ||
| 0x0F | | 0x0F | ||
− | | [[# | + | | [[#ChangeGcModeToSecure]] |
|- | |- | ||
| 0x10 | | 0x10 | ||
Line 121: | Line 121: | ||
|- | |- | ||
| 0x13 | | 0x13 | ||
− | | [[# | + | | [[#ReadRmaInformation]] |
+ | |- | ||
+ | | 0x14 | ||
+ | | [9.0.0+] [[#ChallengeCardExistence]] | ||
|} | |} | ||
− | == | + | == SendFirmware == |
Signals the Gamecard ASIC to receive a 0x7800 byte sized buffer containing the [[#User firmware|ASIC's user firmware]]. | Signals the Gamecard ASIC to receive a 0x7800 byte sized buffer containing the [[#User firmware|ASIC's user firmware]]. | ||
− | == | + | == ReceiveCertificate == |
Signals the Gamecard ASIC to send a 0x400 byte sized buffer containing the ASIC's certificate. | Signals the Gamecard ASIC to send a 0x400 byte sized buffer containing the ASIC's certificate. | ||
− | == | + | == SendSocCertificate == |
Signals the Gamecard ASIC to receive a 0x400 byte sized buffer containing the certificate from [[Settings_services#GetGameCardCertificate|GetGameCardCertificate]]. | Signals the Gamecard ASIC to receive a 0x400 byte sized buffer containing the certificate from [[Settings_services#GetGameCardCertificate|GetGameCardCertificate]]. | ||
− | == | + | == ReceiveRandomValue == |
Signals the Gamecard ASIC to send a 0x100 byte sized buffer containing a RSA-OAEP encrypted message to be decrypted by the host library. The decrypted message will be used to generate a common AES-128 (CBC and CTR) key and IV/CTR shared between the ASIC and the host library. | Signals the Gamecard ASIC to send a 0x100 byte sized buffer containing a RSA-OAEP encrypted message to be decrypted by the host library. The decrypted message will be used to generate a common AES-128 (CBC and CTR) key and IV/CTR shared between the ASIC and the host library. | ||
− | == | + | == SendRandomValue == |
Signals the Gamecard ASIC to receive a 0x100 byte sized buffer containing a RSA-OAEP encrypted message to be decrypted by the ASIC. The decrypted message will be used to generate a common AES-128 (CBC and CTR) key and IV/CTR shared between the ASIC and the host library. | Signals the Gamecard ASIC to receive a 0x100 byte sized buffer containing a RSA-OAEP encrypted message to be decrypted by the ASIC. The decrypted message will be used to generate a common AES-128 (CBC and CTR) key and IV/CTR shared between the ASIC and the host library. | ||
− | == | + | == ReceiveDeviceChallenge == |
Signals the Gamecard ASIC to send a 0x20 byte sized buffer containing AES-128-CBC encrypted authentication data to be decrypted and hashed by the host library. | Signals the Gamecard ASIC to send a 0x20 byte sized buffer containing AES-128-CBC encrypted authentication data to be decrypted and hashed by the host library. | ||
− | == | + | == RespondDeviceChallenge == |
Signals the Gamecard ASIC to receive a 0x20 byte sized buffer containing the AES-128-CBC encrypted hash of the ASIC authentication data. | Signals the Gamecard ASIC to receive a 0x20 byte sized buffer containing the AES-128-CBC encrypted hash of the ASIC authentication data. | ||
− | == | + | == SendHostChallenge == |
Signals the Gamecard ASIC to receive a 0x20 byte sized buffer containing AES-128-CBC encrypted authentication data to be decrypted and hashed by the ASIC. | Signals the Gamecard ASIC to receive a 0x20 byte sized buffer containing AES-128-CBC encrypted authentication data to be decrypted and hashed by the ASIC. | ||
− | == | + | == ReceiveChallengeResponse == |
Signals the Gamecard ASIC to send a 0x20 byte sized buffer containing the AES-128-CBC encrypted hash of the library authentication data. | Signals the Gamecard ASIC to send a 0x20 byte sized buffer containing the AES-128-CBC encrypted hash of the library authentication data. | ||
− | == | + | == ChangeModeToSecure == |
Signals the Gamecard ASIC to enter secure mode. In secure mode, all communication with the Gamecard ASIC must be AES-128-CTR encrypted. | Signals the Gamecard ASIC to enter secure mode. In secure mode, all communication with the Gamecard ASIC must be AES-128-CTR encrypted. | ||
− | == | + | == WriteRegister == |
− | Signals the Gamecard ASIC to write an internal register. The register value is passed in the first word of a 0x200 byte sized buffer while the register index is passed in the actual [[#OperationBuffer]] as follows | + | Signals the Gamecard ASIC to write an internal register. The register value is passed in the first word of a 0x200 byte sized buffer while the register index is passed in the actual [[#OperationBuffer]] as follows: |
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 184: | Line 187: | ||
|} | |} | ||
− | == | + | == ReadRegister == |
− | Signals the Gamecard ASIC to send a 0x30 byte sized buffer containing the values of all ASIC registers | + | Signals the Gamecard ASIC to send a 0x30 byte sized buffer containing the values of all ASIC registers as follows: |
+ | |||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 | ||
+ | | 0x4 | ||
+ | | Status | ||
+ | |- | ||
+ | | 0x4 | ||
+ | | 0x4 | ||
+ | | Access Control | ||
+ | |- | ||
+ | | 0x8 | ||
+ | | 0x4 | ||
+ | | | ||
+ | |- | ||
+ | | 0xC | ||
+ | | 0x4 | ||
+ | | | ||
+ | |- | ||
+ | | 0x10 | ||
+ | | 0x4 | ||
+ | | | ||
+ | |- | ||
+ | | 0x14 | ||
+ | | 0x4 | ||
+ | | | ||
+ | |- | ||
+ | | 0x18 | ||
+ | | 0x4 | ||
+ | | | ||
+ | |- | ||
+ | | 0x1C | ||
+ | | 0x4 | ||
+ | | | ||
+ | |- | ||
+ | | 0x20 | ||
+ | | 0x4 | ||
+ | | | ||
+ | |- | ||
+ | | 0x24 | ||
+ | | 0x4 | ||
+ | | | ||
+ | |- | ||
+ | | 0x28 | ||
+ | | 0x4 | ||
+ | | | ||
+ | |- | ||
+ | | 0x2C | ||
+ | | 0x4 | ||
+ | | | ||
+ | |} | ||
− | == | + | == ChangeGcModeToDebug == |
Signals the Gamecard ASIC to change into debug mode and send a 0x200 byte sized buffer containing information on the current Gamecard. | Signals the Gamecard ASIC to change into debug mode and send a 0x200 byte sized buffer containing information on the current Gamecard. | ||
== GetCardHeader == | == GetCardHeader == | ||
− | Signals the Gamecard ASIC to send a | + | Signals the Gamecard ASIC to send a 0x200 byte sized buffer containing the current Gamecard's header data as follows: |
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 201: | Line 259: | ||
| 0x0 | | 0x0 | ||
| 0x4 | | 0x4 | ||
− | | | + | | CupVersion |
|- | |- | ||
| 0x4 | | 0x4 | ||
| 0x4 | | 0x4 | ||
− | | [[# | + | | [[Filesystem_services#CardId1|CardId1]] |
|- | |- | ||
| 0x8 | | 0x8 | ||
| 0x100 | | 0x100 | ||
− | | [[ | + | | [[XCI#CardHeader|CardHeader]] (without the signature) |
+ | |- | ||
+ | | 0x108 | ||
+ | | 0xD8 | ||
+ | | Reserved | ||
+ | |- | ||
+ | | 0x1E0 | ||
+ | | 0x20 | ||
+ | | [11.0.0+] SHA-256 hash of the data from 0 to 0x1E0 ([1.0.0-10.2.0] Reserved) | ||
|} | |} | ||
− | == | + | == ChangeGcModeToSecure == |
− | Signals the Gamecard ASIC to send a 0x800 byte sized buffer containing the current Gamecard's key area sectors | + | Signals the Gamecard ASIC to send a 0x800 byte sized buffer containing the current Gamecard's key area sectors as follows: |
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
− | ! | + | ! Offset |
! Size | ! Size | ||
! Description | ! Description | ||
|- | |- | ||
− | | | + | | 0x0 |
+ | | 0x4 | ||
+ | | SecurityLevel | ||
+ | |- | ||
+ | | 0x4 | ||
+ | | 0x4 | ||
+ | | Lotus3Status | ||
+ | |- | ||
+ | | 0x8 | ||
+ | | 0x4 | ||
+ | | [[Filesystem_services#CardId1|CardId1]] | ||
+ | |- | ||
+ | | 0xC | ||
+ | | 0x4 | ||
+ | | [[Filesystem_services#CardId2|CardId2]] | ||
+ | |- | ||
+ | | 0x10 | ||
+ | | 0x40 | ||
+ | | CardUid | ||
+ | |- | ||
+ | | 0x50 | ||
+ | | 0x1B0 | ||
+ | | Reserved | ||
+ | |- | ||
+ | | 0x200 | ||
+ | | 0x200 | ||
+ | | [[XCI#CertArea|CertArea]] | ||
+ | |- | ||
+ | | 0x400 | ||
| 0x200 | | 0x200 | ||
− | | | + | | Reserved |
|- | |- | ||
− | | | + | | 0x600 |
| 0x200 | | 0x200 | ||
− | | [[ | + | | [[XCI#InitialData|InitialData]] |
+ | |} | ||
+ | |||
+ | [11.0.0+] This now signals the Gamecard ASIC to send a 0x600 byte sized buffer containing the current Gamecard's key area sectors as follows: | ||
+ | |||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 | ||
+ | | 0x4 | ||
+ | | SecurityLevel | ||
+ | |- | ||
+ | | 0x4 | ||
+ | | 0x4 | ||
+ | | Lotus3Status | ||
+ | |- | ||
+ | | 0x8 | ||
+ | | 0x4 | ||
+ | | [[Filesystem_services#CardId1|CardId1]] | ||
+ | |- | ||
+ | | 0xC | ||
+ | | 0x4 | ||
+ | | [[Filesystem_services#CardId2|CardId2]] | ||
+ | |- | ||
+ | | 0x10 | ||
+ | | 0x40 | ||
+ | | CardUid | ||
+ | |- | ||
+ | | 0x50 | ||
+ | | 0x1B0 | ||
+ | | Reserved | ||
|- | |- | ||
− | |||
| 0x200 | | 0x200 | ||
− | | [[ | + | | 0x200 |
+ | | [[XCI#CertArea|CertArea]] | ||
|- | |- | ||
− | | | + | | 0x400 |
| 0x200 | | 0x200 | ||
− | | | + | | [[XCI#InitialData|InitialData]] |
|} | |} | ||
== SendCardCommand == | == SendCardCommand == | ||
− | Signals the Gamecard ASIC to relay a specific [[#Gamecard commands|command]] to the Gamecard. The command is sent to the Gamecard using the [[#OperationBuffer]] as follows | + | Signals the Gamecard ASIC to relay a specific [[#Gamecard commands|command]] to the Gamecard. The command is sent to the Gamecard using the [[#OperationBuffer]] as follows: |
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 284: | Line 411: | ||
== ExchangeRandomValuesInSecureMode == | == ExchangeRandomValuesInSecureMode == | ||
− | Signals the Gamecard ASIC to exchange random authentication values with the current Gamecard. The Gamecard response values are returned in a 0x20 sized buffer while the host values are passed in the actual [[#OperationBuffer]] as follows | + | Signals the Gamecard ASIC to exchange random authentication values with the current Gamecard. The Gamecard response values are returned in a 0x20 sized buffer while the host values are passed in the actual [[#OperationBuffer]] as follows: |
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 305: | Line 432: | ||
|} | |} | ||
− | == | + | == ReadRmaInformation == |
Signals the Gamecard ASIC to send a 0x200 byte sized buffer containing information on the Gamecard ASIC. This is called by [[Filesystem_services#IDeviceOperator|GetGameCardAsicInfo]]. | Signals the Gamecard ASIC to send a 0x200 byte sized buffer containing information on the Gamecard ASIC. This is called by [[Filesystem_services#IDeviceOperator|GetGameCardAsicInfo]]. | ||
+ | |||
+ | == ChallengeCardExistence == | ||
+ | Signals the Gamecard ASIC to exchange random values with the current Gamecard. The Gamecard response values are returned in a 0x58 sized buffer while the host values are passed in the actual [[#OperationBuffer]] as follows: | ||
+ | |||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 | ||
+ | | 0x1 | ||
+ | | Gamecard ASIC operation command (0x14) | ||
+ | |- | ||
+ | | 0x1 | ||
+ | | 0x1F | ||
+ | | Random value from host | ||
+ | |- | ||
+ | | 0x20 | ||
+ | | 0x20 | ||
+ | | Command verification value | ||
+ | |} | ||
= Gamecard commands = | = Gamecard commands = | ||
Line 319: | Line 468: | ||
|- | |- | ||
| 0x10 | | 0x10 | ||
− | | [[# | + | | [[#ReadId1|ReadId1Write]] |
|- | |- | ||
| 0x11 | | 0x11 | ||
− | | [[# | + | | [[#ReadId2|ReadId2Write]] |
|- | |- | ||
| 0x12 | | 0x12 | ||
− | | [[# | + | | [[#ReadId3|ReadId3Write]] |
|- | |- | ||
| 0x15 | | 0x15 | ||
− | | [[#ReadCrc]] | + | | [[#ReadCrc|ReadCrc]] |
|- | |- | ||
| 0x16 | | 0x16 | ||
− | | [[#WritePage | + | | [[#WritePage|WritePage]] |
|- | |- | ||
| 0x18 | | 0x18 | ||
− | | [[#Erase]] | + | | [[#Erase|Erase]] |
|- | |- | ||
| 0x19 | | 0x19 | ||
− | | [[# | + | | [[#ReadParameter|ReadParameter]] |
|- | |- | ||
| 0x20 | | 0x20 | ||
− | | [[# | + | | [[#WriteParameter|WriteParameter]] |
|- | |- | ||
| 0x21 | | 0x21 | ||
− | | [[#ReadPage | + | | [[#ReadPage|ReadPageSecure]] |
|- | |- | ||
| 0x28 | | 0x28 | ||
− | | [[# | + | | [[#ReadId2|ReadId2]] |
|- | |- | ||
| 0x2E | | 0x2E | ||
− | | [[# | + | | [2.0.0+] [[#ChangeDebugDirect|ChangeDebugDirect]] |
|- | |- | ||
| 0x30 | | 0x30 | ||
− | | [[# | + | | [[#ReadId3|ReadId3Secure]] |
|- | |- | ||
| 0x39 | | 0x39 | ||
− | | [[# | + | | [[#SetKey|SetKey]] |
|- | |- | ||
| 0x56 | | 0x56 | ||
− | | [[# | + | | [[#ReadId1|ReadId1]] |
|- | |- | ||
| 0x83 | | 0x83 | ||
− | | [[#WritePage | + | | [[#WritePage|WritePageSecure]] |
|- | |- | ||
| 0x5B | | 0x5B | ||
− | | [[#ReadPage | + | | [[#ReadPage|ReadPage]] |
|- | |- | ||
| 0x67 | | 0x67 | ||
− | | [[# | + | | [[#ReadId1|ReadId1Secure]] |
|- | |- | ||
| 0xA5 | | 0xA5 | ||
− | | [[# | + | | [[#ReadId3|ReadId3]] |
|- | |- | ||
| 0xB8 | | 0xB8 | ||
− | | [[# | + | | [[#Refresh|Refresh]] |
|- | |- | ||
| 0xC4 | | 0xC4 | ||
− | | [[# | + | | [[#ReadId2|ReadId2Secure]] |
|- | |- | ||
| 0xE0 | | 0xE0 | ||
Line 382: | Line 531: | ||
|- | |- | ||
| 0xE2 | | 0xE2 | ||
− | | | + | | ChangeInitialData |
− | |||
− | |||
− | |||
|} | |} | ||
− | == | + | == ReadId1 == |
Returns the Gamecard ID1 under one of the valid [[#Gamecard modes|Gamecard modes]]. | Returns the Gamecard ID1 under one of the valid [[#Gamecard modes|Gamecard modes]]. | ||
− | The [[#OperationBuffer]] is as follows | + | The [[#OperationBuffer]] is as follows: |
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 444: | Line 590: | ||
|} | |} | ||
− | == | + | == ReadId2 == |
Returns the Gamecard ID2 under one of the valid [[#Gamecard modes|Gamecard modes]]. | Returns the Gamecard ID2 under one of the valid [[#Gamecard modes|Gamecard modes]]. | ||
− | The [[#OperationBuffer]] is as follows | + | The [[#OperationBuffer]] is as follows: |
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 500: | Line 646: | ||
|} | |} | ||
− | == | + | == ReadId3 == |
Returns the Gamecard ID3 under one of the valid [[#Gamecard modes|Gamecard modes]]. | Returns the Gamecard ID3 under one of the valid [[#Gamecard modes|Gamecard modes]]. | ||
− | The [[#OperationBuffer]] is as follows | + | The [[#OperationBuffer]] is as follows: |
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 559: | Line 705: | ||
Reads pages from the Gamecard, calculates their CRC and returns it. This command is only available in [[#Gamecard modes|Write]] mode. | Reads pages from the Gamecard, calculates their CRC and returns it. This command is only available in [[#Gamecard modes|Write]] mode. | ||
− | The [[#OperationBuffer]] is as follows | + | The [[#OperationBuffer]] is as follows: |
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 608: | Line 754: | ||
|} | |} | ||
− | == WritePage | + | == WritePage == |
Writes Gamecard pages. This command is only available in [[#Gamecard modes|Write]] and [[#Gamecard modes|Secure]] modes. | Writes Gamecard pages. This command is only available in [[#Gamecard modes|Write]] and [[#Gamecard modes|Secure]] modes. | ||
− | The [[#OperationBuffer]] is as follows | + | The [[#OperationBuffer]] is as follows: |
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 660: | Line 806: | ||
|} | |} | ||
− | == ReadPage | + | == ReadPage == |
Reads Gamecard pages. This command is only available in [[#Gamecard modes|Normal]] and [[#Gamecard modes|Secure]] modes. | Reads Gamecard pages. This command is only available in [[#Gamecard modes|Normal]] and [[#Gamecard modes|Secure]] modes. | ||
− | The [[#OperationBuffer]] is as follows | + | The [[#OperationBuffer]] is as follows: |
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 715: | Line 861: | ||
Fully erases a Gamecard's contents. This command is only available in [[#Gamecard modes|Write]] mode. | Fully erases a Gamecard's contents. This command is only available in [[#Gamecard modes|Write]] mode. | ||
− | The [[#OperationBuffer]] is as follows | + | The [[#OperationBuffer]] is as follows: |
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 768: | Line 914: | ||
|} | |} | ||
− | == | + | == ReadParameter == |
Reads a development Gamecard's parameters. This command is only available in [[#Gamecard modes|Write]] mode. | Reads a development Gamecard's parameters. This command is only available in [[#Gamecard modes|Write]] mode. | ||
− | The [[#OperationBuffer]] is as follows | + | The [[#OperationBuffer]] is as follows: |
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 824: | Line 970: | ||
|} | |} | ||
− | == | + | == WriteParameter == |
Writes a development Gamecard's parameters. This command is only available in [[#Gamecard modes|Write]] mode. | Writes a development Gamecard's parameters. This command is only available in [[#Gamecard modes|Write]] mode. | ||
− | The [[#OperationBuffer]] is as follows | + | The [[#OperationBuffer]] is as follows: |
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 880: | Line 1,026: | ||
|} | |} | ||
− | == | + | == SetKey == |
− | + | Sets the Gamecard's internal key data. This command is only available in [[#Gamecard modes|Secure]] mode. | |
− | The [[#OperationBuffer]] is as follows | + | The [[#OperationBuffer]] is as follows: |
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 936: | Line 1,082: | ||
|} | |} | ||
− | == | + | == Refresh == |
− | + | Resets the Gamecard's internal status. This command is only available in [[#Gamecard modes|Secure]] mode. | |
− | The [[#OperationBuffer]] is as follows | + | The [[#OperationBuffer]] is as follows: |
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 992: | Line 1,138: | ||
|} | |} | ||
− | == | + | == ChangeDebugDirect == |
Used by [[Filesystem_services#OpenGameCardStorage|OpenGameCardStorage]]. This command is only available in [[#Gamecard modes|Normal]] mode. | Used by [[Filesystem_services#OpenGameCardStorage|OpenGameCardStorage]]. This command is only available in [[#Gamecard modes|Normal]] mode. | ||
− | The [[#OperationBuffer]] is as follows | + | The [[#OperationBuffer]] is as follows: |
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 1,076: | Line 1,222: | ||
= User firmware = | = User firmware = | ||
− | [[Filesystem_services|FS]] provides the appropriate Gamecard ASIC's user firmware (Lotus ASIC Firmware or LAFW) which is encrypted, signed and follows the format below | + | [[Filesystem_services|FS]] provides the appropriate Gamecard ASIC's user firmware (Lotus ASIC Firmware or LAFW) which is encrypted, signed and follows the format below: |
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 1,106: | Line 1,252: | ||
| 0x110 | | 0x110 | ||
| 0x4 | | 0x4 | ||
− | | Version (0, | + | | Version (0, 0x1, [4.0.0+] 0x3, [9.0.0+] 0x7, [11.0.0+] 0xF, [12.0.0+] 0x1F) |
|- | |- | ||
| 0x114 | | 0x114 | ||
Line 1,140: | Line 1,286: | ||
Depending on it's purpose, multiple user firmware blobs exist. | Depending on it's purpose, multiple user firmware blobs exist. | ||
− | === | + | === ReadFw === |
Code for reading retail Gamecards. Only the normal and secure [[#Gamecard modes|Gamecard modes]] are supported. | Code for reading retail Gamecards. Only the normal and secure [[#Gamecard modes|Gamecard modes]] are supported. | ||
Line 1,147: | Line 1,293: | ||
[4.0.0+] This firmware blob was updated to provide support for new Gamecards. | [4.0.0+] This firmware blob was updated to provide support for new Gamecards. | ||
− | === | + | [9.0.0+] This firmware blob was updated. |
+ | |||
+ | [11.0.0+] This firmware blob was updated. | ||
+ | |||
+ | [12.0.0+] This firmware blob was updated. | ||
+ | |||
+ | [14.0.0+] This firmware blob was updated. | ||
+ | |||
+ | === WriterFw === | ||
Code for writing development Gamecards. Only the normal and write [[#Gamecard modes|Gamecard modes]] are supported. | Code for writing development Gamecards. Only the normal and write [[#Gamecard modes|Gamecard modes]] are supported. | ||
Found inside [[Filesystem_services|FS]]. | Found inside [[Filesystem_services|FS]]. | ||
− | === | + | === ReadDevFw === |
Code for reading development Gamecards. Development Gamecards use common [[Gamecard_Format#Initial_Data|initial data]] which justifies the need for a specialized read firmware. | Code for reading development Gamecards. Development Gamecards use common [[Gamecard_Format#Initial_Data|initial data]] which justifies the need for a specialized read firmware. | ||
Found inside [[Filesystem_services|FS]]. | Found inside [[Filesystem_services|FS]]. | ||
− | === | + | [9.0.0+] This firmware blob was updated. |
− | Code for calling [[# | + | |
+ | [11.0.0+] This firmware blob was updated. | ||
+ | |||
+ | [14.0.0+] This firmware blob was updated. | ||
+ | |||
+ | === RmaFw === | ||
+ | Code for calling [[#ReadRmaInformation]]. Must be passed as an argument for [[Filesystem_services#IDeviceOperator|GetGameCardAsicInfo]]. | ||
Never observed (possibly factory only). | Never observed (possibly factory only). | ||
Line 1,164: | Line 1,324: | ||
== Anti-downgrade == | == Anti-downgrade == | ||
Loading an user firmware blob with a certain version field will lock the Gamecard ASIC to only allow running firmware blobs with the same or higher version number. Therefore, it is speculated that the Gamecard ASIC contains some sort of non-volatile memory bank which could be used for this purpose (among others). | Loading an user firmware blob with a certain version field will lock the Gamecard ASIC to only allow running firmware blobs with the same or higher version number. Therefore, it is speculated that the Gamecard ASIC contains some sort of non-volatile memory bank which could be used for this purpose (among others). | ||
− | |||
− |
Latest revision as of 00:29, 16 April 2024
Lotus3 is the Gamecard ASIC, which is a separate chip on the motherboard responsible for communicating with the Gamecard.
It is the Tegra's SDMMC2 device on the Switch and FS communicates with it using a custom protocol based on vendor specific MMC commands.
Protocol
All communication is done using the following MMC_SEND_MANUFACTURER commands.
Command | Name |
---|---|
60 | #WriteOperation |
61 | #FinishOperation |
62 | #Sleep |
63 | #UpdateKey |
WriteOperation
Submits a Gamecard ASIC operation using a 0x40 byte sized OperationBuffer.
OperationBuffer
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | Gamecard ASIC operation command |
0x1 | 0x1F | Operation specific data |
0x20 | 0x20 | Command verification value (secure mode only) |
FinishOperation
Returns the status of a completed operation.
Sleep
Puts the Gamecard ASIC in sleep mode.
UpdateKey
Tells the Gamecard ASIC to generate new random key data.
ASIC commands
The Gamecard ASIC supports a total of 20 operation commands. These commands are passed to the ASIC using the #WriteOperation MMC command.
Additional data buffers are then read/written using standard MMC read/write commands.
Command | Name |
---|---|
0x01 | #SendFirmware |
0x02 | #ReceiveCertificate |
0x03 | #SendSocCertificate |
0x04 | #ReceiveRandomValue |
0x05 | #SendRandomValue |
0x06 | #ReceiveDeviceChallenge |
0x07 | #RespondDeviceChallenge |
0x08 | #SendHostChallenge |
0x09 | #ReceiveChallengeResponse |
0x0A | #ChangeModeToSecure |
0x0B | #WriteRegister |
0x0C | #ReadRegister |
0x0D | #ChangeGcModeToDebug |
0x0E | #GetCardHeader |
0x0F | #ChangeGcModeToSecure |
0x10 | #SendCardCommand |
0x11 | #EnableCardBus |
0x12 | #ExchangeRandomValuesInSecureMode |
0x13 | #ReadRmaInformation |
0x14 | [9.0.0+] #ChallengeCardExistence |
SendFirmware
Signals the Gamecard ASIC to receive a 0x7800 byte sized buffer containing the ASIC's user firmware.
ReceiveCertificate
Signals the Gamecard ASIC to send a 0x400 byte sized buffer containing the ASIC's certificate.
SendSocCertificate
Signals the Gamecard ASIC to receive a 0x400 byte sized buffer containing the certificate from GetGameCardCertificate.
ReceiveRandomValue
Signals the Gamecard ASIC to send a 0x100 byte sized buffer containing a RSA-OAEP encrypted message to be decrypted by the host library. The decrypted message will be used to generate a common AES-128 (CBC and CTR) key and IV/CTR shared between the ASIC and the host library.
SendRandomValue
Signals the Gamecard ASIC to receive a 0x100 byte sized buffer containing a RSA-OAEP encrypted message to be decrypted by the ASIC. The decrypted message will be used to generate a common AES-128 (CBC and CTR) key and IV/CTR shared between the ASIC and the host library.
ReceiveDeviceChallenge
Signals the Gamecard ASIC to send a 0x20 byte sized buffer containing AES-128-CBC encrypted authentication data to be decrypted and hashed by the host library.
RespondDeviceChallenge
Signals the Gamecard ASIC to receive a 0x20 byte sized buffer containing the AES-128-CBC encrypted hash of the ASIC authentication data.
SendHostChallenge
Signals the Gamecard ASIC to receive a 0x20 byte sized buffer containing AES-128-CBC encrypted authentication data to be decrypted and hashed by the ASIC.
ReceiveChallengeResponse
Signals the Gamecard ASIC to send a 0x20 byte sized buffer containing the AES-128-CBC encrypted hash of the library authentication data.
ChangeModeToSecure
Signals the Gamecard ASIC to enter secure mode. In secure mode, all communication with the Gamecard ASIC must be AES-128-CTR encrypted.
WriteRegister
Signals the Gamecard ASIC to write an internal register. The register value is passed in the first word of a 0x200 byte sized buffer while the register index is passed in the actual #OperationBuffer as follows:
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | Gamecard ASIC operation command (0x0B) |
0x1 | 0x3 | Padding |
0x4 | 0x4 | Gamecard ASIC register index |
0x8 | 0x18 | Empty |
0x20 | 0x20 | Command verification value |
ReadRegister
Signals the Gamecard ASIC to send a 0x30 byte sized buffer containing the values of all ASIC registers as follows:
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Status |
0x4 | 0x4 | Access Control |
0x8 | 0x4 | |
0xC | 0x4 | |
0x10 | 0x4 | |
0x14 | 0x4 | |
0x18 | 0x4 | |
0x1C | 0x4 | |
0x20 | 0x4 | |
0x24 | 0x4 | |
0x28 | 0x4 | |
0x2C | 0x4 |
ChangeGcModeToDebug
Signals the Gamecard ASIC to change into debug mode and send a 0x200 byte sized buffer containing information on the current Gamecard.
GetCardHeader
Signals the Gamecard ASIC to send a 0x200 byte sized buffer containing the current Gamecard's header data as follows:
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | CupVersion |
0x4 | 0x4 | CardId1 |
0x8 | 0x100 | CardHeader (without the signature) |
0x108 | 0xD8 | Reserved |
0x1E0 | 0x20 | [11.0.0+] SHA-256 hash of the data from 0 to 0x1E0 ([1.0.0-10.2.0] Reserved) |
ChangeGcModeToSecure
Signals the Gamecard ASIC to send a 0x800 byte sized buffer containing the current Gamecard's key area sectors as follows:
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | SecurityLevel |
0x4 | 0x4 | Lotus3Status |
0x8 | 0x4 | CardId1 |
0xC | 0x4 | CardId2 |
0x10 | 0x40 | CardUid |
0x50 | 0x1B0 | Reserved |
0x200 | 0x200 | CertArea |
0x400 | 0x200 | Reserved |
0x600 | 0x200 | InitialData |
[11.0.0+] This now signals the Gamecard ASIC to send a 0x600 byte sized buffer containing the current Gamecard's key area sectors as follows:
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | SecurityLevel |
0x4 | 0x4 | Lotus3Status |
0x8 | 0x4 | CardId1 |
0xC | 0x4 | CardId2 |
0x10 | 0x40 | CardUid |
0x50 | 0x1B0 | Reserved |
0x200 | 0x200 | CertArea |
0x400 | 0x200 | InitialData |
SendCardCommand
Signals the Gamecard ASIC to relay a specific command to the Gamecard. The command is sent to the Gamecard using the #OperationBuffer as follows:
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | Gamecard ASIC operation command (0x10) |
0x1 | 0x1 | Page size |
0x2 | 0x1 | Direction (0 = read, 1 = write) |
0x3 | 0x1 | Padding |
0x4 | 0x4 | Page count |
0x8 | 0x1 | Gamecard command |
0x9 | 0x17 | Command specific data |
0x20 | 0x20 | Command verification value |
EnableCardBus
Signals the Gamecard ASIC to enable the current Gamecard's bus line.
ExchangeRandomValuesInSecureMode
Signals the Gamecard ASIC to exchange random authentication values with the current Gamecard. The Gamecard response values are returned in a 0x20 sized buffer while the host values are passed in the actual #OperationBuffer as follows:
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | Gamecard ASIC operation command (0x12) |
0x1 | 0x1F | Random value from host |
0x20 | 0x20 | Command verification value |
ReadRmaInformation
Signals the Gamecard ASIC to send a 0x200 byte sized buffer containing information on the Gamecard ASIC. This is called by GetGameCardAsicInfo.
ChallengeCardExistence
Signals the Gamecard ASIC to exchange random values with the current Gamecard. The Gamecard response values are returned in a 0x58 sized buffer while the host values are passed in the actual #OperationBuffer as follows:
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | Gamecard ASIC operation command (0x14) |
0x1 | 0x1F | Random value from host |
0x20 | 0x20 | Command verification value |
Gamecard commands
These commands are issued by the Gamecard ASIC to the actual Gamecard using the #OperationBuffer passed to #SendCardCommand.
Additional data buffers are then read/written using standard MMC read/write commands.
Command | Name |
---|---|
0x10 | ReadId1Write |
0x11 | ReadId2Write |
0x12 | ReadId3Write |
0x15 | ReadCrc |
0x16 | WritePage |
0x18 | Erase |
0x19 | ReadParameter |
0x20 | WriteParameter |
0x21 | ReadPageSecure |
0x28 | ReadId2 |
0x2E | [2.0.0+] ChangeDebugDirect |
0x30 | ReadId3Secure |
0x39 | SetKey |
0x56 | ReadId1 |
0x83 | WritePageSecure |
0x5B | ReadPage |
0x67 | ReadId1Secure |
0xA5 | ReadId3 |
0xB8 | Refresh |
0xC4 | ReadId2Secure |
0xE0 | ReadInitialData |
0xE2 | ChangeInitialData |
ReadId1
Returns the Gamecard ID1 under one of the valid Gamecard modes.
The #OperationBuffer is as follows:
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | Gamecard ASIC operation command (0x10) |
0x1 | 0x1 | Set to 1 |
0x2 | 0x1 | Set to 0 |
0x3 | 0x1 | Padding |
0x4 | 0x4 | Set to 0 |
0x8 | 0x1 | Gamecard command (0x10, 0x56 or 0x67) |
0x9 | 0x4 | Set to 0 |
0xD | 0x2 | Set to 0 |
0xF | 0x1 | Set to 0 |
0x10 | 0x10 | Empty |
0x20 | 0x20 | Command verification value |
ReadId2
Returns the Gamecard ID2 under one of the valid Gamecard modes.
The #OperationBuffer is as follows:
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | Gamecard ASIC operation command (0x10) |
0x1 | 0x1 | Set to 1 |
0x2 | 0x1 | Set to 0 |
0x3 | 0x1 | Padding |
0x4 | 0x4 | Set to 0 |
0x8 | 0x1 | Gamecard command (0x11, 0x28 or 0xC4) |
0x9 | 0x4 | Set to 0 |
0xD | 0x2 | Set to 0 |
0xF | 0x1 | Set to 0 |
0x10 | 0x10 | Empty |
0x20 | 0x20 | Command verification value |
ReadId3
Returns the Gamecard ID3 under one of the valid Gamecard modes.
The #OperationBuffer is as follows:
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | Gamecard ASIC operation command (0x10) |
0x1 | 0x1 | Set to 1 |
0x2 | 0x1 | Set to 0 |
0x3 | 0x1 | Padding |
0x4 | 0x4 | Set to 0 |
0x8 | 0x1 | Gamecard command (0x12, 0x30 or 0xA5) |
0x9 | 0x4 | Set to 0 |
0xD | 0x2 | Set to 0 |
0xF | 0x1 | Set to 0 |
0x10 | 0x10 | Empty |
0x20 | 0x20 | Command verification value |
ReadCrc
Reads pages from the Gamecard, calculates their CRC and returns it. This command is only available in Write mode.
The #OperationBuffer is as follows:
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | Gamecard ASIC operation command (0x10) |
0x1 | 0x1 | Set to 1 |
0x2 | 0x1 | Set to 0 |
0x3 | 0x1 | Padding |
0x4 | 0x4 | Set to 0 |
0x8 | 0x1 | Gamecard command (0x15) |
0x9 | 0x4 | Gamecard page offset |
0xD | 0x3 | Gamecard page count |
0x10 | 0x10 | Empty |
0x20 | 0x20 | Command verification value |
WritePage
Writes Gamecard pages. This command is only available in Write and Secure modes.
The #OperationBuffer is as follows:
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | Gamecard ASIC operation command (0x10) |
0x1 | 0x1 | Set to 3 |
0x2 | 0x1 | Set to 1 |
0x3 | 0x1 | Padding |
0x4 | 0x4 | Gamecard page count (duplicate) |
0x8 | 0x1 | Gamecard command (0x16 or 0x83) |
0x9 | 0x4 | Gamecard page offset |
0xD | 0x3 | Gamecard page count |
0x10 | 0x10 | Empty |
0x20 | 0x20 | Command verification value |
ReadPage
Reads Gamecard pages. This command is only available in Normal and Secure modes.
The #OperationBuffer is as follows:
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | Gamecard ASIC operation command (0x10) |
0x1 | 0x1 | Set to 3 |
0x2 | 0x1 | Set to 0 |
0x3 | 0x1 | Padding |
0x4 | 0x4 | Gamecard page count (duplicate) |
0x8 | 0x1 | Gamecard command (0x21 or 0x5B) |
0x9 | 0x4 | Gamecard page offset |
0xD | 0x3 | Gamecard page count |
0x10 | 0x10 | Empty |
0x20 | 0x20 | Command verification value |
Erase
Fully erases a Gamecard's contents. This command is only available in Write mode.
The #OperationBuffer is as follows:
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | Gamecard ASIC operation command (0x10) |
0x1 | 0x1 | Set to 1 |
0x2 | 0x1 | Set to 0 |
0x3 | 0x1 | Padding |
0x4 | 0x4 | Set to 0 |
0x8 | 0x1 | Gamecard command (0x18) |
0x9 | 0x4 | Set to 0 |
0xD | 0x2 | Set to 0 |
0xF | 0x1 | Set to 0 |
0x10 | 0x10 | Empty |
0x20 | 0x20 | Command verification value |
ReadParameter
Reads a development Gamecard's parameters. This command is only available in Write mode.
The #OperationBuffer is as follows:
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | Gamecard ASIC operation command (0x10) |
0x1 | 0x1 | Set to 3 |
0x2 | 0x1 | Set to 0 |
0x3 | 0x1 | Padding |
0x4 | 0x4 | Set to 1 |
0x8 | 0x1 | Gamecard command (0x19) |
0x9 | 0x4 | Set to 0 |
0xD | 0x2 | Set to 0 |
0xF | 0x1 | Set to 0 |
0x10 | 0x10 | Empty |
0x20 | 0x20 | Command verification value |
WriteParameter
Writes a development Gamecard's parameters. This command is only available in Write mode.
The #OperationBuffer is as follows:
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | Gamecard ASIC operation command (0x10) |
0x1 | 0x1 | Set to 3 |
0x2 | 0x1 | Set to 1 |
0x3 | 0x1 | Padding |
0x4 | 0x4 | Set to 1 |
0x8 | 0x1 | Gamecard command (0x20) |
0x9 | 0x4 | Set to 0 |
0xD | 0x2 | Set to 0 |
0xF | 0x1 | Set to 0 |
0x10 | 0x10 | Empty |
0x20 | 0x20 | Command verification value |
SetKey
Sets the Gamecard's internal key data. This command is only available in Secure mode.
The #OperationBuffer is as follows:
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | Gamecard ASIC operation command (0x10) |
0x1 | 0x1 | Set to 0 |
0x2 | 0x1 | Set to 0 |
0x3 | 0x1 | Padding |
0x4 | 0x4 | Set to 0 |
0x8 | 0x1 | Gamecard command (0x39) |
0x9 | 0x4 | Set to 0 |
0xD | 0x2 | Set to 0 |
0xF | 0x1 | Set to 0 |
0x10 | 0x10 | Empty |
0x20 | 0x20 | Command verification value |
Refresh
Resets the Gamecard's internal status. This command is only available in Secure mode.
The #OperationBuffer is as follows:
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | Gamecard ASIC operation command (0x10) |
0x1 | 0x1 | Set to 2 |
0x2 | 0x1 | Set to 0 |
0x3 | 0x1 | Padding |
0x4 | 0x4 | Set to 0 |
0x8 | 0x1 | Gamecard command (0xB8) |
0x9 | 0x4 | Set to 0 |
0xD | 0x2 | Set to 0 |
0xF | 0x1 | Set to 0 |
0x10 | 0x10 | Empty |
0x20 | 0x20 | Command verification value |
ChangeDebugDirect
Used by OpenGameCardStorage. This command is only available in Normal mode.
The #OperationBuffer is as follows:
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | Gamecard ASIC operation command (0x10) |
0x1 | 0x1 | Set to 1 |
0x2 | 0x1 | Set to 0 |
0x3 | 0x1 | Padding |
0x4 | 0x4 | Set to 0 |
0x8 | 0x1 | Gamecard command (0x2E) |
0x9 | 0xF | Unlock password |
0x18 | 0x8 | Empty |
0x20 | 0x20 | Command verification value |
Modes
Both the Gamecard ASIC and the actual Gamecard can operate in different modes.
ASIC modes
Mode | Name |
---|---|
0x00 | Initial |
0x01 | Secure |
Gamecard modes
Mode | Name |
---|---|
0x00 | Initial |
0x01 | Normal |
0x02 | Secure |
0x03 | Write |
User firmware
FS provides the appropriate Gamecard ASIC's user firmware (Lotus ASIC Firmware or LAFW) which is encrypted, signed and follows the format below:
Offset | Size | Description |
---|---|---|
0x0 | 0x100 | RSA-2048 PKCS #1 signature over the firmware (data from 0x100 to 0x7800) |
0x100 | 0x4 | Magic ("LAFW") |
0x104 | 0x4 | Unknown (0xFF000000, 0xFFFF0000 or 0xFFFFFF00) |
0x108 | 0x4 | Empty |
0x10C | 0x4 | Empty |
0x110 | 0x4 | Version (0, 0x1, [4.0.0+] 0x3, [9.0.0+] 0x7, [11.0.0+] 0xF, [12.0.0+] 0x1F) |
0x114 | 0x4 | Unknown (0x80000000) |
0x118 | 0x4 | Data size |
0x11C | 0x4 | Empty |
0x120 | 0x10 | Encrypted data IV/CTR |
0x130 | 0x10 | Placeholder string ("IDIDIDIDIDIDIDID") |
0x140 | 0x40 | Empty |
0x180 | 0x7680 | Encrypted data |
Types
Depending on it's purpose, multiple user firmware blobs exist.
ReadFw
Code for reading retail Gamecards. Only the normal and secure Gamecard modes are supported.
Found inside FS.
[4.0.0+] This firmware blob was updated to provide support for new Gamecards.
[9.0.0+] This firmware blob was updated.
[11.0.0+] This firmware blob was updated.
[12.0.0+] This firmware blob was updated.
[14.0.0+] This firmware blob was updated.
WriterFw
Code for writing development Gamecards. Only the normal and write Gamecard modes are supported.
Found inside FS.
ReadDevFw
Code for reading development Gamecards. Development Gamecards use common initial data which justifies the need for a specialized read firmware.
Found inside FS.
[9.0.0+] This firmware blob was updated.
[11.0.0+] This firmware blob was updated.
[14.0.0+] This firmware blob was updated.
RmaFw
Code for calling #ReadRmaInformation. Must be passed as an argument for GetGameCardAsicInfo.
Never observed (possibly factory only).
Anti-downgrade
Loading an user firmware blob with a certain version field will lock the Gamecard ASIC to only allow running firmware blobs with the same or higher version number. Therefore, it is speculated that the Gamecard ASIC contains some sort of non-volatile memory bank which could be used for this purpose (among others).