Difference between revisions of "Lotus3"
Line 4: | Line 4: | ||
= Protocol = | = Protocol = | ||
− | All communication is done using | + | All communication is done using custom MMC_SEND_MANUFACTURER commands. |
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
− | ! | + | ! Value |
− | ! | + | ! Description |
|- | |- | ||
| 60 | | 60 | ||
Line 25: | Line 25: | ||
== WriteOperation == | == WriteOperation == | ||
− | + | Sends a Gamecard ASIC [[#AsicOperation|operation]]. | |
+ | |||
+ | == FinishOperation == | ||
+ | Returns the status of a completed Gamecard ASIC operation. | ||
− | === | + | == Sleep == |
+ | Puts the Gamecard ASIC in sleep mode. | ||
+ | |||
+ | == UpdateKey == | ||
+ | Tells the Gamecard ASIC to generate new random key data. | ||
+ | |||
+ | = AsicOperation = | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
Line 36: | Line 45: | ||
| 0x0 | | 0x0 | ||
| 0x1 | | 0x1 | ||
− | | | + | | [[#OperationId|OperationId]] |
|- | |- | ||
| 0x1 | | 0x1 | ||
| 0x1F | | 0x1F | ||
− | | | + | | OperationData |
|- | |- | ||
| 0x20 | | 0x20 | ||
| 0x20 | | 0x20 | ||
− | | | + | | CvValue (secure mode only) |
|} | |} | ||
− | == | + | == OperationId == |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
The Gamecard ASIC supports a total of 20 operation commands. These commands are passed to the ASIC using the [[#WriteOperation]] MMC command. | 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 as pages of 0x200 bytes each, using standard MMC read/write commands. |
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
− | ! | + | ! Value |
− | ! | + | ! Description |
|- | |- | ||
| 0x01 | | 0x01 | ||
Line 127: | Line 127: | ||
|} | |} | ||
− | == SendFirmware == | + | === SendFirmware === |
− | Signals the Gamecard ASIC to receive | + | Signals the Gamecard ASIC to receive the [[#AsicFirmware|firmware]]. |
− | + | This is the only operation handled by the Gamecard ASIC's bootrom. | |
− | |||
− | == | + | === ReceiveCertificate === |
− | Signals the Gamecard ASIC to | + | Signals the Gamecard ASIC to send the ASIC's certificate. |
− | == | + | === SendSocCertificate === |
− | Signals the Gamecard ASIC to | + | Signals the Gamecard ASIC to receive the certificate from [[Settings_services#GetGameCardCertificate|GetGameCardCertificate]]. |
− | == SendRandomValue == | + | === ReceiveRandomValue === |
− | Signals the Gamecard ASIC to receive | + | Signals the Gamecard ASIC to send 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 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 AES-128-CBC encrypted authentication data to be decrypted and hashed by the host library. | ||
+ | |||
+ | === RespondDeviceChallenge === | ||
+ | Signals the Gamecard ASIC to receive the AES-128-CBC encrypted hash of the ASIC authentication data. | ||
+ | |||
+ | === SendHostChallenge === | ||
+ | Signals the Gamecard ASIC to receive AES-128-CBC encrypted authentication data to be decrypted and hashed by the ASIC. | ||
+ | |||
+ | === ReceiveChallengeResponse === | ||
+ | Signals the Gamecard ASIC to send 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. | ||
+ | |||
+ | [[#AsicOperation|OperationData]] becomes: | ||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 | ||
+ | | 0x3 | ||
+ | | Reserved | ||
+ | |- | ||
+ | | 0x3 | ||
+ | | 0x4 | ||
+ | | RegisterAddress | ||
+ | |- | ||
+ | | 0x7 | ||
+ | | 0x18 | ||
+ | | Reserved | ||
+ | |} | ||
− | + | RegisterValue is passed in a data page. | |
− | |||
− | == | + | === ReadRegister === |
− | Signals the Gamecard ASIC to | + | Signals the Gamecard ASIC to send the contents of its [[#AsicRegisters|registers]]. |
− | == | + | === ChangeGcModeToDebug === |
− | Signals the Gamecard ASIC to | + | Signals the Gamecard ASIC to change into debug mode and send information on the current Gamecard. |
− | == | + | === GetCardHeader === |
− | Signals the Gamecard ASIC to send | + | Signals the Gamecard ASIC to send the current Gamecard's [[#CardHeader|header]]. |
− | == | + | === ChangeGcModeToSecure === |
− | Signals the Gamecard ASIC to | + | Signals the Gamecard ASIC to enable secure communication with the Gamecard and return its [[#CardKeyArea|key area]]. |
− | == | + | === SendCardCommand === |
− | Signals the Gamecard ASIC to | + | Signals the Gamecard ASIC to relay commands to the Gamecard. |
+ | [[#AsicOperation|OperationData]] becomes: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
Line 168: | Line 214: | ||
| 0x0 | | 0x0 | ||
| 0x1 | | 0x1 | ||
− | | | + | | PageSize |
+ | |- | ||
+ | | 0x1 | ||
+ | | 0x1 | ||
+ | | Direction (0 = Read, 1 = Write) | ||
|- | |- | ||
+ | | 0x2 | ||
| 0x1 | | 0x1 | ||
+ | | Reserved | ||
+ | |- | ||
| 0x3 | | 0x3 | ||
− | | | + | | 0x4 |
+ | | PageNumber | ||
|- | |- | ||
− | | | + | | 0x7 |
− | | | + | | 0x10 |
− | | | + | | [[#CardCommand|CardCommand]] |
|- | |- | ||
+ | | 0x17 | ||
| 0x8 | | 0x8 | ||
− | | | + | | Reserved |
− | | | + | |} |
+ | |||
+ | === EnableCardBus === | ||
+ | Signals the Gamecard ASIC to enable the Gamecard's bus line. | ||
+ | |||
+ | === ExchangeRandomValuesInSecureMode === | ||
+ | Signals the Gamecard ASIC to exchange random authentication values with the current Gamecard. | ||
+ | |||
+ | [[#AsicOperation|OperationData]] becomes: | ||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 | ||
+ | | 0x1F | ||
+ | | RandomValues | ||
+ | |} | ||
+ | |||
+ | The Gamecard's response is returned in a data page. | ||
+ | |||
+ | === ReadRmaInformation === | ||
+ | Signals the Gamecard ASIC to send 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. | ||
+ | |||
+ | [[#AsicOperation|OperationData]] becomes: | ||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
|- | |- | ||
− | | | + | | 0x0 |
− | | | + | | 0x1F |
− | | | + | | RandomValues |
|} | |} | ||
− | + | The Gamecard's response is returned in a data page. | |
− | |||
+ | = AsicRegisters = | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
Line 245: | Line 333: | ||
|} | |} | ||
− | == | + | = CardHeader = |
− | |||
− | |||
− | |||
− | |||
− | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
Line 278: | Line 361: | ||
|} | |} | ||
− | == | + | = CardKeyArea = |
− | |||
− | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
Line 324: | Line 405: | ||
|} | |} | ||
− | [11.0.0+] This now | + | [11.0.0+] This is now: |
− | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
Line 365: | Line 445: | ||
|} | |} | ||
− | == | + | = CardCommand = |
− | |||
− | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
Line 376: | Line 454: | ||
| 0x0 | | 0x0 | ||
| 0x1 | | 0x1 | ||
− | | | + | | [[#CommandId|CommandId]] |
|- | |- | ||
| 0x1 | | 0x1 | ||
− | | | + | | 0xF |
− | | | + | | CommandData |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
|} | |} | ||
− | == | + | == CommandId == |
− | + | These commands are issued by the Gamecard ASIC to the actual Gamecard using the [[#AsicOperation|OperationData]] passed to [[#SendCardCommand]]. | |
− | + | Additional data buffers are then read/written as pages of 0x200 bytes each, using standard MMC read/write commands. | |
− | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
− | ! | + | ! Value |
− | |||
! Description | ! Description | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
|- | |- | ||
| 0x6 | | 0x6 | ||
Line 474: | Line 478: | ||
|- | |- | ||
| 0x10 | | 0x10 | ||
− | + | | ReadId1Write | |
|- | |- | ||
| 0x11 | | 0x11 | ||
− | + | | ReadId2Write | |
|- | |- | ||
| 0x12 | | 0x12 | ||
− | + | | ReadId3Write | |
|- | |- | ||
| 0x13 | | 0x13 | ||
Line 486: | Line 490: | ||
|- | |- | ||
| 0x15 | | 0x15 | ||
− | | | + | | ReadCrc |
|- | |- | ||
| 0x16 | | 0x16 | ||
− | | | + | | WritePage |
|- | |- | ||
| 0x17 | | 0x17 | ||
Line 495: | Line 499: | ||
|- | |- | ||
| 0x18 | | 0x18 | ||
− | | | + | | Erase |
|- | |- | ||
| 0x19 | | 0x19 | ||
− | | | + | | ReadParameter |
|- | |- | ||
| 0x20 | | 0x20 | ||
− | | | + | | WriteParameter |
|- | |- | ||
| 0x21 | | 0x21 | ||
− | + | | ReadPageSecure | |
|- | |- | ||
| 0x28 | | 0x28 | ||
− | | | + | | ReadId2 |
|- | |- | ||
| 0x2E | | 0x2E | ||
− | | | + | | ChangeDebugDirect |
|- | |- | ||
| 0x30 | | 0x30 | ||
− | + | | ReadId3Secure | |
|- | |- | ||
| 0x39 | | 0x39 | ||
− | | | + | | SetKey |
|- | |- | ||
| 0x56 | | 0x56 | ||
− | | | + | | ReadId1 |
|- | |- | ||
| 0x59 | | 0x59 | ||
Line 525: | Line 529: | ||
|- | |- | ||
| 0x67 | | 0x67 | ||
− | + | | ReadId1Secure | |
|- | |- | ||
| 0x5B | | 0x5B | ||
− | | | + | | ReadPage |
|- | |- | ||
| 0x83 | | 0x83 | ||
− | + | | WritePageSecure | |
|- | |- | ||
| 0x8A | | 0x8A | ||
Line 537: | Line 541: | ||
|- | |- | ||
| 0xA5 | | 0xA5 | ||
− | | | + | | ReadId3 |
|- | |- | ||
| 0xB8 | | 0xB8 | ||
− | | | + | | Refresh |
|- | |- | ||
| 0xC4 | | 0xC4 | ||
− | + | | ReadId2Secure | |
|- | |- | ||
| 0xE0 | | 0xE0 | ||
Line 597: | Line 601: | ||
|} | |} | ||
− | = | + | = AsicFirmware = |
− | + | This is the Gamecard ASIC's user firmware (Lotus ASIC Firmware or LAFW) uploaded through the [[#SendFirmware]] operation. | |
− | |||
− | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 609: | Line 611: | ||
|- | |- | ||
| 0x0 | | 0x0 | ||
− | | | + | | 0x100 |
− | + | | RSA-2048 PKCS #1 signature over the firmware (data from 0x100 to 0x7800) | |
− | |- | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
|- | |- | ||
+ | | 0x100 | ||
| 0x4 | | 0x4 | ||
− | | | + | | Magic ("LAFW") |
− | |||
|- | |- | ||
− | | | + | | 0x104 |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
| 0x1 | | 0x1 | ||
− | | | + | | ProductionFirmwareFlag |
|- | |- | ||
+ | | 0x105 | ||
| 0x1 | | 0x1 | ||
− | | | + | | DevelopmentFirmwareFlag |
− | |||
|- | |- | ||
− | | | + | | 0x106 |
| 0x1 | | 0x1 | ||
− | | | + | | WriterFirmwareFlag |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
|- | |- | ||
+ | | 0x107 | ||
| 0x9 | | 0x9 | ||
− | | | + | | Reserved |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
|- | |- | ||
+ | | 0x110 | ||
| 0x8 | | 0x8 | ||
− | | | + | | [[#FirmwareVersion|FirmwareVersion]] |
− | | | ||
|- | |- | ||
− | | | + | | 0x118 |
| 0x4 | | 0x4 | ||
− | | | + | | FirmwareSize |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
|- | |- | ||
+ | | 0x11C | ||
| 0x4 | | 0x4 | ||
− | | | + | | Reserved |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
|- | |- | ||
+ | | 0x120 | ||
| 0x10 | | 0x10 | ||
− | | | + | | Iv |
− | |||
|- | |- | ||
− | | | + | | 0x130 |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
| 0x10 | | 0x10 | ||
− | | | + | | Lotus3DeviceId |
|- | |- | ||
− | | | + | | 0x140 |
− | | | + | | 0x40 |
− | | | + | | Reserved |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
|- | |- | ||
− | + | | 0x180 | |
− | + | | 0x7680 | |
− | + | | FirmwareData | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | | | ||
− | | | ||
− | | | ||
|} | |} | ||
− | == | + | == FirmwareVersion == |
− | |||
− | |||
− | |||
− | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
− | ! | + | ! Bits |
− | |||
! Description | ! Description | ||
|- | |- | ||
− | | | + | | 0-61 |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
| Version (0, 0x1, [4.0.0+] 0x3, [9.0.0+] 0x7, [11.0.0+] 0xF, [12.0.0+] 0x1F) | | Version (0, 0x1, [4.0.0+] 0x3, [9.0.0+] 0x7, [11.0.0+] 0xF, [12.0.0+] 0x1F) | ||
|- | |- | ||
− | | | + | | 62 |
− | | | + | | IsDevelopment |
− | |||
|- | |- | ||
− | | | + | | 63 |
− | | | + | | IsProduction |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
|} | |} | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
== Anti-downgrade == | == Anti-downgrade == | ||
− | Loading | + | Loading a firmware blob will burn as many OTP fuses as those specified by the [[#FirmwareVersion|Version]] field. This will lock the Gamecard ASIC to only allow running firmware blobs with the same or higher version number. |
Revision as of 23:52, 30 November 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 custom MMC_SEND_MANUFACTURER commands.
Value | Description |
---|---|
60 | #WriteOperation |
61 | #FinishOperation |
62 | #Sleep |
63 | #UpdateKey |
WriteOperation
Sends a Gamecard ASIC operation.
FinishOperation
Returns the status of a completed Gamecard ASIC operation.
Sleep
Puts the Gamecard ASIC in sleep mode.
UpdateKey
Tells the Gamecard ASIC to generate new random key data.
AsicOperation
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | OperationId |
0x1 | 0x1F | OperationData |
0x20 | 0x20 | CvValue (secure mode only) |
OperationId
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 as pages of 0x200 bytes each, using standard MMC read/write commands.
Value | Description |
---|---|
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 the firmware.
This is the only operation handled by the Gamecard ASIC's bootrom.
ReceiveCertificate
Signals the Gamecard ASIC to send the ASIC's certificate.
SendSocCertificate
Signals the Gamecard ASIC to receive the certificate from GetGameCardCertificate.
ReceiveRandomValue
Signals the Gamecard ASIC to send 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 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 AES-128-CBC encrypted authentication data to be decrypted and hashed by the host library.
RespondDeviceChallenge
Signals the Gamecard ASIC to receive the AES-128-CBC encrypted hash of the ASIC authentication data.
SendHostChallenge
Signals the Gamecard ASIC to receive AES-128-CBC encrypted authentication data to be decrypted and hashed by the ASIC.
ReceiveChallengeResponse
Signals the Gamecard ASIC to send 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.
OperationData becomes:
Offset | Size | Description |
---|---|---|
0x0 | 0x3 | Reserved |
0x3 | 0x4 | RegisterAddress |
0x7 | 0x18 | Reserved |
RegisterValue is passed in a data page.
ReadRegister
Signals the Gamecard ASIC to send the contents of its registers.
ChangeGcModeToDebug
Signals the Gamecard ASIC to change into debug mode and send information on the current Gamecard.
GetCardHeader
Signals the Gamecard ASIC to send the current Gamecard's header.
ChangeGcModeToSecure
Signals the Gamecard ASIC to enable secure communication with the Gamecard and return its key area.
SendCardCommand
Signals the Gamecard ASIC to relay commands to the Gamecard.
OperationData becomes:
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | PageSize |
0x1 | 0x1 | Direction (0 = Read, 1 = Write) |
0x2 | 0x1 | Reserved |
0x3 | 0x4 | PageNumber |
0x7 | 0x10 | CardCommand |
0x17 | 0x8 | Reserved |
EnableCardBus
Signals the Gamecard ASIC to enable the Gamecard's bus line.
ExchangeRandomValuesInSecureMode
Signals the Gamecard ASIC to exchange random authentication values with the current Gamecard.
OperationData becomes:
Offset | Size | Description |
---|---|---|
0x0 | 0x1F | RandomValues |
The Gamecard's response is returned in a data page.
ReadRmaInformation
Signals the Gamecard ASIC to send information on the Gamecard ASIC. This is called by GetGameCardAsicInfo.
ChallengeCardExistence
Signals the Gamecard ASIC to exchange random values with the current Gamecard.
OperationData becomes:
Offset | Size | Description |
---|---|---|
0x0 | 0x1F | RandomValues |
The Gamecard's response is returned in a data page.
AsicRegisters
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Lotus3Status |
0x4 | 0x4 | AccCtrl1 |
0x8 | 0x4 | Wait1TimeRead |
0xC | 0x4 | Wait2TimeRead |
0x10 | 0x4 | Wait1TimeWrite |
0x14 | 0x4 | Wait2TimeWrite |
0x18 | 0x4 | PageRemainder |
0x1C | 0x4 | LatencyTime |
0x20 | 0x4 | LimArea |
0x24 | 0x4 | CupVersion |
0x28 | 0x4 | Lotus3Version |
0x2C | 0x4 | Standby2 |
CardHeader
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) |
CardKeyArea
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 is now:
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 |
CardCommand
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | CommandId |
0x1 | 0xF | CommandData |
CommandId
These commands are issued by the Gamecard ASIC to the actual Gamecard using the OperationData passed to #SendCardCommand.
Additional data buffers are then read/written as pages of 0x200 bytes each, using standard MMC read/write commands.
Value | Description |
---|---|
0x6 | |
0xF | |
0x10 | ReadId1Write |
0x11 | ReadId2Write |
0x12 | ReadId3Write |
0x13 | |
0x15 | ReadCrc |
0x16 | WritePage |
0x17 | |
0x18 | Erase |
0x19 | ReadParameter |
0x20 | WriteParameter |
0x21 | ReadPageSecure |
0x28 | ReadId2 |
0x2E | ChangeDebugDirect |
0x30 | ReadId3Secure |
0x39 | SetKey |
0x56 | ReadId1 |
0x59 | |
0x67 | ReadId1Secure |
0x5B | ReadPage |
0x83 | WritePageSecure |
0x8A | |
0xA5 | ReadId3 |
0xB8 | Refresh |
0xC4 | ReadId2Secure |
0xE0 | ReadInitialData |
0xE2 | ChangeInitialData |
0xE3 | |
0xE4 | |
0xE5 | |
0xE6 | |
0xE7 | |
0xE8 | |
0xE9 | |
0xEA | |
0xEB | |
0xEC | |
0xED | |
0xEE | |
0xEF | |
0xF1 | |
0xFA |
AsicFirmware
This is the Gamecard ASIC's user firmware (Lotus ASIC Firmware or LAFW) uploaded through the #SendFirmware operation.
Offset | Size | Description |
---|---|---|
0x0 | 0x100 | RSA-2048 PKCS #1 signature over the firmware (data from 0x100 to 0x7800) |
0x100 | 0x4 | Magic ("LAFW") |
0x104 | 0x1 | ProductionFirmwareFlag |
0x105 | 0x1 | DevelopmentFirmwareFlag |
0x106 | 0x1 | WriterFirmwareFlag |
0x107 | 0x9 | Reserved |
0x110 | 0x8 | FirmwareVersion |
0x118 | 0x4 | FirmwareSize |
0x11C | 0x4 | Reserved |
0x120 | 0x10 | Iv |
0x130 | 0x10 | Lotus3DeviceId |
0x140 | 0x40 | Reserved |
0x180 | 0x7680 | FirmwareData |
FirmwareVersion
Bits | Description |
---|---|
0-61 | Version (0, 0x1, [4.0.0+] 0x3, [9.0.0+] 0x7, [11.0.0+] 0xF, [12.0.0+] 0x1F) |
62 | IsDevelopment |
63 | IsProduction |
Anti-downgrade
Loading a firmware blob will burn as many OTP fuses as those specified by the Version field. This will lock the Gamecard ASIC to only allow running firmware blobs with the same or higher version number.