1
0
Fork 0
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:
Pablo Curiel 2020-04-26 06:04:31 -04:00
parent c6eaf3c8b6
commit bc93001525
6 changed files with 65 additions and 187 deletions

View file

@ -26,7 +26,7 @@
#include <dirent.h> #include <dirent.h>
#include "nca.h" #include "nca.h"
#include "pfs.h" #include "romfs.h"
#include "rsa.h" #include "rsa.h"
@ -92,9 +92,8 @@ int main(int argc, char *argv[])
} }
}; };
u64 pfs_size = 0; u64 romfs_size = 0;
PartitionFileSystemContext pfs_ctx = {0}; RomFileSystemContext romfs_ctx = {0};
PartitionFileSystemEntry *pfs_entry = NULL;
buf = malloc(0x400000); buf = malloc(0x400000);
if (!buf) if (!buf)
@ -145,210 +144,71 @@ int main(int argc, char *argv[])
consoleUpdate(NULL); consoleUpdate(NULL);
tmp_file = fopen("sdmc:/nxdt_test/section0.bin", "wb"); if (!romfsInitializeContext(&romfs_ctx, &(nca_ctx->fs_contexts[1])))
if (tmp_file)
{ {
u64 blksize = 0x400000; printf("romfs initialize ctx failed\n");
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");
goto out2; goto out2;
} }
printf("pfs initialize ctx succeeded\n"); printf("romfs initialize ctx succeeded\n");
consoleUpdate(NULL); 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 { } else {
printf("pfs size failed\n"); printf("romfs size failed\n");
} }
consoleUpdate(NULL); 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) if (tmp_file)
{ {
fwrite(&pfs_ctx, 1, sizeof(PartitionFileSystemContext), tmp_file); fwrite(&romfs_ctx, 1, sizeof(RomFileSystemContext), tmp_file);
fclose(tmp_file); fclose(tmp_file);
tmp_file = NULL; tmp_file = NULL;
printf("pfs ctx saved\n"); printf("romfs ctx saved\n");
} else { } else {
printf("pfs ctx not saved\n"); printf("romfs ctx not saved\n");
} }
consoleUpdate(NULL); 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) 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); fclose(tmp_file);
tmp_file = NULL; tmp_file = NULL;
printf("pfs header saved\n"); printf("dir table saved\n");
} else { } else {
printf("pfs header not saved\n"); printf("dir table not saved\n");
} }
consoleUpdate(NULL); consoleUpdate(NULL);
tmp_file = fopen("sdmc:/nxdt_test/pfs.bin", "wb"); tmp_file = fopen("sdmc:/nxdt_test/file_table.bin", "wb");
if (tmp_file) if (tmp_file)
{ {
u64 blksize = 0x400000; fwrite(romfs_ctx.file_table, 1, romfs_ctx.file_table_size, tmp_file);
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);
}
fclose(tmp_file); fclose(tmp_file);
tmp_file = NULL; tmp_file = NULL;
printf("file table saved\n");
printf("pfs read partition success\n");
} else { } else {
printf("pfs not created\n"); printf("file table not saved\n");
} }
consoleUpdate(NULL); 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: out2:
while(appletMainLoop()) while(appletMainLoop())
@ -360,7 +220,7 @@ out2:
if (tmp_file) fclose(tmp_file); if (tmp_file) fclose(tmp_file);
pfsFreeContext(&pfs_ctx); romfsFreeContext(&romfs_ctx);
if (serviceIsActive(&(ncm_storage.s))) ncmContentStorageClose(&ncm_storage); if (serviceIsActive(&(ncm_storage.s))) ncmContentStorageClose(&ncm_storage);

View file

