[ctrtool] Implemented --listromfs & --romfsdir to work directly with NCCH. Also implemented plainrgn extraction.

This commit is contained in:
jakcron
2015-11-26 14:21:46 +08:00
parent 085e37296e
commit 6ab7c2a0dc
11 changed files with 232 additions and 47 deletions
+47 -13
View File
@@ -31,11 +31,47 @@ void ivfc_set_file(ivfc_context* ctx, FILE* file)
ctx->file = file; ctx->file = file;
} }
void ivfc_set_encrypted(ivfc_context* ctx, u32 encrypted)
{
ctx->encrypted = encrypted;
}
void ivfc_set_key(ivfc_context* ctx, u8 key[16])
{
memcpy(ctx->key, key, 16);
}
void ivfc_set_counter(ivfc_context* ctx, u8 counter[16])
{
memcpy(ctx->counter, counter, 16);
}
void ivfc_fseek(ivfc_context* ctx, u64 offset)
{
u64 data_pos = offset - ctx->offset;
fseeko64(ctx->file, offset, SEEK_SET);
ctr_init_counter(&ctx->aes, ctx->key, ctx->counter);
ctr_add_counter(&ctx->aes, data_pos / 0x10);
}
size_t ivfc_fread(ivfc_context* ctx, void* buffer, size_t size, size_t count)
{
size_t read;
if ((read = fread(buffer, size, count, ctx->file)) != count) {
//printf("ivfc_fread() fail\n");
return read;
}
if (ctx->encrypted) {
ctr_crypt_counter(&ctx->aes, buffer, buffer, size*read);
}
return read;
}
void ivfc_process(ivfc_context* ctx, u32 actions) void ivfc_process(ivfc_context* ctx, u32 actions)
{ {
fseeko64(ctx->file, ctx->offset, SEEK_SET); ivfc_fseek(ctx, ctx->offset);
fread(&ctx->header, 1, sizeof(ivfc_header), ctx->file); ivfc_fread(ctx, &ctx->header, 1, sizeof(ivfc_header));
if (getle32(ctx->header.magic) != MAGIC_IVFC) if (getle32(ctx->header.magic) != MAGIC_IVFC)
{ {
@@ -45,25 +81,23 @@ void ivfc_process(ivfc_context* ctx, u32 actions)
if (getle32(ctx->header.id) == 0x10000) if (getle32(ctx->header.id) == 0x10000)
{ {
fread(&ctx->romfsheader, 1, sizeof(ivfc_header_romfs), ctx->file);
ctx->levelcount = 3; ctx->levelcount = 3;
ctx->level[2].hashblocksize = 1 << getle32(ctx->romfsheader.level3.blocksize); ctx->level[2].hashblocksize = 1 << getle32(ctx->header.level3.blocksize);
ctx->level[1].hashblocksize = 1 << getle32(ctx->romfsheader.level2.blocksize); ctx->level[1].hashblocksize = 1 << getle32(ctx->header.level2.blocksize);
ctx->level[0].hashblocksize = 1 << getle32(ctx->romfsheader.level1.blocksize); ctx->level[0].hashblocksize = 1 << getle32(ctx->header.level1.blocksize);
ctx->bodyoffset = align64(IVFC_HEADER_SIZE + getle32(ctx->romfsheader.masterhashsize), ctx->level[2].hashblocksize); ctx->bodyoffset = align64(IVFC_HEADER_SIZE + getle32(ctx->header.masterhashsize), ctx->level[2].hashblocksize);
ctx->bodysize = getle64(ctx->romfsheader.level3.hashdatasize); ctx->bodysize = getle64(ctx->header.level3.hashdatasize);
ctx->level[2].dataoffset = ctx->bodyoffset; ctx->level[2].dataoffset = ctx->bodyoffset;
ctx->level[2].datasize = align64(ctx->bodysize, ctx->level[2].hashblocksize); ctx->level[2].datasize = align64(ctx->bodysize, ctx->level[2].hashblocksize);
ctx->level[0].dataoffset = ctx->level[2].dataoffset + ctx->level[2].datasize; ctx->level[0].dataoffset = ctx->level[2].dataoffset + ctx->level[2].datasize;
ctx->level[0].datasize = align64(getle64(ctx->romfsheader.level1.hashdatasize), ctx->level[0].hashblocksize); ctx->level[0].datasize = align64(getle64(ctx->header.level1.hashdatasize), ctx->level[0].hashblocksize);
ctx->level[1].dataoffset = ctx->level[0].dataoffset + ctx->level[0].datasize; ctx->level[1].dataoffset = ctx->level[0].dataoffset + ctx->level[0].datasize;
ctx->level[1].datasize = align64(getle64(ctx->romfsheader.level2.hashdatasize), ctx->level[1].hashblocksize); ctx->level[1].datasize = align64(getle64(ctx->header.level2.hashdatasize), ctx->level[1].hashblocksize);
ctx->level[0].hashoffset = IVFC_HEADER_SIZE; ctx->level[0].hashoffset = IVFC_HEADER_SIZE;
ctx->level[1].hashoffset = ctx->level[0].dataoffset; ctx->level[1].hashoffset = ctx->level[0].dataoffset;
@@ -125,8 +159,8 @@ void ivfc_read(ivfc_context* ctx, u64 offset, u64 size, u8* buffer)
return; return;
} }
fseeko64(ctx->file, ctx->offset + offset, SEEK_SET); ivfc_fseek(ctx, ctx->offset + offset);
if (size != fread(buffer, 1, size, ctx->file)) if (size != ivfc_fread(ctx, buffer, 1, size))
{ {
fprintf(stderr, "Error, IVFC could not read file\n"); fprintf(stderr, "Error, IVFC could not read file\n");
return; return;
+14 -8
View File
@@ -2,18 +2,13 @@
#define __IVFC_H__ #define __IVFC_H__
#include "types.h" #include "types.h"
#include "ctr.h"
#include "settings.h" #include "settings.h"
#define IVFC_HEADER_SIZE 0x60 #define IVFC_HEADER_SIZE 0x60
#define IVFC_MAX_LEVEL 4 #define IVFC_MAX_LEVEL 4
#define IVFC_MAX_BUFFERSIZE 0x4000 #define IVFC_MAX_BUFFERSIZE 0x4000
typedef struct
{
u8 magic[4];
u8 id[4];
} ivfc_header;
typedef struct typedef struct
{ {
u8 logicaloffset[8]; u8 logicaloffset[8];
@@ -33,13 +28,15 @@ typedef struct
typedef struct typedef struct
{ {
u8 magic[4];
u8 id[4];
u8 masterhashsize[4]; u8 masterhashsize[4];
ivfc_levelheader level1; ivfc_levelheader level1;
ivfc_levelheader level2; ivfc_levelheader level2;
ivfc_levelheader level3; ivfc_levelheader level3;
u8 reserved[4]; u8 reserved[4];
u8 optionalsize[4]; u8 optionalsize[4];
} ivfc_header_romfs; } ivfc_header;
typedef struct typedef struct
{ {
@@ -47,9 +44,12 @@ typedef struct
u64 offset; u64 offset;
u64 size; u64 size;
settings* usersettings; settings* usersettings;
u8 counter[16];
u8 key[16];
ctr_aes_context aes;
int encrypted;
ivfc_header header; ivfc_header header;
ivfc_header_romfs romfsheader;
u32 levelcount; u32 levelcount;
ivfc_level level[IVFC_MAX_LEVEL]; ivfc_level level[IVFC_MAX_LEVEL];
@@ -64,6 +64,12 @@ void ivfc_set_offset(ivfc_context* ctx, u64 offset);
void ivfc_set_size(ivfc_context* ctx, u64 size); void ivfc_set_size(ivfc_context* ctx, u64 size);
void ivfc_set_file(ivfc_context* ctx, FILE* file); void ivfc_set_file(ivfc_context* ctx, FILE* file);
void ivfc_set_usersettings(ivfc_context* ctx, settings* usersettings); void ivfc_set_usersettings(ivfc_context* ctx, settings* usersettings);
void ivfc_set_encrypted(ivfc_context* ctx, u32 encrypted);
void ivfc_set_key(ivfc_context* ctx, u8 key[16]);
void ivfc_set_counter(ivfc_context* ctx, u8 counter[16]);
void ivfc_fseek(ivfc_context* ctx, u64 offset);
size_t ivfc_fread(ivfc_context* ctx, void* buffer, size_t size, size_t count);
void ivfc_verify(ivfc_context* ctx, u32 flags); void ivfc_verify(ivfc_context* ctx, u32 flags);
void ivfc_print(ivfc_context* ctx); void ivfc_print(ivfc_context* ctx);
+8 -5
View File
@@ -64,11 +64,14 @@ static void usage(const char *argv0)
" --lzssout=file Specify lzss output file\n" " --lzssout=file Specify lzss output file\n"
"CXI/CCI options:\n" "CXI/CCI options:\n"
" -n, --ncch=index Specify NCCH partition index.\n" " -n, --ncch=index Specify NCCH partition index.\n"
" --exheader=file Specify Extended Header file path.\n"
" --logo=file Specify Logo file path.\n"
" --plainrgn=file Specify Plain region file path"
" --exefs=file Specify ExeFS file path.\n" " --exefs=file Specify ExeFS file path.\n"
" --exefsdir=dir Specify ExeFS directory path.\n" " --exefsdir=dir Specify ExeFS directory path.\n"
" --romfs=file Specify RomFS file path.\n" " --romfs=file Specify RomFS file path.\n"
" --exheader=file Specify Extended Header file path.\n" " --romfsdir=dir Specify RomFS directory path.\n"
" --logo=file Specify Logo file path.\n" " --listromfs List files in RomFS.\n"
"CIA options:\n" "CIA options:\n"
" --certs=file Specify Certificate chain file path.\n" " --certs=file Specify Certificate chain file path.\n"
" --tik=file Specify Ticket file path.\n" " --tik=file Specify Ticket file path.\n"
@@ -83,9 +86,6 @@ static void usage(const char *argv0)
"EXEFS options:\n" "EXEFS options:\n"
" --decompresscode Decompress .code section\n" " --decompresscode Decompress .code section\n"
" (only needed when using raw EXEFS file)\n" " (only needed when using raw EXEFS file)\n"
"ROMFS options:\n"
" --romfsdir=dir Specify RomFS directory path.\n"
" --listromfs List files in RomFS.\n"
"\n", "\n",
__TIME__, __DATE__, argv0); __TIME__, __DATE__, argv0);
exit(1); exit(1);
@@ -149,6 +149,7 @@ int main(int argc, char* argv[])
{"logo", 1, NULL, 20}, {"logo", 1, NULL, 20},
{"decompresscode", 0, NULL, 21}, {"decompresscode", 0, NULL, 21},
{"titlekey", 1, NULL, 22}, {"titlekey", 1, NULL, 22},
{"plainrgn", 1, NULL, 23},
{NULL}, {NULL},
}; };
@@ -237,6 +238,7 @@ int main(int argc, char* argv[])
case 20: settings_set_logo_path(&ctx.usersettings, optarg); break; case 20: settings_set_logo_path(&ctx.usersettings, optarg); break;
case 21: ctx.actions |= DecompressCodeFlag; break; case 21: ctx.actions |= DecompressCodeFlag; break;
case 22: keyset_parse_titlekey(&tmpkeys, optarg, strlen(optarg)); break; case 22: keyset_parse_titlekey(&tmpkeys, optarg, strlen(optarg)); break;
case 23: settings_set_plainrgn_path(&ctx.usersettings, optarg); break;
default: default:
usage(argv[0]); usage(argv[0]);
@@ -452,6 +454,7 @@ int main(int argc, char* argv[])
romfs_set_file(&romfsctx, ctx.infile); romfs_set_file(&romfsctx, ctx.infile);
romfs_set_size(&romfsctx, ctx.infilesize); romfs_set_size(&romfsctx, ctx.infilesize);
romfs_set_usersettings(&romfsctx, &ctx.usersettings); romfs_set_usersettings(&romfsctx, &ctx.usersettings);
romfs_set_encrypted(&romfsctx, 0);
romfs_process(&romfsctx, ctx.actions); romfs_process(&romfsctx, ctx.actions);
break; break;
+37 -1
View File
@@ -116,6 +116,13 @@ int ncch_extract_prepare(ncch_context* ctx, u32 type, u32 flags)
} }
break; break;
case NCCHTYPE_PLAINRGN:
{
offset = ncch_get_plainrgn_offset(ctx);
size = ncch_get_plainrgn_size(ctx);
}
break;
default: default:
{ {
fprintf(stderr, "Error invalid NCCH type\n"); fprintf(stderr, "Error invalid NCCH type\n");
@@ -181,6 +188,7 @@ void ncch_save(ncch_context* ctx, u32 type, u32 flags)
case NCCHTYPE_ROMFS: path = settings_get_romfs_path(ctx->usersettings); break; case NCCHTYPE_ROMFS: path = settings_get_romfs_path(ctx->usersettings); break;
case NCCHTYPE_EXHEADER: path = settings_get_exheader_path(ctx->usersettings); break; case NCCHTYPE_EXHEADER: path = settings_get_exheader_path(ctx->usersettings); break;
case NCCHTYPE_LOGO: path = settings_get_logo_path(ctx->usersettings); break; case NCCHTYPE_LOGO: path = settings_get_logo_path(ctx->usersettings); break;
case NCCHTYPE_PLAINRGN: path = settings_get_plainrgn_path(ctx->usersettings); break;
} }
if (path == 0 || path->valid == 0) if (path == 0 || path->valid == 0)
@@ -199,13 +207,14 @@ void ncch_save(ncch_context* ctx, u32 type, u32 flags)
case NCCHTYPE_ROMFS: fprintf(stdout, "Saving RomFS...\n"); break; case NCCHTYPE_ROMFS: fprintf(stdout, "Saving RomFS...\n"); break;
case NCCHTYPE_EXHEADER: fprintf(stdout, "Saving Extended Header...\n"); break; case NCCHTYPE_EXHEADER: fprintf(stdout, "Saving Extended Header...\n"); break;
case NCCHTYPE_LOGO: fprintf(stdout, "Saving Logo...\n"); break; case NCCHTYPE_LOGO: fprintf(stdout, "Saving Logo...\n"); break;
case NCCHTYPE_PLAINRGN: fprintf(stdout, "Saving Plain Region...\n"); break;
} }
while(1) while(1)
{ {
u32 read_len; u32 read_len;
if (0 == ncch_extract_buffer(ctx, buffer, sizeof(buffer), &read_len, type == NCCHTYPE_LOGO)) if (0 == ncch_extract_buffer(ctx, buffer, sizeof(buffer), &read_len, type == NCCHTYPE_LOGO || type == NCCHTYPE_PLAINRGN))
goto clean; goto clean;
if (read_len == 0) if (read_len == 0)
@@ -304,6 +313,7 @@ void ncch_process(ncch_context* ctx, u32 actions)
{ {
u8 exheadercounter[16]; u8 exheadercounter[16];
u8 exefscounter[16]; u8 exefscounter[16];
u8 romfscounter[16];
int result = 1; int result = 1;
@@ -320,6 +330,7 @@ void ncch_process(ncch_context* ctx, u32 actions)
ncch_get_counter(ctx, exheadercounter, NCCHTYPE_EXHEADER); ncch_get_counter(ctx, exheadercounter, NCCHTYPE_EXHEADER);
ncch_get_counter(ctx, exefscounter, NCCHTYPE_EXEFS); ncch_get_counter(ctx, exefscounter, NCCHTYPE_EXEFS);
ncch_get_counter(ctx, romfscounter, NCCHTYPE_ROMFS);
exheader_set_file(&ctx->exheader, ctx->file); exheader_set_file(&ctx->exheader, ctx->file);
@@ -342,6 +353,14 @@ void ncch_process(ncch_context* ctx, u32 actions)
exefs_set_key(&ctx->exefs, ctx->key); exefs_set_key(&ctx->exefs, ctx->key);
exefs_set_encrypted(&ctx->exefs, ctx->encrypted); exefs_set_encrypted(&ctx->exefs, ctx->encrypted);
romfs_set_file(&ctx->romfs, ctx->file);
romfs_set_offset(&ctx->romfs, ncch_get_romfs_offset(ctx));
romfs_set_size(&ctx->romfs, ncch_get_romfs_size(ctx));
romfs_set_usersettings(&ctx->romfs, ctx->usersettings);
romfs_set_counter(&ctx->romfs, romfscounter);
romfs_set_key(&ctx->romfs, ctx->key);
romfs_set_encrypted(&ctx->romfs, ctx->encrypted);
exheader_read(&ctx->exheader, actions); exheader_read(&ctx->exheader, actions);
@@ -357,6 +376,7 @@ void ncch_process(ncch_context* ctx, u32 actions)
ncch_save(ctx, NCCHTYPE_ROMFS, actions); ncch_save(ctx, NCCHTYPE_ROMFS, actions);
ncch_save(ctx, NCCHTYPE_EXHEADER, actions); ncch_save(ctx, NCCHTYPE_EXHEADER, actions);
ncch_save(ctx, NCCHTYPE_LOGO, actions); ncch_save(ctx, NCCHTYPE_LOGO, actions);
ncch_save(ctx, NCCHTYPE_PLAINRGN, actions);
} }
@@ -374,6 +394,11 @@ void ncch_process(ncch_context* ctx, u32 actions)
exefs_set_compressedflag(&ctx->exefs, exheader_get_compressedflag(&ctx->exheader)); exefs_set_compressedflag(&ctx->exefs, exheader_get_compressedflag(&ctx->exheader));
exefs_process(&ctx->exefs, actions); exefs_process(&ctx->exefs, actions);
} }
if (result && ncch_get_romfs_size(ctx))
{
romfs_process(&ctx->romfs, actions);
}
} }
int ncch_signature_verify(ncch_context* ctx, rsakey2048* key) int ncch_signature_verify(ncch_context* ctx, rsakey2048* key)
@@ -425,6 +450,17 @@ u64 ncch_get_logo_size(ncch_context* ctx)
return getle32(ctx->header.logosize) * ncch_get_mediaunit_size(ctx); return getle32(ctx->header.logosize) * ncch_get_mediaunit_size(ctx);
} }
u64 ncch_get_plainrgn_offset(ncch_context* ctx)
{
return ctx->offset + getle32(ctx->header.plainregionoffset) * ncch_get_mediaunit_size(ctx);
}
u64 ncch_get_plainrgn_size(ncch_context* ctx)
{
return getle32(ctx->header.plainregionsize) * ncch_get_mediaunit_size(ctx);
}
u64 ncch_get_mediaunit_size(ncch_context* ctx) u64 ncch_get_mediaunit_size(ncch_context* ctx)
{ {
unsigned int mediaunitsize = settings_get_mediaunit_size(ctx->usersettings); unsigned int mediaunitsize = settings_get_mediaunit_size(ctx->usersettings);
+5
View File
@@ -7,6 +7,7 @@
#include "filepath.h" #include "filepath.h"
#include "ctr.h" #include "ctr.h"
#include "exefs.h" #include "exefs.h"
#include "romfs.h"
#include "exheader.h" #include "exheader.h"
#include "settings.h" #include "settings.h"
@@ -16,6 +17,7 @@ typedef enum
NCCHTYPE_EXEFS = 2, NCCHTYPE_EXEFS = 2,
NCCHTYPE_ROMFS = 3, NCCHTYPE_ROMFS = 3,
NCCHTYPE_LOGO = 4, NCCHTYPE_LOGO = 4,
NCCHTYPE_PLAINRGN = 5,
} ctr_ncchtypes; } ctr_ncchtypes;
typedef struct typedef struct
@@ -63,6 +65,7 @@ typedef struct
ctr_ncchheader header; ctr_ncchheader header;
ctr_aes_context aes; ctr_aes_context aes;
exefs_context exefs; exefs_context exefs;
romfs_context romfs;
exheader_context exheader; exheader_context exheader;
int exefshashcheck; int exefshashcheck;
int romfshashcheck; int romfshashcheck;
@@ -87,6 +90,8 @@ u64 ncch_get_exheader_offset(ncch_context* ctx);
u64 ncch_get_exheader_size(ncch_context* ctx); u64 ncch_get_exheader_size(ncch_context* ctx);
u64 ncch_get_logo_offset(ncch_context* ctx); u64 ncch_get_logo_offset(ncch_context* ctx);
u64 ncch_get_logo_size(ncch_context* ctx); u64 ncch_get_logo_size(ncch_context* ctx);
u64 ncch_get_plainrgn_offset(ncch_context* ctx);
u64 ncch_get_plainrgn_size(ncch_context* ctx);
void ncch_print(ncch_context* ctx); void ncch_print(ncch_context* ctx);
int ncch_signature_verify(ncch_context* ctx, rsakey2048* key); int ncch_signature_verify(ncch_context* ctx, rsakey2048* key);
void ncch_verify(ncch_context* ctx, u32 flags); void ncch_verify(ncch_context* ctx, u32 flags);
+55 -19
View File
@@ -30,7 +30,41 @@ void romfs_set_usersettings(romfs_context* ctx, settings* usersettings)
ctx->usersettings = usersettings; ctx->usersettings = usersettings;
} }
void romfs_set_encrypted(romfs_context* ctx, u32 encrypted)
{
ctx->encrypted = encrypted;
}
void romfs_set_key(romfs_context* ctx, u8 key[16])
{
memcpy(ctx->key, key, 16);
}
void romfs_set_counter(romfs_context* ctx, u8 counter[16])
{
memcpy(ctx->counter, counter, 16);
}
void romfs_fseek(romfs_context* ctx, u64 offset)
{
u64 data_pos = offset - ctx->offset;
fseeko64(ctx->file, offset, SEEK_SET);
ctr_init_counter(&ctx->aes, ctx->key, ctx->counter);
ctr_add_counter(&ctx->aes, data_pos / 0x10);
}
size_t romfs_fread(romfs_context* ctx, void* buffer, size_t size, size_t count)
{
size_t read;
if ((read = fread(buffer, size, count, ctx->file)) != count) {
//printf("romfs_fread() fail\n");
return read;
}
if (ctx->encrypted) {
ctr_crypt_counter(&ctx->aes, buffer, buffer, size*read);
}
return read;
}
void romfs_process(romfs_context* ctx, u32 actions) void romfs_process(romfs_context* ctx, u32 actions)
{ {
@@ -39,15 +73,17 @@ void romfs_process(romfs_context* ctx, u32 actions)
u32 fileblockoffset = 0; u32 fileblockoffset = 0;
u32 fileblocksize = 0; u32 fileblocksize = 0;
ivfc_set_offset(&ctx->ivfc, ctx->offset); ivfc_set_offset(&ctx->ivfc, ctx->offset);
ivfc_set_size(&ctx->ivfc, ctx->size); ivfc_set_size(&ctx->ivfc, ctx->size);
ivfc_set_file(&ctx->ivfc, ctx->file); ivfc_set_file(&ctx->ivfc, ctx->file);
ivfc_set_usersettings(&ctx->ivfc, ctx->usersettings); ivfc_set_usersettings(&ctx->ivfc, ctx->usersettings);
ivfc_set_counter(&ctx->ivfc, ctx->counter);
ivfc_set_key(&ctx->ivfc, ctx->key);
ivfc_set_encrypted(&ctx->ivfc, ctx->encrypted);
ivfc_process(&ctx->ivfc, actions); ivfc_process(&ctx->ivfc, actions);
fseeko64(ctx->file, ctx->offset, SEEK_SET); romfs_fseek(ctx, ctx->offset);
fread(&ctx->header, 1, sizeof(romfs_header), ctx->file); romfs_fread(ctx, &ctx->header, 1, sizeof(romfs_header));
if (getle32(ctx->header.magic) != MAGIC_IVFC) if (getle32(ctx->header.magic) != MAGIC_IVFC)
{ {
@@ -57,8 +93,8 @@ void romfs_process(romfs_context* ctx, u32 actions)
ctx->infoblockoffset = ctx->offset + 0x1000; ctx->infoblockoffset = ctx->offset + 0x1000;
fseeko64(ctx->file, ctx->infoblockoffset, SEEK_SET); romfs_fseek(ctx, ctx->infoblockoffset);
fread(&ctx->infoheader, 1, sizeof(romfs_infoheader), ctx->file); romfs_fread(ctx, &ctx->infoheader, 1, sizeof(romfs_infoheader));
if (getle32(ctx->infoheader.headersize) != sizeof(romfs_infoheader)) if (getle32(ctx->infoheader.headersize) != sizeof(romfs_infoheader))
{ {
@@ -71,25 +107,25 @@ void romfs_process(romfs_context* ctx, u32 actions)
fileblockoffset = ctx->infoblockoffset + getle32(ctx->infoheader.section[3].offset); fileblockoffset = ctx->infoblockoffset + getle32(ctx->infoheader.section[3].offset);
fileblocksize = getle32(ctx->infoheader.section[3].size); fileblocksize = getle32(ctx->infoheader.section[3].size);
u32 hdrsize = getle32(ctx->infoheader.dataoffset);
u8 *block = malloc(hdrsize);
romfs_fseek(ctx, ctx->infoblockoffset);
romfs_fread(ctx, block, hdrsize, 1);
ctx->dirblock = malloc(dirblocksize); ctx->dirblock = malloc(dirblocksize);
ctx->dirblocksize = dirblocksize; ctx->dirblocksize = dirblocksize;
if(ctx->dirblock)
memcpy(ctx->dirblock, block + getle32(ctx->infoheader.section[1].offset), dirblocksize);
ctx->fileblock = malloc(fileblocksize); ctx->fileblock = malloc(fileblocksize);
ctx->fileblocksize = fileblocksize; ctx->fileblocksize = fileblocksize;
if (ctx->fileblock)
memcpy(ctx->fileblock, block + getle32(ctx->infoheader.section[3].offset), fileblocksize);
free(block);
ctx->datablockoffset = ctx->infoblockoffset + getle32(ctx->infoheader.dataoffset); ctx->datablockoffset = ctx->infoblockoffset + getle32(ctx->infoheader.dataoffset);
if (ctx->dirblock)
{
fseeko64(ctx->file, dirblockoffset, SEEK_SET);
fread(ctx->dirblock, 1, dirblocksize, ctx->file);
}
if (ctx->fileblock)
{
fseeko64(ctx->file, fileblockoffset, SEEK_SET);
fread(ctx->fileblock, 1, fileblocksize, ctx->file);
}
if (actions & InfoFlag) if (actions & InfoFlag)
romfs_print(ctx); romfs_print(ctx);
@@ -315,7 +351,7 @@ void romfs_extract_datafile(romfs_context* ctx, u64 offset, u64 size, const osch
offset += ctx->datablockoffset; offset += ctx->datablockoffset;
fseeko64(ctx->file, offset, SEEK_SET); romfs_fseek(ctx, offset);
outfile = os_fopen(path, OS_MODE_WRITE); outfile = os_fopen(path, OS_MODE_WRITE);
if (outfile == NULL) if (outfile == NULL)
{ {
@@ -329,7 +365,7 @@ void romfs_extract_datafile(romfs_context* ctx, u64 offset, u64 size, const osch
if (max > size) if (max > size)
max = size; max = size;
if (max != fread(buffer, 1, max, ctx->file)) if (max != romfs_fread(ctx, buffer, 1, max))
{ {
fprintf(stderr, "Error reading file\n"); fprintf(stderr, "Error reading file\n");
goto clean; goto clean;
+9 -1
View File
@@ -57,6 +57,8 @@ typedef struct
FILE* file; FILE* file;
oschar_t* extractdir; oschar_t* extractdir;
settings* usersettings; settings* usersettings;
u8 counter[16];
u8 key[16];
u64 offset; u64 offset;
u64 size; u64 size;
romfs_header header; romfs_header header;
@@ -70,6 +72,8 @@ typedef struct
romfs_direntry direntry; romfs_direntry direntry;
romfs_fileentry fileentry; romfs_fileentry fileentry;
ivfc_context ivfc; ivfc_context ivfc;
ctr_aes_context aes;
int encrypted;
} romfs_context; } romfs_context;
void romfs_init(romfs_context* ctx); void romfs_init(romfs_context* ctx);
@@ -77,7 +81,11 @@ void romfs_set_file(romfs_context* ctx, FILE* file);
void romfs_set_offset(romfs_context* ctx, u64 offset); void romfs_set_offset(romfs_context* ctx, u64 offset);
void romfs_set_size(romfs_context* ctx, u64 size); void romfs_set_size(romfs_context* ctx, u64 size);
void romfs_set_usersettings(romfs_context* ctx, settings* usersettings); void romfs_set_usersettings(romfs_context* ctx, settings* usersettings);
void romfs_test(romfs_context* ctx); void romfs_set_encrypted(romfs_context* ctx, u32 encrypted);
void romfs_set_key(romfs_context* ctx, u8 key[16]);
void romfs_set_counter(romfs_context* ctx, u8 counter[16]);
void romfs_fseek(romfs_context* ctx, u64 offset);
size_t romfs_fread(romfs_context* ctx, void* buffer, size_t size, size_t count);
int romfs_dirblock_read(romfs_context* ctx, u32 diroffset, u32 dirsize, void* buffer); int romfs_dirblock_read(romfs_context* ctx, u32 diroffset, u32 dirsize, void* buffer);
int romfs_dirblock_readentry(romfs_context* ctx, u32 diroffset, romfs_direntry* entry); int romfs_dirblock_readentry(romfs_context* ctx, u32 diroffset, romfs_direntry* entry);
int romfs_fileblock_read(romfs_context* ctx, u32 fileoffset, u32 filesize, void* buffer); int romfs_fileblock_read(romfs_context* ctx, u32 fileoffset, u32 filesize, void* buffer);
+13
View File
@@ -120,6 +120,14 @@ filepath* settings_get_content_path(settings* usersettings)
return 0; return 0;
} }
filepath* settings_get_plainrgn_path(settings* usersettings)
{
if (usersettings)
return &usersettings->plainrgnpath;
else
return 0;
}
unsigned int settings_get_mediaunit_size(settings* usersettings) unsigned int settings_get_mediaunit_size(settings* usersettings)
{ {
if (usersettings) if (usersettings)
@@ -255,6 +263,11 @@ void settings_set_romfs_dir_path(settings* usersettings, const char* path)
filepath_set(&usersettings->romfsdirpath, path); filepath_set(&usersettings->romfsdirpath, path);
} }
void settings_set_plainrgn_path(settings* usersettings, const char* path)
{
filepath_set(&usersettings->plainrgnpath, path);
}
void settings_set_mediaunit_size(settings* usersettings, unsigned int size) void settings_set_mediaunit_size(settings* usersettings, unsigned int size)
{ {
usersettings->mediaunitsize = size; usersettings->mediaunitsize = size;
+3
View File
@@ -15,6 +15,7 @@ typedef struct
filepath romfsdirpath; filepath romfsdirpath;
filepath exheaderpath; filepath exheaderpath;
filepath logopath; filepath logopath;
filepath plainrgnpath;
filepath certspath; filepath certspath;
filepath contentpath; filepath contentpath;
filepath tikpath; filepath tikpath;
@@ -43,6 +44,7 @@ filepath* settings_get_exefs_dir_path(settings* usersettings);
filepath* settings_get_romfs_dir_path(settings* usersettings); filepath* settings_get_romfs_dir_path(settings* usersettings);
filepath* settings_get_firm_dir_path(settings* usersettings); filepath* settings_get_firm_dir_path(settings* usersettings);
filepath* settings_get_wav_path(settings* usersettings); filepath* settings_get_wav_path(settings* usersettings);
filepath* settings_get_plainrgn_path(settings* usersettings);
unsigned int settings_get_mediaunit_size(settings* usersettings); unsigned int settings_get_mediaunit_size(settings* usersettings);
unsigned char* settings_get_ncch_key(settings* usersettings); unsigned char* settings_get_ncch_key(settings* usersettings);
unsigned char* settings_get_ncch_fixedsystemkey(settings* usersettings); unsigned char* settings_get_ncch_fixedsystemkey(settings* usersettings);
@@ -66,6 +68,7 @@ void settings_set_exefs_dir_path(settings* usersettings, const char* path);
void settings_set_romfs_dir_path(settings* usersettings, const char* path); void settings_set_romfs_dir_path(settings* usersettings, const char* path);
void settings_set_firm_dir_path(settings* usersettings, const char* path); void settings_set_firm_dir_path(settings* usersettings, const char* path);
void settings_set_wav_path(settings* usersettings, const char* path); void settings_set_wav_path(settings* usersettings, const char* path);
void settings_set_plainrgn_path(settings* usersettings, const char* path);
void settings_set_mediaunit_size(settings* usersettings, unsigned int size); void settings_set_mediaunit_size(settings* usersettings, unsigned int size);
void settings_set_ignore_programid(settings* usersettings, int enable); void settings_set_ignore_programid(settings* usersettings, int enable);
void settings_set_list_romfs_files(settings* usersettings, int enable); void settings_set_list_romfs_files(settings* usersettings, int enable);
+37
View File
@@ -84,6 +84,43 @@ void putle32(u8* p, u32 n)
p[3] = n>>24; p[3] = n>>24;
} }
void putle64(u8* p, u64 n)
{
p[0] = n;
p[1] = n >> 8;
p[2] = n >> 16;
p[3] = n >> 24;
p[4] = n >> 32;
p[5] = n >> 40;
p[6] = n >> 48;
p[7] = n >> 56;
}
void putbe16(u8* p, u16 n)
{
p[1] = n;
p[0] = n >> 8;
}
void putbe32(u8* p, u32 n)
{
p[3] = n;
p[2] = n >> 8;
p[1] = n >> 16;
p[0] = n >> 24;
}
void putbe64(u8* p, u64 n)
{
p[7] = n;
p[6] = n >> 8;
p[5] = n >> 16;
p[4] = n >> 24;
p[3] = n >> 32;
p[2] = n >> 40;
p[1] = n >> 48;
p[0] = n >> 56;
}
void readkeyfile(u8* key, const char* keyfname) void readkeyfile(u8* key, const char* keyfname)
{ {
+4
View File
@@ -27,6 +27,10 @@ u32 getbe32(const u8* p);
u32 getbe16(const u8* p); u32 getbe16(const u8* p);
void putle16(u8* p, u16 n); void putle16(u8* p, u16 n);
void putle32(u8* p, u32 n); void putle32(u8* p, u32 n);
void putle64(u8* p, u64 n);
void putbe16(u8* p, u16 n);
void putbe32(u8* p, u32 n);
void putbe64(u8* p, u64 n);
void readkeyfile(u8* key, const char* keyfname); void readkeyfile(u8* key, const char* keyfname);
void memdump(FILE* fout, const char* prefix, const u8* data, u32 size); void memdump(FILE* fout, const char* prefix, const u8* data, u32 size);