2020-04-16 01:06:41 +01:00
/*
2020-07-03 10:31:22 +01:00
* gamecard . h
2020-04-16 01:06:41 +01:00
*
2023-04-08 12:42:22 +01:00
* Copyright ( c ) 2020 - 2023 , DarkMatterCore < pabloacurielz @ gmail . com > .
2020-07-03 10:31:22 +01:00
*
* This file is part of nxdumptool ( https : //github.com/DarkMatterCore/nxdumptool).
*
2021-03-25 19:26:58 +00:00
* nxdumptool is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
2020-04-16 01:06:41 +01:00
*
2021-03-25 19:26:58 +00:00
* nxdumptool is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
2020-04-16 01:06:41 +01:00
*
* You should have received a copy of the GNU General Public License
2021-03-25 19:26:58 +00:00
* along with this program . If not , see < https : //www.gnu.org/licenses/>.
2020-04-16 01:06:41 +01:00
*/
2020-04-15 06:59:12 +01:00
# pragma once
# ifndef __GAMECARD_H__
# define __GAMECARD_H__
# include "fs_ext.h"
2021-03-07 23:22:49 +00:00
# include "hfs.h"
2020-04-15 06:59:12 +01:00
2021-03-24 17:25:19 +00:00
# ifdef __cplusplus
extern " C " {
# endif
2021-04-06 01:40:57 +01:00
# define GAMECARD_HEAD_MAGIC 0x48454144 /* "HEAD". */
2020-04-15 06:59:12 +01:00
2021-04-06 01:40:57 +01:00
# define GAMECARD_PAGE_SIZE 0x200
# define GAMECARD_PAGE_OFFSET(x) ((u64)(x) * GAMECARD_PAGE_SIZE)
2020-04-15 06:59:12 +01:00
2021-04-06 01:40:57 +01:00
# define GAMECARD_UPDATE_TID SYSTEM_UPDATE_TID
2020-07-13 07:36:17 +01:00
2021-04-06 01:40:57 +01:00
# define GAMECARD_CERTIFICATE_OFFSET 0x7000
2020-08-13 07:01:23 +01:00
2020-07-22 09:03:28 +01:00
/// Encrypted using AES-128-ECB with the common titlekek generator key (stored in the .rodata segment from the Lotus firmware).
typedef struct {
2022-03-17 12:37:24 +00:00
union {
u8 value [ 0x10 ] ;
struct {
u64 package_id ; ///< Matches package_id from GameCardHeader.
u8 reserved [ 0x8 ] ; ///< Just zeroes.
} ;
} ;
2020-07-22 09:03:28 +01:00
} GameCardKeySource ;
2021-03-24 17:25:19 +00:00
NXDT_ASSERT ( GameCardKeySource , 0x10 ) ;
2020-07-15 23:50:34 +01:00
/// Plaintext area. Dumped from FS program memory.
2020-07-13 07:36:17 +01:00
typedef struct {
2020-07-22 09:03:28 +01:00
GameCardKeySource key_source ;
2020-07-15 23:50:34 +01:00
u8 encrypted_titlekey [ 0x10 ] ; ///< Encrypted using AES-128-CCM with the decrypted key_source and the nonce from this section.
u8 mac [ 0x10 ] ; ///< Used to verify the validity of the decrypted titlekey.
2020-07-22 09:03:28 +01:00
u8 nonce [ 0xC ] ; ///< Used as the IV to decrypt encrypted_titlekey using AES-128-CCM.
2020-07-13 07:36:17 +01:00
u8 reserved [ 0x1C4 ] ;
2020-07-15 23:50:34 +01:00
} GameCardInitialData ;
2021-03-24 17:25:19 +00:00
NXDT_ASSERT ( GameCardInitialData , 0x200 ) ;
2021-04-05 21:21:46 +01:00
/// Encrypted using AES-128-CTR with the key and IV/counter from the `GameCardTitleKeyAreaEncryption` section. Assumed to be all zeroes in retail gamecards.
2020-07-15 23:50:34 +01:00
typedef struct {
u8 titlekey [ 0x10 ] ; ///< Decrypted titlekey from the `GameCardInitialData` section.
u8 reserved [ 0xCF0 ] ;
2021-04-05 21:21:46 +01:00
} GameCardTitleKeyArea ;
2020-07-15 23:50:34 +01:00
2021-04-05 21:21:46 +01:00
NXDT_ASSERT ( GameCardTitleKeyArea , 0xD00 ) ;
2021-03-24 17:25:19 +00:00
2020-07-17 19:42:48 +01:00
/// Encrypted using RSA-2048-OAEP and a private OAEP key from AuthoringTool. Assumed to be all zeroes in retail gamecards.
2020-07-15 23:50:34 +01:00
typedef struct {
2021-04-05 21:21:46 +01:00
u8 titlekey_encryption_key [ 0x10 ] ; ///< Used as the AES-128-CTR key for the `GameCardTitleKeyArea` section. Randomly generated during XCI creation by AuthoringTool.
u8 titlekey_encryption_iv [ 0x10 ] ; ///< Used as the AES-128-CTR IV/counter for the `GameCardTitleKeyArea` section. Randomly generated during XCI creation by AuthoringTool.
2020-07-15 23:50:34 +01:00
u8 reserved [ 0xE0 ] ;
2021-04-05 21:21:46 +01:00
} GameCardTitleKeyAreaEncryption ;
2020-07-15 23:50:34 +01:00
2021-04-05 21:21:46 +01:00
NXDT_ASSERT ( GameCardTitleKeyAreaEncryption , 0x100 ) ;
2021-03-24 17:25:19 +00:00
2020-07-15 23:50:34 +01:00
/// Used to secure communications between the Lotus and the inserted gamecard.
2022-02-03 03:39:54 +00:00
/// Supposedly precedes the gamecard header.
2020-07-15 23:50:34 +01:00
typedef struct {
GameCardInitialData initial_data ;
2021-04-05 21:21:46 +01:00
GameCardTitleKeyArea titlekey_area ;
GameCardTitleKeyAreaEncryption titlekey_area_encryption ;
2020-07-13 07:36:17 +01:00
} GameCardKeyArea ;
2021-03-24 17:25:19 +00:00
NXDT_ASSERT ( GameCardKeyArea , 0x1000 ) ;
2023-07-17 00:03:05 +01:00
/// Plaintext area. Dumped from FS program memory.
/// Overall structure may change with each new LAFW version.
typedef struct {
u32 asic_security_mode ; ///< Determines how the Lotus ASIC initialised the gamecard security mode. Usually 0xFFFFFFF9.
u32 asic_status ; ///< Bitmask of the internal gamecard interface status. Usually 0x20000000.
FsCardId1 card_id1 ;
FsCardId2 card_id2 ;
u8 card_uid [ 0x40 ] ;
u8 reserved [ 0x190 ] ;
u8 asic_session_hash [ 0x20 ] ; ///< Changes with each gamecard (re)insertion.
} GameCardSpecificData ;
NXDT_ASSERT ( GameCardSpecificData , 0x200 ) ;
/// Plaintext area. Dumped from FS program memory.
/// This struct is returned by Lotus command "ChangeToSecureMode" (0xF). This means it is only available *after* the gamecard secure area has been mounted.
/// A copy of the gamecard header without the RSA-2048 signature and a plaintext GameCardInfo precedes this struct in FS program memory.
typedef struct {
GameCardSpecificData specific_data ;
FsGameCardCertificate certificate ;
u8 reserved [ 0x200 ] ;
GameCardInitialData initial_data ;
} GameCardSecurityInformation ;
NXDT_ASSERT ( GameCardSecurityInformation , 0x800 ) ;
2020-04-15 06:59:12 +01:00
typedef enum {
GameCardKekIndex_Version0 = 0 ,
2023-07-17 00:03:05 +01:00
GameCardKekIndex_VersionForDev = 1 ,
GameCardKekIndex_Count = 2 ///< Total values supported by this enum.
2020-04-15 06:59:12 +01:00
} GameCardKekIndex ;
typedef struct {
u8 kek_index : 4 ; ///< GameCardKekIndex.
u8 titlekey_dec_index : 4 ;
2020-07-22 09:03:28 +01:00
} GameCardKeyIndex ;
2020-04-15 06:59:12 +01:00
2021-03-24 17:25:19 +00:00
NXDT_ASSERT ( GameCardKeyIndex , 0x1 ) ;
2020-04-15 06:59:12 +01:00
typedef enum {
2020-04-16 05:37:16 +01:00
GameCardRomSize_1GiB = 0xFA ,
GameCardRomSize_2GiB = 0xF8 ,
GameCardRomSize_4GiB = 0xF0 ,
GameCardRomSize_8GiB = 0xE0 ,
GameCardRomSize_16GiB = 0xE1 ,
GameCardRomSize_32GiB = 0xE2
2020-04-15 06:59:12 +01:00
} GameCardRomSize ;
2020-05-01 16:06:24 +01:00
typedef enum {
2023-07-17 00:03:05 +01:00
GameCardFlags_None = 0 ,
2020-05-01 16:06:24 +01:00
GameCardFlags_AutoBoot = BIT ( 0 ) ,
GameCardFlags_HistoryErase = BIT ( 1 ) ,
GameCardFlags_RepairTool = BIT ( 2 ) ,
GameCardFlags_DifferentRegionCupToTerraDevice = BIT ( 3 ) ,
2022-03-17 12:37:24 +00:00
GameCardFlags_DifferentRegionCupToGlobalDevice = BIT ( 4 ) ,
2023-07-17 00:03:05 +01:00
GameCardFlags_HasCa10Certificate = BIT ( 7 ) ,
GameCardFlags_Count = 6 ///< Total values supported by this enum.
2020-04-15 06:59:12 +01:00
} GameCardFlags ;
typedef enum {
2020-07-22 09:03:28 +01:00
GameCardSelSec_ForT1 = 1 ,
2023-07-17 00:03:05 +01:00
GameCardSelSec_ForT2 = 2 ,
GameCardSelSec_Count = 2 ///< Total values supported by this enum.
2020-04-15 06:59:12 +01:00
} GameCardSelSec ;
typedef enum {
2021-06-03 15:46:21 +01:00
GameCardFwVersion_ForDev = 0 ,
GameCardFwVersion_Since100NUP = 1 , ///< upp_version >= 0 (0.0.0-0.0) in GameCardInfo.
GameCardFwVersion_Since400NUP = 2 , ///< upp_version >= 268435456 (4.0.0-0.0) in GameCardInfo.
GameCardFwVersion_Since900NUP = 3 , ///< upp_version >= 603979776 (9.0.0-0.0) in GameCardInfo. Seems to be unused.
GameCardFwVersion_Since1100NUP = 4 , ///< upp_version >= 738197504 (11.0.0-0.0) in GameCardInfo.
GameCardFwVersion_Since1200NUP = 5 , ///< upp_version >= 805306368 (12.0.0-0.0) in GameCardInfo.
2023-07-17 00:03:05 +01:00
GameCardFwVersion_Count = 6 ///< Total values supported by this enum.
2020-04-15 06:59:12 +01:00
} GameCardFwVersion ;
typedef enum {
2020-07-22 09:03:28 +01:00
GameCardAccCtrl1_25MHz = 0xA10011 ,
GameCardAccCtrl1_50MHz = 0xA10010 ///< GameCardRomSize_8GiB or greater.
} GameCardAccCtrl1 ;
2020-04-15 06:59:12 +01:00
typedef enum {
GameCardCompatibilityType_Normal = 0 ,
2021-06-14 01:47:49 +01:00
GameCardCompatibilityType_Terra = 1 ,
2023-07-17 00:03:05 +01:00
GameCardCompatibilityType_Count = 2 ///< Total values supported by this enum.
2020-04-15 06:59:12 +01:00
} GameCardCompatibilityType ;
2021-05-22 09:45:40 +01:00
/// Encrypted using AES-128-CBC with the XCI header key (found in FS program memory under HOS 9.0.0+) and the IV from `GameCardHeader`.
2020-07-15 23:50:34 +01:00
typedef struct {
2023-05-24 20:05:34 +01:00
u64 fw_version ; ///< GameCardFwVersion.
u32 acc_ctrl_1 ; ///< GameCardAccCtrl1.
u32 wait_1_time_read ; ///< Always 0x1388.
u32 wait_2_time_read ; ///< Always 0.
u32 wait_1_time_write ; ///< Always 0.
u32 wait_2_time_write ; ///< Always 0.
Version fw_mode ; ///< Current SDK version.
Version upp_version ; ///< Bundled system update version.
u8 compatibility_type ; ///< GameCardCompatibilityType.
2020-05-01 16:11:18 +01:00
u8 reserved_1 [ 0x3 ] ;
2023-05-24 20:05:34 +01:00
u64 upp_hash ; ///< Checksum for the update partition. The exact way it's calculated is currently unknown.
u64 upp_id ; ///< Must match GAMECARD_UPDATE_TID.
2023-07-17 00:03:05 +01:00
u8 reserved_2 [ 0x28 ] ;
u8 unknown [ 0x10 ] ; ///< Unknown purpose. It's not zeroed out in recent (2021+?) gamecards.
2021-04-06 01:40:57 +01:00
} GameCardInfo ;
2020-04-15 06:59:12 +01:00
2021-04-06 01:40:57 +01:00
NXDT_ASSERT ( GameCardInfo , 0x70 ) ;
2021-03-24 17:25:19 +00:00
2020-07-15 23:50:34 +01:00
/// Placed after the `GameCardKeyArea` section.
2020-04-15 06:59:12 +01:00
typedef struct {
2020-10-08 19:31:09 +01:00
u8 signature [ 0x100 ] ; ///< RSA-2048-PSS with SHA-256 signature over the rest of the header.
2020-04-15 06:59:12 +01:00
u32 magic ; ///< "HEAD".
2021-04-06 01:40:57 +01:00
u32 rom_area_start_page_address ; ///< Expressed in GAMECARD_PAGE_SIZE units.
u32 backup_area_start_page_address ; ///< Always 0xFFFFFFFF.
2020-07-22 09:03:28 +01:00
GameCardKeyIndex key_index ;
2020-04-15 06:59:12 +01:00
u8 rom_size ; ///< GameCardRomSize.
2020-07-22 09:03:28 +01:00
u8 header_version ; ///< Always 0.
2020-05-01 16:06:24 +01:00
u8 flags ; ///< GameCardFlags.
2021-07-19 22:09:58 +01:00
u64 package_id ; ///< Used for challenge-response authentication.
2021-04-06 01:40:57 +01:00
u32 valid_data_end_address ; ///< Expressed in GAMECARD_PAGE_SIZE units.
2020-04-15 06:59:12 +01:00
u8 reserved [ 0x4 ] ;
2021-05-22 09:45:40 +01:00
u8 card_info_iv [ AES_128_KEY_SIZE ] ; ///< AES-128-CBC IV for the CardInfo area (reversed).
2021-04-06 01:40:57 +01:00
u64 partition_fs_header_address ; ///< Root Hash File System header offset.
u64 partition_fs_header_size ; ///< Root Hash File System header size.
2020-04-15 06:59:12 +01:00
u8 partition_fs_header_hash [ SHA256_HASH_SIZE ] ;
u8 initial_data_hash [ SHA256_HASH_SIZE ] ;
u32 sel_sec ; ///< GameCardSelSec.
2020-07-22 09:03:28 +01:00
u32 sel_t1_key ; ///< Always 2.
2021-07-19 22:09:58 +01:00
u32 sel_key ; ///< Always 0.
2021-04-06 01:40:57 +01:00
u32 lim_area ; ///< Expressed in GAMECARD_PAGE_SIZE units.
GameCardInfo card_info ;
2020-04-15 06:59:12 +01:00
} GameCardHeader ;
2021-03-24 17:25:19 +00:00
NXDT_ASSERT ( GameCardHeader , 0x200 ) ;
2020-07-17 06:01:31 +01:00
typedef enum {
2021-06-01 02:12:15 +01:00
GameCardStatus_NotInserted = 0 , ///< No gamecard is inserted.
2021-06-13 07:18:14 +01:00
GameCardStatus_Processing = 1 , ///< A gamecard has been inserted and it's being processed.
GameCardStatus_NoGameCardPatchEnabled = 2 , ///< A gamecard has been inserted, but the running CFW enabled the "nogc" patch at boot.
2021-06-01 02:12:15 +01:00
///< This triggers an error whenever fsDeviceOperatorGetGameCardHandle is called. Nothing at all can be done with the inserted gamecard.
2021-06-13 07:18:14 +01:00
GameCardStatus_LotusAsicFirmwareUpdateRequired = 3 , ///< A gamecard has been inserted, but a LAFW update is needed before being able to read the secure storage area.
2021-06-01 02:12:15 +01:00
///< Operations on the normal storage area are still possible, though.
2021-06-13 07:18:14 +01:00
GameCardStatus_InsertedAndInfoNotLoaded = 4 , ///< A gamecard has been inserted, but an unexpected error unrelated to both "nogc" patch and LAFW version occurred.
2023-07-17 00:03:05 +01:00
GameCardStatus_InsertedAndInfoLoaded = 5 , ///< A gamecard has been inserted and all required information could be successfully retrieved from it.
GameCardStatus_Count = 6 ///< Total values supported by this enum.
2020-07-17 06:01:31 +01:00
} GameCardStatus ;
2022-02-03 01:22:57 +00:00
typedef enum {
LotusAsicFirmwareType_ReadFw = 0xFF ,
LotusAsicFirmwareType_ReadDevFw = 0xFFFF ,
LotusAsicFirmwareType_WriterFw = 0xFFFFFF ,
LotusAsicFirmwareType_RmaFw = 0xFFFFFFFF
} LotusAsicFirmwareType ;
typedef enum {
LotusAsicDeviceType_Test = 0 ,
LotusAsicDeviceType_Dev = 1 ,
LotusAsicDeviceType_Prod = 2 ,
2022-02-04 02:04:43 +00:00
LotusAsicDeviceType_Prod2Dev = 3 ,
2023-07-17 00:03:05 +01:00
LotusAsicDeviceType_Count = 4 ///< Total values supported by this enum.
2022-02-03 01:22:57 +00:00
} LotusAsicDeviceType ;
2022-02-03 03:39:54 +00:00
/// Plaintext Lotus ASIC firmware (LAFW) blob. Dumped from FS program memory.
2022-02-03 01:22:57 +00:00
typedef struct {
u8 signature [ 0x100 ] ;
u32 magic ; ///< "LAFW".
u32 fw_type ; ///< LotusAsicFirmwareType.
u8 reserved_1 [ 0x8 ] ;
struct {
u64 fw_version : 62 ; ///< Stored using a bitmask.
u64 device_type : 2 ; ///< LotusAsicDeviceType.
} ;
u32 data_size ;
u8 reserved_2 [ 0x4 ] ;
u8 data_iv [ AES_128_KEY_SIZE ] ;
char placeholder_str [ 0x10 ] ; ///< "IDIDIDIDIDIDIDID".
u8 reserved_3 [ 0x40 ] ;
u8 data [ 0x7680 ] ;
2022-02-03 03:39:54 +00:00
} LotusAsicFirmwareBlob ;
2022-02-03 01:22:57 +00:00
2022-02-03 03:39:54 +00:00
NXDT_ASSERT ( LotusAsicFirmwareBlob , 0x7800 ) ;
2022-02-03 01:22:57 +00:00
2020-04-15 06:59:12 +01:00
/// Initializes data needed to access raw gamecard storage areas.
/// Also spans a background thread to automatically detect gamecard status changes and to cache data from the inserted gamecard.
2020-05-03 00:40:50 +01:00
bool gamecardInitialize ( void ) ;
2020-04-15 06:59:12 +01:00
/// Deinitializes data generated by gamecardInitialize().
/// This includes destroying the background gamecard detection thread and freeing all cached gamecard data.
void gamecardExit ( void ) ;
2020-11-28 06:38:53 +00:00
/// Returns a user-mode gamecard status change event that can be used to wait for status changes on other threads.
2020-05-03 09:40:08 +01:00
/// If the gamecard interface hasn't been initialized, this returns NULL.
UEvent * gamecardGetStatusChangeUserEvent ( void ) ;
2020-07-17 06:01:31 +01:00
/// Returns the current GameCardStatus value.
u8 gamecardGetStatus ( void ) ;
2020-04-15 06:59:12 +01:00
2022-02-03 03:39:54 +00:00
/// Fills the provided GameCardSecurityInformation pointer.
2022-02-03 01:22:57 +00:00
/// This area can't be read using gamecardReadStorage().
2023-05-24 20:05:34 +01:00
bool gamecardGetSecurityInformation ( GameCardSecurityInformation * out ) ;
2022-02-03 01:22:57 +00:00
2022-02-03 01:13:20 +00:00
/// Fills the provided FsGameCardIdSet pointer.
/// This area can't be read using gamecardReadStorage().
bool gamecardGetIdSet ( FsGameCardIdSet * out ) ;
2022-02-03 03:39:54 +00:00
/// Fills the provided pointers with LAFW blob data from FS program memory.
/// 'out_lafw_blob' or 'out_lafw_version' may be set to NULL, but at least one of them must be a valid pointer.
bool gamecardGetLotusAsicFirmwareBlob ( LotusAsicFirmwareBlob * out_lafw_blob , u64 * out_lafw_version ) ;
/// Used to read raw data from the inserted gamecard. Supports unaligned reads.
/// All required handles, changes between normal <-> secure storage areas and proper offset calculations are managed internally.
/// 'offset' + 'read_size' must not exceed the value returned by gamecardGetTotalSize().
bool gamecardReadStorage ( void * out , u64 read_size , u64 offset ) ;
2021-02-12 20:35:23 +00:00
/// Fills the provided GameCardHeader pointer.
/// This area can also be read using gamecardReadStorage(), starting at offset 0.
2020-04-15 06:59:12 +01:00
bool gamecardGetHeader ( GameCardHeader * out ) ;
2021-02-12 20:35:23 +00:00
2021-06-13 20:32:37 +01:00
/// Fills the provided GameCardInfo pointer.
bool gamecardGetDecryptedCardInfoArea ( GameCardInfo * out ) ;
2021-02-12 20:35:23 +00:00
/// Fills the provided FsGameCardCertificate pointer.
/// This area can also be read using gamecardReadStorage(), starting at GAMECARD_CERTIFICATE_OFFSET.
2020-07-13 07:36:17 +01:00
bool gamecardGetCertificate ( FsGameCardCertificate * out ) ;
2021-02-12 20:35:23 +00:00
/// Fills the provided u64 pointer with the total gamecard size, which is the size taken by both Normal and Secure storage areas.
2020-04-16 05:37:16 +01:00
bool gamecardGetTotalSize ( u64 * out ) ;
2021-02-12 20:35:23 +00:00
/// Fills the provided u64 pointer with the trimmed gamecard size, which is the same as the size returned by gamecardGetTotalSize() but using the trimmed Secure storage area size.
2020-04-16 05:37:16 +01:00
bool gamecardGetTrimmedSize ( u64 * out ) ;
2021-02-12 20:35:23 +00:00
/// Fills the provided u64 pointer with the gamecard ROM capacity, based on the GameCardRomSize value from the header. Not the same as gamecardGetTotalSize().
bool gamecardGetRomCapacity ( u64 * out ) ;
2022-03-17 12:37:24 +00:00
/// Fills the provided Version pointer with the bundled firmware update version in the inserted gamecard.
bool gamecardGetBundledFirmwareUpdateVersion ( Version * out ) ;
2020-04-15 06:59:12 +01:00
2021-03-10 01:12:01 +00:00
/// Fills the provided HashFileSystemContext pointer using information from the requested Hash FS partition.
/// Hash FS functions can be used on the retrieved HashFileSystemContext. hfsFreeContext() must be used to free the underlying data from the filled context.
bool gamecardGetHashFileSystemContext ( u8 hfs_partition_type , HashFileSystemContext * out ) ;
2020-07-29 22:02:21 +01:00
2021-03-07 23:22:49 +00:00
/// One-shot function to retrieve meaningful information from a Hash FS entry by name without using gamecardGetHashFileSystemContext() + Hash FS functions.
/// 'out_offset' or 'out_size' may be set to NULL, but at least one of them must be a valid pointer. The returned offset is always relative to the start of the gamecard image.
/// If you need to get entry information by index, just retrieve the Hash FS context for the target partition and use Hash FS functions on it.
bool gamecardGetHashFileSystemEntryInfoByName ( u8 hfs_partition_type , const char * entry_name , u64 * out_offset , u64 * out_size ) ;
2020-04-16 11:13:11 +01:00
2021-08-11 08:17:57 +01:00
/// Takes a GameCardFwVersion value. Returns a pointer to a string that represents the minimum HOS version that matches the provided LAFW version.
/// Returns NULL if the provided value is out of range.
const char * gamecardGetRequiredHosVersionString ( u64 fw_version ) ;
/// Takes a GameCardCompatibilityType value. Returns a pointer to a string that represents the provided compatibility type.
/// Returns NULL if the provided value is out of range.
const char * gamecardGetCompatibilityTypeString ( u8 compatibility_type ) ;
2022-02-03 03:39:54 +00:00
/// Takes a LotusAsicFirmwareType value. Returns a pointer to a string that represents the provided LAFW type.
/// Returns NULL if the provided value is invalid.
2022-02-04 02:04:43 +00:00
const char * gamecardGetLafwTypeString ( u32 fw_type ) ;
/// Takes a LotusAsicDeviceType value. Returns a pointer to a string that represents the provided LAFW device type.
/// Returns NULL if the provided value is out of range.
const char * gamecardGetLafwDeviceTypeString ( u64 device_type ) ;
2022-02-03 01:22:57 +00:00
2021-03-23 14:06:52 +00:00
# ifdef __cplusplus
}
2021-03-24 17:25:19 +00:00
# endif
# endif /* __GAMECARD_H__ */