1
0
Fork 0
mirror of https://github.com/DarkMatterCore/nxdumptool.git synced 2024-11-08 11:51:48 +00:00

Fix some issues + update PoCs.

ncaStorageSetPatchOriginalSubStorage: allow Patch title version to be equal to the Base title version (e.g. sparse titles).

ncaStorageGetHashTargetExtents: actually set proper storage extents.

bktrGetTreeNodeEntryIndex: fix index lookup algorithm.

bktrStorageNodeFind: fix binary search.

bktrVisitorMoveNext / bktrVisitorMovePrevious: fix integer overflows.
This commit is contained in:
Pablo Curiel 2022-07-05 01:25:28 +02:00
parent de6eb1a7e8
commit 91dc20b7f3
9 changed files with 123 additions and 121 deletions

View file

@ -20,7 +20,7 @@
*/
#include "nxdt_utils.h"
#include "bktr.h"
#include "romfs.h"
#include "gamecard.h"
#include "title.h"
@ -37,7 +37,6 @@ typedef struct
{
FILE *fd;
RomFileSystemContext *romfs_ctx;
BktrContext *bktr_ctx;
void *data;
size_t data_size;
size_t data_written;
@ -87,7 +86,7 @@ static void consolePrint(const char *text, ...)
static void read_thread_func(void *arg)
{
ThreadSharedData *shared_data = (ThreadSharedData*)arg;
if (!shared_data || shared_data->fd || !shared_data->data || !shared_data->total_size || (!shared_data->romfs_ctx && !shared_data->bktr_ctx))
if (!shared_data || shared_data->fd || !shared_data->data || !shared_data->total_size || !shared_data->romfs_ctx)
{
shared_data->read_error = true;
goto end;
@ -101,7 +100,7 @@ static void read_thread_func(void *arg)
}
u64 file_table_offset = 0;
u64 file_table_size = (shared_data->bktr_ctx ? shared_data->bktr_ctx->patch_romfs_ctx.file_table_size : shared_data->romfs_ctx->file_table_size);
u64 file_table_size = shared_data->romfs_ctx->file_table_size;
RomFileSystemFileEntry *file_entry = NULL;
char path[FS_MAX_PATH] = {0};
@ -130,15 +129,8 @@ static void read_thread_func(void *arg)
}
/* Retrieve RomFS file entry information. */
if (shared_data->bktr_ctx)
{
shared_data->read_error = (!(file_entry = bktrGetFileEntryByOffset(shared_data->bktr_ctx, file_table_offset)) || \
!bktrGeneratePathFromFileEntry(shared_data->bktr_ctx, file_entry, path + 11, FS_MAX_PATH - 11, RomFileSystemPathIllegalCharReplaceType_KeepAsciiCharsOnly));
} else {
shared_data->read_error = (!(file_entry = romfsGetFileEntryByOffset(shared_data->romfs_ctx, file_table_offset)) || \
!romfsGeneratePathFromFileEntry(shared_data->romfs_ctx, file_entry, path + 11, FS_MAX_PATH - 11, RomFileSystemPathIllegalCharReplaceType_KeepAsciiCharsOnly));
}
shared_data->read_error = (!(file_entry = romfsGetFileEntryByOffset(shared_data->romfs_ctx, file_table_offset)) || \
!romfsGeneratePathFromFileEntry(shared_data->romfs_ctx, file_entry, path + 11, FS_MAX_PATH - 11, RomFileSystemPathIllegalCharReplaceType_KeepAsciiCharsOnly));
if (shared_data->read_error)
{
condvarWakeAll(&g_writeCondvar);
@ -168,8 +160,7 @@ static void read_thread_func(void *arg)
}
/* Read current file data chunk. */
shared_data->read_error = (shared_data->bktr_ctx ? !bktrReadFileEntryData(shared_data->bktr_ctx, file_entry, buf, blksize, offset) : \
!romfsReadFileEntryData(shared_data->romfs_ctx, file_entry, buf, blksize, offset));
shared_data->read_error = !romfsReadFileEntryData(shared_data->romfs_ctx, file_entry, buf, blksize, offset);
if (shared_data->read_error)
{
condvarWakeAll(&g_writeCondvar);
@ -406,7 +397,6 @@ int main(int argc, char *argv[])
NcaContext *base_nca_ctx = NULL, *update_nca_ctx = NULL;
RomFileSystemContext romfs_ctx = {0};
BktrContext bktr_ctx = {0};
ThreadSharedData shared_data = {0};
Thread read_thread = {0}, write_thread = {0};
@ -586,9 +576,18 @@ int main(int argc, char *argv[])
goto out2;
}
if (user_app_data.patch_info)
TitleInfo *latest_patch = NULL;
if (user_app_data.patch_info) latest_patch = get_latest_patch_info(user_app_data.patch_info);
if (base_nca_ctx->fs_ctx[1].has_sparse_layer && (!latest_patch || latest_patch->version.value < user_app_data.app_info->version.value))
{
TitleInfo *latest_patch = get_latest_patch_info(user_app_data.patch_info);
consolePrint("base app is a sparse title and no v%u or greater update could be found\n", user_app_data.app_info->version.value);
goto out2;
}
if (latest_patch)
{
consolePrint("using patch romfs with update v%u\n", latest_patch->version.value);
if (!ncaInitializeContext(update_nca_ctx, latest_patch->storage_id, (latest_patch->storage_id == NcmStorageId_GameCard ? GameCardHashFileSystemPartitionType_Secure : 0), \
titleGetContentInfoByTypeAndIdOffset(latest_patch, NcmContentType_Program, program_id_offset), latest_patch->version.value, NULL))
@ -597,29 +596,26 @@ int main(int argc, char *argv[])
goto out2;
}
if (!bktrInitializeContext(&bktr_ctx, &(base_nca_ctx->fs_ctx[1]), &(update_nca_ctx->fs_ctx[1])))
if (!romfsInitializeContext(&romfs_ctx, &(base_nca_ctx->fs_ctx[1]), &(update_nca_ctx->fs_ctx[1])))
{
consolePrint("bktr initialize ctx failed\n");
consolePrint("romfs initialize ctx failed (update)\n");
goto out2;
}
shared_data.bktr_ctx = &bktr_ctx;
bktrGetTotalDataSize(&bktr_ctx, &(shared_data.total_size));
consolePrint("bktr initialize ctx succeeded\n");
} else {
if (!romfsInitializeContext(&romfs_ctx, &(base_nca_ctx->fs_ctx[1])))
consolePrint("using base romfs only\n");
if (!romfsInitializeContext(&romfs_ctx, &(base_nca_ctx->fs_ctx[1]), NULL))
{
consolePrint("romfs initialize ctx failed\n");
consolePrint("romfs initialize ctx failed (base)\n");
goto out2;
}
shared_data.romfs_ctx = &romfs_ctx;
romfsGetTotalDataSize(&romfs_ctx, &(shared_data.total_size));
consolePrint("romfs initialize ctx succeeded\n");
}
shared_data.romfs_ctx = &romfs_ctx;
romfsGetTotalDataSize(&romfs_ctx, &(shared_data.total_size));
consolePrint("romfs initialize ctx succeeded\n");
shared_data.fd = NULL;
shared_data.data = buf;
shared_data.data_size = 0;
@ -718,7 +714,6 @@ out2:
}
romfsFreeContext(&romfs_ctx);
bktrFreeContext(&bktr_ctx);
if (update_nca_ctx) free(update_nca_ctx);

