diff --git a/include/core/bktr.h b/include/core/bktr.h index cdffa96..09ec5a5 100644 --- a/include/core/bktr.h +++ b/include/core/bktr.h @@ -53,7 +53,7 @@ extern "C" { /// Used as the header for both BucketTreeOffsetNode and BucketTreeEntryNode. typedef struct { u32 index; ///< BucketTreeOffsetNode / BucketTreeEntryNode index. - u32 count; ///< BucketTreeHeader: BucketTreeEntryNode count. BucketTreeEntryNode: entry count. + u32 count; ///< BucketTreeOffsetNode: BucketTreeEntryNode count. BucketTreeEntryNode: entry count. u64 offset; ///< Usually represents a physical or virtual size. } BucketTreeNodeHeader; @@ -146,7 +146,7 @@ typedef enum { BucketTreeStorageType_Indirect = 0, ///< Uses two substorages: index 0 (points to the base NCA) and index 1 (AesCtrEx storage). ///< All reads within storage index 0 use the calculated physical offsets for data decryption. BucketTreeStorageType_AesCtrEx = 1, ///< Used as storage index 1 for BucketTreeStorageType_Indirect. - BucketTreeStorageType_Compressed = 2, ///< Uses LZ4-compressed sections. + BucketTreeStorageType_Compressed = 2, ///< Uses LZ4-compressed sections. If available, this is always the outmost storage type for any NCA. May be used by all title types. BucketTreeStorageType_Sparse = 3, ///< BucketTreeStorageType_Indirect with a twist. Storage index 0 points to the same NCA, and uses virtual offsets for data decryption. ///< Zero-filled output is used for any reads within storage index 1. BucketTreeStorageType_Count = 4 ///< Total values supported by this enum. @@ -157,11 +157,9 @@ typedef enum { ///< May be used as substorage for all other BucketTreeStorage types. BucketTreeSubStorageType_Indirect = 1, ///< Indirect storage. Only used in patches. May be used as substorage for BucketTreeStorageType_Compressed only. BucketTreeSubStorageType_AesCtrEx = 2, ///< AesCtrEx storage. Only used in patches. Must be used as substorage #1 for BucketTreeStorageType_Indirect. - BucketTreeSubStorageType_Compressed = 3, ///< Compressed storage. If available, this is always the outmost storage type for any NCA. May be used by all title types. - ///< May be used as substorage #0 for BucketTreeStorageType_Indirect only. - BucketTreeSubStorageType_Sparse = 4, ///< Sparse storage with CTR crypto, using virtual offsets as lower CTR IVs. Only used in base applications. + BucketTreeSubStorageType_Sparse = 3, ///< Sparse storage with CTR crypto, using virtual offsets as lower CTR IVs. Only used in base applications. ///< May be used as substorage for BucketTreeStorageType_Compressed or BucketTreeStorageType_Indirect (#0). - BucketTreeSubStorageType_Count = 5 ///< Total values supported by this enum. + BucketTreeSubStorageType_Count = 4 ///< Total values supported by this enum. } BucketTreeSubStorageType; // Forward declaration for BucketTreeSubStorage. @@ -200,9 +198,9 @@ bool bktrInitializeCompressedStorageContext(BucketTreeContext *out, BucketTreeSu /// The storage type from the provided BucketTreeContext may only be BucketTreeStorageType_Indirect, BucketTreeStorageType_AesCtrEx or BucketTreeStorageType_Sparse. bool bktrSetRegularSubStorage(BucketTreeContext *ctx, NcaFsSectionContext *nca_fs_ctx); -/// Sets a substorage with type >= BucketTreeStorageType_Indirect and <= BucketTreeStorageType_Compressed at the provided index using a previously initialized BucketTreeContext. +/// Sets a BucketTreeSubStorage at the provided index within the parent BucketTreeContext using a previously initialized child BucketTreeContext. /// The storage type from the provided parent BucketTreeContext may only be BucketTreeStorageType_Indirect. -/// The storage type from the provided child BucketTreeContext may only be BucketTreeStorageType_AesCtrEx, BucketTreeStorageType_Compressed, BucketTreeStorageType_Sparse. +/// The storage type from the provided child BucketTreeContext may only be BucketTreeStorageType_AesCtrEx (#1) or BucketTreeStorageType_Sparse (#0). bool bktrSetBucketTreeSubStorage(BucketTreeContext *parent_ctx, BucketTreeContext *child_ctx, u8 substorage_index); /// Reads data from a Bucket Tree storage using a previously initialized BucketTreeContext. diff --git a/source/core/bktr.c b/source/core/bktr.c index 25515ca..4de3d0f 100644 --- a/source/core/bktr.c +++ b/source/core/bktr.c @@ -175,7 +175,7 @@ bool bktrInitializeCompressedStorageContext(BucketTreeContext *out, BucketTreeSu if (!out || !bktrIsValidSubStorage(substorage) || substorage->index != 0 || !substorage->nca_fs_ctx->enabled || !substorage->nca_fs_ctx->has_compression_layer || \ substorage->nca_fs_ctx->section_type >= NcaFsSectionType_Invalid || !substorage->nca_fs_ctx->nca_ctx || \ (substorage->nca_fs_ctx->nca_ctx->rights_id_available && !substorage->nca_fs_ctx->nca_ctx->titlekey_retrieved) || \ - substorage->type == BucketTreeSubStorageType_AesCtrEx || substorage->type == BucketTreeSubStorageType_Compressed || substorage->type >= BucketTreeSubStorageType_Count) + substorage->type == BucketTreeSubStorageType_AesCtrEx || substorage->type >= BucketTreeSubStorageType_Count) { LOG_MSG_ERROR("Invalid parameters!"); return false; @@ -208,7 +208,7 @@ bool bktrInitializeCompressedStorageContext(BucketTreeContext *out, BucketTreeSu /* Read Compressed storage table data. */ const u64 compression_table_offset = (nca_fs_ctx->hash_region.size + compressed_bucket->offset); - bktrInitializeSubStorageReadParams(¶ms, compressed_table, compression_table_offset, compressed_bucket->size, 0, 0, false, BucketTreeSubStorageType_Compressed); + bktrInitializeSubStorageReadParams(¶ms, compressed_table, compression_table_offset, compressed_bucket->size, 0, 0, false, BucketTreeStorageType_Compressed); if (!bktrReadSubStorage(substorage, ¶ms)) { @@ -286,10 +286,10 @@ bool bktrSetRegularSubStorage(BucketTreeContext *ctx, NcaFsSectionContext *nca_f bool bktrSetBucketTreeSubStorage(BucketTreeContext *parent_ctx, BucketTreeContext *child_ctx, u8 substorage_index) { if (!bktrIsValidContext(parent_ctx) || !bktrIsValidContext(child_ctx) || substorage_index >= BKTR_MAX_SUBSTORAGE_COUNT || \ - parent_ctx->storage_type != BucketTreeStorageType_Indirect || child_ctx->storage_type < BucketTreeStorageType_AesCtrEx || \ - child_ctx->storage_type > BucketTreeStorageType_Sparse || (child_ctx->storage_type == BucketTreeStorageType_AesCtrEx && (substorage_index != 1 || \ - parent_ctx->nca_fs_ctx != child_ctx->nca_fs_ctx)) || ((child_ctx->storage_type == BucketTreeStorageType_Compressed || \ - child_ctx->storage_type == BucketTreeStorageType_Sparse) && (substorage_index != 0 || parent_ctx->nca_fs_ctx == child_ctx->nca_fs_ctx))) + parent_ctx->storage_type != BucketTreeStorageType_Indirect || (child_ctx->storage_type != BucketTreeStorageType_AesCtrEx && \ + child_ctx->storage_type != BucketTreeStorageType_Sparse) || (child_ctx->storage_type == BucketTreeStorageType_AesCtrEx && (substorage_index != 1 || \ + parent_ctx->nca_fs_ctx != child_ctx->nca_fs_ctx)) || (child_ctx->storage_type == BucketTreeStorageType_Sparse && (substorage_index != 0 || \ + parent_ctx->nca_fs_ctx == child_ctx->nca_fs_ctx))) { LOG_MSG_ERROR("Invalid parameters!"); return false; @@ -301,7 +301,7 @@ bool bktrSetBucketTreeSubStorage(BucketTreeContext *parent_ctx, BucketTreeContex substorage->index = substorage_index; substorage->nca_fs_ctx = child_ctx->nca_fs_ctx; - substorage->type = (child_ctx->storage_type + 1); /* Convert to BucketTreeSubStorageType value. */ + substorage->type = (child_ctx->storage_type == BucketTreeStorageType_AesCtrEx ? BucketTreeSubStorageType_AesCtrEx : BucketTreeSubStorageType_Sparse); substorage->bktr_ctx = child_ctx; return true; @@ -1054,7 +1054,7 @@ static bool bktrReadCompressedStorage(BucketTreeVisitor *visitor, void *out, u64 bool success = false; if (!out || !bktrIsValidSubStorage(&(ctx->substorages[0])) || ctx->substorages[0].type == BucketTreeSubStorageType_AesCtrEx || \ - ctx->substorages[0].type == BucketTreeSubStorageType_Compressed || ctx->substorages[0].type >= BucketTreeSubStorageType_Count || (offset + read_size) > ctx->end_offset) + ctx->substorages[0].type >= BucketTreeSubStorageType_Count || (offset + read_size) > ctx->end_offset) { LOG_MSG_ERROR("Invalid parameters!"); return false; diff --git a/source/core/nca_storage.c b/source/core/nca_storage.c index 9464643..58c91ad 100644 --- a/source/core/nca_storage.c +++ b/source/core/nca_storage.c @@ -58,10 +58,10 @@ bool ncaStorageInitializeContext(NcaStorageContext *out, NcaFsSectionContext *nc out->base_storage_type = NcaStorageBaseStorageType_Sparse; } - /* Check if both Indirect and AesCtrEx layers are available. */ + /* Check if both AesCtrEx and Indirect layers are available. */ if (nca_fs_ctx->section_type == NcaFsSectionType_PatchRomFs) { - /* Initialize AesCtrEx layer. */ + /* Initialize AesCtrEx and Indirect layers. */ if (!ncaStorageInitializeBucketTreeContext(&(out->aes_ctr_ex_storage), nca_fs_ctx, BucketTreeStorageType_AesCtrEx) || \ !ncaStorageInitializeBucketTreeContext(&(out->indirect_storage), nca_fs_ctx, BucketTreeStorageType_Indirect)) goto end;