From 460bee888b84f5a545120d5ca95bc04d6cff9644 Mon Sep 17 00:00:00 2001 From: Pablo Curiel Date: Mon, 5 Apr 2021 20:40:57 -0400 Subject: [PATCH] Match changes to the XCI page in Switchbrew. --- include/core/gamecard.h | 42 ++++++++++++++++++++--------------------- source/core/gamecard.c | 18 +++++++++--------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/include/core/gamecard.h b/include/core/gamecard.h index 2451e7c..e68b0f8 100644 --- a/include/core/gamecard.h +++ b/include/core/gamecard.h @@ -31,14 +31,14 @@ extern "C" { #endif -#define GAMECARD_HEAD_MAGIC 0x48454144 /* "HEAD". */ +#define GAMECARD_HEAD_MAGIC 0x48454144 /* "HEAD". */ -#define GAMECARD_MEDIA_UNIT_SIZE 0x200 -#define GAMECARD_MEDIA_UNIT_OFFSET(x) ((u64)(x) * GAMECARD_MEDIA_UNIT_SIZE) +#define GAMECARD_PAGE_SIZE 0x200 +#define GAMECARD_PAGE_OFFSET(x) ((u64)(x) * GAMECARD_PAGE_SIZE) -#define GAMECARD_UPDATE_TID SYSTEM_UPDATE_TID +#define GAMECARD_UPDATE_TID SYSTEM_UPDATE_TID -#define GAMECARD_CERTIFICATE_OFFSET 0x7000 +#define GAMECARD_CERTIFICATE_OFFSET 0x7000 /// Encrypted using AES-128-ECB with the common titlekek generator key (stored in the .rodata segment from the Lotus firmware). typedef struct { @@ -123,8 +123,8 @@ typedef enum { typedef enum { GameCardFwVersion_ForDev = 0, GameCardFwVersion_ForProd = BIT(0), - GameCardFwVersion_ForProdSince400NUP = BIT(1), ///< cup_version >= 268435456 (4.0.0-0.0) in GameCardHeaderEncryptedArea. - GameCardFwVersion_ForProdSince1100NUP = BIT(2) ///< cup_version >= 738197504 (11.0.0-0.0) in GameCardHeaderEncryptedArea. + GameCardFwVersion_ForProdSince400NUP = BIT(1), ///< upp_version >= 268435456 (4.0.0-0.0) in GameCardInfo. + GameCardFwVersion_ForProdSince1100NUP = BIT(2) ///< upp_version >= 738197504 (11.0.0-0.0) in GameCardInfo. } GameCardFwVersion; typedef enum { @@ -148,40 +148,40 @@ typedef struct { u32 wait_2_time_read; ///< Always 0. u32 wait_1_time_write; ///< Always 0. u32 wait_2_time_write; ///< Always 0. - VersionType2 fw_mode; - VersionType1 cup_version; + VersionType2 fw_mode; ///< Current SdkAddonVersion. + VersionType1 upp_version; ///< Bundled system update version. u8 compatibility_type; ///< GameCardCompatibilityType. u8 reserved_1[0x3]; - u64 cup_hash; - u64 cup_id; ///< Must match GAMECARD_UPDATE_TID. + u64 upp_hash; ///< SHA-256 checksum for the update partition. + u64 upp_id; ///< Must match GAMECARD_UPDATE_TID. u8 reserved_2[0x38]; -} GameCardHeaderEncryptedArea; +} GameCardInfo; -NXDT_ASSERT(GameCardHeaderEncryptedArea, 0x70); +NXDT_ASSERT(GameCardInfo, 0x70); /// Placed after the `GameCardKeyArea` section. typedef struct { u8 signature[0x100]; ///< RSA-2048-PSS with SHA-256 signature over the rest of the header. u32 magic; ///< "HEAD". - u32 secure_area_start_address; ///< Expressed in GAMECARD_MEDIA_UNIT_SIZE blocks. - u32 backup_area_start_address; ///< Always 0xFFFFFFFF. + u32 rom_area_start_page_address; ///< Expressed in GAMECARD_PAGE_SIZE units. + u32 backup_area_start_page_address; ///< Always 0xFFFFFFFF. GameCardKeyIndex key_index; u8 rom_size; ///< GameCardRomSize. u8 header_version; ///< Always 0. u8 flags; ///< GameCardFlags. - u64 package_id; - u32 valid_data_end_address; ///< Expressed in GAMECARD_MEDIA_UNIT_SIZE blocks. + u64 package_id; ///< Used for challenge–response authentication. + u32 valid_data_end_address; ///< Expressed in GAMECARD_PAGE_SIZE units. u8 reserved[0x4]; u8 iv[0x10]; - u64 partition_fs_header_address; ///< Root HFS0 header offset. - u64 partition_fs_header_size; ///< Root HFS0 header size. + u64 partition_fs_header_address; ///< Root Hash File System header offset. + u64 partition_fs_header_size; ///< Root Hash File System header size. u8 partition_fs_header_hash[SHA256_HASH_SIZE]; u8 initial_data_hash[SHA256_HASH_SIZE]; u32 sel_sec; ///< GameCardSelSec. u32 sel_t1_key; ///< Always 2. u32 sel_key; ///> Always 0. - u32 normal_area_end_address; ///< Expressed in GAMECARD_MEDIA_UNIT_SIZE blocks. - GameCardHeaderEncryptedArea encrypted_area; + u32 lim_area; ///< Expressed in GAMECARD_PAGE_SIZE units. + GameCardInfo card_info; } GameCardHeader; NXDT_ASSERT(GameCardHeader, 0x200); diff --git a/source/core/gamecard.c b/source/core/gamecard.c index 11e03bd..3c24def 100644 --- a/source/core/gamecard.c +++ b/source/core/gamecard.c @@ -30,7 +30,7 @@ #define GAMECARD_ACCESS_WAIT_TIME 3 /* Seconds. */ #define GAMECARD_UNUSED_AREA_BLOCK_SIZE 0x24 -#define GAMECARD_UNUSED_AREA_SIZE(x) (((x) / GAMECARD_MEDIA_UNIT_SIZE) * GAMECARD_UNUSED_AREA_BLOCK_SIZE) +#define GAMECARD_UNUSED_AREA_SIZE(x) (((x) / GAMECARD_PAGE_SIZE) * GAMECARD_UNUSED_AREA_BLOCK_SIZE) #define GAMECARD_STORAGE_AREA_NAME(x) ((x) == GameCardStorageArea_Normal ? "normal" : ((x) == GameCardStorageArea_Secure ? "secure" : "none")) @@ -322,7 +322,7 @@ bool gamecardGetTrimmedSize(u64 *out) { mutexLock(&g_gameCardMutex); bool ret = (g_gameCardInserted && g_gameCardInfoLoaded && out); - if (ret) *out = (sizeof(GameCardHeader) + GAMECARD_MEDIA_UNIT_OFFSET(g_gameCardHeader.valid_data_end_address)); + if (ret) *out = (sizeof(GameCardHeader) + GAMECARD_PAGE_OFFSET(g_gameCardHeader.valid_data_end_address)); mutexUnlock(&g_gameCardMutex); return ret; } @@ -840,9 +840,9 @@ static bool gamecardReadStorageArea(void *out, u64 read_size, u64 offset, bool l /* Calculate appropiate storage area offset and retrieve the right storage area pointer. */ u64 base_offset = (area == GameCardStorageArea_Normal ? offset : (offset - g_gameCardStorageNormalAreaSize)); - if (!(base_offset % GAMECARD_MEDIA_UNIT_SIZE) && !(read_size % GAMECARD_MEDIA_UNIT_SIZE)) + if (!(base_offset % GAMECARD_PAGE_SIZE) && !(read_size % GAMECARD_PAGE_SIZE)) { - /* Optimization for reads that are already aligned to a GAMECARD_MEDIA_UNIT_SIZE boundary. */ + /* Optimization for reads that are already aligned to a GAMECARD_PAGE_SIZE boundary. */ rc = fsStorageRead(&g_gameCardStorage, base_offset, out_u8, read_size); if (R_FAILED(rc)) { @@ -853,8 +853,8 @@ static bool gamecardReadStorageArea(void *out, u64 read_size, u64 offset, bool l success = true; } else { /* Fix offset and/or size to avoid unaligned reads. */ - u64 block_start_offset = ALIGN_DOWN(base_offset, GAMECARD_MEDIA_UNIT_SIZE); - u64 block_end_offset = ALIGN_UP(base_offset + read_size, GAMECARD_MEDIA_UNIT_SIZE); + u64 block_start_offset = ALIGN_DOWN(base_offset, GAMECARD_PAGE_SIZE); + u64 block_end_offset = ALIGN_UP(base_offset + read_size, GAMECARD_PAGE_SIZE); u64 block_size = (block_end_offset - block_start_offset); u64 data_start_offset = (base_offset - block_start_offset); @@ -976,8 +976,8 @@ static HashFileSystemContext *gamecardInitializeHashFileSystemContext(const char bool success = false, dump_fs_header = false; - if ((name && !*name) || offset < (GAMECARD_CERTIFICATE_OFFSET + sizeof(FsGameCardCertificate)) || !IS_ALIGNED(offset, GAMECARD_MEDIA_UNIT_SIZE) || \ - (size && (!IS_ALIGNED(size, GAMECARD_MEDIA_UNIT_SIZE) || (offset + size) > g_gameCardStorageTotalSize))) + if ((name && !*name) || offset < (GAMECARD_CERTIFICATE_OFFSET + sizeof(FsGameCardCertificate)) || !IS_ALIGNED(offset, GAMECARD_PAGE_SIZE) || \ + (size && (!IS_ALIGNED(size, GAMECARD_PAGE_SIZE) || (offset + size) > g_gameCardStorageTotalSize))) { LOG_MSG("Invalid parameters!"); goto end; @@ -1039,7 +1039,7 @@ static HashFileSystemContext *gamecardInitializeHashFileSystemContext(const char /* Calculate full Hash FS header size. */ fs_ctx->header_size = (sizeof(HashFileSystemHeader) + (fs_header.entry_count * sizeof(HashFileSystemEntry)) + fs_header.name_table_size); - fs_ctx->header_size = ALIGN_UP(fs_ctx->header_size, GAMECARD_MEDIA_UNIT_SIZE); + fs_ctx->header_size = ALIGN_UP(fs_ctx->header_size, GAMECARD_PAGE_SIZE); /* Allocate memory for the full Hash FS header. */ fs_ctx->header = calloc(fs_ctx->header_size, sizeof(u8));