1
0
Fork 0
mirror of https://github.com/DarkMatterCore/nxdumptool.git synced 2024-11-22 18:26:39 +00:00

Optimize modified NCA header(s) write code.

This commit is contained in:
Pablo Curiel 2020-10-25 20:03:02 -04:00
parent d777183d9f
commit da5290189b
3 changed files with 27 additions and 10 deletions

View file

@ -115,7 +115,7 @@ static void nspDump(TitleInfo *title_info)
pfsInitializeFileContext(&pfs_file_ctx); pfsInitializeFileContext(&pfs_file_ctx);
char entry_name[64] = {0}; char entry_name[64] = {0};
u64 nsp_header_size = 0, nsp_size = 0; u64 nsp_header_size = 0, nsp_size = 0, nsp_offset = 0;
Sha256Context sha256_ctx = {0}; Sha256Context sha256_ctx = {0};
u8 sha256_hash[SHA256_HASH_SIZE] = {0}; u8 sha256_hash[SHA256_HASH_SIZE] = {0};
@ -457,13 +457,14 @@ static void nspDump(TitleInfo *title_info)
goto end; goto end;
} }
consolePrint("dump process started. please wait... yes, i'm too lazy to print progress here...\n"); consolePrint("dump process started. please wait...\n");
time_t start = time(NULL); time_t start = time(NULL);
// write placeholder header // write placeholder header
memset(buf, 0, nsp_header_size); memset(buf, 0, nsp_header_size);
fwrite(buf, 1, nsp_header_size, fd); fwrite(buf, 1, nsp_header_size, fd);
nsp_offset += nsp_header_size;
// write ncas // write ncas
for(u32 i = 0; i < title_info->content_count; i++) for(u32 i = 0; i < title_info->content_count; i++)
@ -482,7 +483,7 @@ static void nspDump(TitleInfo *title_info)
bool dirty_header = ncaIsHeaderDirty(cur_nca_ctx); bool dirty_header = ncaIsHeaderDirty(cur_nca_ctx);
for(u64 offset = 0; offset < cur_nca_ctx->content_size; offset += blksize) for(u64 offset = 0; offset < cur_nca_ctx->content_size; offset += blksize, nsp_offset += blksize)
{ {
if ((cur_nca_ctx->content_size - offset) < blksize) blksize = (cur_nca_ctx->content_size - offset); if ((cur_nca_ctx->content_size - offset) < blksize) blksize = (cur_nca_ctx->content_size - offset);
@ -496,7 +497,7 @@ static void nspDump(TitleInfo *title_info)
if (dirty_header) if (dirty_header)
{ {
// write re-encrypted headers // write re-encrypted headers
ncaWriteEncryptedHeaderDataToMemoryBuffer(cur_nca_ctx, buf, blksize, offset); if (!cur_nca_ctx->header_written) ncaWriteEncryptedHeaderDataToMemoryBuffer(cur_nca_ctx, buf, blksize, offset);
if (cur_nca_ctx->content_type_ctx_patch) if (cur_nca_ctx->content_type_ctx_patch)
{ {
@ -521,6 +522,9 @@ static void nspDump(TitleInfo *title_info)
break; break;
} }
} }
// update flag to avoid entering this code block if it's not needed anymore
dirty_header = (!cur_nca_ctx->header_written || cur_nca_ctx->content_type_ctx_patch);
} }
// update hash calculation // update hash calculation
@ -560,6 +564,7 @@ static void nspDump(TitleInfo *title_info)
// write cnmt xml // write cnmt xml
fwrite(cnmt_ctx.authoring_tool_xml, 1, cnmt_ctx.authoring_tool_xml_size, fd); fwrite(cnmt_ctx.authoring_tool_xml, 1, cnmt_ctx.authoring_tool_xml_size, fd);
nsp_offset += cnmt_ctx.authoring_tool_xml_size;
// update cnmt xml pfs entry name // update cnmt xml pfs entry name
if (!pfsUpdateEntryNameFromFileContext(&pfs_file_ctx, meta_nca_ctx->content_type_ctx_data_idx, meta_nca_ctx->content_id_str)) if (!pfsUpdateEntryNameFromFileContext(&pfs_file_ctx, meta_nca_ctx->content_type_ctx_data_idx, meta_nca_ctx->content_id_str))
@ -600,6 +605,7 @@ static void nspDump(TitleInfo *title_info)
// write icon // write icon
fwrite(icon_ctx->icon_data, 1, icon_ctx->icon_size, fd); fwrite(icon_ctx->icon_data, 1, icon_ctx->icon_size, fd);
nsp_offset += icon_ctx->icon_size;
// update pfs entry name // update pfs entry name
if (!pfsUpdateEntryNameFromFileContext(&pfs_file_ctx, data_idx++, cur_nca_ctx->content_id_str)) if (!pfsUpdateEntryNameFromFileContext(&pfs_file_ctx, data_idx++, cur_nca_ctx->content_id_str))
@ -624,6 +630,7 @@ static void nspDump(TitleInfo *title_info)
// write xml // write xml
fwrite(authoring_tool_xml, 1, authoring_tool_xml_size, fd); fwrite(authoring_tool_xml, 1, authoring_tool_xml_size, fd);
nsp_offset += authoring_tool_xml_size;
// update pfs entry name // update pfs entry name
if (!pfsUpdateEntryNameFromFileContext(&pfs_file_ctx, data_idx, cur_nca_ctx->content_id_str)) if (!pfsUpdateEntryNameFromFileContext(&pfs_file_ctx, data_idx, cur_nca_ctx->content_id_str))
@ -637,9 +644,11 @@ static void nspDump(TitleInfo *title_info)
{ {
// write ticket // write ticket
fwrite(tik.data, 1, tik.size, fd); fwrite(tik.data, 1, tik.size, fd);
nsp_offset += tik.size;
// write cert // write cert
fwrite(raw_cert_chain, 1, raw_cert_chain_size, fd); fwrite(raw_cert_chain, 1, raw_cert_chain_size, fd);
nsp_offset += raw_cert_chain_size;
} }
// write new pfs0 header // write new pfs0 header

