mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-22 18:26:39 +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:
parent
de6eb1a7e8
commit
91dc20b7f3
9 changed files with 123 additions and 121 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#ifndef __LEGAL_INFO_H__
|
||||
#define __LEGAL_INFO_H__
|
||||
|
||||
#include "nca.h"
|
||||
#include "romfs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
|
||||
#include "nxdt_utils.h"
|
||||
#include "legal_info.h"
|
||||
#include "romfs.h"
|
||||
|
||||
bool legalInfoInitializeContext(LegalInfoContext *out, NcaContext *nca_ctx)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
6
todo.txt
6
todo.txt
|
@ -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?)
|
||||
|
|
Loading…
Reference in a new issue