2020-10-01 07:17:59 +01:00
/*
* cnmt . c
*
2023-04-08 12:42:22 +01:00
* Copyright ( c ) 2020 - 2023 , DarkMatterCore < pabloacurielz @ gmail . com > .
2020-10-01 07:17:59 +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-10-01 07:17:59 +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-10-01 07:17:59 +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-10-01 07:17:59 +01:00
*/
2021-03-26 04:35:14 +00:00
# include "nxdt_utils.h"
2020-10-01 07:17:59 +01:00
# include "cnmt.h"
# include "title.h"
2022-03-18 16:48:16 +00:00
/* Helper macros. */
2020-10-01 07:17:59 +01:00
# define CNMT_MINIMUM_FILENAME_LENGTH 23 /* Content Meta Type + "_" + Title ID + ".cnmt". */
2022-03-18 16:48:16 +00:00
# define CNMT_ADD_FMT_STR(fmt, ...) utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, fmt, ##__VA_ARGS__)
2020-10-01 07:17:59 +01:00
2020-10-14 01:15:21 +01:00
/* Global variables. */
static const char * g_cnmtAttributeStrings [ ContentMetaAttribute_Count ] = {
" IncludesExFatDriver " ,
" Rebootless " ,
" Compacted "
} ;
2020-10-01 07:17:59 +01:00
/* Function prototypes. */
static bool cnmtGetContentMetaTypeAndTitleIdFromFileName ( const char * cnmt_filename , size_t cnmt_filename_len , u8 * out_content_meta_type , u64 * out_title_id ) ;
2020-10-02 10:53:58 +01:00
static const char * cnmtGetRequiredTitleVersionString ( u8 content_meta_type ) ;
static const char * cnmtGetRequiredTitleTypeString ( u8 content_meta_type ) ;
2020-10-01 07:17:59 +01:00
bool cnmtInitializeContext ( ContentMetaContext * out , NcaContext * nca_ctx )
{
2020-10-15 01:06:53 +01:00
if ( ! out | | ! nca_ctx | | ! * ( nca_ctx - > content_id_str ) | | nca_ctx - > content_type ! = NcmContentType_Meta | | nca_ctx - > content_size < NCA_FULL_HEADER_LENGTH | | \
2020-10-01 07:17:59 +01:00
( nca_ctx - > storage_id ! = NcmStorageId_GameCard & & ! nca_ctx - > ncm_storage ) | | ( nca_ctx - > storage_id = = NcmStorageId_GameCard & & ! nca_ctx - > gamecard_offset ) | | \
2020-11-08 19:08:30 +00:00
nca_ctx - > header . content_type ! = NcaContentType_Meta | | nca_ctx - > content_type_ctx | | ! out )
2020-10-01 07:17:59 +01:00
{
2022-07-12 17:34:49 +01:00
LOG_MSG_ERROR ( " Invalid parameters! " ) ;
2020-10-01 07:17:59 +01:00
return false ;
}
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
u32 i = 0 , pfs_entry_count = 0 ;
size_t cnmt_filename_len = 0 ;
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
u8 content_meta_type = 0 ;
u64 title_id = 0 , cur_offset = 0 ;
2022-07-05 02:04:28 +01:00
Preliminar 15.x support.
This commit uses my yet unmerged libnx PR to update ncm_types.h.
PoC code hasn't been updated yet, so proper support for DLC updates will arrive at a later time.
Note to self: implement a way to provide access to loaded DataPatch TitleInfo entries (linked list hell).
* bktr: renamed bktrBucketInitializeSubStorageReadParams to bktrInitializeSubStorageReadParams to avoid redundancy, added debug code to dump BucketInfo and BucketTree tables if BucketTree storage initialization fails.
* cnmt: updated ContentMetaAddOnContentMetaExtendedHeader struct to its 15.x equivalent, added ContentMetaLegacyAddOnContentMetaExtendedHeader struct, added ContentMetaDataPatchMetaExtendedHeader struct, updated the cnmtGetRequiredTitleId and cnmtGetRequiredTitleVersion functions to support DataPatch titles, updated cnmtInitializeContext to support both the new AddOnContent extended header and DataPatch titles, added debug code to dump the whole CNMT if context initialization fails, updated cnmtGenerateAuthoringToolXml to support DataPatch titles.
* keys: updated block hashes to match 15.x keyset, use case-insensitive comparison while looking for entry names in keysReadKeysFromFile, make sure the eticket_rsa_kek is non-zero before proceeding in keysGetDecryptedEticketRsaDeviceKey.
* nca: updated NcaKeyGeneration enum, added reminder about updating NcaSignatureKeyGeneration if necessary, replaced ncaFsSectionCheckHashRegionAccess with ncaFsSectionCheckPlaintextHashRegionAccess, removed all extents checks on Patch RomFS and sparse sections, updated ncaGetFsSectionTypeName to reflect if a FS section holds a sparse layer or not.
* nca_storage: updated ncaStorageInitializeContext to avoid initializing a compressed storage if a sparse layer is also used (fixes issues with Them's Fightin' Herds), updated ncaStorageSetPatchOriginalSubStorage to enforce the presence of a compressed storage in a patch if the base FS holds a compressed storage.
* npdm: added reminder about updating NpdmSignatureKeyGeneration if necessary, updated NpdmFsAccessControlFlags enum, updated NpdmAccessibility enum, updated NpdmSystemCallId enum, fixed typos.
* title: updated all relevant functions that deal with NcmContentMetaType values to also handle DataPatch titles, added functions to handle DataPatchId values, removed titleConvertNcmContentSizeToU64 and titleConvertU64ToNcmContentSize functions in favor of ncmContentInfoSizeToU64 and ncmU64ToContentInfoSize from my unmerged libnx PR, updated internal arrays to match 15.x changes, renamed titleOrphanTitleInfoSortFunction to titleInfoEntrySortFunction and updated it to also sort entries by version and storage ID, updated titleGenerateTitleInfoEntriesForTitleStorage to sort TitleInfo entries, simplified titleDuplicateTitleInfo a bit by using macros.
2022-10-23 15:44:47 +01:00
bool success = false , invalid_ext_header_size = false , invalid_ext_data_size = false , dump_cnmt = false ;
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
/* Free output context beforehand. */
cnmtFreeContext ( out ) ;
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
/* Initialize Partition FS context. */
2020-10-13 15:00:03 +01:00
if ( ! pfsInitializeContext ( & ( out - > pfs_ctx ) , & ( nca_ctx - > fs_ctx [ 0 ] ) ) )
2020-10-01 07:17:59 +01:00
{
2022-07-12 17:34:49 +01:00
LOG_MSG_ERROR ( " Failed to initialize Partition FS context! " ) ;
2020-10-01 07:17:59 +01:00
goto end ;
}
2022-07-05 02:04:28 +01:00
2020-10-09 10:58:53 +01:00
/* Get Partition FS entry count. Edge case, we should never trigger this. */
2020-10-01 07:17:59 +01:00
if ( ! ( pfs_entry_count = pfsGetEntryCount ( & ( out - > pfs_ctx ) ) ) )
{
2022-07-12 17:34:49 +01:00
LOG_MSG_ERROR ( " Partition FS has no file entries! " ) ;
2020-10-01 07:17:59 +01:00
goto end ;
}
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
/* Look for the '.cnmt' file entry index. */
for ( i = 0 ; i < pfs_entry_count ; i + + )
{
if ( ( out - > cnmt_filename = pfsGetEntryNameByIndex ( & ( out - > pfs_ctx ) , i ) ) & & ( cnmt_filename_len = strlen ( out - > cnmt_filename ) ) > = CNMT_MINIMUM_FILENAME_LENGTH & & \
2021-05-11 07:00:33 +01:00
! strcasecmp ( out - > cnmt_filename + cnmt_filename_len - 5 , " .cnmt " ) ) break ;
2020-10-01 07:17:59 +01:00
}
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
if ( i > = pfs_entry_count )
{
2022-07-12 17:34:49 +01:00
LOG_MSG_ERROR ( " '.cnmt' entry unavailable in Partition FS! " ) ;
2020-10-01 07:17:59 +01:00
goto end ;
}
2022-07-05 02:04:28 +01:00
2022-07-12 17:34:49 +01:00
LOG_MSG_INFO ( " Found '.cnmt' entry \" %s \" in Meta NCA \" %s \" . " , out - > cnmt_filename , nca_ctx - > content_id_str ) ;
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
/* Retrieve content meta type and title ID from the '.cnmt' filename. */
if ( ! cnmtGetContentMetaTypeAndTitleIdFromFileName ( out - > cnmt_filename , cnmt_filename_len , & content_meta_type , & title_id ) ) goto end ;
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
/* Get '.cnmt' file entry. */
if ( ! ( out - > pfs_entry = pfsGetEntryByIndex ( & ( out - > pfs_ctx ) , i ) ) )
{
2022-07-12 17:34:49 +01:00
LOG_MSG_ERROR ( " Failed to get '.cnmt' entry from Partition FS! " ) ;
2020-10-01 07:17:59 +01:00
goto end ;
}
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
/* Check raw CNMT size. */
if ( ! out - > pfs_entry - > size )
{
2022-07-12 17:34:49 +01:00
LOG_DATA_ERROR ( out - > pfs_entry , sizeof ( PartitionFileSystemEntry ) , " Invalid raw CNMT size! Partition FS entry dump: " ) ;
2020-10-01 07:17:59 +01:00
goto end ;
}
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
/* Allocate memory for the raw CNMT data. */
out - > raw_data_size = out - > pfs_entry - > size ;
2020-10-09 10:58:53 +01:00
if ( ! ( out - > raw_data = malloc ( out - > raw_data_size ) ) )
2020-10-01 07:17:59 +01:00
{
2022-07-12 17:34:49 +01:00
LOG_MSG_ERROR ( " Failed to allocate memory for the raw CNMT data! " ) ;
2020-10-01 07:17:59 +01:00
goto end ;
}
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
/* Read raw CNMT data into memory buffer. */
if ( ! pfsReadEntryData ( & ( out - > pfs_ctx ) , out - > pfs_entry , out - > raw_data , out - > raw_data_size , 0 ) )
{
2022-07-12 17:34:49 +01:00
LOG_MSG_ERROR ( " Failed to read raw CNMT data! " ) ;
2020-10-01 07:17:59 +01:00
goto end ;
}
2022-07-05 02:04:28 +01:00
Preliminar 15.x support.
This commit uses my yet unmerged libnx PR to update ncm_types.h.
PoC code hasn't been updated yet, so proper support for DLC updates will arrive at a later time.
Note to self: implement a way to provide access to loaded DataPatch TitleInfo entries (linked list hell).
* bktr: renamed bktrBucketInitializeSubStorageReadParams to bktrInitializeSubStorageReadParams to avoid redundancy, added debug code to dump BucketInfo and BucketTree tables if BucketTree storage initialization fails.
* cnmt: updated ContentMetaAddOnContentMetaExtendedHeader struct to its 15.x equivalent, added ContentMetaLegacyAddOnContentMetaExtendedHeader struct, added ContentMetaDataPatchMetaExtendedHeader struct, updated the cnmtGetRequiredTitleId and cnmtGetRequiredTitleVersion functions to support DataPatch titles, updated cnmtInitializeContext to support both the new AddOnContent extended header and DataPatch titles, added debug code to dump the whole CNMT if context initialization fails, updated cnmtGenerateAuthoringToolXml to support DataPatch titles.
* keys: updated block hashes to match 15.x keyset, use case-insensitive comparison while looking for entry names in keysReadKeysFromFile, make sure the eticket_rsa_kek is non-zero before proceeding in keysGetDecryptedEticketRsaDeviceKey.
* nca: updated NcaKeyGeneration enum, added reminder about updating NcaSignatureKeyGeneration if necessary, replaced ncaFsSectionCheckHashRegionAccess with ncaFsSectionCheckPlaintextHashRegionAccess, removed all extents checks on Patch RomFS and sparse sections, updated ncaGetFsSectionTypeName to reflect if a FS section holds a sparse layer or not.
* nca_storage: updated ncaStorageInitializeContext to avoid initializing a compressed storage if a sparse layer is also used (fixes issues with Them's Fightin' Herds), updated ncaStorageSetPatchOriginalSubStorage to enforce the presence of a compressed storage in a patch if the base FS holds a compressed storage.
* npdm: added reminder about updating NpdmSignatureKeyGeneration if necessary, updated NpdmFsAccessControlFlags enum, updated NpdmAccessibility enum, updated NpdmSystemCallId enum, fixed typos.
* title: updated all relevant functions that deal with NcmContentMetaType values to also handle DataPatch titles, added functions to handle DataPatchId values, removed titleConvertNcmContentSizeToU64 and titleConvertU64ToNcmContentSize functions in favor of ncmContentInfoSizeToU64 and ncmU64ToContentInfoSize from my unmerged libnx PR, updated internal arrays to match 15.x changes, renamed titleOrphanTitleInfoSortFunction to titleInfoEntrySortFunction and updated it to also sort entries by version and storage ID, updated titleGenerateTitleInfoEntriesForTitleStorage to sort TitleInfo entries, simplified titleDuplicateTitleInfo a bit by using macros.
2022-10-23 15:44:47 +01:00
dump_cnmt = true ;
2020-10-02 10:53:58 +01:00
/* Calculate SHA-256 checksum for the whole raw CNMT. */
sha256CalculateHash ( out - > raw_data_hash , out - > raw_data , out - > raw_data_size ) ;
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
/* Verify packaged header. */
2020-10-02 11:28:41 +01:00
out - > packaged_header = ( ContentMetaPackagedContentMetaHeader * ) out - > raw_data ;
cur_offset + = sizeof ( ContentMetaPackagedContentMetaHeader ) ;
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
if ( out - > packaged_header - > title_id ! = title_id )
{
2022-07-12 17:34:49 +01:00
LOG_MSG_ERROR ( " CNMT title ID mismatch! (%016lX != %016lX). " , out - > packaged_header - > title_id , title_id ) ;
2020-10-01 07:17:59 +01:00
goto end ;
}
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
if ( out - > packaged_header - > content_meta_type ! = content_meta_type )
{
2022-07-12 17:34:49 +01:00
LOG_MSG_ERROR ( " CNMT content meta type mismatch! (0x%02X != 0x%02X). " , out - > packaged_header - > content_meta_type , content_meta_type ) ;
2020-10-01 07:17:59 +01:00
goto end ;
}
2022-07-05 02:04:28 +01:00
2023-10-12 10:24:03 +01:00
if ( out - > packaged_header - > content_meta_platform > = ContentMetaPlatform_Count )
{
LOG_MSG_ERROR ( " Invalid platform! " ) ;
goto end ;
}
2020-10-13 03:46:59 +01:00
if ( ! out - > packaged_header - > content_count & & out - > packaged_header - > content_meta_type ! = NcmContentMetaType_SystemUpdate )
2020-10-01 07:17:59 +01:00
{
2022-07-12 17:34:49 +01:00
LOG_MSG_ERROR ( " Invalid content count! " ) ;
2020-10-01 07:17:59 +01:00
goto end ;
}
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
if ( ( out - > packaged_header - > content_meta_type = = NcmContentMetaType_SystemUpdate & & ! out - > packaged_header - > content_meta_count ) | | \
( out - > packaged_header - > content_meta_type ! = NcmContentMetaType_SystemUpdate & & out - > packaged_header - > content_meta_count ) )
{
2022-07-12 17:34:49 +01:00
LOG_MSG_ERROR ( " Invalid content meta count! " ) ;
2020-10-01 07:17:59 +01:00
goto end ;
}
2022-07-05 02:04:28 +01:00
2020-10-02 10:53:58 +01:00
/* Save pointer to extended header. */
2020-10-01 07:17:59 +01:00
if ( out - > packaged_header - > extended_header_size )
{
out - > extended_header = ( out - > raw_data + cur_offset ) ;
cur_offset + = out - > packaged_header - > extended_header_size ;
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
switch ( out - > packaged_header - > content_meta_type )
{
case NcmContentMetaType_SystemUpdate :
invalid_ext_header_size = ( out - > packaged_header - > extended_header_size ! = ( u16 ) sizeof ( ContentMetaSystemUpdateMetaExtendedHeader ) ) ;
out - > extended_data_size = ( ! invalid_ext_header_size ? ( ( ContentMetaSystemUpdateMetaExtendedHeader * ) out - > extended_header ) - > extended_data_size : 0 ) ;
invalid_ext_data_size = ( out - > extended_data_size < = sizeof ( ContentMetaSystemUpdateMetaExtendedDataHeader ) ) ;
break ;
case NcmContentMetaType_Application :
invalid_ext_header_size = ( out - > packaged_header - > extended_header_size ! = ( u16 ) sizeof ( ContentMetaApplicationMetaExtendedHeader ) ) ;
break ;
case NcmContentMetaType_Patch :
invalid_ext_header_size = ( out - > packaged_header - > extended_header_size ! = ( u16 ) sizeof ( ContentMetaPatchMetaExtendedHeader ) ) ;
out - > extended_data_size = ( ! invalid_ext_header_size ? ( ( ContentMetaPatchMetaExtendedHeader * ) out - > extended_header ) - > extended_data_size : 0 ) ;
invalid_ext_data_size = ( out - > extended_data_size < = sizeof ( ContentMetaPatchMetaExtendedDataHeader ) ) ;
break ;
case NcmContentMetaType_AddOnContent :
Preliminar 15.x support.
This commit uses my yet unmerged libnx PR to update ncm_types.h.
PoC code hasn't been updated yet, so proper support for DLC updates will arrive at a later time.
Note to self: implement a way to provide access to loaded DataPatch TitleInfo entries (linked list hell).
* bktr: renamed bktrBucketInitializeSubStorageReadParams to bktrInitializeSubStorageReadParams to avoid redundancy, added debug code to dump BucketInfo and BucketTree tables if BucketTree storage initialization fails.
* cnmt: updated ContentMetaAddOnContentMetaExtendedHeader struct to its 15.x equivalent, added ContentMetaLegacyAddOnContentMetaExtendedHeader struct, added ContentMetaDataPatchMetaExtendedHeader struct, updated the cnmtGetRequiredTitleId and cnmtGetRequiredTitleVersion functions to support DataPatch titles, updated cnmtInitializeContext to support both the new AddOnContent extended header and DataPatch titles, added debug code to dump the whole CNMT if context initialization fails, updated cnmtGenerateAuthoringToolXml to support DataPatch titles.
* keys: updated block hashes to match 15.x keyset, use case-insensitive comparison while looking for entry names in keysReadKeysFromFile, make sure the eticket_rsa_kek is non-zero before proceeding in keysGetDecryptedEticketRsaDeviceKey.
* nca: updated NcaKeyGeneration enum, added reminder about updating NcaSignatureKeyGeneration if necessary, replaced ncaFsSectionCheckHashRegionAccess with ncaFsSectionCheckPlaintextHashRegionAccess, removed all extents checks on Patch RomFS and sparse sections, updated ncaGetFsSectionTypeName to reflect if a FS section holds a sparse layer or not.
* nca_storage: updated ncaStorageInitializeContext to avoid initializing a compressed storage if a sparse layer is also used (fixes issues with Them's Fightin' Herds), updated ncaStorageSetPatchOriginalSubStorage to enforce the presence of a compressed storage in a patch if the base FS holds a compressed storage.
* npdm: added reminder about updating NpdmSignatureKeyGeneration if necessary, updated NpdmFsAccessControlFlags enum, updated NpdmAccessibility enum, updated NpdmSystemCallId enum, fixed typos.
* title: updated all relevant functions that deal with NcmContentMetaType values to also handle DataPatch titles, added functions to handle DataPatchId values, removed titleConvertNcmContentSizeToU64 and titleConvertU64ToNcmContentSize functions in favor of ncmContentInfoSizeToU64 and ncmU64ToContentInfoSize from my unmerged libnx PR, updated internal arrays to match 15.x changes, renamed titleOrphanTitleInfoSortFunction to titleInfoEntrySortFunction and updated it to also sort entries by version and storage ID, updated titleGenerateTitleInfoEntriesForTitleStorage to sort TitleInfo entries, simplified titleDuplicateTitleInfo a bit by using macros.
2022-10-23 15:44:47 +01:00
invalid_ext_header_size = ( out - > packaged_header - > extended_header_size ! = ( u16 ) sizeof ( ContentMetaAddOnContentMetaExtendedHeader ) & & \
out - > packaged_header - > extended_header_size ! = ( u16 ) sizeof ( ContentMetaLegacyAddOnContentMetaExtendedHeader ) ) ;
2020-10-01 07:17:59 +01:00
break ;
case NcmContentMetaType_Delta :
invalid_ext_header_size = ( out - > packaged_header - > extended_header_size ! = ( u16 ) sizeof ( ContentMetaDeltaMetaExtendedHeader ) ) ;
out - > extended_data_size = ( ! invalid_ext_header_size ? ( ( ContentMetaDeltaMetaExtendedHeader * ) out - > extended_header ) - > extended_data_size : 0 ) ;
invalid_ext_data_size = ( out - > extended_data_size < = sizeof ( ContentMetaDeltaMetaExtendedDataHeader ) ) ;
break ;
Preliminar 15.x support.
This commit uses my yet unmerged libnx PR to update ncm_types.h.
PoC code hasn't been updated yet, so proper support for DLC updates will arrive at a later time.
Note to self: implement a way to provide access to loaded DataPatch TitleInfo entries (linked list hell).
* bktr: renamed bktrBucketInitializeSubStorageReadParams to bktrInitializeSubStorageReadParams to avoid redundancy, added debug code to dump BucketInfo and BucketTree tables if BucketTree storage initialization fails.
* cnmt: updated ContentMetaAddOnContentMetaExtendedHeader struct to its 15.x equivalent, added ContentMetaLegacyAddOnContentMetaExtendedHeader struct, added ContentMetaDataPatchMetaExtendedHeader struct, updated the cnmtGetRequiredTitleId and cnmtGetRequiredTitleVersion functions to support DataPatch titles, updated cnmtInitializeContext to support both the new AddOnContent extended header and DataPatch titles, added debug code to dump the whole CNMT if context initialization fails, updated cnmtGenerateAuthoringToolXml to support DataPatch titles.
* keys: updated block hashes to match 15.x keyset, use case-insensitive comparison while looking for entry names in keysReadKeysFromFile, make sure the eticket_rsa_kek is non-zero before proceeding in keysGetDecryptedEticketRsaDeviceKey.
* nca: updated NcaKeyGeneration enum, added reminder about updating NcaSignatureKeyGeneration if necessary, replaced ncaFsSectionCheckHashRegionAccess with ncaFsSectionCheckPlaintextHashRegionAccess, removed all extents checks on Patch RomFS and sparse sections, updated ncaGetFsSectionTypeName to reflect if a FS section holds a sparse layer or not.
* nca_storage: updated ncaStorageInitializeContext to avoid initializing a compressed storage if a sparse layer is also used (fixes issues with Them's Fightin' Herds), updated ncaStorageSetPatchOriginalSubStorage to enforce the presence of a compressed storage in a patch if the base FS holds a compressed storage.
* npdm: added reminder about updating NpdmSignatureKeyGeneration if necessary, updated NpdmFsAccessControlFlags enum, updated NpdmAccessibility enum, updated NpdmSystemCallId enum, fixed typos.
* title: updated all relevant functions that deal with NcmContentMetaType values to also handle DataPatch titles, added functions to handle DataPatchId values, removed titleConvertNcmContentSizeToU64 and titleConvertU64ToNcmContentSize functions in favor of ncmContentInfoSizeToU64 and ncmU64ToContentInfoSize from my unmerged libnx PR, updated internal arrays to match 15.x changes, renamed titleOrphanTitleInfoSortFunction to titleInfoEntrySortFunction and updated it to also sort entries by version and storage ID, updated titleGenerateTitleInfoEntriesForTitleStorage to sort TitleInfo entries, simplified titleDuplicateTitleInfo a bit by using macros.
2022-10-23 15:44:47 +01:00
case NcmContentMetaType_DataPatch :
invalid_ext_header_size = ( out - > packaged_header - > extended_header_size ! = ( u16 ) sizeof ( ContentMetaDataPatchMetaExtendedHeader ) ) ;
out - > extended_data_size = ( ! invalid_ext_header_size ? ( ( ContentMetaDataPatchMetaExtendedHeader * ) out - > extended_header ) - > extended_data_size : 0 ) ;
2023-03-29 22:14:21 +01:00
invalid_ext_data_size = ( out - > extended_data_size < = sizeof ( ContentMetaPatchMetaExtendedDataHeader ) ) ;
Preliminar 15.x support.
This commit uses my yet unmerged libnx PR to update ncm_types.h.
PoC code hasn't been updated yet, so proper support for DLC updates will arrive at a later time.
Note to self: implement a way to provide access to loaded DataPatch TitleInfo entries (linked list hell).
* bktr: renamed bktrBucketInitializeSubStorageReadParams to bktrInitializeSubStorageReadParams to avoid redundancy, added debug code to dump BucketInfo and BucketTree tables if BucketTree storage initialization fails.
* cnmt: updated ContentMetaAddOnContentMetaExtendedHeader struct to its 15.x equivalent, added ContentMetaLegacyAddOnContentMetaExtendedHeader struct, added ContentMetaDataPatchMetaExtendedHeader struct, updated the cnmtGetRequiredTitleId and cnmtGetRequiredTitleVersion functions to support DataPatch titles, updated cnmtInitializeContext to support both the new AddOnContent extended header and DataPatch titles, added debug code to dump the whole CNMT if context initialization fails, updated cnmtGenerateAuthoringToolXml to support DataPatch titles.
* keys: updated block hashes to match 15.x keyset, use case-insensitive comparison while looking for entry names in keysReadKeysFromFile, make sure the eticket_rsa_kek is non-zero before proceeding in keysGetDecryptedEticketRsaDeviceKey.
* nca: updated NcaKeyGeneration enum, added reminder about updating NcaSignatureKeyGeneration if necessary, replaced ncaFsSectionCheckHashRegionAccess with ncaFsSectionCheckPlaintextHashRegionAccess, removed all extents checks on Patch RomFS and sparse sections, updated ncaGetFsSectionTypeName to reflect if a FS section holds a sparse layer or not.
* nca_storage: updated ncaStorageInitializeContext to avoid initializing a compressed storage if a sparse layer is also used (fixes issues with Them's Fightin' Herds), updated ncaStorageSetPatchOriginalSubStorage to enforce the presence of a compressed storage in a patch if the base FS holds a compressed storage.
* npdm: added reminder about updating NpdmSignatureKeyGeneration if necessary, updated NpdmFsAccessControlFlags enum, updated NpdmAccessibility enum, updated NpdmSystemCallId enum, fixed typos.
* title: updated all relevant functions that deal with NcmContentMetaType values to also handle DataPatch titles, added functions to handle DataPatchId values, removed titleConvertNcmContentSizeToU64 and titleConvertU64ToNcmContentSize functions in favor of ncmContentInfoSizeToU64 and ncmU64ToContentInfoSize from my unmerged libnx PR, updated internal arrays to match 15.x changes, renamed titleOrphanTitleInfoSortFunction to titleInfoEntrySortFunction and updated it to also sort entries by version and storage ID, updated titleGenerateTitleInfoEntriesForTitleStorage to sort TitleInfo entries, simplified titleDuplicateTitleInfo a bit by using macros.
2022-10-23 15:44:47 +01:00
break ;
2020-10-01 07:17:59 +01:00
default :
Preliminar 15.x support.
This commit uses my yet unmerged libnx PR to update ncm_types.h.
PoC code hasn't been updated yet, so proper support for DLC updates will arrive at a later time.
Note to self: implement a way to provide access to loaded DataPatch TitleInfo entries (linked list hell).
* bktr: renamed bktrBucketInitializeSubStorageReadParams to bktrInitializeSubStorageReadParams to avoid redundancy, added debug code to dump BucketInfo and BucketTree tables if BucketTree storage initialization fails.
* cnmt: updated ContentMetaAddOnContentMetaExtendedHeader struct to its 15.x equivalent, added ContentMetaLegacyAddOnContentMetaExtendedHeader struct, added ContentMetaDataPatchMetaExtendedHeader struct, updated the cnmtGetRequiredTitleId and cnmtGetRequiredTitleVersion functions to support DataPatch titles, updated cnmtInitializeContext to support both the new AddOnContent extended header and DataPatch titles, added debug code to dump the whole CNMT if context initialization fails, updated cnmtGenerateAuthoringToolXml to support DataPatch titles.
* keys: updated block hashes to match 15.x keyset, use case-insensitive comparison while looking for entry names in keysReadKeysFromFile, make sure the eticket_rsa_kek is non-zero before proceeding in keysGetDecryptedEticketRsaDeviceKey.
* nca: updated NcaKeyGeneration enum, added reminder about updating NcaSignatureKeyGeneration if necessary, replaced ncaFsSectionCheckHashRegionAccess with ncaFsSectionCheckPlaintextHashRegionAccess, removed all extents checks on Patch RomFS and sparse sections, updated ncaGetFsSectionTypeName to reflect if a FS section holds a sparse layer or not.
* nca_storage: updated ncaStorageInitializeContext to avoid initializing a compressed storage if a sparse layer is also used (fixes issues with Them's Fightin' Herds), updated ncaStorageSetPatchOriginalSubStorage to enforce the presence of a compressed storage in a patch if the base FS holds a compressed storage.
* npdm: added reminder about updating NpdmSignatureKeyGeneration if necessary, updated NpdmFsAccessControlFlags enum, updated NpdmAccessibility enum, updated NpdmSystemCallId enum, fixed typos.
* title: updated all relevant functions that deal with NcmContentMetaType values to also handle DataPatch titles, added functions to handle DataPatchId values, removed titleConvertNcmContentSizeToU64 and titleConvertU64ToNcmContentSize functions in favor of ncmContentInfoSizeToU64 and ncmU64ToContentInfoSize from my unmerged libnx PR, updated internal arrays to match 15.x changes, renamed titleOrphanTitleInfoSortFunction to titleInfoEntrySortFunction and updated it to also sort entries by version and storage ID, updated titleGenerateTitleInfoEntriesForTitleStorage to sort TitleInfo entries, simplified titleDuplicateTitleInfo a bit by using macros.
2022-10-23 15:44:47 +01:00
invalid_ext_header_size = ( out - > packaged_header - > extended_header_size ! = 0 ) ;
2020-10-01 07:17:59 +01:00
break ;
}
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
if ( invalid_ext_header_size )
{
2022-07-12 17:34:49 +01:00
LOG_MSG_ERROR ( " Invalid extended header size! " ) ;
2020-10-01 07:17:59 +01:00
goto end ;
}
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
if ( invalid_ext_data_size )
{
2022-07-12 17:34:49 +01:00
LOG_DATA_ERROR ( out - > extended_header , out - > packaged_header - > extended_header_size , " Invalid extended data size! CNMT Extended Header dump: " ) ;
2020-10-01 07:17:59 +01:00
goto end ;
}
}
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
/* Save pointer to packaged content infos. */
2020-10-13 03:46:59 +01:00
if ( out - > packaged_header - > content_count )
{
out - > packaged_content_info = ( NcmPackagedContentInfo * ) ( out - > raw_data + cur_offset ) ;
cur_offset + = ( out - > packaged_header - > content_count * sizeof ( NcmPackagedContentInfo ) ) ;
}
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
/* Save pointer to content meta infos. */
if ( out - > packaged_header - > content_meta_count )
{
out - > content_meta_info = ( NcmContentMetaInfo * ) ( out - > raw_data + cur_offset ) ;
cur_offset + = ( out - > packaged_header - > content_meta_count * sizeof ( NcmContentMetaInfo ) ) ;
}
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
/* Save pointer to the extended data block. */
if ( out - > extended_data_size )
{
out - > extended_data = ( out - > raw_data + cur_offset ) ;
cur_offset + = out - > extended_data_size ;
}
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
/* Save pointer to digest. */
out - > digest = ( out - > raw_data + cur_offset ) ;
cur_offset + = CNMT_DIGEST_SIZE ;
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
/* Safety check: verify raw CNMT size. */
if ( cur_offset ! = out - > raw_data_size )
{
2022-07-12 17:34:49 +01:00
LOG_MSG_ERROR ( " Raw CNMT size mismatch! (0x%lX != 0x%lX). " , cur_offset , out - > raw_data_size ) ;
2020-10-01 07:17:59 +01:00
goto end ;
}
2022-07-05 02:04:28 +01:00
2020-10-21 05:27:48 +01:00
/* Update output context. */
out - > nca_ctx = nca_ctx ;
2022-07-05 02:04:28 +01:00
2020-10-21 05:27:48 +01:00
/* Update content type context info in NCA context. */
nca_ctx - > content_type_ctx = out ;
nca_ctx - > content_type_ctx_patch = false ;
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
success = true ;
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
end :
2021-03-07 23:22:49 +00:00
if ( ! success )
{
Preliminar 15.x support.
This commit uses my yet unmerged libnx PR to update ncm_types.h.
PoC code hasn't been updated yet, so proper support for DLC updates will arrive at a later time.
Note to self: implement a way to provide access to loaded DataPatch TitleInfo entries (linked list hell).
* bktr: renamed bktrBucketInitializeSubStorageReadParams to bktrInitializeSubStorageReadParams to avoid redundancy, added debug code to dump BucketInfo and BucketTree tables if BucketTree storage initialization fails.
* cnmt: updated ContentMetaAddOnContentMetaExtendedHeader struct to its 15.x equivalent, added ContentMetaLegacyAddOnContentMetaExtendedHeader struct, added ContentMetaDataPatchMetaExtendedHeader struct, updated the cnmtGetRequiredTitleId and cnmtGetRequiredTitleVersion functions to support DataPatch titles, updated cnmtInitializeContext to support both the new AddOnContent extended header and DataPatch titles, added debug code to dump the whole CNMT if context initialization fails, updated cnmtGenerateAuthoringToolXml to support DataPatch titles.
* keys: updated block hashes to match 15.x keyset, use case-insensitive comparison while looking for entry names in keysReadKeysFromFile, make sure the eticket_rsa_kek is non-zero before proceeding in keysGetDecryptedEticketRsaDeviceKey.
* nca: updated NcaKeyGeneration enum, added reminder about updating NcaSignatureKeyGeneration if necessary, replaced ncaFsSectionCheckHashRegionAccess with ncaFsSectionCheckPlaintextHashRegionAccess, removed all extents checks on Patch RomFS and sparse sections, updated ncaGetFsSectionTypeName to reflect if a FS section holds a sparse layer or not.
* nca_storage: updated ncaStorageInitializeContext to avoid initializing a compressed storage if a sparse layer is also used (fixes issues with Them's Fightin' Herds), updated ncaStorageSetPatchOriginalSubStorage to enforce the presence of a compressed storage in a patch if the base FS holds a compressed storage.
* npdm: added reminder about updating NpdmSignatureKeyGeneration if necessary, updated NpdmFsAccessControlFlags enum, updated NpdmAccessibility enum, updated NpdmSystemCallId enum, fixed typos.
* title: updated all relevant functions that deal with NcmContentMetaType values to also handle DataPatch titles, added functions to handle DataPatchId values, removed titleConvertNcmContentSizeToU64 and titleConvertU64ToNcmContentSize functions in favor of ncmContentInfoSizeToU64 and ncmU64ToContentInfoSize from my unmerged libnx PR, updated internal arrays to match 15.x changes, renamed titleOrphanTitleInfoSortFunction to titleInfoEntrySortFunction and updated it to also sort entries by version and storage ID, updated titleGenerateTitleInfoEntriesForTitleStorage to sort TitleInfo entries, simplified titleDuplicateTitleInfo a bit by using macros.
2022-10-23 15:44:47 +01:00
if ( dump_cnmt ) LOG_DATA_DEBUG ( out - > raw_data , out - > raw_data_size , " Raw CNMT dump: " ) ;
2021-03-07 23:22:49 +00:00
cnmtFreeContext ( out ) ;
}
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
return success ;
}
2023-11-03 01:22:47 +00:00
bool cnmtVerifyContentHash ( ContentMetaContext * cnmt_ctx , NcaContext * nca_ctx , const u8 * hash )
{
if ( ! cnmtIsValidContext ( cnmt_ctx ) | | ! nca_ctx | | ! * ( nca_ctx - > content_id_str ) | | nca_ctx - > content_type > NcmContentType_DeltaFragment | | ! nca_ctx - > content_size | | ! hash )
{
LOG_MSG_ERROR ( " Invalid parameters! " ) ;
return false ;
}
/* Return right away if we're dealing with a Meta NCA. */
if ( nca_ctx - > content_type = = NcmContentType_Meta ) return true ;
NcmPackagedContentInfo * packaged_content_info = NULL ;
bool success = false ;
/* Loop through all of our content info entries. */
for ( u16 i = 0 ; i < cnmt_ctx - > packaged_header - > content_count ; i + + )
{
/* Check if we got a matching content ID. */
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 ;
packaged_content_info = NULL ;
}
if ( ! packaged_content_info )
{
LOG_MSG_ERROR ( " Unable to find CNMT content record for \" %s \" NCA! (title ID %016lX, size 0x%lX, type 0x%02X, ID offset 0x%02X). " , nca_ctx - > content_id_str , \
cnmt_ctx - > packaged_header - > title_id , nca_ctx - > content_size , nca_ctx - > content_type , nca_ctx - > id_offset ) ;
goto end ;
}
/* Verify content hash. */
success = ( memcmp ( packaged_content_info - > hash , hash , SHA256_HASH_SIZE ) = = 0 ) ;
# if LOG_LEVEL <= LOG_LEVEL_ERROR
if ( ! success )
{
char got [ SHA256_HASH_STR_SIZE ] = { 0 } , expected [ SHA256_HASH_STR_SIZE ] = { 0 } ;
utilsGenerateHexString ( got , sizeof ( got ) , hash , SHA256_HASH_SIZE , true ) ;
utilsGenerateHexString ( expected , sizeof ( expected ) , packaged_content_info - > hash , SHA256_HASH_SIZE , true ) ;
LOG_MSG_ERROR ( " Invalid hash for \" %s \" NCA! Got \" %s \" , expected \" %s \" (title ID %016lX, size 0x%lX, type 0x%02X, ID offset 0x%02X). " , nca_ctx - > content_id_str , \
got , expected , cnmt_ctx - > packaged_header - > title_id , nca_ctx - > content_size , nca_ctx - > content_type , nca_ctx - > id_offset ) ;
}
# endif
end :
return success ;
}
2020-10-22 05:38:14 +01:00
bool cnmtUpdateContentInfo ( ContentMetaContext * cnmt_ctx , NcaContext * nca_ctx )
{
if ( ! cnmtIsValidContext ( cnmt_ctx ) | | ! nca_ctx | | ! * ( nca_ctx - > content_id_str ) | | ! * ( nca_ctx - > hash_str ) | | nca_ctx - > content_type > NcmContentType_DeltaFragment | | ! nca_ctx - > content_size )
{
2022-07-12 17:34:49 +01:00
LOG_MSG_ERROR ( " Invalid parameters! " ) ;
2020-10-22 05:38:14 +01:00
return false ;
}
2022-07-05 02:04:28 +01:00
2020-10-22 05:38:14 +01:00
/* Return right away if we're dealing with a Meta NCA. */
if ( nca_ctx - > content_type = = NcmContentType_Meta ) return true ;
2022-07-05 02:04:28 +01:00
2020-10-22 05:38:14 +01:00
bool success = false ;
2022-07-05 02:04:28 +01:00
2020-10-22 05:38:14 +01:00
for ( u16 i = 0 ; i < cnmt_ctx - > packaged_header - > content_count ; i + + )
{
NcmPackagedContentInfo * packaged_content_info = & ( cnmt_ctx - > packaged_content_info [ i ] ) ;
NcmContentInfo * content_info = & ( packaged_content_info - > info ) ;
u64 content_size = 0 ;
2022-07-05 02:04:28 +01:00
Preliminar 15.x support.
This commit uses my yet unmerged libnx PR to update ncm_types.h.
PoC code hasn't been updated yet, so proper support for DLC updates will arrive at a later time.
Note to self: implement a way to provide access to loaded DataPatch TitleInfo entries (linked list hell).
* bktr: renamed bktrBucketInitializeSubStorageReadParams to bktrInitializeSubStorageReadParams to avoid redundancy, added debug code to dump BucketInfo and BucketTree tables if BucketTree storage initialization fails.
* cnmt: updated ContentMetaAddOnContentMetaExtendedHeader struct to its 15.x equivalent, added ContentMetaLegacyAddOnContentMetaExtendedHeader struct, added ContentMetaDataPatchMetaExtendedHeader struct, updated the cnmtGetRequiredTitleId and cnmtGetRequiredTitleVersion functions to support DataPatch titles, updated cnmtInitializeContext to support both the new AddOnContent extended header and DataPatch titles, added debug code to dump the whole CNMT if context initialization fails, updated cnmtGenerateAuthoringToolXml to support DataPatch titles.
* keys: updated block hashes to match 15.x keyset, use case-insensitive comparison while looking for entry names in keysReadKeysFromFile, make sure the eticket_rsa_kek is non-zero before proceeding in keysGetDecryptedEticketRsaDeviceKey.
* nca: updated NcaKeyGeneration enum, added reminder about updating NcaSignatureKeyGeneration if necessary, replaced ncaFsSectionCheckHashRegionAccess with ncaFsSectionCheckPlaintextHashRegionAccess, removed all extents checks on Patch RomFS and sparse sections, updated ncaGetFsSectionTypeName to reflect if a FS section holds a sparse layer or not.
* nca_storage: updated ncaStorageInitializeContext to avoid initializing a compressed storage if a sparse layer is also used (fixes issues with Them's Fightin' Herds), updated ncaStorageSetPatchOriginalSubStorage to enforce the presence of a compressed storage in a patch if the base FS holds a compressed storage.
* npdm: added reminder about updating NpdmSignatureKeyGeneration if necessary, updated NpdmFsAccessControlFlags enum, updated NpdmAccessibility enum, updated NpdmSystemCallId enum, fixed typos.
* title: updated all relevant functions that deal with NcmContentMetaType values to also handle DataPatch titles, added functions to handle DataPatchId values, removed titleConvertNcmContentSizeToU64 and titleConvertU64ToNcmContentSize functions in favor of ncmContentInfoSizeToU64 and ncmU64ToContentInfoSize from my unmerged libnx PR, updated internal arrays to match 15.x changes, renamed titleOrphanTitleInfoSortFunction to titleInfoEntrySortFunction and updated it to also sort entries by version and storage ID, updated titleGenerateTitleInfoEntriesForTitleStorage to sort TitleInfo entries, simplified titleDuplicateTitleInfo a bit by using macros.
2022-10-23 15:44:47 +01:00
ncmContentInfoSizeToU64 ( content_info , & content_size ) ;
2022-07-05 02:04:28 +01:00
2020-10-22 05:38:14 +01:00
if ( content_size = = nca_ctx - > content_size & & content_info - > content_type = = nca_ctx - > content_type & & content_info - > id_offset = = nca_ctx - > id_offset )
{
/* Jackpot. Copy content ID and hash to our raw CNMT. */
memcpy ( packaged_content_info - > hash , nca_ctx - > hash , sizeof ( nca_ctx - > hash ) ) ;
memcpy ( & ( content_info - > content_id ) , & ( nca_ctx - > content_id ) , sizeof ( NcmContentId ) ) ;
2022-07-12 17:34:49 +01:00
LOG_MSG_INFO ( " Updated CNMT content record #%u (title ID %016lX, size 0x%lX, type 0x%02X, ID offset 0x%02X). " , i , cnmt_ctx - > packaged_header - > title_id , content_size , content_info - > content_type , \
content_info - > id_offset ) ;
2020-10-22 05:38:14 +01:00
success = true ;
break ;
}
}
2022-07-05 02:04:28 +01:00
2023-11-03 01:22:47 +00:00
if ( ! success ) LOG_MSG_ERROR ( " Unable to find CNMT content info entry for \" %s \" NCA! (title ID %016lX, size 0x%lX, type 0x%02X, ID offset 0x%02X). " , nca_ctx - > content_id_str , \
2021-03-07 23:22:49 +00:00
cnmt_ctx - > packaged_header - > title_id , nca_ctx - > content_size , nca_ctx - > content_type , nca_ctx - > id_offset ) ;
2022-07-05 02:04:28 +01:00
2020-10-22 05:38:14 +01:00
return success ;
}
bool cnmtGenerateNcaPatch ( ContentMetaContext * cnmt_ctx )
{
if ( ! cnmtIsValidContext ( cnmt_ctx ) )
{
2022-07-12 17:34:49 +01:00
LOG_MSG_ERROR ( " Invalid parameters! " ) ;
2020-10-22 05:38:14 +01:00
return false ;
}
2022-07-05 02:04:28 +01:00
2020-10-22 05:38:14 +01:00
/* Check if we really need to generate this patch. */
u8 cnmt_hash [ SHA256_HASH_SIZE ] = { 0 } ;
sha256CalculateHash ( cnmt_hash , cnmt_ctx - > raw_data , cnmt_ctx - > raw_data_size ) ;
if ( ! memcmp ( cnmt_hash , cnmt_ctx - > raw_data_hash , sizeof ( cnmt_hash ) ) )
{
2022-07-12 17:34:49 +01:00
LOG_MSG_INFO ( " Skipping CNMT patching - no content records have been changed. " ) ;
2020-10-22 05:38:14 +01:00
return true ;
}
2022-07-05 02:04:28 +01:00
2020-10-22 05:38:14 +01:00
/* Generate Partition FS entry patch. */
if ( ! pfsGenerateEntryPatch ( & ( cnmt_ctx - > pfs_ctx ) , cnmt_ctx - > pfs_entry , cnmt_ctx - > raw_data , cnmt_ctx - > raw_data_size , 0 , & ( cnmt_ctx - > nca_patch ) ) )
{
2022-07-12 17:34:49 +01:00
LOG_MSG_ERROR ( " Failed to generate Partition FS entry patch! " ) ;
2020-10-22 05:38:14 +01:00
return false ;
}
2022-07-05 02:04:28 +01:00
2020-10-22 05:38:14 +01:00
/* Update NCA content type context patch status. */
cnmt_ctx - > nca_ctx - > content_type_ctx_patch = true ;
2022-07-05 02:04:28 +01:00
2020-10-22 05:38:14 +01:00
return true ;
}
void cnmtWriteNcaPatch ( ContentMetaContext * cnmt_ctx , void * buf , u64 buf_size , u64 buf_offset )
{
2020-11-08 19:08:30 +00:00
NcaContext * nca_ctx = NULL ;
NcaHierarchicalSha256Patch * nca_patch = ( cnmt_ctx ? & ( cnmt_ctx - > nca_patch ) : NULL ) ;
2022-07-05 02:04:28 +01:00
2020-10-22 05:38:14 +01:00
/* Using cnmtIsValidContext() here would probably take up precious CPU cycles. */
2020-11-08 19:08:30 +00:00
if ( ! nca_patch | | nca_patch - > written | | ! ( nca_ctx = cnmt_ctx - > nca_ctx ) | | nca_ctx - > content_type ! = NcmContentType_Meta | | ! nca_ctx - > content_type_ctx_patch ) return ;
2022-07-05 02:04:28 +01:00
2020-10-28 22:48:46 +00:00
/* Attempt to write Partition FS entry patch. */
2020-11-08 19:08:30 +00:00
pfsWriteEntryPatchToMemoryBuffer ( & ( cnmt_ctx - > pfs_ctx ) , nca_patch , buf , buf_size , buf_offset ) ;
2022-07-05 02:04:28 +01:00
2020-10-22 05:38:14 +01:00
/* Check if we need to update the NCA content type context patch status. */
2020-11-08 19:08:30 +00:00
if ( nca_patch - > written )
2020-10-22 05:38:14 +01:00
{
2020-11-08 19:08:30 +00:00
nca_ctx - > content_type_ctx_patch = false ;
2022-07-12 17:34:49 +01:00
LOG_MSG_INFO ( " CNMT Partition FS entry patch successfully written to NCA \" %s \" ! " , nca_ctx - > content_id_str ) ;
2020-10-22 05:38:14 +01:00
}
}
2020-10-02 10:53:58 +01:00
bool cnmtGenerateAuthoringToolXml ( ContentMetaContext * cnmt_ctx , NcaContext * nca_ctx , u32 nca_ctx_count )
{
2020-10-28 04:30:13 +00:00
if ( ! cnmtIsValidContext ( cnmt_ctx ) | | ! nca_ctx | | ! nca_ctx_count | | nca_ctx_count > ( ( u32 ) cnmt_ctx - > packaged_header - > content_count + 1 ) )
2020-10-02 10:53:58 +01:00
{
2022-07-12 17:34:49 +01:00
LOG_MSG_ERROR ( " Invalid parameters! " ) ;
2020-10-02 10:53:58 +01:00
return false ;
}
2022-07-05 02:04:28 +01:00
2020-10-03 18:09:29 +01:00
u32 i , j ;
2020-10-02 10:53:58 +01:00
char * xml_buf = NULL ;
u64 xml_buf_size = 0 ;
2023-11-03 01:22:47 +00:00
char digest_str [ SHA256_HASH_STR_SIZE ] = { 0 } ;
Preliminar 15.x support.
This commit uses my yet unmerged libnx PR to update ncm_types.h.
PoC code hasn't been updated yet, so proper support for DLC updates will arrive at a later time.
Note to self: implement a way to provide access to loaded DataPatch TitleInfo entries (linked list hell).
* bktr: renamed bktrBucketInitializeSubStorageReadParams to bktrInitializeSubStorageReadParams to avoid redundancy, added debug code to dump BucketInfo and BucketTree tables if BucketTree storage initialization fails.
* cnmt: updated ContentMetaAddOnContentMetaExtendedHeader struct to its 15.x equivalent, added ContentMetaLegacyAddOnContentMetaExtendedHeader struct, added ContentMetaDataPatchMetaExtendedHeader struct, updated the cnmtGetRequiredTitleId and cnmtGetRequiredTitleVersion functions to support DataPatch titles, updated cnmtInitializeContext to support both the new AddOnContent extended header and DataPatch titles, added debug code to dump the whole CNMT if context initialization fails, updated cnmtGenerateAuthoringToolXml to support DataPatch titles.
* keys: updated block hashes to match 15.x keyset, use case-insensitive comparison while looking for entry names in keysReadKeysFromFile, make sure the eticket_rsa_kek is non-zero before proceeding in keysGetDecryptedEticketRsaDeviceKey.
* nca: updated NcaKeyGeneration enum, added reminder about updating NcaSignatureKeyGeneration if necessary, replaced ncaFsSectionCheckHashRegionAccess with ncaFsSectionCheckPlaintextHashRegionAccess, removed all extents checks on Patch RomFS and sparse sections, updated ncaGetFsSectionTypeName to reflect if a FS section holds a sparse layer or not.
* nca_storage: updated ncaStorageInitializeContext to avoid initializing a compressed storage if a sparse layer is also used (fixes issues with Them's Fightin' Herds), updated ncaStorageSetPatchOriginalSubStorage to enforce the presence of a compressed storage in a patch if the base FS holds a compressed storage.
* npdm: added reminder about updating NpdmSignatureKeyGeneration if necessary, updated NpdmFsAccessControlFlags enum, updated NpdmAccessibility enum, updated NpdmSystemCallId enum, fixed typos.
* title: updated all relevant functions that deal with NcmContentMetaType values to also handle DataPatch titles, added functions to handle DataPatchId values, removed titleConvertNcmContentSizeToU64 and titleConvertU64ToNcmContentSize functions in favor of ncmContentInfoSizeToU64 and ncmU64ToContentInfoSize from my unmerged libnx PR, updated internal arrays to match 15.x changes, renamed titleOrphanTitleInfoSortFunction to titleInfoEntrySortFunction and updated it to also sort entries by version and storage ID, updated titleGenerateTitleInfoEntriesForTitleStorage to sort TitleInfo entries, simplified titleDuplicateTitleInfo a bit by using macros.
2022-10-23 15:44:47 +01:00
u8 count = 0 , content_meta_type = cnmt_ctx - > packaged_header - > content_meta_type ;
2020-10-02 10:53:58 +01:00
bool success = false , invalid_nca = false ;
2022-07-05 02:04:28 +01:00
2020-10-02 10:53:58 +01:00
/* Free AuthoringTool-like XML data if needed. */
if ( cnmt_ctx - > authoring_tool_xml ) free ( cnmt_ctx - > authoring_tool_xml ) ;
cnmt_ctx - > authoring_tool_xml = NULL ;
cnmt_ctx - > authoring_tool_xml_size = 0 ;
2022-07-05 02:04:28 +01:00
2022-03-18 16:48:16 +00:00
if ( ! CNMT_ADD_FMT_STR ( " <?xml version= \" 1.0 \" encoding= \" utf-8 \" ?> \n " \
" <ContentMeta> \n " \
" <Type>%s</Type> \n " \
" <Id>0x%016lx</Id> \n " \
" <Version>%u</Version> \n " \
" <ReleaseVersion>%u</ReleaseVersion> \n " \
" <PrivateVersion>%u</PrivateVersion> \n " , \
Preliminar 15.x support.
This commit uses my yet unmerged libnx PR to update ncm_types.h.
PoC code hasn't been updated yet, so proper support for DLC updates will arrive at a later time.
Note to self: implement a way to provide access to loaded DataPatch TitleInfo entries (linked list hell).
* bktr: renamed bktrBucketInitializeSubStorageReadParams to bktrInitializeSubStorageReadParams to avoid redundancy, added debug code to dump BucketInfo and BucketTree tables if BucketTree storage initialization fails.
* cnmt: updated ContentMetaAddOnContentMetaExtendedHeader struct to its 15.x equivalent, added ContentMetaLegacyAddOnContentMetaExtendedHeader struct, added ContentMetaDataPatchMetaExtendedHeader struct, updated the cnmtGetRequiredTitleId and cnmtGetRequiredTitleVersion functions to support DataPatch titles, updated cnmtInitializeContext to support both the new AddOnContent extended header and DataPatch titles, added debug code to dump the whole CNMT if context initialization fails, updated cnmtGenerateAuthoringToolXml to support DataPatch titles.
* keys: updated block hashes to match 15.x keyset, use case-insensitive comparison while looking for entry names in keysReadKeysFromFile, make sure the eticket_rsa_kek is non-zero before proceeding in keysGetDecryptedEticketRsaDeviceKey.
* nca: updated NcaKeyGeneration enum, added reminder about updating NcaSignatureKeyGeneration if necessary, replaced ncaFsSectionCheckHashRegionAccess with ncaFsSectionCheckPlaintextHashRegionAccess, removed all extents checks on Patch RomFS and sparse sections, updated ncaGetFsSectionTypeName to reflect if a FS section holds a sparse layer or not.
* nca_storage: updated ncaStorageInitializeContext to avoid initializing a compressed storage if a sparse layer is also used (fixes issues with Them's Fightin' Herds), updated ncaStorageSetPatchOriginalSubStorage to enforce the presence of a compressed storage in a patch if the base FS holds a compressed storage.
* npdm: added reminder about updating NpdmSignatureKeyGeneration if necessary, updated NpdmFsAccessControlFlags enum, updated NpdmAccessibility enum, updated NpdmSystemCallId enum, fixed typos.
* title: updated all relevant functions that deal with NcmContentMetaType values to also handle DataPatch titles, added functions to handle DataPatchId values, removed titleConvertNcmContentSizeToU64 and titleConvertU64ToNcmContentSize functions in favor of ncmContentInfoSizeToU64 and ncmU64ToContentInfoSize from my unmerged libnx PR, updated internal arrays to match 15.x changes, renamed titleOrphanTitleInfoSortFunction to titleInfoEntrySortFunction and updated it to also sort entries by version and storage ID, updated titleGenerateTitleInfoEntriesForTitleStorage to sort TitleInfo entries, simplified titleDuplicateTitleInfo a bit by using macros.
2022-10-23 15:44:47 +01:00
titleGetNcmContentMetaTypeName ( content_meta_type ) , \
2022-03-18 16:48:16 +00:00
cnmt_ctx - > packaged_header - > title_id , \
cnmt_ctx - > packaged_header - > version . value , \
cnmt_ctx - > packaged_header - > version . application_version . release_ver , \
cnmt_ctx - > packaged_header - > version . application_version . private_ver ) ) goto end ;
2022-07-05 02:04:28 +01:00
2020-10-14 01:15:21 +01:00
/* ContentMetaAttribute. */
for ( i = 0 ; i < ContentMetaAttribute_Count ; i + + )
{
if ( ! ( cnmt_ctx - > packaged_header - > content_meta_attribute & ( u8 ) BIT ( i ) ) ) continue ;
2022-03-18 16:48:16 +00:00
if ( ! CNMT_ADD_FMT_STR ( " <ContentMetaAttribute>%s</ContentMetaAttribute> \n " , g_cnmtAttributeStrings [ i ] ) ) goto end ;
2020-10-14 01:15:21 +01:00
count + + ;
}
2022-07-05 02:04:28 +01:00
2022-03-18 16:48:16 +00:00
if ( ! count & & ! CNMT_ADD_FMT_STR ( " <ContentMetaAttribute /> \n " ) ) goto end ;
2022-07-05 02:04:28 +01:00
2022-03-18 16:48:16 +00:00
/* RequiredDownloadSystemVersion. */
if ( ! CNMT_ADD_FMT_STR ( " <RequiredDownloadSystemVersion>%u</RequiredDownloadSystemVersion> \n " , cnmt_ctx - > packaged_header - > required_download_system_version . value ) ) goto end ;
2022-07-05 02:04:28 +01:00
2022-03-18 16:48:16 +00:00
/* Contents. */
2020-10-02 10:53:58 +01:00
for ( i = 0 ; i < nca_ctx_count ; i + + )
{
2020-10-14 19:58:33 +01:00
NcaContext * cur_nca_ctx = & ( nca_ctx [ i ] ) ;
2022-07-05 02:04:28 +01:00
2020-10-02 10:53:58 +01:00
/* Check if this NCA is really referenced by our CNMT. */
2020-10-14 19:58:33 +01:00
if ( cur_nca_ctx - > content_type ! = NcmContentType_Meta )
2020-10-02 10:53:58 +01:00
{
/* 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 + + )
{
2020-10-14 19:58:33 +01:00
if ( ! memcmp ( cnmt_ctx - > packaged_content_info [ j ] . info . content_id . c , cur_nca_ctx - > content_id . c , 0x10 ) ) break ;
2020-10-02 10:53:58 +01:00
}
2022-07-05 02:04:28 +01:00
2020-10-02 10:53:58 +01:00
invalid_nca = ( j > = cnmt_ctx - > packaged_header - > content_count ) ;
} else {
/* Meta NCAs: quick and dirty pointer comparison because why not. */
2020-10-14 19:58:33 +01:00
invalid_nca = ( cnmt_ctx - > nca_ctx ! = cur_nca_ctx ) ;
2020-10-02 10:53:58 +01:00
}
2022-07-05 02:04:28 +01:00
2020-10-02 10:53:58 +01:00
if ( invalid_nca )
{
2022-07-12 17:34:49 +01:00
LOG_MSG_ERROR ( " NCA \" %s \" isn't referenced by this CNMT! " , cur_nca_ctx - > content_id_str ) ;
2020-10-02 10:53:58 +01:00
goto end ;
}
2022-07-05 02:04:28 +01:00
2022-03-18 16:48:16 +00:00
if ( ! CNMT_ADD_FMT_STR ( " <Content> \n " \
" <Type>%s</Type> \n " \
" <Id>%s</Id> \n " \
" <Size>%lu</Size> \n " \
" <Hash>%s</Hash> \n " \
" <KeyGeneration>%u</KeyGeneration> \n " \
" <IdOffset>%u</IdOffset> \n " \
" </Content> \n " , \
titleGetNcmContentTypeName ( cur_nca_ctx - > content_type ) , \
cur_nca_ctx - > content_id_str , \
cur_nca_ctx - > content_size , \
cur_nca_ctx - > hash_str , \
cur_nca_ctx - > key_generation , \
cur_nca_ctx - > id_offset ) ) goto end ;
2020-10-02 10:53:58 +01:00
}
2022-07-05 02:04:28 +01:00
2023-10-22 23:44:40 +01:00
utilsGenerateHexString ( digest_str , sizeof ( digest_str ) , cnmt_ctx - > digest , CNMT_DIGEST_SIZE , false ) ;
2022-07-05 02:04:28 +01:00
2022-03-18 16:48:16 +00:00
/* ContentMeta, Digest, KeyGenerationMin, KeepGeneration and KeepGenerationSpecified. */
if ( ! CNMT_ADD_FMT_STR ( " <ContentMeta /> \n " \
" <Digest>%s</Digest> \n " \
" <KeyGenerationMin>%u</KeyGenerationMin> \n " \
" <KeepGeneration /> \n " \
" <KeepGenerationSpecified /> \n " , \
digest_str , \
cnmt_ctx - > nca_ctx - > key_generation ) ) goto end ;
2022-07-05 02:04:28 +01:00
Preliminar 15.x support.
This commit uses my yet unmerged libnx PR to update ncm_types.h.
PoC code hasn't been updated yet, so proper support for DLC updates will arrive at a later time.
Note to self: implement a way to provide access to loaded DataPatch TitleInfo entries (linked list hell).
* bktr: renamed bktrBucketInitializeSubStorageReadParams to bktrInitializeSubStorageReadParams to avoid redundancy, added debug code to dump BucketInfo and BucketTree tables if BucketTree storage initialization fails.
* cnmt: updated ContentMetaAddOnContentMetaExtendedHeader struct to its 15.x equivalent, added ContentMetaLegacyAddOnContentMetaExtendedHeader struct, added ContentMetaDataPatchMetaExtendedHeader struct, updated the cnmtGetRequiredTitleId and cnmtGetRequiredTitleVersion functions to support DataPatch titles, updated cnmtInitializeContext to support both the new AddOnContent extended header and DataPatch titles, added debug code to dump the whole CNMT if context initialization fails, updated cnmtGenerateAuthoringToolXml to support DataPatch titles.
* keys: updated block hashes to match 15.x keyset, use case-insensitive comparison while looking for entry names in keysReadKeysFromFile, make sure the eticket_rsa_kek is non-zero before proceeding in keysGetDecryptedEticketRsaDeviceKey.
* nca: updated NcaKeyGeneration enum, added reminder about updating NcaSignatureKeyGeneration if necessary, replaced ncaFsSectionCheckHashRegionAccess with ncaFsSectionCheckPlaintextHashRegionAccess, removed all extents checks on Patch RomFS and sparse sections, updated ncaGetFsSectionTypeName to reflect if a FS section holds a sparse layer or not.
* nca_storage: updated ncaStorageInitializeContext to avoid initializing a compressed storage if a sparse layer is also used (fixes issues with Them's Fightin' Herds), updated ncaStorageSetPatchOriginalSubStorage to enforce the presence of a compressed storage in a patch if the base FS holds a compressed storage.
* npdm: added reminder about updating NpdmSignatureKeyGeneration if necessary, updated NpdmFsAccessControlFlags enum, updated NpdmAccessibility enum, updated NpdmSystemCallId enum, fixed typos.
* title: updated all relevant functions that deal with NcmContentMetaType values to also handle DataPatch titles, added functions to handle DataPatchId values, removed titleConvertNcmContentSizeToU64 and titleConvertU64ToNcmContentSize functions in favor of ncmContentInfoSizeToU64 and ncmU64ToContentInfoSize from my unmerged libnx PR, updated internal arrays to match 15.x changes, renamed titleOrphanTitleInfoSortFunction to titleInfoEntrySortFunction and updated it to also sort entries by version and storage ID, updated titleGenerateTitleInfoEntriesForTitleStorage to sort TitleInfo entries, simplified titleDuplicateTitleInfo a bit by using macros.
2022-10-23 15:44:47 +01:00
/* RequiredSystemVersion (Application, Patch) / RequiredApplicationVersion (AddOnContent, DataPatch). */
/* PatchId (Application) / ApplicationId (Patch, AddOnContent, DataPatch). */
if ( content_meta_type = = NcmContentMetaType_Application | | content_meta_type = = NcmContentMetaType_Patch | | content_meta_type = = NcmContentMetaType_AddOnContent | | \
content_meta_type = = NcmContentMetaType_DataPatch )
2020-10-02 10:53:58 +01:00
{
2020-10-06 16:41:26 +01:00
u32 required_title_version = cnmtGetRequiredTitleVersion ( cnmt_ctx ) ;
Preliminar 15.x support.
This commit uses my yet unmerged libnx PR to update ncm_types.h.
PoC code hasn't been updated yet, so proper support for DLC updates will arrive at a later time.
Note to self: implement a way to provide access to loaded DataPatch TitleInfo entries (linked list hell).
* bktr: renamed bktrBucketInitializeSubStorageReadParams to bktrInitializeSubStorageReadParams to avoid redundancy, added debug code to dump BucketInfo and BucketTree tables if BucketTree storage initialization fails.
* cnmt: updated ContentMetaAddOnContentMetaExtendedHeader struct to its 15.x equivalent, added ContentMetaLegacyAddOnContentMetaExtendedHeader struct, added ContentMetaDataPatchMetaExtendedHeader struct, updated the cnmtGetRequiredTitleId and cnmtGetRequiredTitleVersion functions to support DataPatch titles, updated cnmtInitializeContext to support both the new AddOnContent extended header and DataPatch titles, added debug code to dump the whole CNMT if context initialization fails, updated cnmtGenerateAuthoringToolXml to support DataPatch titles.
* keys: updated block hashes to match 15.x keyset, use case-insensitive comparison while looking for entry names in keysReadKeysFromFile, make sure the eticket_rsa_kek is non-zero before proceeding in keysGetDecryptedEticketRsaDeviceKey.
* nca: updated NcaKeyGeneration enum, added reminder about updating NcaSignatureKeyGeneration if necessary, replaced ncaFsSectionCheckHashRegionAccess with ncaFsSectionCheckPlaintextHashRegionAccess, removed all extents checks on Patch RomFS and sparse sections, updated ncaGetFsSectionTypeName to reflect if a FS section holds a sparse layer or not.
* nca_storage: updated ncaStorageInitializeContext to avoid initializing a compressed storage if a sparse layer is also used (fixes issues with Them's Fightin' Herds), updated ncaStorageSetPatchOriginalSubStorage to enforce the presence of a compressed storage in a patch if the base FS holds a compressed storage.
* npdm: added reminder about updating NpdmSignatureKeyGeneration if necessary, updated NpdmFsAccessControlFlags enum, updated NpdmAccessibility enum, updated NpdmSystemCallId enum, fixed typos.
* title: updated all relevant functions that deal with NcmContentMetaType values to also handle DataPatch titles, added functions to handle DataPatchId values, removed titleConvertNcmContentSizeToU64 and titleConvertU64ToNcmContentSize functions in favor of ncmContentInfoSizeToU64 and ncmU64ToContentInfoSize from my unmerged libnx PR, updated internal arrays to match 15.x changes, renamed titleOrphanTitleInfoSortFunction to titleInfoEntrySortFunction and updated it to also sort entries by version and storage ID, updated titleGenerateTitleInfoEntriesForTitleStorage to sort TitleInfo entries, simplified titleDuplicateTitleInfo a bit by using macros.
2022-10-23 15:44:47 +01:00
const char * required_title_version_str = cnmtGetRequiredTitleVersionString ( content_meta_type ) ;
2022-07-05 02:04:28 +01:00
2020-10-06 16:41:26 +01:00
u64 required_title_id = cnmtGetRequiredTitleId ( cnmt_ctx ) ;
Preliminar 15.x support.
This commit uses my yet unmerged libnx PR to update ncm_types.h.
PoC code hasn't been updated yet, so proper support for DLC updates will arrive at a later time.
Note to self: implement a way to provide access to loaded DataPatch TitleInfo entries (linked list hell).
* bktr: renamed bktrBucketInitializeSubStorageReadParams to bktrInitializeSubStorageReadParams to avoid redundancy, added debug code to dump BucketInfo and BucketTree tables if BucketTree storage initialization fails.
* cnmt: updated ContentMetaAddOnContentMetaExtendedHeader struct to its 15.x equivalent, added ContentMetaLegacyAddOnContentMetaExtendedHeader struct, added ContentMetaDataPatchMetaExtendedHeader struct, updated the cnmtGetRequiredTitleId and cnmtGetRequiredTitleVersion functions to support DataPatch titles, updated cnmtInitializeContext to support both the new AddOnContent extended header and DataPatch titles, added debug code to dump the whole CNMT if context initialization fails, updated cnmtGenerateAuthoringToolXml to support DataPatch titles.
* keys: updated block hashes to match 15.x keyset, use case-insensitive comparison while looking for entry names in keysReadKeysFromFile, make sure the eticket_rsa_kek is non-zero before proceeding in keysGetDecryptedEticketRsaDeviceKey.
* nca: updated NcaKeyGeneration enum, added reminder about updating NcaSignatureKeyGeneration if necessary, replaced ncaFsSectionCheckHashRegionAccess with ncaFsSectionCheckPlaintextHashRegionAccess, removed all extents checks on Patch RomFS and sparse sections, updated ncaGetFsSectionTypeName to reflect if a FS section holds a sparse layer or not.
* nca_storage: updated ncaStorageInitializeContext to avoid initializing a compressed storage if a sparse layer is also used (fixes issues with Them's Fightin' Herds), updated ncaStorageSetPatchOriginalSubStorage to enforce the presence of a compressed storage in a patch if the base FS holds a compressed storage.
* npdm: added reminder about updating NpdmSignatureKeyGeneration if necessary, updated NpdmFsAccessControlFlags enum, updated NpdmAccessibility enum, updated NpdmSystemCallId enum, fixed typos.
* title: updated all relevant functions that deal with NcmContentMetaType values to also handle DataPatch titles, added functions to handle DataPatchId values, removed titleConvertNcmContentSizeToU64 and titleConvertU64ToNcmContentSize functions in favor of ncmContentInfoSizeToU64 and ncmU64ToContentInfoSize from my unmerged libnx PR, updated internal arrays to match 15.x changes, renamed titleOrphanTitleInfoSortFunction to titleInfoEntrySortFunction and updated it to also sort entries by version and storage ID, updated titleGenerateTitleInfoEntriesForTitleStorage to sort TitleInfo entries, simplified titleDuplicateTitleInfo a bit by using macros.
2022-10-23 15:44:47 +01:00
const char * required_title_type_str = cnmtGetRequiredTitleTypeString ( content_meta_type ) ;
2022-07-05 02:04:28 +01:00
2022-03-18 16:48:16 +00:00
if ( ! CNMT_ADD_FMT_STR ( " <%s>%u</%s> \n " \
" <%s>0x%016lx</%s> \n " , \
required_title_version_str , required_title_version , required_title_version_str , \
required_title_type_str , required_title_id , required_title_type_str ) ) goto end ;
2020-10-02 10:53:58 +01:00
}
2022-07-05 02:04:28 +01:00
2022-03-18 16:48:16 +00:00
/* RequiredApplicationVersion (Application). */
Preliminar 15.x support.
This commit uses my yet unmerged libnx PR to update ncm_types.h.
PoC code hasn't been updated yet, so proper support for DLC updates will arrive at a later time.
Note to self: implement a way to provide access to loaded DataPatch TitleInfo entries (linked list hell).
* bktr: renamed bktrBucketInitializeSubStorageReadParams to bktrInitializeSubStorageReadParams to avoid redundancy, added debug code to dump BucketInfo and BucketTree tables if BucketTree storage initialization fails.
* cnmt: updated ContentMetaAddOnContentMetaExtendedHeader struct to its 15.x equivalent, added ContentMetaLegacyAddOnContentMetaExtendedHeader struct, added ContentMetaDataPatchMetaExtendedHeader struct, updated the cnmtGetRequiredTitleId and cnmtGetRequiredTitleVersion functions to support DataPatch titles, updated cnmtInitializeContext to support both the new AddOnContent extended header and DataPatch titles, added debug code to dump the whole CNMT if context initialization fails, updated cnmtGenerateAuthoringToolXml to support DataPatch titles.
* keys: updated block hashes to match 15.x keyset, use case-insensitive comparison while looking for entry names in keysReadKeysFromFile, make sure the eticket_rsa_kek is non-zero before proceeding in keysGetDecryptedEticketRsaDeviceKey.
* nca: updated NcaKeyGeneration enum, added reminder about updating NcaSignatureKeyGeneration if necessary, replaced ncaFsSectionCheckHashRegionAccess with ncaFsSectionCheckPlaintextHashRegionAccess, removed all extents checks on Patch RomFS and sparse sections, updated ncaGetFsSectionTypeName to reflect if a FS section holds a sparse layer or not.
* nca_storage: updated ncaStorageInitializeContext to avoid initializing a compressed storage if a sparse layer is also used (fixes issues with Them's Fightin' Herds), updated ncaStorageSetPatchOriginalSubStorage to enforce the presence of a compressed storage in a patch if the base FS holds a compressed storage.
* npdm: added reminder about updating NpdmSignatureKeyGeneration if necessary, updated NpdmFsAccessControlFlags enum, updated NpdmAccessibility enum, updated NpdmSystemCallId enum, fixed typos.
* title: updated all relevant functions that deal with NcmContentMetaType values to also handle DataPatch titles, added functions to handle DataPatchId values, removed titleConvertNcmContentSizeToU64 and titleConvertU64ToNcmContentSize functions in favor of ncmContentInfoSizeToU64 and ncmU64ToContentInfoSize from my unmerged libnx PR, updated internal arrays to match 15.x changes, renamed titleOrphanTitleInfoSortFunction to titleInfoEntrySortFunction and updated it to also sort entries by version and storage ID, updated titleGenerateTitleInfoEntriesForTitleStorage to sort TitleInfo entries, simplified titleDuplicateTitleInfo a bit by using macros.
2022-10-23 15:44:47 +01:00
if ( content_meta_type = = NcmContentMetaType_Application & & \
! CNMT_ADD_FMT_STR ( " <RequiredApplicationVersion>%u</RequiredApplicationVersion> \n " , \
( ( ContentMetaApplicationMetaExtendedHeader * ) cnmt_ctx - > extended_header ) - > required_application_version . value ) ) goto end ;
/* DataPatchId (AddOnContent). */
if ( content_meta_type = = NcmContentMetaType_AddOnContent & & \
cnmt_ctx - > packaged_header - > extended_header_size = = ( u16 ) sizeof ( ContentMetaAddOnContentMetaExtendedHeader ) & & \
! CNMT_ADD_FMT_STR ( " <DataPatchId>0x%016lx</DataPatchId> \n " , ( ( ContentMetaAddOnContentMetaExtendedHeader * ) cnmt_ctx - > extended_header ) - > data_patch_id ) ) goto end ;
/* DataId (DataPatch). */
if ( content_meta_type = = NcmContentMetaType_DataPatch & & \
! CNMT_ADD_FMT_STR ( " <DataId>0x%016lx</DataId> \n " , ( ( ContentMetaDataPatchMetaExtendedHeader * ) cnmt_ctx - > extended_header ) - > data_id ) ) goto end ;
2022-07-05 02:04:28 +01:00
2022-03-18 16:48:16 +00:00
if ( ! ( success = CNMT_ADD_FMT_STR ( " </ContentMeta> " ) ) ) goto end ;
2022-07-05 02:04:28 +01:00
2020-10-02 10:53:58 +01:00
/* Update CNMT context. */
cnmt_ctx - > authoring_tool_xml = xml_buf ;
cnmt_ctx - > authoring_tool_xml_size = strlen ( xml_buf ) ;
2022-07-05 02:04:28 +01:00
2020-10-02 10:53:58 +01:00
end :
if ( ! success )
{
if ( xml_buf ) free ( xml_buf ) ;
2022-07-12 17:34:49 +01:00
LOG_MSG_ERROR ( " Failed to generate CNMT AuthoringTool XML! " ) ;
2020-10-02 10:53:58 +01:00
}
2022-07-05 02:04:28 +01:00
2020-10-02 10:53:58 +01:00
return success ;
}
2020-10-01 07:17:59 +01:00
static bool cnmtGetContentMetaTypeAndTitleIdFromFileName ( const char * cnmt_filename , size_t cnmt_filename_len , u8 * out_content_meta_type , u64 * out_title_id )
{
if ( ! cnmt_filename | | cnmt_filename_len < CNMT_MINIMUM_FILENAME_LENGTH | | ! out_content_meta_type | | ! out_title_id )
{
2022-07-12 17:34:49 +01:00
LOG_MSG_ERROR ( " Invalid parameters! " ) ;
2020-10-01 07:17:59 +01:00
return false ;
}
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
u8 i = 0 ;
const char * pch1 = NULL , * pch2 = NULL ;
size_t content_meta_type_str_len = 0 ;
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
pch1 = ( const char * ) strstr ( cnmt_filename , " _ " ) ;
pch2 = ( cnmt_filename + cnmt_filename_len - 5 ) ;
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
if ( ! pch1 | | ! ( content_meta_type_str_len = ( pch1 - cnmt_filename ) ) | | ( pch2 - + + pch1 ) ! = 16 )
{
2022-07-12 17:34:49 +01:00
LOG_MSG_ERROR ( " Invalid '.cnmt' filename in Partition FS! ( \" %s \" ). " , cnmt_filename ) ;
2020-10-01 07:17:59 +01:00
return false ;
}
2022-07-05 02:04:28 +01:00
Preliminar 15.x support.
This commit uses my yet unmerged libnx PR to update ncm_types.h.
PoC code hasn't been updated yet, so proper support for DLC updates will arrive at a later time.
Note to self: implement a way to provide access to loaded DataPatch TitleInfo entries (linked list hell).
* bktr: renamed bktrBucketInitializeSubStorageReadParams to bktrInitializeSubStorageReadParams to avoid redundancy, added debug code to dump BucketInfo and BucketTree tables if BucketTree storage initialization fails.
* cnmt: updated ContentMetaAddOnContentMetaExtendedHeader struct to its 15.x equivalent, added ContentMetaLegacyAddOnContentMetaExtendedHeader struct, added ContentMetaDataPatchMetaExtendedHeader struct, updated the cnmtGetRequiredTitleId and cnmtGetRequiredTitleVersion functions to support DataPatch titles, updated cnmtInitializeContext to support both the new AddOnContent extended header and DataPatch titles, added debug code to dump the whole CNMT if context initialization fails, updated cnmtGenerateAuthoringToolXml to support DataPatch titles.
* keys: updated block hashes to match 15.x keyset, use case-insensitive comparison while looking for entry names in keysReadKeysFromFile, make sure the eticket_rsa_kek is non-zero before proceeding in keysGetDecryptedEticketRsaDeviceKey.
* nca: updated NcaKeyGeneration enum, added reminder about updating NcaSignatureKeyGeneration if necessary, replaced ncaFsSectionCheckHashRegionAccess with ncaFsSectionCheckPlaintextHashRegionAccess, removed all extents checks on Patch RomFS and sparse sections, updated ncaGetFsSectionTypeName to reflect if a FS section holds a sparse layer or not.
* nca_storage: updated ncaStorageInitializeContext to avoid initializing a compressed storage if a sparse layer is also used (fixes issues with Them's Fightin' Herds), updated ncaStorageSetPatchOriginalSubStorage to enforce the presence of a compressed storage in a patch if the base FS holds a compressed storage.
* npdm: added reminder about updating NpdmSignatureKeyGeneration if necessary, updated NpdmFsAccessControlFlags enum, updated NpdmAccessibility enum, updated NpdmSystemCallId enum, fixed typos.
* title: updated all relevant functions that deal with NcmContentMetaType values to also handle DataPatch titles, added functions to handle DataPatchId values, removed titleConvertNcmContentSizeToU64 and titleConvertU64ToNcmContentSize functions in favor of ncmContentInfoSizeToU64 and ncmU64ToContentInfoSize from my unmerged libnx PR, updated internal arrays to match 15.x changes, renamed titleOrphanTitleInfoSortFunction to titleInfoEntrySortFunction and updated it to also sort entries by version and storage ID, updated titleGenerateTitleInfoEntriesForTitleStorage to sort TitleInfo entries, simplified titleDuplicateTitleInfo a bit by using macros.
2022-10-23 15:44:47 +01:00
for ( i = NcmContentMetaType_SystemProgram ; i < = NcmContentMetaType_DataPatch ; i + + )
2020-10-01 07:17:59 +01:00
{
2021-03-07 23:22:49 +00:00
/* Dirty loop hack, but whatever. */
2020-10-01 07:17:59 +01:00
if ( i > NcmContentMetaType_BootImagePackageSafe & & i < NcmContentMetaType_Application )
{
i = ( NcmContentMetaType_Application - 1 ) ;
continue ;
}
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
if ( ! strncasecmp ( cnmt_filename , titleGetNcmContentMetaTypeName ( i ) , content_meta_type_str_len ) )
{
* out_content_meta_type = i ;
break ;
}
}
2022-07-05 02:04:28 +01:00
Preliminar 15.x support.
This commit uses my yet unmerged libnx PR to update ncm_types.h.
PoC code hasn't been updated yet, so proper support for DLC updates will arrive at a later time.
Note to self: implement a way to provide access to loaded DataPatch TitleInfo entries (linked list hell).
* bktr: renamed bktrBucketInitializeSubStorageReadParams to bktrInitializeSubStorageReadParams to avoid redundancy, added debug code to dump BucketInfo and BucketTree tables if BucketTree storage initialization fails.
* cnmt: updated ContentMetaAddOnContentMetaExtendedHeader struct to its 15.x equivalent, added ContentMetaLegacyAddOnContentMetaExtendedHeader struct, added ContentMetaDataPatchMetaExtendedHeader struct, updated the cnmtGetRequiredTitleId and cnmtGetRequiredTitleVersion functions to support DataPatch titles, updated cnmtInitializeContext to support both the new AddOnContent extended header and DataPatch titles, added debug code to dump the whole CNMT if context initialization fails, updated cnmtGenerateAuthoringToolXml to support DataPatch titles.
* keys: updated block hashes to match 15.x keyset, use case-insensitive comparison while looking for entry names in keysReadKeysFromFile, make sure the eticket_rsa_kek is non-zero before proceeding in keysGetDecryptedEticketRsaDeviceKey.
* nca: updated NcaKeyGeneration enum, added reminder about updating NcaSignatureKeyGeneration if necessary, replaced ncaFsSectionCheckHashRegionAccess with ncaFsSectionCheckPlaintextHashRegionAccess, removed all extents checks on Patch RomFS and sparse sections, updated ncaGetFsSectionTypeName to reflect if a FS section holds a sparse layer or not.
* nca_storage: updated ncaStorageInitializeContext to avoid initializing a compressed storage if a sparse layer is also used (fixes issues with Them's Fightin' Herds), updated ncaStorageSetPatchOriginalSubStorage to enforce the presence of a compressed storage in a patch if the base FS holds a compressed storage.
* npdm: added reminder about updating NpdmSignatureKeyGeneration if necessary, updated NpdmFsAccessControlFlags enum, updated NpdmAccessibility enum, updated NpdmSystemCallId enum, fixed typos.
* title: updated all relevant functions that deal with NcmContentMetaType values to also handle DataPatch titles, added functions to handle DataPatchId values, removed titleConvertNcmContentSizeToU64 and titleConvertU64ToNcmContentSize functions in favor of ncmContentInfoSizeToU64 and ncmU64ToContentInfoSize from my unmerged libnx PR, updated internal arrays to match 15.x changes, renamed titleOrphanTitleInfoSortFunction to titleInfoEntrySortFunction and updated it to also sort entries by version and storage ID, updated titleGenerateTitleInfoEntriesForTitleStorage to sort TitleInfo entries, simplified titleDuplicateTitleInfo a bit by using macros.
2022-10-23 15:44:47 +01:00
if ( i > NcmContentMetaType_DataPatch )
2020-10-01 07:17:59 +01:00
{
2022-07-12 17:34:49 +01:00
LOG_MSG_ERROR ( " Invalid content meta type \" %.*s \" in '.cnmt' filename! ( \" %s \" ). " , ( int ) content_meta_type_str_len , cnmt_filename , cnmt_filename ) ;
2020-10-01 07:17:59 +01:00
return false ;
}
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
if ( ! ( * out_title_id = strtoull ( pch1 , NULL , 16 ) ) )
{
2022-07-12 17:34:49 +01:00
LOG_MSG_ERROR ( " Invalid title ID in '.cnmt' filename! ( \" %s \" ). " , cnmt_filename ) ;
2020-10-01 07:17:59 +01:00
return false ;
}
2022-07-05 02:04:28 +01:00
2020-10-01 07:17:59 +01:00
return true ;
}
2020-10-02 10:53:58 +01:00
static const char * cnmtGetRequiredTitleVersionString ( u8 content_meta_type )
{
const char * str = NULL ;
2022-07-05 02:04:28 +01:00
2020-10-02 10:53:58 +01:00
switch ( content_meta_type )
{
case NcmContentMetaType_Application :
case NcmContentMetaType_Patch :
str = " RequiredSystemVersion " ;
break ;
case NcmContentMetaType_AddOnContent :
Preliminar 15.x support.
This commit uses my yet unmerged libnx PR to update ncm_types.h.
PoC code hasn't been updated yet, so proper support for DLC updates will arrive at a later time.
Note to self: implement a way to provide access to loaded DataPatch TitleInfo entries (linked list hell).
* bktr: renamed bktrBucketInitializeSubStorageReadParams to bktrInitializeSubStorageReadParams to avoid redundancy, added debug code to dump BucketInfo and BucketTree tables if BucketTree storage initialization fails.
* cnmt: updated ContentMetaAddOnContentMetaExtendedHeader struct to its 15.x equivalent, added ContentMetaLegacyAddOnContentMetaExtendedHeader struct, added ContentMetaDataPatchMetaExtendedHeader struct, updated the cnmtGetRequiredTitleId and cnmtGetRequiredTitleVersion functions to support DataPatch titles, updated cnmtInitializeContext to support both the new AddOnContent extended header and DataPatch titles, added debug code to dump the whole CNMT if context initialization fails, updated cnmtGenerateAuthoringToolXml to support DataPatch titles.
* keys: updated block hashes to match 15.x keyset, use case-insensitive comparison while looking for entry names in keysReadKeysFromFile, make sure the eticket_rsa_kek is non-zero before proceeding in keysGetDecryptedEticketRsaDeviceKey.
* nca: updated NcaKeyGeneration enum, added reminder about updating NcaSignatureKeyGeneration if necessary, replaced ncaFsSectionCheckHashRegionAccess with ncaFsSectionCheckPlaintextHashRegionAccess, removed all extents checks on Patch RomFS and sparse sections, updated ncaGetFsSectionTypeName to reflect if a FS section holds a sparse layer or not.
* nca_storage: updated ncaStorageInitializeContext to avoid initializing a compressed storage if a sparse layer is also used (fixes issues with Them's Fightin' Herds), updated ncaStorageSetPatchOriginalSubStorage to enforce the presence of a compressed storage in a patch if the base FS holds a compressed storage.
* npdm: added reminder about updating NpdmSignatureKeyGeneration if necessary, updated NpdmFsAccessControlFlags enum, updated NpdmAccessibility enum, updated NpdmSystemCallId enum, fixed typos.
* title: updated all relevant functions that deal with NcmContentMetaType values to also handle DataPatch titles, added functions to handle DataPatchId values, removed titleConvertNcmContentSizeToU64 and titleConvertU64ToNcmContentSize functions in favor of ncmContentInfoSizeToU64 and ncmU64ToContentInfoSize from my unmerged libnx PR, updated internal arrays to match 15.x changes, renamed titleOrphanTitleInfoSortFunction to titleInfoEntrySortFunction and updated it to also sort entries by version and storage ID, updated titleGenerateTitleInfoEntriesForTitleStorage to sort TitleInfo entries, simplified titleDuplicateTitleInfo a bit by using macros.
2022-10-23 15:44:47 +01:00
case NcmContentMetaType_DataPatch :
2020-10-02 10:53:58 +01:00
str = " RequiredApplicationVersion " ;
break ;
default :
str = " Unknown " ;
break ;
}
2022-07-05 02:04:28 +01:00
2020-10-02 10:53:58 +01:00
return str ;
}
static const char * cnmtGetRequiredTitleTypeString ( u8 content_meta_type )
{
const char * str = NULL ;
2022-07-05 02:04:28 +01:00
2020-10-02 10:53:58 +01:00
switch ( content_meta_type )
{
case NcmContentMetaType_Application :
str = " PatchId " ;
break ;
case NcmContentMetaType_Patch :
case NcmContentMetaType_AddOnContent :
str = " ApplicationId " ;
break ;
default :
str = " Unknown " ;
break ;
}
2022-07-05 02:04:28 +01:00
2020-10-02 10:53:58 +01:00
return str ;
}