View file

@ -436,23 +436,29 @@ bool ncaEncryptHeader(NcaContext *ctx)
void ncaWriteEncryptedHeaderDataToMemoryBuffer(NcaContext *ctx, void *buf, u64 buf_size, u64 buf_offset) void ncaWriteEncryptedHeaderDataToMemoryBuffer(NcaContext *ctx, void *buf, u64 buf_size, u64 buf_offset)
{ {
/* Return right away if we're dealing with invalid parameters, or if the buffer data is not part of the range covered by the encrypted header data (NCA2/3 optimization, last condition). */ /* Return right away if we're dealing with invalid parameters. */
/* In order to avoid taking up too much execution time when this function is called (ideally inside a loop), we won't use ncaIsHeaderDirty() here. Let the user take care of it instead. */ /* In order to avoid taking up too much execution time when this function is called (ideally inside a loop), we won't use ncaIsHeaderDirty() here. Let the user take care of it instead. */
if (!ctx || ctx->content_size < NCA_FULL_HEADER_LENGTH || !buf || !buf_size || (buf_offset + buf_size) > ctx->content_size || \ if (!ctx || ctx->header_written || ctx->content_size < NCA_FULL_HEADER_LENGTH || !buf || !buf_size || (buf_offset + buf_size) > ctx->content_size) return;
(ctx->format_version != NcaVersion_Nca0 && buf_offset >= NCA_FULL_HEADER_LENGTH)) return;
ctx->header_written = true;
/* Attempt to write the NCA header. */ /* Attempt to write the NCA header. */
/* Return right away if the NCA header was only partially written. */ /* Return right away if the NCA header was only partially written. */
if (buf_offset < sizeof(NcaHeader) && !ncaWritePatchToMemoryBuffer(ctx, &(ctx->encrypted_header), sizeof(NcaHeader), 0, buf, buf_size, buf_offset)) return; if (buf_offset < sizeof(NcaHeader) && !ncaWritePatchToMemoryBuffer(ctx, &(ctx->encrypted_header), sizeof(NcaHeader), 0, buf, buf_size, buf_offset))
{
ctx->header_written = false;
return;
}
/* Attempt to write NCA FS section headers. */ /* Attempt to write NCA FS section headers. */
for(u8 i = 0; i < NCA_FS_HEADER_COUNT; i++) for(u8 i = 0; i < NCA_FS_HEADER_COUNT; i++)
{ {
NcaFsSectionContext *fs_ctx = &(ctx->fs_ctx[i]); NcaFsSectionContext *fs_ctx = &(ctx->fs_ctx[i]);
if (!fs_ctx->enabled) continue; if (!fs_ctx->enabled || fs_ctx->header_written) continue;
u64 fs_header_offset = (ctx->format_version != NcaVersion_Nca0 ? (sizeof(NcaHeader) + (i * sizeof(NcaFsHeader))) : fs_ctx->section_offset); u64 fs_header_offset = (ctx->format_version != NcaVersion_Nca0 ? (sizeof(NcaHeader) + (i * sizeof(NcaFsHeader))) : fs_ctx->section_offset);
ncaWritePatchToMemoryBuffer(ctx, &(fs_ctx->encrypted_header), sizeof(NcaFsHeader), fs_header_offset, buf, buf_size, buf_offset); fs_ctx->header_written = ncaWritePatchToMemoryBuffer(ctx, &(fs_ctx->encrypted_header), sizeof(NcaFsHeader), fs_header_offset, buf, buf_size, buf_offset);
if (!fs_ctx->header_written) ctx->header_written = false;
} }
} }

