mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-26 12:12:02 +00:00
Fix Patch RomFS ctx init w/missing base NCA FS.
This bug was introduced in c474435ea8
.
Other changes include:
* nxdt_rw_poc, bktr: minor cosmetic code changes.
* cnmt: add ContentMetaPlatform enum.
This commit is contained in:
parent
bb4608118d
commit
ecaeddf356
7 changed files with 44 additions and 28 deletions
|
@ -934,7 +934,7 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
consoleClear();
|
consoleClear();
|
||||||
consolePrint(APP_TITLE " v" APP_VERSION " (" GIT_REV "). Built on " BUILD_TIMESTAMP ".\n");
|
consolePrint(APP_TITLE " v" APP_VERSION " (" GIT_REV ").\nBuilt on " BUILD_TIMESTAMP ".\n");
|
||||||
consolePrint("______________________________\n\n");
|
consolePrint("______________________________\n\n");
|
||||||
if (cur_menu->parent) consolePrint("press b to go back\n");
|
if (cur_menu->parent) consolePrint("press b to go back\n");
|
||||||
if (g_umsDeviceCount) consolePrint("press x to safely remove all ums devices\n");
|
if (g_umsDeviceCount) consolePrint("press x to safely remove all ums devices\n");
|
||||||
|
|
|
@ -41,6 +41,11 @@ typedef enum {
|
||||||
ContentMetaAttribute_Count = 3 ///< Total values supported by this enum.
|
ContentMetaAttribute_Count = 3 ///< Total values supported by this enum.
|
||||||
} ContentMetaAttribute;
|
} ContentMetaAttribute;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ContentMetaPlatform_Nx = 0,
|
||||||
|
ContentMetaPlatform_Count = 1 ///< Total values supported by this enum.
|
||||||
|
} ContentMetaPlatform;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ContentMetaInstallState_None = 0,
|
ContentMetaInstallState_None = 0,
|
||||||
ContentMetaInstallState_Committed = BIT(0),
|
ContentMetaInstallState_Committed = BIT(0),
|
||||||
|
@ -56,7 +61,7 @@ typedef struct {
|
||||||
u64 title_id;
|
u64 title_id;
|
||||||
Version version;
|
Version version;
|
||||||
u8 content_meta_type; ///< NcmContentMetaType.
|
u8 content_meta_type; ///< NcmContentMetaType.
|
||||||
u8 reserved_1;
|
u8 content_meta_platform; ///< ContentMetaPlatform.
|
||||||
u16 extended_header_size; ///< Must match the size from the extended header struct for this content meta type (SystemUpdate, Application, Patch, AddOnContent, Delta).
|
u16 extended_header_size; ///< Must match the size from the extended header struct for this content meta type (SystemUpdate, Application, Patch, AddOnContent, Delta).
|
||||||
u16 content_count; ///< Determines how many NcmPackagedContentInfo entries are available after the extended header.
|
u16 content_count; ///< Determines how many NcmPackagedContentInfo entries are available after the extended header.
|
||||||
u16 content_meta_count; ///< Determines how many NcmContentMetaInfo entries are available after the NcmPackagedContentInfo entries. Only used for SystemUpdate.
|
u16 content_meta_count; ///< Determines how many NcmContentMetaInfo entries are available after the NcmPackagedContentInfo entries. Only used for SystemUpdate.
|
||||||
|
@ -65,7 +70,7 @@ typedef struct {
|
||||||
u8 content_install_type; ///< NcmContentInstallType.
|
u8 content_install_type; ///< NcmContentInstallType.
|
||||||
u8 install_state; ///< ContentMetaInstallState.
|
u8 install_state; ///< ContentMetaInstallState.
|
||||||
Version required_download_system_version;
|
Version required_download_system_version;
|
||||||
u8 reserved_2[0x4];
|
u8 reserved[0x4];
|
||||||
} ContentMetaPackagedContentMetaHeader;
|
} ContentMetaPackagedContentMetaHeader;
|
||||||
|
|
||||||
NXDT_ASSERT(ContentMetaPackagedContentMetaHeader, 0x20);
|
NXDT_ASSERT(ContentMetaPackagedContentMetaHeader, 0x20);
|
||||||
|
|
|
@ -50,9 +50,8 @@ typedef struct {
|
||||||
} NcaStorageContext;
|
} NcaStorageContext;
|
||||||
|
|
||||||
/// Initializes a NCA storage context using a NCA FS section context, optionally providing a pointer to a base NcaStorageContext.
|
/// Initializes a NCA storage context using a NCA FS section context, optionally providing a pointer to a base NcaStorageContext.
|
||||||
/// 'base_ctx' must be provided if dealing with a patch NCA. One of its storages will be set as the original substorage for the initialized NcaStorageContext's Indirect Storage.
|
/// 'base_ctx' shall be provided if dealing with a patch NCA with available base NCA data. This is needed to perform combined reads between a base NCA and a patch NCA.
|
||||||
/// This is needed to perform combined reads between a base NCA and a patch NCA.
|
/// 'base_ctx' shall be NULL if dealing with a base NCA *or* a patch NCA with missing base NCA data.
|
||||||
/// 'base_ctx' shall be NULL if dealing with a base NCA.
|
|
||||||
bool ncaStorageInitializeContext(NcaStorageContext *out, NcaFsSectionContext *nca_fs_ctx, NcaStorageContext *base_ctx);
|
bool ncaStorageInitializeContext(NcaStorageContext *out, NcaFsSectionContext *nca_fs_ctx, NcaStorageContext *base_ctx);
|
||||||
|
|
||||||
/// Retrieves the underlying NCA FS section's hierarchical hash target layer extents. Virtual extents may be returned, depending on the base storage type.
|
/// Retrieves the underlying NCA FS section's hierarchical hash target layer extents. Virtual extents may be returned, depending on the base storage type.
|
||||||
|
|
|
@ -1138,8 +1138,8 @@ static bool bktrReadCompressedStorage(BucketTreeVisitor *visitor, void *out, u64
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Decompress LZ4 block. */
|
/* Decompress LZ4 block. */
|
||||||
int lz4_res = 0;
|
int lz4_res = LZ4_decompress_safe((char*)read_ptr, (char*)buffer, (int)compressed_data_size, (int)buffer_size);
|
||||||
if ((lz4_res = LZ4_decompress_safe((char*)read_ptr, (char*)buffer, (int)compressed_data_size, (int)buffer_size)) != (int)decompressed_data_size)
|
if (lz4_res != (int)decompressed_data_size)
|
||||||
{
|
{
|
||||||
LOG_MSG_ERROR("Failed to decompress 0x%lX-byte long compressed block! (%d).", compressed_data_size, lz4_res);
|
LOG_MSG_ERROR("Failed to decompress 0x%lX-byte long compressed block! (%d).", compressed_data_size, lz4_res);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
|
|
@ -146,6 +146,12 @@ bool cnmtInitializeContext(ContentMetaContext *out, NcaContext *nca_ctx)
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (out->packaged_header->content_meta_platform >= ContentMetaPlatform_Count)
|
||||||
|
{
|
||||||
|
LOG_MSG_ERROR("Invalid platform!");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
if (!out->packaged_header->content_count && out->packaged_header->content_meta_type != NcmContentMetaType_SystemUpdate)
|
if (!out->packaged_header->content_count && out->packaged_header->content_meta_type != NcmContentMetaType_SystemUpdate)
|
||||||
{
|
{
|
||||||
LOG_MSG_ERROR("Invalid content count!");
|
LOG_MSG_ERROR("Invalid content count!");
|
||||||
|
|
|
@ -25,13 +25,13 @@
|
||||||
/* Function prototypes. */
|
/* Function prototypes. */
|
||||||
|
|
||||||
static bool ncaStorageInitializeBucketTreeContext(BucketTreeContext **out, NcaFsSectionContext *nca_fs_ctx, u8 storage_type);
|
static bool ncaStorageInitializeBucketTreeContext(BucketTreeContext **out, NcaFsSectionContext *nca_fs_ctx, u8 storage_type);
|
||||||
static bool ncaStorageSetPatchOriginalSubStorage(NcaStorageContext *patch_ctx, NcaFsSectionContext *patch_nca_fs_ctx, NcaStorageContext *base_ctx);
|
static bool ncaStorageSetPatchOriginalSubStorage(NcaStorageContext *patch_ctx, NcaStorageContext *base_ctx);
|
||||||
static bool ncaStorageInitializeCompressedStorageBucketTreeContext(NcaStorageContext *out, NcaFsSectionContext *nca_fs_ctx);
|
static bool ncaStorageInitializeCompressedStorageBucketTreeContext(NcaStorageContext *out, NcaFsSectionContext *nca_fs_ctx);
|
||||||
|
|
||||||
bool ncaStorageInitializeContext(NcaStorageContext *out, NcaFsSectionContext *nca_fs_ctx, NcaStorageContext *base_ctx)
|
bool ncaStorageInitializeContext(NcaStorageContext *out, NcaFsSectionContext *nca_fs_ctx, NcaStorageContext *base_ctx)
|
||||||
{
|
{
|
||||||
if (!out || !nca_fs_ctx || !nca_fs_ctx->enabled || (nca_fs_ctx->section_type == NcaFsSectionType_PatchRomFs && \
|
if (!out || !nca_fs_ctx || !nca_fs_ctx->enabled || (nca_fs_ctx->section_type == NcaFsSectionType_PatchRomFs && \
|
||||||
(!nca_fs_ctx->has_patch_indirect_layer || !nca_fs_ctx->has_patch_aes_ctr_ex_layer || nca_fs_ctx->has_sparse_layer || !base_ctx)))
|
(!nca_fs_ctx->has_patch_indirect_layer || !nca_fs_ctx->has_patch_aes_ctr_ex_layer || nca_fs_ctx->has_sparse_layer)))
|
||||||
{
|
{
|
||||||
LOG_MSG_ERROR("Invalid parameters!");
|
LOG_MSG_ERROR("Invalid parameters!");
|
||||||
return false;
|
return false;
|
||||||
|
@ -61,7 +61,7 @@ bool ncaStorageInitializeContext(NcaStorageContext *out, NcaFsSectionContext *nc
|
||||||
/* Check if both Indirect and AesCtrEx layers are available. */
|
/* Check if both Indirect and AesCtrEx layers are available. */
|
||||||
if (nca_fs_ctx->section_type == NcaFsSectionType_PatchRomFs)
|
if (nca_fs_ctx->section_type == NcaFsSectionType_PatchRomFs)
|
||||||
{
|
{
|
||||||
/* Initialize AesCtrEx and Indirect layers. */
|
/* Initialize AesCtrEx layer. */
|
||||||
if (!ncaStorageInitializeBucketTreeContext(&(out->aes_ctr_ex_storage), nca_fs_ctx, BucketTreeStorageType_AesCtrEx) || \
|
if (!ncaStorageInitializeBucketTreeContext(&(out->aes_ctr_ex_storage), nca_fs_ctx, BucketTreeStorageType_AesCtrEx) || \
|
||||||
!ncaStorageInitializeBucketTreeContext(&(out->indirect_storage), nca_fs_ctx, BucketTreeStorageType_Indirect)) goto end;
|
!ncaStorageInitializeBucketTreeContext(&(out->indirect_storage), nca_fs_ctx, BucketTreeStorageType_Indirect)) goto end;
|
||||||
|
|
||||||
|
@ -69,8 +69,8 @@ bool ncaStorageInitializeContext(NcaStorageContext *out, NcaFsSectionContext *nc
|
||||||
if (!bktrSetRegularSubStorage(out->aes_ctr_ex_storage, nca_fs_ctx)) goto end;
|
if (!bktrSetRegularSubStorage(out->aes_ctr_ex_storage, nca_fs_ctx)) goto end;
|
||||||
|
|
||||||
/* Set Indirect layer's substorages (Base + AesCtrEx). */
|
/* Set Indirect layer's substorages (Base + AesCtrEx). */
|
||||||
if (!ncaStorageSetPatchOriginalSubStorage(out, nca_fs_ctx, base_ctx)) goto end;
|
if (!ncaStorageSetPatchOriginalSubStorage(out, base_ctx) || \
|
||||||
if (!bktrSetBucketTreeSubStorage(out->indirect_storage, out->aes_ctr_ex_storage, 1)) goto end;
|
!bktrSetBucketTreeSubStorage(out->indirect_storage, out->aes_ctr_ex_storage, 1)) goto end;
|
||||||
|
|
||||||
/* Update base storage type. */
|
/* Update base storage type. */
|
||||||
out->base_storage_type = NcaStorageBaseStorageType_Indirect;
|
out->base_storage_type = NcaStorageBaseStorageType_Indirect;
|
||||||
|
@ -261,21 +261,27 @@ end:
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ncaStorageSetPatchOriginalSubStorage(NcaStorageContext *patch_ctx, NcaFsSectionContext *patch_nca_fs_ctx, NcaStorageContext *base_ctx)
|
static bool ncaStorageSetPatchOriginalSubStorage(NcaStorageContext *patch_ctx, NcaStorageContext *base_ctx)
|
||||||
{
|
{
|
||||||
|
NcaFsSectionContext *patch_nca_fs_ctx = NULL, *base_nca_fs_ctx = NULL;
|
||||||
NcaContext *patch_nca_ctx = NULL, *base_nca_ctx = NULL;
|
NcaContext *patch_nca_ctx = NULL, *base_nca_ctx = NULL;
|
||||||
|
|
||||||
if (!patch_ctx || !patch_ctx->indirect_storage || !patch_ctx->aes_ctr_ex_storage || !patch_nca_fs_ctx || !ncaStorageIsValidContext(base_ctx) || \
|
bool missing_base_ctx = !ncaStorageIsValidContext(base_ctx);
|
||||||
!(patch_nca_ctx = patch_nca_fs_ctx->nca_ctx) || !(base_nca_ctx = base_ctx->nca_fs_ctx->nca_ctx) || \
|
|
||||||
patch_nca_fs_ctx->section_type != NcaFsSectionType_PatchRomFs || base_ctx->nca_fs_ctx->section_type != NcaFsSectionType_RomFs || \
|
bool success = false;
|
||||||
|
|
||||||
|
if (!patch_ctx || !patch_ctx->indirect_storage || !patch_ctx->aes_ctr_ex_storage || !(patch_nca_fs_ctx = patch_ctx->indirect_storage->nca_fs_ctx) || \
|
||||||
|
patch_nca_fs_ctx->section_type != NcaFsSectionType_PatchRomFs || !(patch_nca_ctx = patch_nca_fs_ctx->nca_ctx) || \
|
||||||
|
(!missing_base_ctx && (!(base_nca_fs_ctx = base_ctx->nca_fs_ctx) || base_nca_fs_ctx->section_type != NcaFsSectionType_RomFs || !(base_nca_ctx = base_nca_fs_ctx->nca_ctx) || \
|
||||||
patch_nca_ctx->header.program_id != base_nca_ctx->header.program_id || patch_nca_ctx->header.content_type != base_nca_ctx->header.content_type || \
|
patch_nca_ctx->header.program_id != base_nca_ctx->header.program_id || patch_nca_ctx->header.content_type != base_nca_ctx->header.content_type || \
|
||||||
patch_nca_ctx->id_offset != base_nca_ctx->id_offset || patch_nca_ctx->title_version.value < base_nca_ctx->title_version.value)
|
patch_nca_ctx->id_offset != base_nca_ctx->id_offset || patch_nca_ctx->title_version.value < base_nca_ctx->title_version.value)))
|
||||||
{
|
{
|
||||||
LOG_MSG_ERROR("Invalid parameters!");
|
LOG_MSG_ERROR("Invalid parameters!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool success = false;
|
/* Return immediately if we passed all patch context checks, but we're missing a base context. */
|
||||||
|
if (missing_base_ctx) return true;
|
||||||
|
|
||||||
/* Set original substorage. */
|
/* Set original substorage. */
|
||||||
switch(base_ctx->base_storage_type)
|
switch(base_ctx->base_storage_type)
|
||||||
|
|
|
@ -66,7 +66,7 @@ bool romfsInitializeContext(RomFileSystemContext *out, NcaFsSectionContext *base
|
||||||
if (patch_nca_fs_ctx)
|
if (patch_nca_fs_ctx)
|
||||||
{
|
{
|
||||||
/* Initialize base NCA storage context. */
|
/* Initialize base NCA storage context. */
|
||||||
if (!ncaStorageInitializeContext(patch_storage_ctx, patch_nca_fs_ctx, base_storage_ctx))
|
if (!ncaStorageInitializeContext(patch_storage_ctx, patch_nca_fs_ctx, missing_base_romfs ? NULL : base_storage_ctx))
|
||||||
{
|
{
|
||||||
LOG_MSG_ERROR("Failed to initialize patch NCA storage context!");
|
LOG_MSG_ERROR("Failed to initialize patch NCA storage context!");
|
||||||
goto end;
|
goto end;
|
||||||
|
|
Loading…
Reference in a new issue