mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-26 12:12:02 +00:00
BKTR rewrite part 2: partially implement BucketTreeVisitor.
This commit is contained in:
parent
29e5af2064
commit
7c38b6847d
2 changed files with 36 additions and 20 deletions
|
@ -156,6 +156,9 @@ typedef struct {
|
||||||
u32 entry_set_count; ///< Number of BucketTreeEntryNode elements available in this storage.
|
u32 entry_set_count; ///< Number of BucketTreeEntryNode elements available in this storage.
|
||||||
u64 start_offset; ///< Virtual storage start offset.
|
u64 start_offset; ///< Virtual storage start offset.
|
||||||
u64 end_offset; ///< Virtual storage end offset.
|
u64 end_offset; ///< Virtual storage end offset.
|
||||||
|
|
||||||
|
// TODO: add sub storage
|
||||||
|
|
||||||
} BucketTreeContext;
|
} BucketTreeContext;
|
||||||
|
|
||||||
/// Initializes a Bucket Tree context using the provided NCA FS section context and a storage
|
/// Initializes a Bucket Tree context using the provided NCA FS section context and a storage
|
||||||
|
|
|
@ -37,6 +37,13 @@ typedef struct {
|
||||||
u32 index;
|
u32 index;
|
||||||
} BucketTreeStorageNode;
|
} BucketTreeStorageNode;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
BucketTreeContext *bktr_ctx;
|
||||||
|
BucketTreeNodeHeader entry_set;
|
||||||
|
u32 entry_index;
|
||||||
|
void *entry;
|
||||||
|
} BucketTreeVisitor;
|
||||||
|
|
||||||
/* Global variables. */
|
/* Global variables. */
|
||||||
|
|
||||||
static const char *g_bktrStorageTypeNames[] = {
|
static const char *g_bktrStorageTypeNames[] = {
|
||||||
|
@ -71,7 +78,7 @@ NX_INLINE const u64 *bktrGetOffsetNodeArray(const BucketTreeOffsetNode *offset_n
|
||||||
NX_INLINE const u64 *bktrGetOffsetNodeBegin(const BucketTreeOffsetNode *offset_node);
|
NX_INLINE const u64 *bktrGetOffsetNodeBegin(const BucketTreeOffsetNode *offset_node);
|
||||||
NX_INLINE const u64 *bktrGetOffsetNodeEnd(const BucketTreeOffsetNode *offset_node);
|
NX_INLINE const u64 *bktrGetOffsetNodeEnd(const BucketTreeOffsetNode *offset_node);
|
||||||
|
|
||||||
static bool bktrFindStorageEntry(BucketTreeContext *ctx, u64 virtual_offset, void **out_entry);
|
static bool bktrFindStorageEntry(BucketTreeContext *ctx, u64 virtual_offset, BucketTreeVisitor *out_visitor);
|
||||||
static bool bktrGetTreeNodeEntryIndex(const u64 *start, const u64 *end, u64 virtual_offset, u32 *out_index);
|
static bool bktrGetTreeNodeEntryIndex(const u64 *start, const u64 *end, u64 virtual_offset, u32 *out_index);
|
||||||
static bool bktrGetEntryNodeEntryIndex(const BucketTreeNodeHeader *node_header, u64 node_offset, u64 entry_size, u64 virtual_offset, u32 *out_index);
|
static bool bktrGetEntryNodeEntryIndex(const BucketTreeNodeHeader *node_header, u64 node_offset, u64 entry_size, u64 virtual_offset, u32 *out_index);
|
||||||
|
|
||||||
|
@ -79,7 +86,7 @@ static bool bktrFindEntrySet(u32 *out_index, u64 virtual_offset, u32 node_index)
|
||||||
static const BucketTreeNodeHeader *bktrGetTreeNodeHeader(BucketTreeContext *ctx, u32 node_index);
|
static const BucketTreeNodeHeader *bktrGetTreeNodeHeader(BucketTreeContext *ctx, u32 node_index);
|
||||||
NX_INLINE u32 bktrGetEntrySetIndex(BucketTreeContext *ctx, u32 node_index, u32 offset_index);
|
NX_INLINE u32 bktrGetEntrySetIndex(BucketTreeContext *ctx, u32 node_index, u32 offset_index);
|
||||||
|
|
||||||
static bool bktrFindEntry(BucketTreeContext *ctx, void **out_entry, u64 virtual_offset, u32 entry_set_index);
|
static bool bktrFindEntry(BucketTreeContext *ctx, BucketTreeVisitor *out_visitor, u64 virtual_offset, u32 entry_set_index);
|
||||||
static const BucketTreeNodeHeader *bktrGetEntryNodeHeader(BucketTreeContext *ctx, u32 entry_set_index);
|
static const BucketTreeNodeHeader *bktrGetEntryNodeHeader(BucketTreeContext *ctx, u32 entry_set_index);
|
||||||
NX_INLINE u64 bktrGetEntryNodeEntryOffset(u64 entry_set_offset, u64 entry_size, u32 entry_index);
|
NX_INLINE u64 bktrGetEntryNodeEntryOffset(u64 entry_set_offset, u64 entry_size, u32 entry_index);
|
||||||
|
|
||||||
|
@ -138,11 +145,11 @@ bool bktrReadStorage(BucketTreeContext *ctx, void *out, u64 read_size, u64 offse
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *storage_entry = NULL;
|
BucketTreeVisitor visitor = {0};
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
/* Find storage entry. */
|
/* Find storage entry. */
|
||||||
if (!bktrFindStorageEntry(ctx, offset, &storage_entry))
|
if (!bktrFindStorageEntry(ctx, offset, &visitor))
|
||||||
{
|
{
|
||||||
LOG_MSG("Unable to find %s storage entry for offset 0x%lX!", bktrGetStorageTypeName(ctx->storage_type), offset);
|
LOG_MSG("Unable to find %s storage entry for offset 0x%lX!", bktrGetStorageTypeName(ctx->storage_type), offset);
|
||||||
goto end;
|
goto end;
|
||||||
|
@ -153,13 +160,13 @@ bool bktrReadStorage(BucketTreeContext *ctx, void *out, u64 read_size, u64 offse
|
||||||
{
|
{
|
||||||
case BucketTreeStorageType_Indirect:
|
case BucketTreeStorageType_Indirect:
|
||||||
case BucketTreeStorageType_Sparse:
|
case BucketTreeStorageType_Sparse:
|
||||||
success = bktrReadIndirectStorage(ctx, storage_entry, read_size, offset);
|
success = bktrReadIndirectStorage(&visitor, read_size, offset);
|
||||||
break;
|
break;
|
||||||
case BucketTreeStorageType_AesCtrEx:
|
case BucketTreeStorageType_AesCtrEx:
|
||||||
//success = bktrInitializeAesCtrExStorageContext(out, nca_fs_ctx);
|
success = bktrReadAesCtrExStorage(&visitor, read_size, offset);
|
||||||
break;
|
break;
|
||||||
case BucketTreeStorageType_Compressed:
|
case BucketTreeStorageType_Compressed:
|
||||||
//success = bktrInitializeCompressedStorageContext(out, nca_fs_ctx);
|
success = bktrReadCompressedStorage(&visitor, read_size, offset);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -175,20 +182,21 @@ end:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static bool bktrReadIndirectStorage(BucketTreeContext *ctx, void *storage_entry, u64 read_size, u64 offset)
|
static bool bktrReadIndirectStorage(BucketTreeVisitor *visitor, u64 read_size, u64 offset)
|
||||||
{
|
{
|
||||||
|
BucketTreeContext *ctx = visitor->bktr_ctx;
|
||||||
NcaFsSectionContext *nca_fs_ctx = ctx->nca_fs_ctx;
|
NcaFsSectionContext *nca_fs_ctx = ctx->nca_fs_ctx;
|
||||||
bool is_sparse = (ctx->storage_type == BucketTreeStorageType_Sparse);
|
bool is_sparse = (ctx->storage_type == BucketTreeStorageType_Sparse);
|
||||||
BucketTreeIndirectStorageEntry *entry = (BucketTreeIndirectStorageEntry*)storage_entry;
|
BucketTreeIndirectStorageEntry *entry = (BucketTreeIndirectStorageEntry*)visitor->entry;
|
||||||
|
|
||||||
/* Validate Indirect Storage entry. */
|
/* Validate Indirect Storage entry. */
|
||||||
if (!bktrIsOffsetWithinStorageRange(entry->virtual_offset) || (nca_fs_ctx->section_offset + entry->physical_offset) >= nca_fs_ctx->section_size)
|
if (!bktrIsOffsetWithinStorageRange(entry->virtual_offset) || (nca_fs_ctx->section_offset + entry->physical_offset) >= nca_fs_ctx->section_size)
|
||||||
{
|
{
|
||||||
LOG_MSG("Invalid Indirect Storage entry offsets! (0x%lX, 0x%lX).", entry->virtual_offset, entry->physical_offset);
|
LOG_MSG("Invalid Indirect Storage entry! (0x%lX, 0x%lX).", entry->virtual_offset, entry->physical_offset);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Prepare to operate in chunks. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -592,9 +600,9 @@ NX_INLINE const u64 *bktrGetOffsetNodeEnd(const BucketTreeOffsetNode *offset_nod
|
||||||
return (bktrGetOffsetNodeArray(offset_node) + offset_node->header.count);
|
return (bktrGetOffsetNodeArray(offset_node) + offset_node->header.count);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool bktrFindStorageEntry(BucketTreeContext *ctx, u64 virtual_offset, void **out_entry)
|
static bool bktrFindStorageEntry(BucketTreeContext *ctx, u64 virtual_offset, BucketTreeVisitor *out_visitor)
|
||||||
{
|
{
|
||||||
if (!ctx || !out_entry || virtual_offset >= ctx->storage_table->offset_node.header.offset)
|
if (!ctx || virtual_offset >= ctx->storage_table->offset_node.header.offset || !out_visitor)
|
||||||
{
|
{
|
||||||
LOG_MSG("Invalid parameters!");
|
LOG_MSG("Invalid parameters!");
|
||||||
return false;
|
return false;
|
||||||
|
@ -647,8 +655,8 @@ static bool bktrFindStorageEntry(BucketTreeContext *ctx, u64 virtual_offset, voi
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the entry. */
|
/* Find the entry. */
|
||||||
success = bktrFindEntry(ctx, out_entry, virtual_offset, entry_set_index);
|
success = bktrFindEntry(ctx, out_visitor, virtual_offset, entry_set_index);
|
||||||
if (!success) LOG_MSG("Failed to retrieve storage entry pointer!");
|
if (!success) LOG_MSG("Failed to retrieve storage entry!");
|
||||||
|
|
||||||
end:
|
end:
|
||||||
return success;
|
return success;
|
||||||
|
@ -747,7 +755,7 @@ static const BucketTreeNodeHeader *bktrGetTreeNodeHeader(BucketTreeContext *ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get offset node header. */
|
/* Get offset node header. */
|
||||||
const BucketTreeNodeHeader *node_header = (const BucketTreeNodeHeader*)((u8*)ctx->table + node_offset);
|
const BucketTreeNodeHeader *node_header = (const BucketTreeNodeHeader*)((u8*)ctx->storage_table + node_offset);
|
||||||
|
|
||||||
/* Validate offset node header. */
|
/* Validate offset node header. */
|
||||||
if (!bktrVerifyNodeHeader(node_header, node_index, node_size, sizeof(u64)))
|
if (!bktrVerifyNodeHeader(node_header, node_index, node_size, sizeof(u64)))
|
||||||
|
@ -764,7 +772,7 @@ NX_INLINE u32 bktrGetEntrySetIndex(BucketTreeContext *ctx, u32 node_index, u32 o
|
||||||
return (u32)((ctx->offset_count - ctx->storage_table->offset_node.header.count) + (ctx->offset_count * node_index) + offset_index);
|
return (u32)((ctx->offset_count - ctx->storage_table->offset_node.header.count) + (ctx->offset_count * node_index) + offset_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool bktrFindEntry(BucketTreeContext *ctx, void **out_entry, u64 virtual_offset, u32 entry_set_index)
|
static bool bktrFindEntry(BucketTreeContext *ctx, BucketTreeVisitor *out_visitor, u64 virtual_offset, u32 entry_set_index)
|
||||||
{
|
{
|
||||||
/* Get entry node header. */
|
/* Get entry node header. */
|
||||||
const BucketTreeNodeHeader *entry_set_header = bktrGetEntryNodeHeader(ctx, entry_set_index);
|
const BucketTreeNodeHeader *entry_set_header = bktrGetEntryNodeHeader(ctx, entry_set_index);
|
||||||
|
@ -795,8 +803,13 @@ static bool bktrFindEntry(BucketTreeContext *ctx, void **out_entry, u64 virtual_
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update entry pointer. */
|
/* Update output visitor. */
|
||||||
*out_entry = ((u8*)ctx->table + entry_offset);
|
memset(out, 0, sizeof(BucketTreeVisitor));
|
||||||
|
|
||||||
|
out_visitor->bktr_ctx = ctx;
|
||||||
|
memcpy(&(out_visitor->entry_set), entry_set_header, BKTR_NODE_HEADER_SIZE);
|
||||||
|
out_visitor->entry_index = entry_index
|
||||||
|
out_visitor->entry = ((u8*)ctx->storage_table + entry_offset);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -815,7 +828,7 @@ static const BucketTreeNodeHeader *bktrGetEntryNodeHeader(BucketTreeContext *ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get entry node header. */
|
/* Get entry node header. */
|
||||||
const BucketTreeNodeHeader *entry_set_header = (const BucketTreeNodeHeader*)((u8*)ctx->table + entry_set_offset);
|
const BucketTreeNodeHeader *entry_set_header = (const BucketTreeNodeHeader*)((u8*)ctx->storage_table + entry_set_offset);
|
||||||
|
|
||||||
/* Validate entry node header. */
|
/* Validate entry node header. */
|
||||||
if (!bktrVerifyNodeHeader(entry_set_header, entry_set_index, entry_set_size, entry_size))
|
if (!bktrVerifyNodeHeader(entry_set_header, entry_set_index, entry_set_size, entry_size))
|
||||||
|
|
Loading…
Reference in a new issue