1
0
Fork 0
mirror of https://github.com/DarkMatterCore/nxdumptool.git synced 2024-11-09 12:11:44 +00:00

nca: fix impl issues in ncaInitializeContextCommon()

Other changes include:

* cnmt, nca: handle NcmContentId elements in a more uniform way.

* gamecard: add some comments to the GameCardFlags enum.

* nxdt_log: make sure log messages are horizontally aligned.
This commit is contained in:
Pablo Curiel 2024-08-12 12:10:34 +02:00
parent a06a511ce7
commit 89b211c146
4 changed files with 34 additions and 40 deletions

View file

@ -172,8 +172,8 @@ typedef enum {
typedef enum { typedef enum {
GameCardFlags_None = 0, GameCardFlags_None = 0,
GameCardFlags_AutoBoot = BIT(0), GameCardFlags_AutoBoot = BIT(0), ///< The gamecard is capable of autobooting if it's inserted into the console before powering it up.
GameCardFlags_HistoryErase = BIT(1), GameCardFlags_HistoryErase = BIT(1), ///< Inserting the gamecard won't add any permanent icons to the HOME menu.
GameCardFlags_RepairTool = BIT(2), GameCardFlags_RepairTool = BIT(2),
GameCardFlags_DifferentRegionCupToTerraDevice = BIT(3), GameCardFlags_DifferentRegionCupToTerraDevice = BIT(3),
GameCardFlags_DifferentRegionCupToGlobalDevice = BIT(4), GameCardFlags_DifferentRegionCupToGlobalDevice = BIT(4),

View file

@ -289,7 +289,7 @@ bool cnmtVerifyContentHash(ContentMetaContext *cnmt_ctx, NcaContext *nca_ctx, co
/* Check if we got a matching content ID. */ /* Check if we got a matching content ID. */
packaged_content_info = &(cnmt_ctx->packaged_content_info[i]); packaged_content_info = &(cnmt_ctx->packaged_content_info[i]);
if (!memcmp(packaged_content_info->info.content_id.c, nca_ctx->content_id.c, sizeof(nca_ctx->content_id.c))) break; if (!memcmp(&(packaged_content_info->info.content_id), &(nca_ctx->content_id), sizeof(NcmContentId))) break;
packaged_content_info = NULL; packaged_content_info = NULL;
} }
@ -465,7 +465,7 @@ bool cnmtGenerateAuthoringToolXml(ContentMetaContext *cnmt_ctx, NcaContext *nca_
/* Non-Meta NCAs: check if their content IDs are part of the packaged content info entries from the CNMT. */ /* Non-Meta NCAs: check if their content IDs are part of the packaged content info entries from the CNMT. */
for(j = 0; j < cnmt_ctx->packaged_header->content_count; j++) for(j = 0; j < cnmt_ctx->packaged_header->content_count; j++)
{ {
if (!memcmp(cnmt_ctx->packaged_content_info[j].info.content_id.c, cur_nca_ctx->content_id.c, 0x10)) break; if (!memcmp(&(cnmt_ctx->packaged_content_info[j].info.content_id), &(cur_nca_ctx->content_id), sizeof(NcmContentId))) break;
} }
invalid_nca = (j >= cnmt_ctx->packaged_header->content_count); invalid_nca = (j >= cnmt_ctx->packaged_header->content_count);

View file

@ -127,7 +127,7 @@ static const u8 g_nca0KeyAreaHash[SHA256_HASH_SIZE] = {
/* Function prototypes. */ /* Function prototypes. */
static bool ncaInitializeContextCommon(NcaContext *out, u8 storage_id, NcmContentStorage *ncm_storage, Ticket *tik); static bool ncaInitializeContextCommon(NcaContext *out, u8 storage_id, u8 hfs_partition_type, NcmContentStorage *ncm_storage, Ticket *tik);
NX_INLINE bool ncaIsFsInfoEntryValid(NcaFsInfo *fs_info); NX_INLINE bool ncaIsFsInfoEntryValid(NcaFsInfo *fs_info);
@ -198,6 +198,7 @@ bool ncaInitializeContext(NcaContext *out, u8 storage_id, u8 hfs_partition_type,
out->title_type = meta_key->type; out->title_type = meta_key->type;
memcpy(&(out->content_id), &(content_info->content_id), sizeof(NcmContentId)); memcpy(&(out->content_id), &(content_info->content_id), sizeof(NcmContentId));
utilsGenerateHexString(out->content_id_str, sizeof(out->content_id_str), out->content_id.c, sizeof(out->content_id.c), false);
ncmContentInfoSizeToU64(content_info, &(out->content_size)); ncmContentInfoSizeToU64(content_info, &(out->content_size));
utilsGenerateFormattedSizeString((double)out->content_size, out->content_size_str, sizeof(out->content_size_str)); utilsGenerateFormattedSizeString((double)out->content_size, out->content_size_str, sizeof(out->content_size_str));
@ -211,21 +212,7 @@ bool ncaInitializeContext(NcaContext *out, u8 storage_id, u8 hfs_partition_type,
return false; return false;
} }
if (out->storage_id == NcmStorageId_GameCard) return ncaInitializeContextCommon(out, storage_id, hfs_partition_type, ncm_storage, tik);
{
/* Generate gamecard NCA filename. */
char nca_filename[0x30] = {0};
sprintf(nca_filename, "%s.%s", out->content_id_str, out->content_type == NcmContentType_Meta ? "cnmt.nca" : "nca");
/* Retrieve gamecard NCA offset. */
if (!gamecardGetHashFileSystemEntryInfoByName(hfs_partition_type, nca_filename, &(out->gamecard_offset), NULL))
{
LOG_MSG_ERROR("Error retrieving offset for \"%s\" entry in secure hash FS partition!", nca_filename);
return false;
}
}
return ncaInitializeContextCommon(out, storage_id, ncm_storage, tik);
} }
bool ncaInitializeContextByHashFileSystemEntry(NcaContext *out, HashFileSystemContext *hfs_ctx, HashFileSystemEntry *hfs_entry, Ticket *tik) bool ncaInitializeContextByHashFileSystemEntry(NcaContext *out, HashFileSystemContext *hfs_ctx, HashFileSystemEntry *hfs_entry, Ticket *tik)
@ -254,21 +241,16 @@ bool ncaInitializeContextByHashFileSystemEntry(NcaContext *out, HashFileSystemCo
} }
/* Fill NCA context. */ /* Fill NCA context. */
utilsParseHexString(&(out->content_id), sizeof(out->content_id), hfs_entry_name, NCA_CONTENT_ID_STR_LENGTH); utilsParseHexString(out->content_id.c, sizeof(out->content_id.c), hfs_entry_name, NCA_CONTENT_ID_STR_LENGTH);
snprintf(out->content_id_str, sizeof(out->content_id_str), "%.*s", NCA_CONTENT_ID_STR_LENGTH, hfs_entry_name);
//LOG_DATA_DEBUG(&(out->content_id), sizeof(NcmContentId), "Parsed ID (%s):", out->content_id_str);
out->content_size = hfs_entry->size; out->content_size = hfs_entry->size;
utilsGenerateFormattedSizeString((double)out->content_size, out->content_size_str, sizeof(out->content_size_str)); utilsGenerateFormattedSizeString((double)out->content_size, out->content_size_str, sizeof(out->content_size_str));
if (hfs_entry_name_len == NCA_HFS_META_NAME_LENGTH) out->content_type = NcmContentType_Meta; /* Set Meta as the content type if we know it. */ if (hfs_entry_name_len == NCA_HFS_META_NAME_LENGTH) out->content_type = NcmContentType_Meta; /* Set Meta as the content type if we know it. */
/* Retrieve gamecard NCA offset. */ return ncaInitializeContextCommon(out, NcmStorageId_GameCard, hfs_ctx->type, NULL, tik);
if (!gamecardGetHashFileSystemEntryInfoByName(hfs_ctx->type, hfs_entry_name, &(out->gamecard_offset), NULL))
{
LOG_MSG_ERROR("Error retrieving offset for \"%s\" entry in %s hash FS partition!", hfs_entry_name, hfsGetPartitionNameString(hfs_ctx->type));
return false;
}
return ncaInitializeContextCommon(out, NcmStorageId_GameCard, NULL, tik);
} }
bool ncaReadContentFile(NcaContext *ctx, void *out, u64 read_size, u64 offset) bool ncaReadContentFile(NcaContext *ctx, void *out, u64 read_size, u64 offset)
@ -365,7 +347,7 @@ bool ncaGenerateHierarchicalSha256Patch(NcaFsSectionContext *ctx, const void *da
void ncaWriteHierarchicalSha256PatchToMemoryBuffer(NcaContext *ctx, NcaHierarchicalSha256Patch *patch, void *buf, u64 buf_size, u64 buf_offset) void ncaWriteHierarchicalSha256PatchToMemoryBuffer(NcaContext *ctx, NcaHierarchicalSha256Patch *patch, void *buf, u64 buf_size, u64 buf_offset)
{ {
if (!ctx || !*(ctx->content_id_str) || ctx->content_size < NCA_FULL_HEADER_LENGTH || !patch || patch->written || \ if (!ctx || !*(ctx->content_id_str) || ctx->content_size < NCA_FULL_HEADER_LENGTH || !patch || patch->written || \
memcmp(patch->content_id.c, ctx->content_id.c, sizeof(NcmContentId)) != 0 || !patch->hash_region_count || \ memcmp(&(patch->content_id), &(ctx->content_id), sizeof(NcmContentId)) != 0 || !patch->hash_region_count || \
patch->hash_region_count > NCA_HIERARCHICAL_SHA256_MAX_REGION_COUNT || !buf || !buf_size || (buf_offset + buf_size) > ctx->content_size) return; patch->hash_region_count > NCA_HIERARCHICAL_SHA256_MAX_REGION_COUNT || !buf || !buf_size || (buf_offset + buf_size) > ctx->content_size) return;
patch->written = true; patch->written = true;
@ -390,7 +372,7 @@ bool ncaGenerateHierarchicalIntegrityPatch(NcaFsSectionContext *ctx, const void
void ncaWriteHierarchicalIntegrityPatchToMemoryBuffer(NcaContext *ctx, NcaHierarchicalIntegrityPatch *patch, void *buf, u64 buf_size, u64 buf_offset) void ncaWriteHierarchicalIntegrityPatchToMemoryBuffer(NcaContext *ctx, NcaHierarchicalIntegrityPatch *patch, void *buf, u64 buf_size, u64 buf_offset)
{ {
if (!ctx || !*(ctx->content_id_str) || ctx->content_size < NCA_FULL_HEADER_LENGTH || !patch || patch->written || \ if (!ctx || !*(ctx->content_id_str) || ctx->content_size < NCA_FULL_HEADER_LENGTH || !patch || patch->written || \
memcmp(patch->content_id.c, ctx->content_id.c, sizeof(NcmContentId)) != 0 || !buf || !buf_size || (buf_offset + buf_size) > ctx->content_size) return; memcmp(&(patch->content_id), &(ctx->content_id), sizeof(NcmContentId)) != 0 || !buf || !buf_size || (buf_offset + buf_size) > ctx->content_size) return;
patch->written = true; patch->written = true;
@ -578,9 +560,9 @@ const char *ncaGetFsSectionTypeName(NcaFsSectionContext *ctx)
return str; return str;
} }
static bool ncaInitializeContextCommon(NcaContext *out, u8 storage_id, NcmContentStorage *ncm_storage, Ticket *tik) static bool ncaInitializeContextCommon(NcaContext *out, u8 storage_id, u8 hfs_partition_type, NcmContentStorage *ncm_storage, Ticket *tik)
{ {
if (!out || out->content_size < NCA_FULL_HEADER_LENGTH) if (!out || !*(out->content_id_str) || out->content_size < NCA_FULL_HEADER_LENGTH || (storage_id != NcmStorageId_GameCard && !ncm_storage))
{ {
LOG_MSG_ERROR("Invalid parameters!"); LOG_MSG_ERROR("Invalid parameters!");
return false; return false;
@ -592,10 +574,22 @@ static bool ncaInitializeContextCommon(NcaContext *out, u8 storage_id, NcmConten
out->storage_id = storage_id; out->storage_id = storage_id;
out->ncm_storage = (out->storage_id != NcmStorageId_GameCard ? ncm_storage : NULL); out->ncm_storage = (out->storage_id != NcmStorageId_GameCard ? ncm_storage : NULL);
utilsGenerateHexString(out->content_id_str, sizeof(out->content_id_str), out->content_id.c, sizeof(out->content_id.c), false);
utilsGenerateHexString(out->hash_str, sizeof(out->hash_str), out->hash, sizeof(out->hash), false); /* Placeholder, needs to be manually calculated. */ utilsGenerateHexString(out->hash_str, sizeof(out->hash_str), out->hash, sizeof(out->hash), false); /* Placeholder, needs to be manually calculated. */
if (storage_id == NcmStorageId_GameCard)
{
/* Generate gamecard NCA filename. */
char nca_filename[0x30] = {0};
sprintf(nca_filename, "%s.%s", out->content_id_str, out->content_type == NcmContentType_Meta ? "cnmt.nca" : "nca");
/* Retrieve gamecard NCA offset. */
if (!gamecardGetHashFileSystemEntryInfoByName(hfs_partition_type, nca_filename, &(out->gamecard_offset), NULL))
{
LOG_MSG_ERROR("Error retrieving offset for \"%s\" entry in %s hash FS partition!", nca_filename, hfsGetPartitionNameString(hfs_partition_type));
return false;
}
}
/* Read decrypted NCA header and NCA FS section headers. */ /* Read decrypted NCA header and NCA FS section headers. */
if (!ncaReadDecryptedHeader(out)) if (!ncaReadDecryptedHeader(out))
{ {

View file

@ -35,14 +35,14 @@ static s64 g_logFileOffset = 0;
static char *g_logBuffer = NULL; static char *g_logBuffer = NULL;
static size_t g_logBufferLength = 0; static size_t g_logBufferLength = 0;
static const char *g_logStrFormat = "[%d-%02d-%02d %02d:%02d:%02d.%09lu] [%s] %s|%d|%s -> "; static const char *g_logStrFormat = "[%d-%02d-%02d %02d:%02d:%02d.%09lu] %s %s|%d|%s -> ";
static const char *g_logSessionSeparator = "________________________________________________________________\r\n"; static const char *g_logSessionSeparator = "________________________________________________________________\r\n";
static const char *g_logLevelNames[] = { static const char *g_logLevelNames[] = {
[LOG_LEVEL_DEBUG] = "DEBUG", [LOG_LEVEL_DEBUG] = "[DEBUG] ",
[LOG_LEVEL_INFO] = "INFO", [LOG_LEVEL_INFO] = "[INFO] ",
[LOG_LEVEL_WARNING] = "WARNING", [LOG_LEVEL_WARNING] = "[WARNING]",
[LOG_LEVEL_ERROR] = "ERROR" [LOG_LEVEL_ERROR] = "[ERROR] "
}; };
/* Function prototypes. */ /* Function prototypes. */