mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-26 04:02:11 +00:00
BKTR finished.
This commit is contained in:
parent
4774aeae9c
commit
efb9b2d103
3 changed files with 138 additions and 174 deletions
|
@ -126,9 +126,8 @@ bool bktrInitializeContext(BktrContext *out, NcaFsSectionContext *base_nca_fs_ct
|
|||
}
|
||||
|
||||
BktrIndirectStorageBucket *last_indirect_bucket = bktrGetIndirectStorageBucket(out->indirect_block, out->indirect_block->bucket_count - 1);
|
||||
last_indirect_bucket->indirect_storage_entries[last_indirect_bucket->entry_count].virtual_offset = out->indirect_block->virtual_size;
|
||||
|
||||
BktrAesCtrExStorageBucket *last_aes_ctr_ex_bucket = bktrGetAesCtrExStorageBucket(out->aes_ctr_ex_block, out->aes_ctr_ex_block->bucket_count - 1);
|
||||
last_indirect_bucket->indirect_storage_entries[last_indirect_bucket->entry_count].virtual_offset = out->indirect_block->virtual_size;
|
||||
last_aes_ctr_ex_bucket->aes_ctr_ex_storage_entries[last_aes_ctr_ex_bucket->entry_count].offset = patch_info->indirect_offset;
|
||||
last_aes_ctr_ex_bucket->aes_ctr_ex_storage_entries[last_aes_ctr_ex_bucket->entry_count].generation = update_nca_fs_ctx->header->generation;
|
||||
last_aes_ctr_ex_bucket->aes_ctr_ex_storage_entries[last_aes_ctr_ex_bucket->entry_count + 1].offset = update_nca_fs_ctx->section_size;
|
||||
|
@ -170,7 +169,7 @@ bool bktrInitializeContext(BktrContext *out, NcaFsSectionContext *base_nca_fs_ct
|
|||
goto exit;
|
||||
}
|
||||
|
||||
if (!bktrPhysicalSectionRead(out, &(out->patch_romfs_ctx.dir_table), out->patch_romfs_ctx.dir_table_size, out->patch_romfs_ctx.offset + dir_table_offset))
|
||||
if (!bktrPhysicalSectionRead(out, out->patch_romfs_ctx.dir_table, out->patch_romfs_ctx.dir_table_size, out->patch_romfs_ctx.offset + dir_table_offset))
|
||||
{
|
||||
LOGFILE("Failed to read update NCA RomFS directory entries table!");
|
||||
goto exit;
|
||||
|
@ -193,7 +192,7 @@ bool bktrInitializeContext(BktrContext *out, NcaFsSectionContext *base_nca_fs_ct
|
|||
goto exit;
|
||||
}
|
||||
|
||||
if (!bktrPhysicalSectionRead(out, &(out->patch_romfs_ctx.file_table), out->patch_romfs_ctx.file_table_size, out->patch_romfs_ctx.offset + file_table_offset))
|
||||
if (!bktrPhysicalSectionRead(out, out->patch_romfs_ctx.file_table, out->patch_romfs_ctx.file_table_size, out->patch_romfs_ctx.offset + file_table_offset))
|
||||
{
|
||||
LOGFILE("Failed to read update NCA RomFS file entries table!");
|
||||
goto exit;
|
||||
|
@ -259,7 +258,7 @@ static bool bktrPhysicalSectionRead(BktrContext *ctx, void *out, u64 read_size,
|
|||
u64 section_offset = 0, indirect_block_size = 0;
|
||||
|
||||
/* Determine which FS section to use + the actual offset to start reading from */
|
||||
/* No better way to do this than to make all BKTR addresses virtual */
|
||||
/* There's no better way to do this than making all BKTR addresses virtual */
|
||||
indirect_entry = bktrGetIndirectStorageEntry(ctx->indirect_block, offset);
|
||||
if (!indirect_entry)
|
||||
{
|
||||
|
@ -267,27 +266,30 @@ static bool bktrPhysicalSectionRead(BktrContext *ctx, void *out, u64 read_size,
|
|||
return false;
|
||||
}
|
||||
|
||||
next_indirect_entry = (indirect_entry + 1);
|
||||
section_offset = (offset - indirect_entry->virtual_offset + indirect_entry->physical_offset);
|
||||
|
||||
/* Perform read operation */
|
||||
bool success = false;
|
||||
next_indirect_entry = (indirect_entry + 1);
|
||||
if ((offset + read_size) <= next_indirect_entry->virtual_offset)
|
||||
{
|
||||
/* Easy path: read only within the current indirect storage entry */
|
||||
/* Read only within the current indirect storage entry */
|
||||
/* If we're not dealing with an indirect storage entry with a patch index, just retrieve the data from the base RomFS */
|
||||
if (indirect_entry->indirect_storage_index == BktrIndirectStorageIndex_Patch)
|
||||
{
|
||||
success = bktrAesCtrExStorageRead(ctx, out, read_size, offset, section_offset);
|
||||
if (!success) LOGFILE("Failed to read 0x%lX bytes block from BKTR AesCtrEx storage at offset 0x%lX!", read_size, section_offset);
|
||||
} else {
|
||||
success = ncaReadFsSection(ctx->base_romfs_ctx.nca_fs_ctx, out, read_size, section_offset);
|
||||
if (!success) LOGFILE("Failed to read 0x%lX bytes block from base RomFS at offset 0x%lX!", read_size, section_offset);
|
||||
}
|
||||
} else {
|
||||
/* Handle read that spans multiple indirect storage entries */
|
||||
/* Handle reads that span multiple indirect storage entries */
|
||||
indirect_block_size = (next_indirect_entry->virtual_offset - offset);
|
||||
|
||||
success = (bktrReadFileSystemData(ctx, out, indirect_block_size, offset) && \
|
||||
bktrReadFileSystemData(ctx, (u8*)out + indirect_block_size, read_size - indirect_block_size, offset + indirect_block_size));
|
||||
success = (bktrPhysicalSectionRead(ctx, out, indirect_block_size, offset) && \
|
||||
bktrPhysicalSectionRead(ctx, (u8*)out + indirect_block_size, read_size - indirect_block_size, offset + indirect_block_size));
|
||||
if (!success) LOGFILE("Failed to read 0x%lX bytes block from multiple BKTR indirect storage entries at offset 0x%lX!", read_size, section_offset);
|
||||
}
|
||||
|
||||
return success;
|
||||
|
@ -310,19 +312,20 @@ static bool bktrAesCtrExStorageRead(BktrContext *ctx, void *out, u64 read_size,
|
|||
return false;
|
||||
}
|
||||
|
||||
next_aes_ctr_ex_entry = (aes_ctr_ex_entry + 1);
|
||||
|
||||
/* Perform read operation */
|
||||
bool success = false;
|
||||
next_aes_ctr_ex_entry = (aes_ctr_ex_entry + 1);
|
||||
if ((section_offset + read_size) <= next_aes_ctr_ex_entry->offset)
|
||||
{
|
||||
/* Read AesCtrEx storage entry data */
|
||||
/* Read only within the current AesCtrEx storage entry */
|
||||
success = ncaReadAesCtrExStorageFromBktrSection(ctx->patch_romfs_ctx.nca_fs_ctx, out, read_size, section_offset, aes_ctr_ex_entry->generation);
|
||||
} else {
|
||||
/* Handle read that spans multiple AesCtrEx storage entries */
|
||||
u64 aes_ctr_ex_block_size = (next_aes_ctr_ex_entry->offset - section_offset);
|
||||
|
||||
success = (bktrReadFileSystemData(ctx, out, aes_ctr_ex_block_size, virtual_offset) && \
|
||||
bktrReadFileSystemData(ctx, (u8*)out + aes_ctr_ex_block_size, read_size - aes_ctr_ex_block_size, virtual_offset + aes_ctr_ex_block_size));
|
||||
success = (bktrPhysicalSectionRead(ctx, out, aes_ctr_ex_block_size, virtual_offset) && \
|
||||
bktrPhysicalSectionRead(ctx, (u8*)out + aes_ctr_ex_block_size, read_size - aes_ctr_ex_block_size, virtual_offset + aes_ctr_ex_block_size));
|
||||
}
|
||||
|
||||
return success;
|
||||
|
@ -331,12 +334,12 @@ static bool bktrAesCtrExStorageRead(BktrContext *ctx, void *out, u64 read_size,
|
|||
NX_INLINE BktrIndirectStorageBucket *bktrGetIndirectStorageBucket(BktrIndirectStorageBlock *block, u32 bucket_num)
|
||||
{
|
||||
if (!block || bucket_num >= block->bucket_count) return NULL;
|
||||
return (BktrIndirectStorageBucket*)((u8*)block->indirect_storage_buckets + ((sizeof(BktrIndirectStorageBucket) + sizeof(BktrIndirectStorageEntry)) * bucket_num));
|
||||
return (BktrIndirectStorageBucket*)((u8*)block->indirect_storage_buckets + ((sizeof(BktrIndirectStorageBucket) + sizeof(BktrIndirectStorageEntry)) * (u64)bucket_num));
|
||||
}
|
||||
|
||||
static BktrIndirectStorageEntry *bktrGetIndirectStorageEntry(BktrIndirectStorageBlock *block, u64 offset)
|
||||
{
|
||||
if (!block || offset >= block->virtual_size)
|
||||
if (!block || !block->bucket_count || offset >= block->virtual_size)
|
||||
{
|
||||
LOGFILE("Invalid parameters!");
|
||||
return NULL;
|
||||
|
@ -384,12 +387,12 @@ static BktrIndirectStorageEntry *bktrGetIndirectStorageEntry(BktrIndirectStorage
|
|||
NX_INLINE BktrAesCtrExStorageBucket *bktrGetAesCtrExStorageBucket(BktrAesCtrExStorageBlock *block, u32 bucket_num)
|
||||
{
|
||||
if (!block || bucket_num >= block->bucket_count) return NULL;
|
||||
return (BktrAesCtrExStorageBucket*)((u8*)block->aes_ctr_ex_storage_buckets + ((sizeof(BktrAesCtrExStorageBucket) + sizeof(BktrAesCtrExStorageEntry)) * bucket_num));
|
||||
return (BktrAesCtrExStorageBucket*)((u8*)block->aes_ctr_ex_storage_buckets + ((sizeof(BktrAesCtrExStorageBucket) + sizeof(BktrAesCtrExStorageEntry)) * (u64)bucket_num));
|
||||
}
|
||||
|
||||
static BktrAesCtrExStorageEntry *bktrGetAesCtrExStorageEntry(BktrAesCtrExStorageBlock *block, u64 offset)
|
||||
{
|
||||
if (!block || offset >= block->physical_size)
|
||||
if (!block || !block->bucket_count || offset >= block->physical_size)
|
||||
{
|
||||
LOGFILE("Invalid parameters!");
|
||||
return NULL;
|
||||
|
@ -398,9 +401,8 @@ static BktrAesCtrExStorageEntry *bktrGetAesCtrExStorageEntry(BktrAesCtrExStorage
|
|||
u32 bucket_num = 0;
|
||||
BktrAesCtrExStorageBucket *last_bucket = NULL, *bucket = NULL;
|
||||
|
||||
/* If offset is past the virtual, we're reading from the BKTR_HEADER subsection */
|
||||
last_bucket = bktrGetAesCtrExStorageBucket(block, block->bucket_count - 1);
|
||||
if (!last_bucket)
|
||||
if (!last_bucket || !last_bucket->entry_count)
|
||||
{
|
||||
LOGFILE("Error retrieving last BKTR AesCtrEx storage bucket!");
|
||||
return NULL;
|
||||
|
@ -414,7 +416,7 @@ static BktrAesCtrExStorageEntry *bktrGetAesCtrExStorageEntry(BktrAesCtrExStorage
|
|||
}
|
||||
|
||||
bucket = bktrGetAesCtrExStorageBucket(block, bucket_num);
|
||||
if (!bucket)
|
||||
if (!bucket || !bucket->entry_count)
|
||||
{
|
||||
LOGFILE("Error retrieving BKTR AesCtrEx storage bucket #%u!", bucket_num);
|
||||
return NULL;
|
||||
|
|
|
@ -25,13 +25,13 @@
|
|||
typedef enum {
|
||||
BktrIndirectStorageIndex_Original = 0,
|
||||
BktrIndirectStorageIndex_Patch = 1
|
||||
} BktrIndirectStorageIndex;
|
||||
} PACKED BktrIndirectStorageIndex;
|
||||
|
||||
typedef struct {
|
||||
u64 virtual_offset;
|
||||
u64 physical_offset;
|
||||
u32 indirect_storage_index; ///< BktrIndirectStorageIndex.
|
||||
} BktrIndirectStorageEntry;
|
||||
} PACKED BktrIndirectStorageEntry;
|
||||
|
||||
typedef struct {
|
||||
u32 index;
|
||||
|
@ -39,7 +39,7 @@ typedef struct {
|
|||
u64 end_offset;
|
||||
BktrIndirectStorageEntry indirect_storage_entries[0x3FF0 / sizeof(BktrIndirectStorageEntry)];
|
||||
u8 reserved[0x3FF0 % sizeof(BktrIndirectStorageEntry)];
|
||||
} BktrIndirectStorageBucket;
|
||||
} PACKED BktrIndirectStorageBucket;
|
||||
|
||||
typedef struct {
|
||||
u32 index;
|
||||
|
@ -47,20 +47,20 @@ typedef struct {
|
|||
u64 virtual_size;
|
||||
u64 virtual_offsets[0x3FF0 / sizeof(u64)];
|
||||
BktrIndirectStorageBucket indirect_storage_buckets[];
|
||||
} BktrIndirectStorageBlock;
|
||||
} PACKED BktrIndirectStorageBlock;
|
||||
|
||||
typedef struct {
|
||||
u64 offset;
|
||||
u32 size;
|
||||
u32 generation;
|
||||
} BktrAesCtrExStorageEntry;
|
||||
} PACKED BktrAesCtrExStorageEntry;
|
||||
|
||||
typedef struct {
|
||||
u32 index;
|
||||
u32 entry_count;
|
||||
u64 end_offset;
|
||||
BktrAesCtrExStorageEntry aes_ctr_ex_storage_entries[0x3FF];
|
||||
} BktrAesCtrExStorageBucket;
|
||||
} PACKED BktrAesCtrExStorageBucket;
|
||||
|
||||
typedef struct {
|
||||
u32 index;
|
||||
|
@ -68,7 +68,7 @@ typedef struct {
|
|||
u64 physical_size;
|
||||
u64 physical_offsets[0x3FF0 / sizeof(u64)];
|
||||
BktrAesCtrExStorageBucket aes_ctr_ex_storage_buckets[];
|
||||
} BktrAesCtrExStorageBlock;
|
||||
} PACKED BktrAesCtrExStorageBlock;
|
||||
|
||||
typedef struct {
|
||||
RomFileSystemContext base_romfs_ctx; ///< Base NCA RomFS context.
|
||||
|
|
254
source/main.c
254
source/main.c
|
@ -25,10 +25,7 @@
|
|||
|
||||
#include <dirent.h>
|
||||
|
||||
#include "nca.h"
|
||||
#include "pfs.h"
|
||||
#include "romfs.h"
|
||||
#include "rsa.h"
|
||||
#include "bktr.h"
|
||||
|
||||
|
||||
|
||||
|
@ -63,10 +60,13 @@ int main(int argc, char *argv[])
|
|||
u8 *buf = NULL;
|
||||
FILE *tmp_file = NULL;
|
||||
|
||||
Ticket tik = {0};
|
||||
NcaContext *nca_ctx = NULL;
|
||||
Ticket base_tik = {0}, update_tik = {0};
|
||||
NcaContext *base_nca_ctx = NULL, *update_nca_ctx = NULL;
|
||||
NcmContentStorage ncm_storage = {0};
|
||||
|
||||
BktrContext bktr_ctx = {0};
|
||||
RomFileSystemFileEntry *bktr_file_entry = NULL;
|
||||
|
||||
Result rc = 0;
|
||||
|
||||
mkdir("sdmc:/nxdt_test", 0744);
|
||||
|
@ -75,8 +75,8 @@ int main(int argc, char *argv[])
|
|||
.c = { 0x01, 0x00, 0x82, 0x40, 0x0B, 0xCC, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08 } // Untitled Goose Game
|
||||
};*/
|
||||
|
||||
// Untitled Goose Game's Program NCA
|
||||
NcmPackagedContentInfo content_info = {
|
||||
// Untitled Goose Game's Base Program NCA
|
||||
NcmPackagedContentInfo base_program_content_info = {
|
||||
.hash = {
|
||||
0x8E, 0xF9, 0x20, 0xD4, 0x5E, 0xE1, 0x9E, 0xD1, 0xD2, 0x04, 0xC4, 0xC8, 0x22, 0x50, 0x79, 0xE8,
|
||||
0xD3, 0xE2, 0xE2, 0xA0, 0x66, 0xFD, 0x2B, 0xB6, 0x5C, 0x73, 0xF6, 0x89, 0xE2, 0x25, 0x0A, 0x82
|
||||
|
@ -93,27 +93,23 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
};
|
||||
|
||||
// Untitled Goose Game's Control NCA
|
||||
/*NcmPackagedContentInfo content_info = {
|
||||
// Untitled Goose Game's Update Program NCA
|
||||
NcmPackagedContentInfo update_program_content_info = {
|
||||
.hash = {
|
||||
0xCE, 0x6E, 0x17, 0x1F, 0x93, 0x2D, 0x29, 0x28, 0xC1, 0x62, 0x94, 0x5B, 0x86, 0x2C, 0x42, 0x93,
|
||||
0xAC, 0x2C, 0x0D, 0x3E, 0xD7, 0xCE, 0x07, 0xA2, 0x34, 0x33, 0x43, 0xD9, 0x21, 0x8A, 0xA3, 0xFE
|
||||
0xDB, 0xEE, 0x62, 0x0E, 0x8F, 0x64, 0x37, 0xE4, 0x8A, 0x5C, 0x63, 0x61, 0xE8, 0xD2, 0x32, 0x6A,
|
||||
0x21, 0x0D, 0x79, 0x50, 0x3A, 0xAF, 0x0D, 0x66, 0x76, 0xE2, 0xBC, 0x84, 0xF7, 0x0A, 0x21, 0xE2
|
||||
},
|
||||
.info = {
|
||||
.content_id = {
|
||||
.c = { 0xCE, 0x6E, 0x17, 0x1F, 0x93, 0x2D, 0x29, 0x28, 0xC1, 0x62, 0x94, 0x5B, 0x86, 0x2C, 0x42, 0x93 }
|
||||
.c = { 0xDB, 0xEE, 0x62, 0x0E, 0x8F, 0x64, 0x37, 0xE4, 0x8A, 0x5C, 0x63, 0x61, 0xE8, 0xD2, 0x32, 0x6A }
|
||||
},
|
||||
.size = {
|
||||
0x00, 0x74, 0x0A, 0x00, 0x00, 0x00
|
||||
0x00, 0xF4, 0xA0, 0x0E, 0x00, 0x00
|
||||
},
|
||||
.content_type = NcmContentType_Control,
|
||||
.content_type = NcmContentType_Program,
|
||||
.id_offset = 0
|
||||
}
|
||||
};*/
|
||||
|
||||
PartitionFileSystemEntry *pfs_entry = NULL;
|
||||
PartitionFileSystemContext pfs_ctx = {0};
|
||||
NcaHierarchicalSha256Patch pfs_patch = {0};
|
||||
};
|
||||
|
||||
buf = malloc(0x400000);
|
||||
if (!buf)
|
||||
|
@ -125,14 +121,24 @@ int main(int argc, char *argv[])
|
|||
printf("read buf succeeded\n");
|
||||
consoleUpdate(NULL);
|
||||
|
||||
nca_ctx = calloc(1, sizeof(NcaContext));
|
||||
if (!nca_ctx)
|
||||
base_nca_ctx = calloc(1, sizeof(NcaContext));
|
||||
if (!base_nca_ctx)
|
||||
{
|
||||
printf("nca ctx buf failed\n");
|
||||
printf("base nca ctx buf failed\n");
|
||||
goto out2;
|
||||
}
|
||||
|
||||
printf("nca ctx buf succeeded\n");
|
||||
printf("base nca ctx buf succeeded\n");
|
||||
consoleUpdate(NULL);
|
||||
|
||||
update_nca_ctx = calloc(1, sizeof(NcaContext));
|
||||
if (!update_nca_ctx)
|
||||
{
|
||||
printf("update nca ctx buf failed\n");
|
||||
goto out2;
|
||||
}
|
||||
|
||||
printf("update nca ctx buf succeeded\n");
|
||||
consoleUpdate(NULL);
|
||||
|
||||
rc = ncmOpenContentStorage(&ncm_storage, NcmStorageId_SdCard);
|
||||
|
@ -145,171 +151,127 @@ int main(int argc, char *argv[])
|
|||
printf("ncm open storage succeeded\n");
|
||||
consoleUpdate(NULL);
|
||||
|
||||
if (!ncaInitializeContext(nca_ctx, NcmStorageId_SdCard, &ncm_storage, 0, &content_info, &tik))
|
||||
if (!ncaInitializeContext(base_nca_ctx, NcmStorageId_SdCard, &ncm_storage, 0, &base_program_content_info, &base_tik))
|
||||
{
|
||||
printf("nca initialize ctx failed\n");
|
||||
printf("base nca initialize ctx failed\n");
|
||||
goto out2;
|
||||
}
|
||||
|
||||
tmp_file = fopen("sdmc:/nxdt_test/nca_ctx.bin", "wb");
|
||||
tmp_file = fopen("sdmc:/nxdt_test/base_nca_ctx.bin", "wb");
|
||||
if (tmp_file)
|
||||
{
|
||||
fwrite(nca_ctx, 1, sizeof(NcaContext), tmp_file);
|
||||
fwrite(base_nca_ctx, 1, sizeof(NcaContext), tmp_file);
|
||||
fclose(tmp_file);
|
||||
tmp_file = NULL;
|
||||
printf("nca ctx saved\n");
|
||||
printf("base nca ctx saved\n");
|
||||
} else {
|
||||
printf("nca ctx not saved\n");
|
||||
printf("base nca ctx not saved\n");
|
||||
}
|
||||
|
||||
consoleUpdate(NULL);
|
||||
|
||||
if (!pfsInitializeContext(&pfs_ctx, &(nca_ctx->fs_contexts[0])))
|
||||
if (!ncaInitializeContext(update_nca_ctx, NcmStorageId_SdCard, &ncm_storage, 0, &update_program_content_info, &update_tik))
|
||||
{
|
||||
printf("pfs initialize ctx failed\n");
|
||||
printf("update nca initialize ctx failed\n");
|
||||
goto out2;
|
||||
}
|
||||
|
||||
printf("pfs initialize ctx succeeded\n");
|
||||
consoleUpdate(NULL);
|
||||
|
||||
tmp_file = fopen("sdmc:/nxdt_test/pfs_ctx.bin", "wb");
|
||||
tmp_file = fopen("sdmc:/nxdt_test/update_nca_ctx.bin", "wb");
|
||||
if (tmp_file)
|
||||
{
|
||||
fwrite(&pfs_ctx, 1, sizeof(PartitionFileSystemContext), tmp_file);
|
||||
fwrite(update_nca_ctx, 1, sizeof(NcaContext), tmp_file);
|
||||
fclose(tmp_file);
|
||||
tmp_file = NULL;
|
||||
printf("pfs ctx saved\n");
|
||||
printf("update nca ctx saved\n");
|
||||
} else {
|
||||
printf("pfs ctx not saved\n");
|
||||
printf("update nca ctx not saved\n");
|
||||
}
|
||||
|
||||
consoleUpdate(NULL);
|
||||
|
||||
tmp_file = fopen("sdmc:/nxdt_test/pfs_header.bin", "wb");
|
||||
if (tmp_file)
|
||||
if (!bktrInitializeContext(&bktr_ctx, &(base_nca_ctx->fs_contexts[1]), &(update_nca_ctx->fs_contexts[1])))
|
||||
{
|
||||
fwrite(pfs_ctx.header, 1, pfs_ctx.header_size, tmp_file);
|
||||
fclose(tmp_file);
|
||||
tmp_file = NULL;
|
||||
printf("pfs header saved\n");
|
||||
} else {
|
||||
printf("pfs header not saved\n");
|
||||
}
|
||||
|
||||
consoleUpdate(NULL);
|
||||
|
||||
pfs_entry = pfsGetEntryByName(&pfs_ctx, "main.npdm");
|
||||
if (!pfs_entry)
|
||||
{
|
||||
printf("pfs get entry by name failed\n");
|
||||
printf("bktr initialize ctx failed\n");
|
||||
goto out2;
|
||||
}
|
||||
|
||||
printf("pfs get entry by name succeeded\n");
|
||||
printf("bktr initialize ctx succeeded\n");
|
||||
consoleUpdate(NULL);
|
||||
|
||||
if (!pfsReadEntryData(&pfs_ctx, pfs_entry, buf, pfs_entry->size, 0))
|
||||
tmp_file = fopen("sdmc:/nxdt_test/bktr_ctx.bin", "wb");
|
||||
if (tmp_file)
|
||||
{
|
||||
printf("pfs read entry data failed\n");
|
||||
fwrite(&bktr_ctx, 1, sizeof(BktrContext), tmp_file);
|
||||
fclose(tmp_file);
|
||||
tmp_file = NULL;
|
||||
printf("bktr ctx saved\n");
|
||||
} else {
|
||||
printf("bktr ctx not saved\n");
|
||||
}
|
||||
|
||||
consoleUpdate(NULL);
|
||||
|
||||
bktr_file_entry = bktrGetFileEntryByPath(&bktr_ctx, "/Data/resources.assets");
|
||||
if (!bktr_file_entry)
|
||||
{
|
||||
printf("bktr get file entry by path failed\n");
|
||||
goto out2;
|
||||
}
|
||||
|
||||
printf("pfs read entry data succeeded\n");
|
||||
printf("bktr get file entry by path success: %.*s | 0x%lX\n", bktr_file_entry->name_length, bktr_file_entry->name, bktr_file_entry->size);
|
||||
consoleUpdate(NULL);
|
||||
|
||||
tmp_file = fopen("sdmc:/nxdt_test/main.npdm", "wb");
|
||||
/*tmp_file = fopen("sdmc:/nxdt_test/resources.assets", "wb");
|
||||
if (tmp_file)
|
||||
{
|
||||
fwrite(buf, 1, pfs_entry->size, tmp_file);
|
||||
fclose(tmp_file);
|
||||
tmp_file = NULL;
|
||||
printf("main.npdm saved\n");
|
||||
} else {
|
||||
printf("main.npdm not saved\n");
|
||||
}
|
||||
|
||||
consoleUpdate(NULL);
|
||||
|
||||
u32 acid_offset = 0;
|
||||
memcpy(&acid_offset, buf + 0x78, sizeof(u32));
|
||||
memcpy(buf + acid_offset + RSA2048_SIGNATURE_SIZE, rsa2048GetCustomAcidPublicKey(), RSA2048_SIGNATURE_SIZE);
|
||||
|
||||
tmp_file = fopen("sdmc:/nxdt_test/main_mod.npdm", "wb");
|
||||
if (tmp_file)
|
||||
{
|
||||
fwrite(buf, 1, pfs_entry->size, tmp_file);
|
||||
fclose(tmp_file);
|
||||
tmp_file = NULL;
|
||||
printf("main_mod.npdm saved\n");
|
||||
} else {
|
||||
printf("main_mod.npdm not saved\n");
|
||||
}
|
||||
|
||||
consoleUpdate(NULL);
|
||||
|
||||
if (!pfsGenerateEntryPatch(&pfs_ctx, pfs_entry, buf + acid_offset + RSA2048_SIGNATURE_SIZE, RSA2048_SIGNATURE_SIZE, acid_offset + RSA2048_SIGNATURE_SIZE, &pfs_patch))
|
||||
{
|
||||
printf("pfs entry patch failed\n");
|
||||
goto out2;
|
||||
}
|
||||
|
||||
printf("pfs entry patch succeeded\n");
|
||||
consoleUpdate(NULL);
|
||||
|
||||
tmp_file = fopen("sdmc:/nxdt_test/pfs_patch.bin", "wb");
|
||||
if (tmp_file)
|
||||
{
|
||||
fwrite(&pfs_patch, 1, sizeof(NcaHierarchicalSha256Patch), tmp_file);
|
||||
fclose(tmp_file);
|
||||
tmp_file = NULL;
|
||||
printf("pfs patch saved\n");
|
||||
} else {
|
||||
printf("pfs patch not saved\n");
|
||||
}
|
||||
|
||||
for(u8 i = 0; i < 2; i++)
|
||||
{
|
||||
NcaHashInfoLayerPatch *layer_patch = (i == 0 ? &(pfs_patch.hash_data_layer_patch) : &(pfs_patch.hash_target_layer_patch));
|
||||
if (!layer_patch->size || !layer_patch->data) continue;
|
||||
|
||||
char path[64];
|
||||
sprintf(path, "sdmc:/nxdt_test/pfs_patch_l%u.bin", i);
|
||||
|
||||
tmp_file = fopen(path, "wb");
|
||||
if (tmp_file)
|
||||
u64 curpos = 0, blksize = 0x400000;
|
||||
for(curpos = 0; curpos < bktr_file_entry->size; curpos += blksize)
|
||||
{
|
||||
fwrite(layer_patch->data, 1, layer_patch->size, tmp_file);
|
||||
fclose(tmp_file);
|
||||
tmp_file = NULL;
|
||||
printf("pfs patch #%u saved\n", i);
|
||||
} else {
|
||||
printf("pfs patch #%u not saved\n", i);
|
||||
if (blksize > (bktr_file_entry->size - curpos)) blksize = (bktr_file_entry->size - curpos);
|
||||
|
||||
if (!bktrReadFileEntryData(&bktr_ctx, bktr_file_entry, buf, blksize, curpos)) break;
|
||||
|
||||
fwrite(buf, 1, blksize, tmp_file);
|
||||
}
|
||||
|
||||
consoleUpdate(NULL);
|
||||
}
|
||||
|
||||
if (!ncaEncryptHeader(nca_ctx))
|
||||
{
|
||||
printf("nca header mod not encrypted\n");
|
||||
goto out2;
|
||||
}
|
||||
|
||||
printf("nca header mod encrypted\n");
|
||||
consoleUpdate(NULL);
|
||||
|
||||
tmp_file = fopen("sdmc:/nxdt_test/nca_header_mod.bin", "wb");
|
||||
if (tmp_file)
|
||||
{
|
||||
fwrite(&(nca_ctx->header), 1, sizeof(NcaHeader), tmp_file);
|
||||
fclose(tmp_file);
|
||||
tmp_file = NULL;
|
||||
printf("nca header mod saved\n");
|
||||
|
||||
if (curpos < bktr_file_entry->size)
|
||||
{
|
||||
printf("resources.assets read error\n");
|
||||
} else {
|
||||
printf("resources.assets saved\n");
|
||||
}
|
||||
} else {
|
||||
printf("nca header mod not saved\n");
|
||||
}
|
||||
printf("resources.assets not saved\n");
|
||||
}*/
|
||||
|
||||
tmp_file = fopen("sdmc:/nxdt_test/romfs.bin", "wb");
|
||||
if (tmp_file)
|
||||
{
|
||||
u64 curpos = 0, blksize = 0x400000;
|
||||
for(curpos = 0; curpos < bktr_ctx.size; curpos += blksize)
|
||||
{
|
||||
if (blksize > (bktr_ctx.size - curpos)) blksize = (bktr_ctx.size - curpos);
|
||||
|
||||
if (!bktrReadFileSystemData(&bktr_ctx, buf, blksize, curpos)) break;
|
||||
|
||||
fwrite(buf, 1, blksize, tmp_file);
|
||||
}
|
||||
|
||||
fclose(tmp_file);
|
||||
tmp_file = NULL;
|
||||
|
||||
if (curpos < bktr_ctx.size)
|
||||
{
|
||||
printf("romfs read error\n");
|
||||
} else {
|
||||
printf("romfs saved\n");
|
||||
}
|
||||
} else {
|
||||
printf("romfs not saved\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -331,13 +293,13 @@ out2:
|
|||
|
||||
if (tmp_file) fclose(tmp_file);
|
||||
|
||||
ncaFreeHierarchicalSha256Patch(&pfs_patch);
|
||||
|
||||
pfsFreeContext(&pfs_ctx);
|
||||
bktrFreeContext(&bktr_ctx);
|
||||
|
||||
if (serviceIsActive(&(ncm_storage.s))) ncmContentStorageClose(&ncm_storage);
|
||||
|
||||
if (nca_ctx) free(nca_ctx);
|
||||
if (update_nca_ctx) free(update_nca_ctx);
|
||||
|
||||
if (base_nca_ctx) free(base_nca_ctx);
|
||||
|
||||
if (buf) free(buf);
|
||||
|
||||
|
|
Loading…
Reference in a new issue