@ -370,7 +370,7 @@ NX_INLINE bool ncaValidateHierarchicalSha256Offsets(NcaHierarchicalSha256 *hiera
NX_INLINE bool ncaValidateHierarchicalIntegrityOffsets(NcaHierarchicalIntegrity *hierarchical_integrity, u64 section_size) 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 || \ 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 */ /* Validate layer offsets and sizes */
for(u8 i = 0; i < (NCA_IVFC_HASH_DATA_LAYER_COUNT + 1); i++) for(u8 i = 0; i < (NCA_IVFC_HASH_DATA_LAYER_COUNT + 1); i++)

View file

@ -134,7 +134,7 @@ bool pfsReadEntryData(PartitionFileSystemContext *ctx, PartitionFileSystemEntry
return true; 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; NcaContext *nca_ctx = NULL;

View file

@ -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_offset; ///< New hash block offset (relative to the start of the NCA content file).
u64 hash_block_size; ///< New hash block size. u64 hash_block_size; ///< New hash block size.
u8 *hash_block; ///< New hash block contents. 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. u64 data_block_size; ///< New data block size.
u8 *data_block; ///< New data block contents. u8 *data_block; ///< New data block contents.
} PartitionFileSystemModifiedBlockInfo; } PartitionFileSystemPatchInfo;
/// Initializes a partition FS context. /// Initializes a partition FS context.
bool pfsInitializeContext(PartitionFileSystemContext *out, NcaFsSectionContext *nca_fs_ctx); 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. /// 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. /// 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. /// 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. /// Miscellaneous functions.

View file

@ -86,7 +86,7 @@ bool romfsInitializeContext(RomFileSystemContext *out, NcaFsSectionContext *nca_
} }
/* Read directory entries table */ /* 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); 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) 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; 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!"); LOGFILE("Failed to read RomFS directory entries table!");
return false; return false;
} }
/* Read file entries table */ /* 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); 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) 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; 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!"); LOGFILE("Failed to read RomFS file entries table!");
return false; return false;
} }
/* Calculate file data body offset */ /* Get 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)); 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) if (out->body_offset >= out->size)
{ {
LOGFILE("Invalid RomFS file data body!"); LOGFILE("Invalid RomFS file data body!");
@ -142,20 +142,35 @@ bool romfsInitializeContext(RomFileSystemContext *out, NcaFsSectionContext *nca_
return true; 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) 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) !out || !read_size || offset >= file_entry->size || (offset + read_size) > file_entry->size)
{ {
LOGFILE("Invalid parameters!"); LOGFILE("Invalid parameters!");
return false; 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 */ /* 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!"); LOGFILE("Failed to read RomFS file entry data!");
return false; return false;

View file

@ -99,7 +99,7 @@ typedef struct {
RomFileSystemDirectoryEntry *dir_table; ///< RomFS directory entries table. RomFileSystemDirectoryEntry *dir_table; ///< RomFS directory entries table.
u64 file_table_size; ///< RomFS file entries table size. u64 file_table_size; ///< RomFS file entries table size.
RomFileSystemFileEntry *file_table; ///< RomFS file entries table. 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; } RomFileSystemContext;
/// Initializes a RomFS context. /// Initializes a RomFS context.
@ -114,6 +114,9 @@ NX_INLINE void romfsFreeContext(RomFileSystemContext *ctx)
memset(ctx, 0, sizeof(RomFileSystemContext)); 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. /// 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); 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. /// 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; if (!ctx || !ctx->dir_table || (dir_entry_offset + sizeof(RomFileSystemDirectoryEntry)) > ctx->dir_table_size) return NULL;
return (RomFileSystemDirectoryEntry*)((u8*)ctx->dir_table + file_entry_offset); 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; if (!ctx || !ctx->file_table || (file_entry_offset + sizeof(RomFileSystemFileEntry)) > ctx->file_table_size) return NULL;
return (RomFileSystemFileEntry*)((u8*)ctx->file_table + dir_entry_offset); return (RomFileSystemFileEntry*)((u8*)ctx->file_table + file_entry_offset);
} }
#endif /* __ROMFS_H__ */ #endif /* __ROMFS_H__ */