From de6eb1a7e8f48fdfed7c6cbc5dc12eee9a7aa921 Mon Sep 17 00:00:00 2001 From: Pablo Curiel Date: Mon, 4 Jul 2022 14:30:48 +0200 Subject: [PATCH] romfs: add support for Patch RomFS. Uses the new NCA storage interface. Also implemented ncaStorageGetHashTargetExtents(). --- include/core/nca.h | 4 +- include/core/nca_storage.h | 7 ++- include/core/pfs.h | 3 +- include/core/romfs.h | 40 +++++++++-------- source/core/bfttf.c | 2 +- source/core/bktr.c | 2 +- source/core/legal_info.c | 2 +- source/core/nacp.c | 2 +- source/core/nca.c | 6 +-- source/core/nca_storage.c | 58 +++++++++++++++++++++++- source/core/nxdt_bfsar.c | 2 +- source/core/pfs.c | 4 +- source/core/romfs.c | 92 ++++++++++++++++++++++++-------------- 13 files changed, 158 insertions(+), 66 deletions(-) diff --git a/include/core/nca.h b/include/core/nca.h index ccf0d58..015b553 100644 --- a/include/core/nca.h +++ b/include/core/nca.h @@ -488,10 +488,10 @@ bool ncaInitializeContext(NcaContext *out, u8 storage_id, u8 hfs_partition_type, /// Input offset must be relative to the start of the NCA content file. bool ncaReadContentFile(NcaContext *ctx, void *out, u64 read_size, u64 offset); -/// Retrieves the offset and/or size from the FS section hierarchical hash target layer. +/// Retrieves the FS section's hierarchical hash target layer extents. /// Output offset is relative to the start of the FS section. /// Either 'out_offset' or 'out_size' can be NULL, but at least one of them must be a valid pointer. -bool ncaGetFsSectionHashTargetProperties(NcaFsSectionContext *ctx, u64 *out_offset, u64 *out_size); +bool ncaGetFsSectionHashTargetExtents(NcaFsSectionContext *ctx, u64 *out_offset, u64 *out_size); /// Reads decrypted data from a NCA FS section using an input context. /// Input offset must be relative to the start of the NCA FS section. diff --git a/include/core/nca_storage.h b/include/core/nca_storage.h index 38cd341..1ee0777 100644 --- a/include/core/nca_storage.h +++ b/include/core/nca_storage.h @@ -38,7 +38,7 @@ typedef enum { NcaStorageBaseStorageType_Compressed = 4 } NcaStorageBaseStorageType; -/// Used to perform multi-layer reads within a single NCA FS section. +/// Used to perform multi-layered reads within a single NCA FS section. typedef struct { u8 base_storage_type; ///< NcaStorageBaseStorageType. NcaFsSectionContext *nca_fs_ctx; ///< NCA FS section context used to initialize this context. @@ -55,6 +55,11 @@ bool ncaStorageInitializeContext(NcaStorageContext *out, NcaFsSectionContext *nc /// Needed to perform combined reads between a base NCA and a patch NCA. bool ncaStorageSetPatchOriginalSubStorage(NcaStorageContext *patch_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. +/// Output offset is relative to the start of the NCA FS section. +/// Either 'out_offset' or 'out_size' can be NULL, but at least one of them must be a valid pointer. +bool ncaStorageGetHashTargetExtents(NcaStorageContext *ctx, u64 *out_offset, u64 *out_size); + /// Reads data from the NCA storage using a previously initialized NcaStorageContext. bool ncaStorageRead(NcaStorageContext *ctx, void *out, u64 read_size, u64 offset); diff --git a/include/core/pfs.h b/include/core/pfs.h index e8205ab..b515e1b 100644 --- a/include/core/pfs.h +++ b/include/core/pfs.h @@ -155,7 +155,8 @@ NX_INLINE PartitionFileSystemEntry *pfsGetEntryByName(PartitionFileSystemContext NX_INLINE void pfsWriteEntryPatchToMemoryBuffer(PartitionFileSystemContext *ctx, NcaHierarchicalSha256Patch *patch, void *buf, u64 buf_size, u64 buf_offset) { - if (!ctx || !ncaStorageIsValidContext(&(ctx->storage_ctx)) || ctx->nca_fs_ctx != ctx->storage_ctx.nca_fs_ctx) return; + if (!ctx || !ncaStorageIsValidContext(&(ctx->storage_ctx)) || ctx->nca_fs_ctx != ctx->storage_ctx.nca_fs_ctx || \ + ctx->storage_ctx.base_storage_type != NcaStorageBaseStorageType_Regular) return; ncaWriteHierarchicalSha256PatchToMemoryBuffer((NcaContext*)ctx->nca_fs_ctx->nca_ctx, patch, buf, buf_size, buf_offset); } diff --git a/include/core/romfs.h b/include/core/romfs.h index 1927df2..b89db8f 100644 --- a/include/core/romfs.h +++ b/include/core/romfs.h @@ -107,17 +107,18 @@ typedef struct { NXDT_ASSERT(RomFileSystemFileEntry, 0x20); typedef struct { - NcaStorageContext storage_ctx; ///< Used to read NCA FS section data. - NcaFsSectionContext *nca_fs_ctx; ///< Same as storage_ctx.nca_fs_ctx. Placed here for convenience. - u64 offset; ///< RomFS offset (relative to the start of the NCA FS section). - u64 size; ///< RomFS size. - RomFileSystemHeader header; ///< RomFS header. - u64 dir_table_size; ///< RomFS directory entries table size. - RomFileSystemDirectoryEntry *dir_table; ///< RomFS directory entries table. - u64 file_table_size; ///< RomFS file entries table size. - RomFileSystemFileEntry *file_table; ///< RomFS file entries table. - u64 body_offset; ///< RomFS file data body offset (relative to the start of the RomFS). - u32 cur_dir_offset; ///< Current RomFS directory offset (relative to the start of the directory entries table). Used for RomFS browsing. + bool is_patch; ///< Set to true if this we're dealing with a Patch RomFS. + NcaStorageContext storage_ctx[2]; ///< Used to read NCA FS section data. Index 0: base storage. Index 1: patch storage. + NcaStorageContext *default_storage_ctx; ///< Default NCA storage context. Points to one of the two contexts from 'storage_ctx'. Placed here for convenience. + u64 offset; ///< RomFS offset (relative to the start of the NCA FS section). + u64 size; ///< RomFS size. + RomFileSystemHeader header; ///< RomFS header. + u64 dir_table_size; ///< RomFS directory entries table size. + RomFileSystemDirectoryEntry *dir_table; ///< RomFS directory entries table. + u64 file_table_size; ///< RomFS file entries table size. + RomFileSystemFileEntry *file_table; ///< RomFS file entries table. + u64 body_offset; ///< RomFS file data body offset (relative to the start of the RomFS). + u32 cur_dir_offset; ///< Current RomFS directory offset (relative to the start of the directory entries table). Used for RomFS browsing. } RomFileSystemContext; typedef struct { @@ -133,8 +134,10 @@ typedef enum { RomFileSystemPathIllegalCharReplaceType_KeepAsciiCharsOnly = 2 } RomFileSystemPathIllegalCharReplaceType; -/// Initializes a RomFS context. -bool romfsInitializeContext(RomFileSystemContext *out, NcaFsSectionContext *nca_fs_ctx); +/// Initializes a RomFS or Patch RomFS context. +/// 'base_nca_fs_ctx' must always be provided. +/// 'patch_nca_fs_ctx' shall be NULL if not dealing with a Patch RomFS. +bool romfsInitializeContext(RomFileSystemContext *out, NcaFsSectionContext *base_nca_fs_ctx, NcaFsSectionContext *patch_nca_fs_ctx); /// Reads raw filesystem data using a RomFS context. /// Input offset must be relative to the start of the RomFS. @@ -175,7 +178,8 @@ bool romfsGenerateFileEntryPatch(RomFileSystemContext *ctx, RomFileSystemFileEnt NX_INLINE void romfsFreeContext(RomFileSystemContext *ctx) { if (!ctx) return; - ncaStorageFreeContext(&(ctx->storage_ctx)); + ncaStorageFreeContext(&(ctx->storage_ctx[0])); + ncaStorageFreeContext(&(ctx->storage_ctx[1])); if (ctx->dir_table) free(ctx->dir_table); if (ctx->file_table) free(ctx->file_table); memset(ctx, 0, sizeof(RomFileSystemContext)); @@ -195,11 +199,11 @@ NX_INLINE RomFileSystemFileEntry *romfsGetFileEntryByOffset(RomFileSystemContext NX_INLINE void romfsWriteFileEntryPatchToMemoryBuffer(RomFileSystemContext *ctx, RomFileSystemFileEntryPatch *patch, void *buf, u64 buf_size, u64 buf_offset) { - if (!ctx || !ncaStorageIsValidContext(&(ctx->storage_ctx)) || ctx->nca_fs_ctx != ctx->storage_ctx.nca_fs_ctx || !patch || \ - (!patch->use_old_format_patch && ctx->nca_fs_ctx->section_type == NcaFsSectionType_Nca0RomFs) || \ - (patch->use_old_format_patch && ctx->nca_fs_ctx->section_type != NcaFsSectionType_Nca0RomFs)) return; + if (!ctx || ctx->is_patch || !ncaStorageIsValidContext(ctx->default_storage_ctx) || ctx->default_storage_ctx->base_storage_type != NcaStorageBaseStorageType_Regular || !patch || \ + (!patch->use_old_format_patch && ctx->default_storage_ctx->nca_fs_ctx->section_type == NcaFsSectionType_Nca0RomFs) || \ + (patch->use_old_format_patch && ctx->default_storage_ctx->nca_fs_ctx->section_type != NcaFsSectionType_Nca0RomFs)) return; - NcaContext *nca_ctx = (NcaContext*)ctx->nca_fs_ctx->nca_ctx; + NcaContext *nca_ctx = (NcaContext*)ctx->default_storage_ctx->nca_fs_ctx->nca_ctx; if (patch->use_old_format_patch) { diff --git a/source/core/bfttf.c b/source/core/bfttf.c index 6a75830..4c05ec1 100644 --- a/source/core/bfttf.c +++ b/source/core/bfttf.c @@ -113,7 +113,7 @@ bool bfttfInitialize(void) /* Initialize RomFS context. */ /* This will also free a previous RomFS context, if available. */ - if (!romfsInitializeContext(&romfs_ctx, &(nca_ctx->fs_ctx[0]))) + if (!romfsInitializeContext(&romfs_ctx, &(nca_ctx->fs_ctx[0]), NULL)) { LOG_MSG("Failed to initialize RomFS context for Data NCA from %016lX!", font_info->title_id); continue; diff --git a/source/core/bktr.c b/source/core/bktr.c index 62af187..1374b7e 100644 --- a/source/core/bktr.c +++ b/source/core/bktr.c @@ -439,7 +439,7 @@ static bool bktrReadIndirectStorage(BucketTreeVisitor *visitor, void *out, u64 r if (cur_entry.storage_index == BucketTreeIndirectStorageIndex_Original) { /* Retrieve data from the original data storage. */ - /* This may either be a Regular/Compressed storage from the base NCA (Indirect) or a Regular storage from this very same NCA (Sparse). */ + /* This may either be a Regular/Sparse/Compressed storage from the base NCA (Indirect) or a Regular storage from this very same NCA (Sparse). */ success = bktrReadSubStorage(&(ctx->substorages[0]), ¶ms); if (!success) LOG_MSG("Failed to read 0x%lX-byte long chunk from offset 0x%lX in original data storage!", read_size, data_offset); } else { diff --git a/source/core/legal_info.c b/source/core/legal_info.c index 388e859..a66fced 100644 --- a/source/core/legal_info.c +++ b/source/core/legal_info.c @@ -42,7 +42,7 @@ bool legalInfoInitializeContext(LegalInfoContext *out, NcaContext *nca_ctx) legalInfoFreeContext(out); /* Initialize RomFS context. */ - if (!romfsInitializeContext(&romfs_ctx, &(nca_ctx->fs_ctx[0]))) + if (!romfsInitializeContext(&romfs_ctx, &(nca_ctx->fs_ctx[0]), NULL)) { LOG_MSG("Failed to initialize RomFS context!"); goto end; diff --git a/source/core/nacp.c b/source/core/nacp.c index 7116827..6f71693 100644 --- a/source/core/nacp.c +++ b/source/core/nacp.c @@ -248,7 +248,7 @@ bool nacpInitializeContext(NacpContext *out, NcaContext *nca_ctx) nacpFreeContext(out); /* Initialize RomFS context. */ - if (!romfsInitializeContext(&(out->romfs_ctx), &(nca_ctx->fs_ctx[0]))) + if (!romfsInitializeContext(&(out->romfs_ctx), &(nca_ctx->fs_ctx[0]), NULL)) { LOG_MSG("Failed to initialize RomFS context!"); goto end; diff --git a/source/core/nca.c b/source/core/nca.c index 3d8813d..ff2af63 100644 --- a/source/core/nca.c +++ b/source/core/nca.c @@ -209,7 +209,7 @@ bool ncaReadContentFile(NcaContext *ctx, void *out, u64 read_size, u64 offset) return ret; } -bool ncaGetFsSectionHashTargetProperties(NcaFsSectionContext *ctx, u64 *out_offset, u64 *out_size) +bool ncaGetFsSectionHashTargetExtents(NcaFsSectionContext *ctx, u64 *out_offset, u64 *out_size) { if (!ctx || (!out_offset && !out_size)) { @@ -865,7 +865,7 @@ static bool ncaInitializeFsSectionContext(NcaContext *nca_ctx, u32 section_idx) u64 raw_storage_size = compression_bucket->size; /* Get target hash layer offset. */ - if (!ncaGetFsSectionHashTargetProperties(fs_ctx, &raw_storage_offset, NULL)) + if (!ncaGetFsSectionHashTargetExtents(fs_ctx, &raw_storage_offset, NULL)) { LOG_MSG("Invalid hash type for FS section #%u in \"%s\" (0x%02X). Skipping FS section.", fs_ctx->section_idx, nca_ctx->content_id_str, fs_ctx->hash_type); goto end; @@ -948,7 +948,7 @@ static bool ncaInitializeFsSectionContext(NcaContext *nca_ctx, u32 section_idx) /* Get hash layer region size (offset must always be 0). */ fs_ctx->hash_region.offset = 0; - if (!ncaGetFsSectionHashTargetProperties(fs_ctx, &(fs_ctx->hash_region.size), NULL)) + if (!ncaGetFsSectionHashTargetExtents(fs_ctx, &(fs_ctx->hash_region.size), NULL)) { LOG_MSG("Invalid hash type for FS section #%u in \"%s\" (0x%02X). Skipping FS section.", fs_ctx->section_idx, nca_ctx->content_id_str, fs_ctx->hash_type); goto end; diff --git a/source/core/nca_storage.c b/source/core/nca_storage.c index a497f4f..7b619ca 100644 --- a/source/core/nca_storage.c +++ b/source/core/nca_storage.c @@ -127,7 +127,7 @@ bool ncaStorageSetPatchOriginalSubStorage(NcaStorageContext *patch_ctx, NcaStora bool success = false; - /* Set base storage. */ + /* Set original substorage. */ switch(base_ctx->base_storage_type) { case NcaStorageBaseStorageType_Regular: @@ -148,6 +148,62 @@ bool ncaStorageSetPatchOriginalSubStorage(NcaStorageContext *patch_ctx, NcaStora return success; } +bool ncaStorageGetHashTargetExtents(NcaStorageContext *ctx, u64 *out_offset, u64 *out_size) +{ + if (!ncaStorageIsValidContext(ctx) || (!out_offset && !out_size)) + { + LOG_MSG("Invalid parameters!"); + return false; + } + + u64 hash_target_offset = 0, hash_target_size = 0; + bool success = false; + + /* Get hash target extents from the NCA FS section. */ + if (!ncaGetFsSectionHashTargetExtents(ctx->nca_fs_ctx, &hash_target_offset, &hash_target_size)) + { + LOG_MSG("Failed to retrieve NCA FS section's hash target extents!"); + goto end; + } + + /* Set proper hash target extents. */ + switch(ctx->base_storage_type) + { + case NcaStorageBaseStorageType_Regular: + { + /* Just provide the NCA FS section hash target extents. */ + if (out_offset) *out_offset = hash_target_offset; + if (out_size) *out_size = hash_target_size; + break; + } + case NcaStorageBaseStorageType_Sparse: + case NcaStorageBaseStorageType_Indirect: + { + /* Sparse/Indirect storages encompass the entire virtual section. */ + /* Let's substract the NCA FS section hash target offset from the storage's virtual end offset. */ + BucketTreeContext *bktr_ctx = (ctx->base_storage_type == NcaStorageBaseStorageType_Sparse ? ctx->sparse_storage : ctx->indirect_storage); + if (out_offset) *out_offset = hash_target_offset; + if (out_size) *out_size = (bktr_ctx->end_offset - hash_target_offset); + break; + } + case NcaStorageBaseStorageType_Compressed: + { + /* Compressed sections already reference the hash target section, so there's no need calculate the full size. */ + if (out_offset) *out_offset = 0; + if (out_size) *out_size = ctx->compressed_storage->end_offset; + break; + } + default: + break; + } + + /* Update return value. */ + success = true; + +end: + return success; +} + bool ncaStorageRead(NcaStorageContext *ctx, void *out, u64 read_size, u64 offset) { if (!ncaStorageIsValidContext(ctx) || !out || !read_size) diff --git a/source/core/nxdt_bfsar.c b/source/core/nxdt_bfsar.c index d587eea..a835acd 100644 --- a/source/core/nxdt_bfsar.c +++ b/source/core/nxdt_bfsar.c @@ -113,7 +113,7 @@ bool bfsarInitialize(void) } /* Initialize RomFS context. */ - if (!romfsInitializeContext(&romfs_ctx, &(nca_ctx->fs_ctx[1]))) + if (!romfsInitializeContext(&romfs_ctx, &(nca_ctx->fs_ctx[1]), NULL)) { LOG_MSG("Failed to initialize RomFS context for qlaunch Program NCA!"); break; diff --git a/source/core/pfs.c b/source/core/pfs.c index 09e689e..16ebf83 100644 --- a/source/core/pfs.c +++ b/source/core/pfs.c @@ -57,9 +57,9 @@ bool pfsInitializeContext(PartitionFileSystemContext *out, NcaFsSectionContext * out->nca_fs_ctx = storage_ctx->nca_fs_ctx; /* Get Partition FS offset and size. */ - if (!ncaGetFsSectionHashTargetProperties(nca_fs_ctx, &(out->offset), &(out->size))) + if (!ncaStorageGetHashTargetExtents(storage_ctx, &(out->offset), &(out->size))) { - LOG_MSG("Failed to get target hash layer properties!"); + LOG_MSG("Failed to get target hash layer extents!"); goto end; } diff --git a/source/core/romfs.c b/source/core/romfs.c index b60c5f1..e50c4f0 100644 --- a/source/core/romfs.c +++ b/source/core/romfs.c @@ -27,17 +27,19 @@ static RomFileSystemDirectoryEntry *romfsGetChildDirectoryEntryByName(RomFileSystemContext *ctx, RomFileSystemDirectoryEntry *dir_entry, const char *name); static RomFileSystemFileEntry *romfsGetChildFileEntryByName(RomFileSystemContext *ctx, RomFileSystemDirectoryEntry *dir_entry, const char *name); -bool romfsInitializeContext(RomFileSystemContext *out, NcaFsSectionContext *nca_fs_ctx) +bool romfsInitializeContext(RomFileSystemContext *out, NcaFsSectionContext *base_nca_fs_ctx, NcaFsSectionContext *patch_nca_fs_ctx) { - NcaContext *nca_ctx = NULL; u64 dir_table_offset = 0, file_table_offset = 0; - bool success = false, dump_fs_header = false; + NcaContext *base_nca_ctx = NULL, *patch_nca_ctx = NULL; + bool dump_fs_header = false, is_patch = (patch_nca_fs_ctx != NULL), success = false; - if (!out || !nca_fs_ctx || !nca_fs_ctx->enabled || nca_fs_ctx->has_sparse_layer || !(nca_ctx = (NcaContext*)nca_fs_ctx->nca_ctx) || \ - (nca_ctx->format_version == NcaVersion_Nca0 && (nca_fs_ctx->section_type != NcaFsSectionType_Nca0RomFs || nca_fs_ctx->hash_type != NcaHashType_HierarchicalSha256)) || \ - (nca_ctx->format_version != NcaVersion_Nca0 && (nca_fs_ctx->section_type != NcaFsSectionType_RomFs || \ - (nca_fs_ctx->hash_type != NcaHashType_HierarchicalIntegrity && nca_fs_ctx->hash_type != NcaHashType_HierarchicalIntegritySha3))) || \ - (nca_ctx->rights_id_available && !nca_ctx->titlekey_retrieved)) + if (!out || !base_nca_fs_ctx || !base_nca_fs_ctx->enabled || (base_nca_fs_ctx->has_sparse_layer && !is_patch) || !(base_nca_ctx = (NcaContext*)base_nca_fs_ctx->nca_ctx) || \ + (base_nca_ctx->format_version == NcaVersion_Nca0 && (base_nca_fs_ctx->section_type != NcaFsSectionType_Nca0RomFs || \ + base_nca_fs_ctx->hash_type != NcaHashType_HierarchicalSha256)) || (base_nca_ctx->format_version != NcaVersion_Nca0 && \ + (base_nca_fs_ctx->section_type != NcaFsSectionType_RomFs || (base_nca_fs_ctx->hash_type != NcaHashType_HierarchicalIntegrity && \ + base_nca_fs_ctx->hash_type != NcaHashType_HierarchicalIntegritySha3))) || (base_nca_ctx->rights_id_available && !base_nca_ctx->titlekey_retrieved) || \ + (is_patch && (!patch_nca_fs_ctx->enabled || !(patch_nca_ctx = (NcaContext*)patch_nca_fs_ctx->nca_ctx) || patch_nca_ctx->format_version != base_nca_ctx->format_version || \ + patch_nca_fs_ctx->section_type != NcaFsSectionType_PatchRomFs || (patch_nca_ctx->rights_id_available && !patch_nca_ctx->titlekey_retrieved)))) { LOG_MSG("Invalid parameters!"); return false; @@ -46,32 +48,56 @@ bool romfsInitializeContext(RomFileSystemContext *out, NcaFsSectionContext *nca_ /* Free output context beforehand. */ romfsFreeContext(out); - /* Initialize NCA storage context. */ - NcaStorageContext *storage_ctx = &(out->storage_ctx); - if (!ncaStorageInitializeContext(storage_ctx, nca_fs_ctx)) + NcaStorageContext *base_storage_ctx = &(out->storage_ctx[0]), *patch_storage_ctx = &(out->storage_ctx[1]); + bool is_nca0_romfs = (base_nca_fs_ctx->section_type == NcaFsSectionType_Nca0RomFs); + + /* Initialize base NCA storage context. */ + if (!ncaStorageInitializeContext(base_storage_ctx, base_nca_fs_ctx)) { - LOG_MSG("Failed to initialize NCA storage context!"); + LOG_MSG("Failed to initialize base NCA storage context!"); goto end; } - out->nca_fs_ctx = storage_ctx->nca_fs_ctx; + out->is_patch = is_patch; + + if (is_patch) + { + /* Initialize base NCA storage context. */ + if (!ncaStorageInitializeContext(patch_storage_ctx, patch_nca_fs_ctx)) + { + LOG_MSG("Failed to initialize patch NCA storage context!"); + goto end; + } + + /* Set patch NCA storage original substorage. */ + if (!ncaStorageSetPatchOriginalSubStorage(patch_storage_ctx, base_storage_ctx)) + { + LOG_MSG("Failed to set patch NCA storage context's original substorage!"); + goto end; + } + + /* Set default NCA FS storage context. */ + out->default_storage_ctx = patch_storage_ctx; + } else { + /* Set default NCA FS storage context. */ + out->default_storage_ctx = base_storage_ctx; + } /* Get RomFS offset and size. */ - if (!ncaGetFsSectionHashTargetProperties(nca_fs_ctx, &(out->offset), &(out->size))) + if (!ncaStorageGetHashTargetExtents(out->default_storage_ctx, &(out->offset), &(out->size))) { - LOG_MSG("Failed to get target hash layer properties!"); + LOG_MSG("Failed to get target hash layer extents!"); goto end; } /* Read RomFS header. */ - if (!ncaStorageRead(storage_ctx, &(out->header), sizeof(RomFileSystemHeader), out->offset)) + if (!ncaStorageRead(out->default_storage_ctx, &(out->header), sizeof(RomFileSystemHeader), out->offset)) { LOG_MSG("Failed to read RomFS header!"); goto end; } - if ((nca_fs_ctx->section_type == NcaFsSectionType_Nca0RomFs && out->header.old_format.header_size != ROMFS_OLD_HEADER_SIZE) || \ - (nca_fs_ctx->section_type == NcaFsSectionType_RomFs && out->header.cur_format.header_size != ROMFS_HEADER_SIZE)) + if ((is_nca0_romfs && out->header.old_format.header_size != ROMFS_OLD_HEADER_SIZE) || (!is_nca0_romfs && out->header.cur_format.header_size != ROMFS_HEADER_SIZE)) { LOG_MSG("Invalid RomFS header size!"); dump_fs_header = true; @@ -79,8 +105,8 @@ bool romfsInitializeContext(RomFileSystemContext *out, NcaFsSectionContext *nca_ } /* Read directory entries table. */ - dir_table_offset = (nca_fs_ctx->section_type == NcaFsSectionType_Nca0RomFs ? (u64)out->header.old_format.directory_entry_offset : out->header.cur_format.directory_entry_offset); - out->dir_table_size = (nca_fs_ctx->section_type == NcaFsSectionType_Nca0RomFs ? (u64)out->header.old_format.directory_entry_size : out->header.cur_format.directory_entry_size); + dir_table_offset = (is_nca0_romfs ? (u64)out->header.old_format.directory_entry_offset : out->header.cur_format.directory_entry_offset); + out->dir_table_size = (is_nca0_romfs ? (u64)out->header.old_format.directory_entry_size : out->header.cur_format.directory_entry_size); if (!out->dir_table_size || (dir_table_offset + out->dir_table_size) > out->size) { @@ -96,15 +122,15 @@ bool romfsInitializeContext(RomFileSystemContext *out, NcaFsSectionContext *nca_ goto end; } - if (!ncaStorageRead(storage_ctx, out->dir_table, out->dir_table_size, out->offset + dir_table_offset)) + if (!ncaStorageRead(out->default_storage_ctx, out->dir_table, out->dir_table_size, out->offset + dir_table_offset)) { LOG_MSG("Failed to read RomFS directory entries table!"); goto end; } /* Read file entries table. */ - file_table_offset = (nca_fs_ctx->section_type == NcaFsSectionType_Nca0RomFs ? (u64)out->header.old_format.file_entry_offset : out->header.cur_format.file_entry_offset); - out->file_table_size = (nca_fs_ctx->section_type == NcaFsSectionType_Nca0RomFs ? (u64)out->header.old_format.file_entry_size : out->header.cur_format.file_entry_size); + file_table_offset = (is_nca0_romfs ? (u64)out->header.old_format.file_entry_offset : out->header.cur_format.file_entry_offset); + out->file_table_size = (is_nca0_romfs ? (u64)out->header.old_format.file_entry_size : out->header.cur_format.file_entry_size); if (!out->file_table_size || (file_table_offset + out->file_table_size) > out->size) { @@ -120,14 +146,14 @@ bool romfsInitializeContext(RomFileSystemContext *out, NcaFsSectionContext *nca_ goto end; } - if (!ncaStorageRead(storage_ctx, out->file_table, out->file_table_size, out->offset + file_table_offset)) + if (!ncaStorageRead(out->default_storage_ctx, out->file_table, out->file_table_size, out->offset + file_table_offset)) { LOG_MSG("Failed to read RomFS file entries table!"); goto end; } /* Get file data body offset. */ - out->body_offset = (nca_fs_ctx->section_type == NcaFsSectionType_Nca0RomFs ? (u64)out->header.old_format.body_offset : out->header.cur_format.body_offset); + out->body_offset = (is_nca0_romfs ? (u64)out->header.old_format.body_offset : out->header.cur_format.body_offset); if (out->body_offset >= out->size) { LOG_MSG("Invalid RomFS file data body!"); @@ -151,14 +177,14 @@ end: bool romfsReadFileSystemData(RomFileSystemContext *ctx, void *out, u64 read_size, u64 offset) { - if (!ctx || !ncaStorageIsValidContext(&(ctx->storage_ctx)) || !ctx->size || !out || !read_size || (offset + read_size) > ctx->size) + if (!ctx || !ncaStorageIsValidContext(ctx->default_storage_ctx) || !ctx->size || !out || !read_size || (offset + read_size) > ctx->size) { LOG_MSG("Invalid parameters!"); return false; } /* Read filesystem data. */ - if (!ncaStorageRead(&(ctx->storage_ctx), out, read_size, ctx->offset + offset)) + if (!ncaStorageRead(ctx->default_storage_ctx, out, read_size, ctx->offset + offset)) { LOG_MSG("Failed to read RomFS data!"); return false; @@ -314,8 +340,8 @@ RomFileSystemFileEntry *romfsGetFileEntryByPath(RomFileSystemContext *ctx, const RomFileSystemDirectoryEntry *dir_entry = NULL; NcaContext *nca_ctx = NULL; - if (!ctx || !ctx->file_table || !ctx->file_table_size || !ncaStorageIsValidContext(&(ctx->storage_ctx)) || !(nca_ctx = (NcaContext*)ctx->nca_fs_ctx->nca_ctx) || \ - !path || *path != '/' || (path_len = strlen(path)) <= 1) + if (!ctx || !ctx->file_table || !ctx->file_table_size || !ncaStorageIsValidContext(ctx->default_storage_ctx) || \ + !(nca_ctx = (NcaContext*)ctx->default_storage_ctx->nca_fs_ctx->nca_ctx) || !path || *path != '/' || (path_len = strlen(path)) <= 1) { LOG_MSG("Invalid parameters!"); return NULL; @@ -506,15 +532,15 @@ bool romfsGeneratePathFromFileEntry(RomFileSystemContext *ctx, RomFileSystemFile bool romfsGenerateFileEntryPatch(RomFileSystemContext *ctx, RomFileSystemFileEntry *file_entry, const void *data, u64 data_size, u64 data_offset, RomFileSystemFileEntryPatch *out) { - if (!ctx || !ncaStorageIsValidContext(&(ctx->storage_ctx)) || ctx->storage_ctx.base_storage_type != NcaStorageBaseStorageType_Regular || !ctx->body_offset || \ - (ctx->nca_fs_ctx->section_type != NcaFsSectionType_Nca0RomFs && ctx->nca_fs_ctx->section_type != NcaFsSectionType_RomFs) || !file_entry || \ - !file_entry->size || (file_entry->offset + file_entry->size) > ctx->size || !data || !data_size || (data_offset + data_size) > file_entry->size || !out) + if (!ctx || ctx->is_patch || !ncaStorageIsValidContext(ctx->default_storage_ctx) || ctx->default_storage_ctx->base_storage_type != NcaStorageBaseStorageType_Regular || \ + !ctx->body_offset || (ctx->default_storage_ctx->nca_fs_ctx->section_type != NcaFsSectionType_Nca0RomFs && ctx->default_storage_ctx->nca_fs_ctx->section_type != NcaFsSectionType_RomFs) || \ + !file_entry || !file_entry->size || (file_entry->offset + file_entry->size) > ctx->size || !data || !data_size || (data_offset + data_size) > file_entry->size || !out) { LOG_MSG("Invalid parameters!"); return false; } - NcaFsSectionContext *nca_fs_ctx = ctx->nca_fs_ctx; + NcaFsSectionContext *nca_fs_ctx = ctx->default_storage_ctx->nca_fs_ctx; u64 fs_offset = (ctx->body_offset + file_entry->offset + data_offset); bool success = false;