View file

@ -167,7 +167,7 @@ static void dumpRomFs(TitleInfo *info, NcaFsSectionContext *nca_fs_ctx)
size_t path_len = 0;
*path = '\0';
if (!romfsInitializeContext(&romfs_ctx, nca_fs_ctx))
if (!romfsInitializeContext(&romfs_ctx, nca_fs_ctx, NULL))
{
consolePrint("romfs initialize ctx failed!\n");
goto end;

View file

@ -20,7 +20,7 @@
*/
#include "nxdt_utils.h"
#include "bktr.h"
#include "romfs.h"
#include "gamecard.h"
#include "usb.h"
#include "title.h"
@ -38,7 +38,6 @@ typedef struct
{
//FILE *fileobj;
RomFileSystemContext *romfs_ctx;
BktrContext *bktr_ctx;
void *data;
size_t data_size;
size_t data_written;
@ -88,7 +87,7 @@ static void consolePrint(const char *text, ...)
static void read_thread_func(void *arg)
{
ThreadSharedData *shared_data = (ThreadSharedData*)arg;
if (!shared_data || !shared_data->data || !shared_data->total_size || (!shared_data->romfs_ctx && !shared_data->bktr_ctx))
if (!shared_data || !shared_data->data || !shared_data->total_size || !shared_data->romfs_ctx)
{
shared_data->read_error = true;
goto end;
@ -102,7 +101,7 @@ static void read_thread_func(void *arg)
}
u64 file_table_offset = 0;
u64 file_table_size = (shared_data->bktr_ctx ? shared_data->bktr_ctx->patch_romfs_ctx.file_table_size : shared_data->romfs_ctx->file_table_size);
u64 file_table_size = shared_data->romfs_ctx->file_table_size;
RomFileSystemFileEntry *file_entry = NULL;
char path[FS_MAX_PATH] = {0};
@ -116,15 +115,8 @@ static void read_thread_func(void *arg)
}
/* Retrieve RomFS file entry information */
if (shared_data->bktr_ctx)
{
shared_data->read_error = (!(file_entry = bktrGetFileEntryByOffset(shared_data->bktr_ctx, file_table_offset)) || \
!bktrGeneratePathFromFileEntry(shared_data->bktr_ctx, file_entry, path, FS_MAX_PATH, RomFileSystemPathIllegalCharReplaceType_IllegalFsChars));
} else {
shared_data->read_error = (!(file_entry = romfsGetFileEntryByOffset(shared_data->romfs_ctx, file_table_offset)) || \
!romfsGeneratePathFromFileEntry(shared_data->romfs_ctx, file_entry, path, FS_MAX_PATH, RomFileSystemPathIllegalCharReplaceType_IllegalFsChars));
}
shared_data->read_error = (!(file_entry = romfsGetFileEntryByOffset(shared_data->romfs_ctx, file_table_offset)) || \
!romfsGeneratePathFromFileEntry(shared_data->romfs_ctx, file_entry, path, FS_MAX_PATH, RomFileSystemPathIllegalCharReplaceType_IllegalFsChars));
if (shared_data->read_error)
{
condvarWakeAll(&g_writeCondvar);
@ -157,8 +149,7 @@ static void read_thread_func(void *arg)
}
/* Read current file data chunk */
shared_data->read_error = (shared_data->bktr_ctx ? !bktrReadFileEntryData(shared_data->bktr_ctx, file_entry, buf, blksize, offset) : \
!romfsReadFileEntryData(shared_data->romfs_ctx, file_entry, buf, blksize, offset));
shared_data->read_error = !romfsReadFileEntryData(shared_data->romfs_ctx, file_entry, buf, blksize, offset);
if (shared_data->read_error)
{
condvarWakeAll(&g_writeCondvar);
@ -385,7 +376,6 @@ int main(int argc, char *argv[])
NcaContext *base_nca_ctx = NULL, *update_nca_ctx = NULL;
RomFileSystemContext romfs_ctx = {0};
BktrContext bktr_ctx = {0};
ThreadSharedData shared_data = {0};
Thread read_thread = {0}, write_thread = {0};
@ -559,9 +549,18 @@ int main(int argc, char *argv[])
goto out2;
}
if (user_app_data.patch_info)
TitleInfo *latest_patch = NULL;
if (user_app_data.patch_info) latest_patch = get_latest_patch_info(user_app_data.patch_info);
if (base_nca_ctx->fs_ctx[1].has_sparse_layer && (!latest_patch || latest_patch->version.value < user_app_data.app_info->version.value))
{
TitleInfo *latest_patch = get_latest_patch_info(user_app_data.patch_info);
consolePrint("base app is a sparse title and no v%u or greater update could be found\n", user_app_data.app_info->version.value);
goto out2;
}
if (latest_patch)
{
consolePrint("using patch romfs with update v%u\n", latest_patch->version.value);
if (!ncaInitializeContext(update_nca_ctx, latest_patch->storage_id, (latest_patch->storage_id == NcmStorageId_GameCard ? GameCardHashFileSystemPartitionType_Secure : 0), \
titleGetContentInfoByTypeAndIdOffset(latest_patch, NcmContentType_Program, program_id_offset), latest_patch->version.value, NULL))
@ -570,29 +569,26 @@ int main(int argc, char *argv[])
goto out2;
}
if (!bktrInitializeContext(&bktr_ctx, &(base_nca_ctx->fs_ctx[1]), &(update_nca_ctx->fs_ctx[1])))
if (!romfsInitializeContext(&romfs_ctx, &(base_nca_ctx->fs_ctx[1]), &(update_nca_ctx->fs_ctx[1])))
{
consolePrint("bktr initialize ctx failed\n");
consolePrint("romfs initialize ctx failed (update)\n");
goto out2;
}
shared_data.bktr_ctx = &bktr_ctx;
bktrGetTotalDataSize(&bktr_ctx, &(shared_data.total_size));
consolePrint("bktr initialize ctx succeeded\n");
} else {
if (!romfsInitializeContext(&romfs_ctx, &(base_nca_ctx->fs_ctx[1])))
consolePrint("using base romfs only\n");
if (!romfsInitializeContext(&romfs_ctx, &(base_nca_ctx->fs_ctx[1]), NULL))
{
consolePrint("romfs initialize ctx failed\n");
consolePrint("romfs initialize ctx failed (base)\n");
goto out2;
}
shared_data.romfs_ctx = &romfs_ctx;
romfsGetTotalDataSize(&romfs_ctx, &(shared_data.total_size));
consolePrint("romfs initialize ctx succeeded\n");
}
shared_data.romfs_ctx = &romfs_ctx;
romfsGetTotalDataSize(&romfs_ctx, &(shared_data.total_size));
consolePrint("romfs initialize ctx succeeded\n");
shared_data.data = buf;
shared_data.data_size = 0;
shared_data.data_written = 0;
@ -719,7 +715,6 @@ out2:
}
romfsFreeContext(&romfs_ctx);
bktrFreeContext(&bktr_ctx);
if (update_nca_ctx) free(update_nca_ctx);

