mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-22 18:26:39 +00:00
RomFS ctx working.
Need to create filepath methods.
This commit is contained in:
parent
c6eaf3c8b6
commit
bc93001525
6 changed files with 65 additions and 187 deletions
184
source/main.c
184
source/main.c
|
@ -26,7 +26,7 @@
|
|||
#include <dirent.h>
|
||||
|
||||
#include "nca.h"
|
||||
#include "pfs.h"
|
||||
#include "romfs.h"
|
||||
#include "rsa.h"
|
||||
|
||||
|
||||
|
@ -92,9 +92,8 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
};
|
||||
|
||||
u64 pfs_size = 0;
|
||||
PartitionFileSystemContext pfs_ctx = {0};
|
||||
PartitionFileSystemEntry *pfs_entry = NULL;
|
||||
u64 romfs_size = 0;
|
||||
RomFileSystemContext romfs_ctx = {0};
|
||||
|
||||
buf = malloc(0x400000);
|
||||
if (!buf)
|
||||
|
@ -145,210 +144,71 @@ int main(int argc, char *argv[])
|
|||
|
||||
consoleUpdate(NULL);
|
||||
|
||||
tmp_file = fopen("sdmc:/nxdt_test/section0.bin", "wb");
|
||||
if (tmp_file)
|
||||
if (!romfsInitializeContext(&romfs_ctx, &(nca_ctx->fs_contexts[1])))
|
||||
{
|
||||
u64 blksize = 0x400000;
|
||||
u64 total = nca_ctx->fs_contexts[0].section_size;
|
||||
|
||||
printf("nca section0 created: 0x%lX\n", total);
|
||||
consoleUpdate(NULL);
|
||||
|
||||
for(u64 curpos = 0; curpos < total; curpos += blksize)
|
||||
{
|
||||
if (blksize > (total - curpos)) blksize = (total - curpos);
|
||||
|
||||
if (!ncaReadFsSection(&(nca_ctx->fs_contexts[0]), buf, blksize, curpos))
|
||||
{
|
||||
printf("nca read section failed\n");
|
||||
goto out2;
|
||||
}
|
||||
|
||||
fwrite(buf, 1, blksize, tmp_file);
|
||||
}
|
||||
|
||||
fclose(tmp_file);
|
||||
tmp_file = NULL;
|
||||
|
||||
printf("nca read section0 success\n");
|
||||
} else {
|
||||
printf("nca section0 not created\n");
|
||||
}
|
||||
|
||||
consoleUpdate(NULL);
|
||||
|
||||
if (!pfsInitializeContext(&pfs_ctx, &(nca_ctx->fs_contexts[0])))
|
||||
{
|
||||
printf("pfs initialize ctx failed\n");
|
||||
printf("romfs initialize ctx failed\n");
|
||||
goto out2;
|
||||
}
|
||||
|
||||
printf("pfs initialize ctx succeeded\n");
|
||||
printf("romfs initialize ctx succeeded\n");
|
||||
consoleUpdate(NULL);
|
||||
|
||||
if (pfsGetTotalDataSize(&pfs_ctx, &pfs_size))
|
||||
if (romfsGetTotalDataSize(&romfs_ctx, &romfs_size))
|
||||
{
|
||||
printf("pfs size succeeded: 0x%lX\n", pfs_size);
|
||||
printf("romfs size succeeded: 0x%lX\n", romfs_size);
|
||||
} else {
|
||||
printf("pfs size failed\n");
|
||||
printf("romfs size failed\n");
|
||||
}
|
||||
|
||||
consoleUpdate(NULL);
|
||||
|
||||
tmp_file = fopen("sdmc:/nxdt_test/pfs_ctx.bin", "wb");
|
||||
tmp_file = fopen("sdmc:/nxdt_test/romfs_ctx.bin", "wb");
|
||||
if (tmp_file)
|
||||
{
|
||||
fwrite(&pfs_ctx, 1, sizeof(PartitionFileSystemContext), tmp_file);
|
||||
fwrite(&romfs_ctx, 1, sizeof(RomFileSystemContext), tmp_file);
|
||||
fclose(tmp_file);
|
||||
tmp_file = NULL;
|
||||
printf("pfs ctx saved\n");
|
||||
printf("romfs ctx saved\n");
|
||||
} else {
|
||||
printf("pfs ctx not saved\n");
|
||||
printf("romfs ctx not saved\n");
|
||||
}
|
||||
|
||||
consoleUpdate(NULL);
|
||||
|
||||
tmp_file = fopen("sdmc:/nxdt_test/pfs_header.bin", "wb");
|
||||
tmp_file = fopen("sdmc:/nxdt_test/dir_table.bin", "wb");
|
||||
if (tmp_file)
|
||||
{
|
||||
fwrite(pfs_ctx.header, 1, pfs_ctx.header_size, tmp_file);
|
||||
fwrite(romfs_ctx.dir_table, 1, romfs_ctx.dir_table_size, tmp_file);
|
||||
fclose(tmp_file);
|
||||
tmp_file = NULL;
|
||||
printf("pfs header saved\n");
|
||||
printf("dir table saved\n");
|
||||
} else {
|
||||
printf("pfs header not saved\n");
|
||||
printf("dir table not saved\n");
|
||||
}
|
||||
|
||||
consoleUpdate(NULL);
|
||||
|
||||
tmp_file = fopen("sdmc:/nxdt_test/pfs.bin", "wb");
|
||||
tmp_file = fopen("sdmc:/nxdt_test/file_table.bin", "wb");
|
||||
if (tmp_file)
|
||||
{
|
||||
u64 blksize = 0x400000;
|
||||
u64 total = pfs_ctx.size;
|
||||
|
||||
printf("pfs created: 0x%lX\n", total);
|
||||
consoleUpdate(NULL);
|
||||
|
||||
for(u64 curpos = 0; curpos < total; curpos += blksize)
|
||||
{
|
||||
if (blksize > (total - curpos)) blksize = (total - curpos);
|
||||
|
||||
if (!pfsReadPartitionData(&pfs_ctx, buf, blksize, curpos))
|
||||
{
|
||||
printf("pfs read partition failed\n");
|
||||
goto out2;
|
||||
}
|
||||
|
||||
fwrite(buf, 1, blksize, tmp_file);
|
||||
}
|
||||
|
||||
fwrite(romfs_ctx.file_table, 1, romfs_ctx.file_table_size, tmp_file);
|
||||
fclose(tmp_file);
|
||||
tmp_file = NULL;
|
||||
|
||||
printf("pfs read partition success\n");
|
||||
printf("file table saved\n");
|
||||
} else {
|
||||
printf("pfs not created\n");
|
||||
printf("file table not saved\n");
|
||||
}
|
||||
|
||||
consoleUpdate(NULL);
|
||||
|
||||
pfs_entry = pfsGetEntryByName(&pfs_ctx, "main.npdm");
|
||||
if (!pfs_entry)
|
||||
{
|
||||
printf("pfs get entry by name failed\n");
|
||||
goto out2;
|
||||
}
|
||||
|
||||
printf("pfs get entry by name succeeded\n");
|
||||
consoleUpdate(NULL);
|
||||
|
||||
tmp_file = fopen("sdmc:/nxdt_test/main.npdm", "wb");
|
||||
if (tmp_file)
|
||||
{
|
||||
printf("main.npdm created. Target size -> 0x%lX\n", pfs_entry->size);
|
||||
consoleUpdate(NULL);
|
||||
|
||||
if (!pfsReadEntryData(&pfs_ctx, pfs_entry, buf, pfs_entry->size, 0))
|
||||
{
|
||||
printf("pfs read entry data failed\n");
|
||||
goto out2;
|
||||
}
|
||||
|
||||
fwrite(buf, 1, pfs_entry->size, tmp_file);
|
||||
fclose(tmp_file);
|
||||
tmp_file = NULL;
|
||||
|
||||
printf("pfs read main.npdm success\n");
|
||||
} else {
|
||||
printf("main.npdm not created\n");
|
||||
}
|
||||
|
||||
consoleUpdate(NULL);
|
||||
|
||||
u32 acid_offset = 0;
|
||||
memcpy(&acid_offset, buf + 0x78, sizeof(u32));
|
||||
|
||||
PartitionFileSystemModifiedBlockInfo pfs_block_info = {0};
|
||||
|
||||
if (pfsGenerateModifiedEntryData(&pfs_ctx, pfs_entry, rsa2048GetCustomAcidPublicKey(), RSA2048_SIGNATURE_SIZE, acid_offset + RSA2048_SIGNATURE_SIZE, &pfs_block_info))
|
||||
{
|
||||
printf("pfs mod data success | hbo: 0x%lX | hbs: 0x%lX | dbo: 0x%lX | dbs: 0x%lX\n", pfs_block_info.hash_block_offset, pfs_block_info.hash_block_size, pfs_block_info.data_block_offset, pfs_block_info.data_block_size);
|
||||
|
||||
consoleUpdate(NULL);
|
||||
|
||||
tmp_file = fopen("sdmc:/nxdt_test/pfs_mod.bin", "wb");
|
||||
if (tmp_file)
|
||||
{
|
||||
fwrite(&pfs_block_info, 1, sizeof(PartitionFileSystemModifiedBlockInfo), tmp_file);
|
||||
fclose(tmp_file);
|
||||
tmp_file = NULL;
|
||||
printf("pfs mod data saved\n");
|
||||
} else {
|
||||
printf("pfs mod data not saved\n");
|
||||
}
|
||||
|
||||
consoleUpdate(NULL);
|
||||
|
||||
tmp_file = fopen("sdmc:/nxdt_test/pfs_hash_mod.bin", "wb");
|
||||
if (tmp_file)
|
||||
{
|
||||
fwrite(pfs_block_info.hash_block, 1, pfs_block_info.hash_block_size, tmp_file);
|
||||
fclose(tmp_file);
|
||||
tmp_file = NULL;
|
||||
printf("pfs hash mod data saved\n");
|
||||
} else {
|
||||
printf("pfs hash mod data not saved\n");
|
||||
}
|
||||
|
||||
consoleUpdate(NULL);
|
||||
|
||||
tmp_file = fopen("sdmc:/nxdt_test/pfs_data_mod.bin", "wb");
|
||||
if (tmp_file)
|
||||
{
|
||||
fwrite(pfs_block_info.data_block, 1, pfs_block_info.data_block_size, tmp_file);
|
||||
fclose(tmp_file);
|
||||
tmp_file = NULL;
|
||||
printf("pfs data mod data saved\n");
|
||||
} else {
|
||||
printf("pfs data mod data not saved\n");
|
||||
}
|
||||
|
||||
consoleUpdate(NULL);
|
||||
|
||||
tmp_file = fopen("sdmc:/nxdt_test/new_nca_ctx.bin", "wb");
|
||||
if (tmp_file)
|
||||
{
|
||||
fwrite(nca_ctx, 1, sizeof(NcaContext), tmp_file);
|
||||
fclose(tmp_file);
|
||||
tmp_file = NULL;
|
||||
printf("nca ctx saved\n");
|
||||
} else {
|
||||
printf("nca ctx not saved\n");
|
||||
}
|
||||
} else {
|
||||
printf("pfs mod data failed\n");
|
||||
}
|
||||
|
||||
out2:
|
||||
while(appletMainLoop())
|
||||
|
@ -360,7 +220,7 @@ out2:
|
|||
|
||||
if (tmp_file) fclose(tmp_file);
|
||||
|
||||
pfsFreeContext(&pfs_ctx);
|
||||
romfsFreeContext(&romfs_ctx);
|
||||
|
||||
if (serviceIsActive(&(ncm_storage.s))) ncmContentStorageClose(&ncm_storage);
|
||||
|
||||
|
|
|
@ -370,7 +370,7 @@ NX_INLINE bool ncaValidateHierarchicalSha256Offsets(NcaHierarchicalSha256 *hiera
|
|||
NX_INLINE bool ncaValidateHierarchicalIntegrityOffsets(NcaHierarchicalIntegrity *hierarchical_integrity, u64 section_size)
|
||||
{
|
||||
if (!hierarchical_integrity || !section_size || __builtin_bswap32(hierarchical_integrity->magic) != NCA_IVFC_MAGIC || !hierarchical_integrity->master_hash_size || \
|
||||
hierarchical_integrity->layer_count != NCA_IVFC_HASH_DATA_LAYER_COUNT) return false;
|
||||
hierarchical_integrity->layer_count < NCA_IVFC_HASH_DATA_LAYER_COUNT) return false;
|
||||
|
||||
/* Validate layer offsets and sizes */
|
||||
for(u8 i = 0; i < (NCA_IVFC_HASH_DATA_LAYER_COUNT + 1); i++)
|
||||
|
|
|
@ -134,7 +134,7 @@ bool pfsReadEntryData(PartitionFileSystemContext *ctx, PartitionFileSystemEntry
|
|||
return true;
|
||||
}
|
||||
|
||||
bool pfsGenerateModifiedEntryData(PartitionFileSystemContext *ctx, PartitionFileSystemEntry *fs_entry, const void *data, u64 data_size, u64 data_offset, PartitionFileSystemModifiedBlockInfo *out)
|
||||
bool pfsGenerateEntryPatch(PartitionFileSystemContext *ctx, PartitionFileSystemEntry *fs_entry, const void *data, u64 data_size, u64 data_offset, PartitionFileSystemPatchInfo *out)
|
||||
{
|
||||
NcaContext *nca_ctx = NULL;
|
||||
|
||||
|
|
|
@ -52,10 +52,10 @@ typedef struct {
|
|||
u64 hash_block_offset; ///< New hash block offset (relative to the start of the NCA content file).
|
||||
u64 hash_block_size; ///< New hash block size.
|
||||
u8 *hash_block; ///< New hash block contents.
|
||||
u64 data_block_offset; ///< New data block offset.
|
||||
u64 data_block_offset; ///< New data block offset (relative to the start of the NCA content file).
|
||||
u64 data_block_size; ///< New data block size.
|
||||
u8 *data_block; ///< New data block contents.
|
||||
} PartitionFileSystemModifiedBlockInfo;
|
||||
} PartitionFileSystemPatchInfo;
|
||||
|
||||
/// Initializes a partition FS context.
|
||||
bool pfsInitializeContext(PartitionFileSystemContext *out, NcaFsSectionContext *nca_fs_ctx);
|
||||
|
@ -78,7 +78,7 @@ bool pfsReadEntryData(PartitionFileSystemContext *ctx, PartitionFileSystemEntry
|
|||
/// Input offset must be relative to the start of the partition FS entry data.
|
||||
/// Bear in mind that this function recalculates both the NcaHashInfo block master hash and the NCA FS header hash from the NCA header, and enables the 'dirty_header' flag from the NCA context.
|
||||
/// As such, this function is only capable of modifying a single file from a partition FS in a NCA content file.
|
||||
bool pfsGenerateModifiedEntryData(PartitionFileSystemContext *ctx, PartitionFileSystemEntry *fs_entry, const void *data, u64 data_size, u64 data_offset, PartitionFileSystemModifiedBlockInfo *out);
|
||||
bool pfsGenerateEntryPatch(PartitionFileSystemContext *ctx, PartitionFileSystemEntry *fs_entry, const void *data, u64 data_size, u64 data_offset, PartitionFileSystemPatchInfo *out);
|
||||
|
||||
/// Miscellaneous functions.
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ bool romfsInitializeContext(RomFileSystemContext *out, NcaFsSectionContext *nca_
|
|||
}
|
||||
|
||||
/* Read directory entries table */
|
||||
dir_table_offset = (out->offset + (nca_fs_ctx->section_type == NcaFsSectionType_Nca0RomFs ? (u64)out->header.old_format.directory_entry_offset : out->header.cur_format.directory_entry_offset));
|
||||
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);
|
||||
|
||||
if (dir_table_offset >= out->size || !out->dir_table_size || (dir_table_offset + out->dir_table_size) > out->size)
|
||||
|
@ -102,14 +102,14 @@ bool romfsInitializeContext(RomFileSystemContext *out, NcaFsSectionContext *nca_
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!ncaReadFsSection(nca_fs_ctx, out->dir_table, out->dir_table_size, dir_table_offset))
|
||||
if (!ncaReadFsSection(nca_fs_ctx, out->dir_table, out->dir_table_size, out->offset + dir_table_offset))
|
||||
{
|
||||
LOGFILE("Failed to read RomFS directory entries table!");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Read file entries table */
|
||||
file_table_offset = (out->offset + (nca_fs_ctx->section_type == NcaFsSectionType_Nca0RomFs ? (u64)out->header.old_format.file_entry_offset : out->header.cur_format.file_entry_offset));
|
||||
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);
|
||||
|
||||
if (file_table_offset >= out->size || !out->file_table_size || (file_table_offset + out->file_table_size) > out->size)
|
||||
|
@ -125,14 +125,14 @@ bool romfsInitializeContext(RomFileSystemContext *out, NcaFsSectionContext *nca_
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!ncaReadFsSection(nca_fs_ctx, out->file_table, out->file_table_size, file_table_offset))
|
||||
if (!ncaReadFsSection(nca_fs_ctx, out->file_table, out->file_table_size, out->offset + file_table_offset))
|
||||
{
|
||||
LOGFILE("Failed to read RomFS file entries table!");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Calculate file data body offset */
|
||||
out->body_offset = (out->offset + (nca_fs_ctx->section_type == NcaFsSectionType_Nca0RomFs ? (u64)out->header.old_format.body_offset : out->header.cur_format.body_offset));
|
||||
/* 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);
|
||||
if (out->body_offset >= out->size)
|
||||
{
|
||||
LOGFILE("Invalid RomFS file data body!");
|
||||
|
@ -142,20 +142,35 @@ bool romfsInitializeContext(RomFileSystemContext *out, NcaFsSectionContext *nca_
|
|||
return true;
|
||||
}
|
||||
|
||||
bool romfsReadFileSystemData(RomFileSystemContext *ctx, void *out, u64 read_size, u64 offset)
|
||||
{
|
||||
if (!ctx || !ctx->nca_fs_ctx || !ctx->size || !out || !read_size || offset >= ctx->size || (offset + read_size) > ctx->size)
|
||||
{
|
||||
LOGFILE("Invalid parameters!");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Read filesystem data */
|
||||
if (!ncaReadFsSection(ctx->nca_fs_ctx, out, read_size, ctx->offset + offset))
|
||||
{
|
||||
LOGFILE("Failed to read RomFS data!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool romfsReadFileEntryData(RomFileSystemContext *ctx, RomFileSystemFileEntry *file_entry, void *out, u64 read_size, u64 offset)
|
||||
{
|
||||
if (!ctx || !ctx->nca_fs_ctx || !ctx->size || !ctx->body_offset || !file_entry || !file_entry->size || file_entry->offset >= ctx->size || (file_entry->offset + file_entry->size) > ctx->size || \
|
||||
if (!ctx || !ctx->body_offset || !file_entry || !file_entry->size || file_entry->offset >= ctx->size || (file_entry->offset + file_entry->size) > ctx->size || \
|
||||
!out || !read_size || offset >= file_entry->size || (offset + read_size) > file_entry->size)
|
||||
{
|
||||
LOGFILE("Invalid parameters!");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Calculate offset relative to the start of the NCA FS section */
|
||||
u64 section_offset = (ctx->body_offset + file_entry->offset + offset);
|
||||
|
||||
/* Read entry data */
|
||||
if (!ncaReadFsSection(ctx->nca_fs_ctx, out, read_size, section_offset))
|
||||
if (!romfsReadFileSystemData(ctx, out, read_size, ctx->body_offset + file_entry->offset + offset))
|
||||
{
|
||||
LOGFILE("Failed to read RomFS file entry data!");
|
||||
return false;
|
||||
|
|
|
@ -99,7 +99,7 @@ typedef struct {
|
|||
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 NCA FS section).
|
||||
u64 body_offset; ///< RomFS file data body offset (relative to the start of the RomFS).
|
||||
} RomFileSystemContext;
|
||||
|
||||
/// Initializes a RomFS context.
|
||||
|
@ -114,6 +114,9 @@ NX_INLINE void romfsFreeContext(RomFileSystemContext *ctx)
|
|||
memset(ctx, 0, sizeof(RomFileSystemContext));
|
||||
}
|
||||
|
||||
/// Reads raw filesystem data using a RomFS context.
|
||||
bool romfsReadFileSystemData(RomFileSystemContext *ctx, void *out, u64 read_size, u64 offset);
|
||||
|
||||
/// Reads data from a previously retrieved RomFileSystemFileEntry using a RomFS context.
|
||||
bool romfsReadFileEntryData(RomFileSystemContext *ctx, RomFileSystemFileEntry *file_entry, void *out, u64 read_size, u64 offset);
|
||||
|
||||
|
@ -125,16 +128,16 @@ bool romfsGetDirectoryDataSize(RomFileSystemContext *ctx, u32 dir_entry_offset,
|
|||
|
||||
/// Miscellaneous functions.
|
||||
|
||||
NX_INLINE RomFileSystemDirectoryEntry *romfsGetDirectoryEntry(RomFileSystemContext *ctx, u32 file_entry_offset)
|
||||
NX_INLINE RomFileSystemDirectoryEntry *romfsGetDirectoryEntry(RomFileSystemContext *ctx, u32 dir_entry_offset)
|
||||
{
|
||||
if (!ctx || !ctx->dir_table || file_entry_offset >= ctx->dir_table_size) return NULL;
|
||||
return (RomFileSystemDirectoryEntry*)((u8*)ctx->dir_table + file_entry_offset);
|
||||
if (!ctx || !ctx->dir_table || (dir_entry_offset + sizeof(RomFileSystemDirectoryEntry)) > ctx->dir_table_size) return NULL;
|
||||
return (RomFileSystemDirectoryEntry*)((u8*)ctx->dir_table + dir_entry_offset);
|
||||
}
|
||||
|
||||
NX_INLINE RomFileSystemFileEntry *romfsGetFileEntry(RomFileSystemContext *ctx, u32 dir_entry_offset)
|
||||
NX_INLINE RomFileSystemFileEntry *romfsGetFileEntry(RomFileSystemContext *ctx, u32 file_entry_offset)
|
||||
{
|
||||
if (!ctx || !ctx->file_table || dir_entry_offset >= ctx->file_table_size) return NULL;
|
||||
return (RomFileSystemFileEntry*)((u8*)ctx->file_table + dir_entry_offset);
|
||||
if (!ctx || !ctx->file_table || (file_entry_offset + sizeof(RomFileSystemFileEntry)) > ctx->file_table_size) return NULL;
|
||||
return (RomFileSystemFileEntry*)((u8*)ctx->file_table + file_entry_offset);
|
||||
}
|
||||
|
||||
#endif /* __ROMFS_H__ */
|
||||
|
|
Loading…
Reference in a new issue