1
0
Fork 0
mirror of https://github.com/DarkMatterCore/nxdumptool.git synced 2024-12-23 09:02:06 +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 "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);

View file

@ -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++)

View file

@ -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;

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_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.

View file

@ -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;

View file

@ -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__ */