View file

@ -24,7 +24,7 @@
#ifndef __LEGAL_INFO_H__
#define __LEGAL_INFO_H__
#include "nca.h"
#include "romfs.h"
#ifdef __cplusplus
extern "C" {

View file

@ -123,7 +123,7 @@ NX_INLINE bool bktrIsExistOffsetL2OnL1(BucketTreeContext *ctx);
static void bktrInitializeStorageNode(BucketTreeStorageNode *out, u64 entry_size, u32 entry_count);
static void bktrStorageNodeFind(BucketTreeStorageNode *storage_node, const BucketTreeNodeHeader *node_header, u64 virtual_offset);
NX_INLINE BucketTreeStorageNodeOffset bktrStorageNodeOffsetAdd(BucketTreeStorageNodeOffset *ofs, u64 value);
NX_INLINE u64 bktrStorageNodeOffsetSubstract(BucketTreeStorageNodeOffset *ofs1, BucketTreeStorageNodeOffset *ofs2);
NX_INLINE const u64 bktrStorageNodeOffsetGetEntryVirtualOffset(const BucketTreeNodeHeader *node_header, const BucketTreeStorageNodeOffset *ofs);
NX_INLINE bool bktrVisitorIsValid(BucketTreeVisitor *visitor);
NX_INLINE bool bktrVisitorCanMoveNext(BucketTreeVisitor *visitor);
@ -1104,21 +1104,27 @@ static bool bktrGetTreeNodeEntryIndex(const u64 *start_ptr, const u64 *end_ptr,
}
u64 *pos = (u64*)start_ptr;
bool found = false;
u32 index = 0;
while(pos < end_ptr)
{
if (start_ptr < pos && *pos > virtual_offset)
if (start_ptr < pos)
{
*out_index = ((u32)(pos - start_ptr) - 1);
found = true;
break;
/* Stop looking if we have found the right offset node. */
if (*pos > virtual_offset) break;
/* Increment index. */
index++;
}
/* Increment offset node pointer. */
pos++;
}
return found;
/* Update output index. */
*out_index = index;
return true;
}
static bool bktrGetEntryNodeEntryIndex(const BucketTreeNodeHeader *node_header, u64 entry_size, u64 virtual_offset, u32 *out_index)
@ -1299,25 +1305,41 @@ static void bktrInitializeStorageNode(BucketTreeStorageNode *out, u64 entry_size
static void bktrStorageNodeFind(BucketTreeStorageNode *storage_node, const BucketTreeNodeHeader *node_header, u64 virtual_offset)
{
u32 end = storage_node->count;
BucketTreeStorageNodeOffset pos = storage_node->start;
while(end > 0)
/* Check for edge case, short circuit. */
if (storage_node->count == 1)
{
u32 half = (end / 2);
BucketTreeStorageNodeOffset mid = bktrStorageNodeOffsetAdd(&pos, half);
const u64 offset = *((const u64*)((const u8*)node_header + mid.offset));
if (offset <= virtual_offset)
{
pos = bktrStorageNodeOffsetAdd(&mid, 1);
end -= (half + 1);
} else {
end = half;
}
storage_node->index = 0;
return;
}
storage_node->index = ((u32)bktrStorageNodeOffsetSubstract(&pos, &(storage_node->start)) - 1);
/* Perform a binary search. */
u32 entry_count = storage_node->count, low = 0, high = (entry_count - 1);
BucketTreeStorageNodeOffset *start = &(storage_node->start);
while(low <= high)
{
/* Get the offset to the middle entry within our current lookup range. */
u32 half = ((low + high) / 2);
BucketTreeStorageNodeOffset mid = bktrStorageNodeOffsetAdd(start, half);
/* Check middle entry's virtual offset. */
if (bktrStorageNodeOffsetGetEntryVirtualOffset(node_header, &mid) > virtual_offset)
{
/* Update our upper limit. */
high = (half - 1);
} else {
/* Check for success. */
BucketTreeStorageNodeOffset pos = bktrStorageNodeOffsetAdd(&mid, 1);
if (half == (entry_count - 1) || bktrStorageNodeOffsetGetEntryVirtualOffset(node_header, &pos) > virtual_offset)
{
storage_node->index = half;
break;
}
/* Update our lower limit. */
low = (half + 1);
}
}
}
NX_INLINE BucketTreeStorageNodeOffset bktrStorageNodeOffsetAdd(BucketTreeStorageNodeOffset *ofs, u64 value)
@ -1326,9 +1348,9 @@ NX_INLINE BucketTreeStorageNodeOffset bktrStorageNodeOffsetAdd(BucketTreeStorage
return out;
}
NX_INLINE u64 bktrStorageNodeOffsetSubstract(BucketTreeStorageNodeOffset *ofs1, BucketTreeStorageNodeOffset *ofs2)
NX_INLINE const u64 bktrStorageNodeOffsetGetEntryVirtualOffset(const BucketTreeNodeHeader *node_header, const BucketTreeStorageNodeOffset *ofs)
{
return (u64)((ofs1->offset - ofs2->offset) / ofs1->stride);
return *((const u64*)((const u8*)node_header + ofs->offset));
}
NX_INLINE bool bktrVisitorIsValid(BucketTreeVisitor *visitor)
@ -1356,12 +1378,12 @@ static bool bktrVisitorMoveNext(BucketTreeVisitor *visitor)
BucketTreeContext *ctx = visitor->bktr_ctx;
BucketTreeEntrySetHeader *entry_set = &(visitor->entry_set);
u32 entry_index = (visitor->entry_index + 1);
bool success = false;
/* Invalidate index. */
visitor->entry_index = UINT32_MAX;
u32 entry_index = (visitor->entry_index + 1);
if (entry_index == entry_set->header.count)
{
/* We have reached the end of this entry node. Let's try to retrieve the first entry from the next one. */
@ -1428,12 +1450,12 @@ static bool bktrVisitorMovePrevious(BucketTreeVisitor *visitor)
BucketTreeContext *ctx = visitor->bktr_ctx;
BucketTreeEntrySetHeader *entry_set = &(visitor->entry_set);
u32 entry_index = visitor->entry_index;
bool success = false;
/* Invalidate index. */
visitor->entry_index = UINT32_MAX;
u32 entry_index = visitor->entry_index;
if (entry_index == 0)
{
/* We have reached the start of this entry node. Let's try to retrieve the last entry from the previous one. */

View file

@ -21,7 +21,6 @@
#include "nxdt_utils.h"
#include "legal_info.h"
#include "romfs.h"
bool legalInfoInitializeContext(LegalInfoContext *out, NcaContext *nca_ctx)
{

View file

@ -119,7 +119,7 @@ bool ncaStorageSetPatchOriginalSubStorage(NcaStorageContext *patch_ctx, NcaStora
!(patch_nca_ctx = (NcaContext*)patch_ctx->nca_fs_ctx->nca_ctx) || !(base_nca_ctx = (NcaContext*)base_ctx->nca_fs_ctx->nca_ctx) || \
patch_ctx->nca_fs_ctx->section_type != NcaFsSectionType_PatchRomFs || base_ctx->nca_fs_ctx->section_type != NcaFsSectionType_RomFs || \
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 <= base_nca_ctx->title_version || !patch_ctx->indirect_storage)
patch_nca_ctx->id_offset != base_nca_ctx->id_offset || patch_nca_ctx->title_version < base_nca_ctx->title_version || !patch_ctx->indirect_storage)
{
LOG_MSG("Invalid parameters!");
return false;
@ -170,26 +170,19 @@ bool ncaStorageGetHashTargetExtents(NcaStorageContext *ctx, u64 *out_offset, u64
switch(ctx->base_storage_type)
{
case NcaStorageBaseStorageType_Regular:
case NcaStorageBaseStorageType_Sparse:
case NcaStorageBaseStorageType_Indirect:
{
/* Just provide the NCA FS section hash target extents. */
/* Regular: just provide the NCA FS section hash target extents -- they already represent physical information. */
/* Sparse/Indirect: the base storage's virtual section encompasses the hash layers, too. The NCA FS section hash target extents represent valid virtual information. */
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;
/* Compressed sections already point to the hash target layer. */
if (out_offset) *out_offset = ctx->compressed_storage->start_offset;
if (out_size) *out_size = ctx->compressed_storage->end_offset;
break;
}
@ -232,7 +225,7 @@ bool ncaStorageRead(NcaStorageContext *ctx, void *out, u64 read_size, u64 offset
break;
}
if (!success) LOG_MSG("Failed to read 0x%lX-byte long block from offset 0x%lX in base storage! (%u).", read_size, offset, ctx->base_storage_type);
if (!success) LOG_MSG("Failed to read 0x%lX-byte long block from offset 0x%lX in base storage! (type: %u).", read_size, offset, ctx->base_storage_type);
return success;
}

View file

@ -31,14 +31,14 @@ bool romfsInitializeContext(RomFileSystemContext *out, NcaFsSectionContext *base
{
u64 dir_table_offset = 0, file_table_offset = 0;
NcaContext *base_nca_ctx = NULL, *patch_nca_ctx = NULL;
bool dump_fs_header = false, is_patch = (patch_nca_fs_ctx != NULL), success = false;
bool dump_fs_header = false, success = false;
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) || \
if (!out || !base_nca_fs_ctx || !base_nca_fs_ctx->enabled || (base_nca_fs_ctx->has_sparse_layer && !patch_nca_fs_ctx) || !(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 && (!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!");
@ -58,9 +58,7 @@ bool romfsInitializeContext(RomFileSystemContext *out, NcaFsSectionContext *base
goto end;
}
out->is_patch = is_patch;
if (is_patch)
if (patch_nca_fs_ctx)
{
/* Initialize base NCA storage context. */
if (!ncaStorageInitializeContext(patch_storage_ctx, patch_nca_fs_ctx))
@ -77,9 +75,11 @@ bool romfsInitializeContext(RomFileSystemContext *out, NcaFsSectionContext *base
}
/* Set default NCA FS storage context. */
out->is_patch = true;
out->default_storage_ctx = patch_storage_ctx;
} else {
/* Set default NCA FS storage context. */
out->is_patch = false;
out->default_storage_ctx = base_storage_ctx;
}

View file

@ -1,7 +1,7 @@
todo:
nca: support for sparse sections
nca: support for compressed fs sections
nca / nca_storage / bktr: re-test support for all section types
nca: add function to retrieve a pointer to a nca fs ctx based on section type? (e.g. like titleGetContentInfoByTypeAndIdOffset)
log: verbosity levels
log: nxlink output for advanced users
@ -18,8 +18,6 @@ todo:
romfs: functions to display filelist
bktr: functions to display filelist (wrappers for romfs functions tbh)
usb: change buffer size?
usb: change chunk size?
usb: improve abi (make it rest-like?)