View file

@ -278,6 +278,7 @@ typedef struct {
NcaFsHeader header; ///< Plaintext NCA FS section header. NcaFsHeader header; ///< Plaintext NCA FS section header.
NcaFsHeader encrypted_header; ///< Encrypted NCA FS section header. If the plaintext NCA FS section header is modified, this will hold an encrypted copy of it. NcaFsHeader encrypted_header; ///< Encrypted NCA FS section header. If the plaintext NCA FS section header is modified, this will hold an encrypted copy of it.
///< Otherwise, this holds the unmodified, encrypted NCA FS section header. ///< Otherwise, this holds the unmodified, encrypted NCA FS section header.
bool header_written; ///< Set to true after this FS section header has been written to an output dump.
u8 section_num; u8 section_num;
u64 section_offset; u64 section_offset;
u64 section_size; u64 section_size;
@ -322,6 +323,7 @@ typedef struct {
u8 header_hash[SHA256_HASH_SIZE]; ///< Plaintext NCA header hash. Used to determine if it's necessary to replace the NCA header while dumping this NCA. u8 header_hash[SHA256_HASH_SIZE]; ///< Plaintext NCA header hash. Used to determine if it's necessary to replace the NCA header while dumping this NCA.
NcaHeader encrypted_header; ///< Encrypted NCA header. If the plaintext NCA header is modified, this will hold an encrypted copy of it. NcaHeader encrypted_header; ///< Encrypted NCA header. If the plaintext NCA header is modified, this will hold an encrypted copy of it.
///< Otherwise, this holds the unmodified, encrypted NCA header. ///< Otherwise, this holds the unmodified, encrypted NCA header.
bool header_written; ///< Set to true after the NCA header and the FS section headers have been written to an output dump.
NcaFsSectionContext fs_ctx[NCA_FS_HEADER_COUNT]; NcaFsSectionContext fs_ctx[NCA_FS_HEADER_COUNT];
NcaDecryptedKeyArea decrypted_key_area; NcaDecryptedKeyArea decrypted_key_area;
void *content_type_ctx; ///< Pointer to a content type context (e.g. ContentMetaContext, ProgramInfoContext, NacpContext, LegalInfoContext). Set to NULL if unused. void *content_type_ctx; ///< Pointer to a content type context (e.g. ContentMetaContext, ProgramInfoContext, NacpContext, LegalInfoContext). Set to NULL if unused.