mirror of
https://github.com/DarkStore-3DS/Project_CTR.git
synced 2026-07-03 08:49:03 +00:00
9c548197c1
lots cleaned, added cia to cci conv, it 's called a block, separated reading from building, improved ncch keyx stuff, and basic verbose for keys, elf checking and romfs
180 lines
5.2 KiB
C
180 lines
5.2 KiB
C
#include "lib.h"
|
|
#include "ncch_build.h"
|
|
#include "exefs_build.h"
|
|
|
|
// Private Prototypes
|
|
u32 PredictExeFS_Size(exefs_buildctx *ctx);
|
|
int GenerateExeFS_Header(exefs_buildctx *ctx, u8 *outbuff);
|
|
void FreeExeFSContext(exefs_buildctx *ctx);
|
|
int ImportDatatoExeFS(exefs_buildctx *ctx, u8 *outbuff);
|
|
int ImportToExeFSContext(exefs_buildctx *ctx, char *name, u8 *buffer, u32 size);
|
|
|
|
// ExeFs Build Functions
|
|
int BuildExeFs(ncch_settings *ncchset)
|
|
{
|
|
/* Intialising ExeFs Build Context */
|
|
exefs_buildctx *ctx = calloc(1,sizeof(exefs_buildctx));
|
|
if(!ctx) {
|
|
fprintf(stderr,"[EXEFS ERROR] Not enough memory\n");
|
|
return MEM_ERROR;
|
|
}
|
|
ctx->blockSize = ncchset->options.blockSize;
|
|
|
|
/* Importing ExeFs */
|
|
if(ncchset->exefsSections.code.size)
|
|
ImportToExeFSContext(ctx,".code",ncchset->exefsSections.code.buffer,ncchset->exefsSections.code.size);
|
|
if(ncchset->exefsSections.banner.size)
|
|
ImportToExeFSContext(ctx,"banner",ncchset->exefsSections.banner.buffer,ncchset->exefsSections.banner.size);
|
|
if(ncchset->exefsSections.icon.size)
|
|
ImportToExeFSContext(ctx,"icon",ncchset->exefsSections.icon.buffer,ncchset->exefsSections.icon.size);
|
|
if(ncchset->sections.logo.size && ncchset->options.IncludeExeFsLogo)
|
|
ImportToExeFSContext(ctx,"logo",ncchset->sections.logo.buffer,ncchset->sections.logo.size);
|
|
|
|
if(ctx->fileCount == 0){ // no exefs needed
|
|
ncchset->sections.exeFs.size = 0;
|
|
ncchset->sections.exeFs.buffer = NULL;
|
|
return 0;
|
|
}
|
|
|
|
/* Allocating Memory for ExeFs */
|
|
ncchset->sections.exeFs.size = PredictExeFS_Size(ctx);
|
|
ncchset->sections.exeFs.buffer = malloc(ncchset->sections.exeFs.size);
|
|
if(!ncchset->sections.exeFs.buffer){
|
|
printf("[EXEFS ERROR] Could Not Allocate Memory for ExeFS\n");
|
|
return Fail;
|
|
}
|
|
memset(ncchset->sections.exeFs.buffer,0,ncchset->sections.exeFs.size);
|
|
|
|
/* Generating Header, and writing sections to buffer */
|
|
GenerateExeFS_Header(ctx,ncchset->sections.exeFs.buffer);
|
|
ImportDatatoExeFS(ctx,ncchset->sections.exeFs.buffer);
|
|
|
|
/* Finish */
|
|
FreeExeFSContext(ctx);
|
|
return 0;
|
|
}
|
|
|
|
u32 PredictExeFS_Size(exefs_buildctx *ctx)
|
|
{
|
|
u32 exefs_size = sizeof(exefs_hdr); // Size of header
|
|
for(int i = 0; i < ctx->fileCount; i++)
|
|
exefs_size += align(ctx->fileSize[i],ctx->blockSize);
|
|
//exefs_size = align(ctx->exefs_size,ctx->mediaUnit);
|
|
return exefs_size;
|
|
}
|
|
|
|
int GenerateExeFS_Header(exefs_buildctx *ctx, u8 *outbuff)
|
|
{
|
|
for(int i = 0; i < ctx->fileCount; i++){
|
|
if(i == 0)
|
|
ctx->fileOffset[i] = 0;
|
|
else
|
|
ctx->fileOffset[i] = align((ctx->fileOffset[i-1]+ctx->fileSize[i-1]),ctx->blockSize);
|
|
|
|
memcpy(ctx->fileHdr[i].name,ctx->fileName[i],8);
|
|
u32_to_u8(ctx->fileHdr[i].offset,ctx->fileOffset[i],LE);
|
|
u32_to_u8(ctx->fileHdr[i].size,ctx->fileSize[i],LE);
|
|
ctr_sha(ctx->file[i],ctx->fileSize[i],ctx->fileHashes[9-i],CTR_SHA_256);
|
|
}
|
|
memcpy(outbuff,ctx->fileHdr,sizeof(exefs_filehdr)*10);
|
|
memcpy(outbuff+0xc0,ctx->fileHashes,0x20*10);
|
|
return 0;
|
|
}
|
|
|
|
void FreeExeFSContext(exefs_buildctx *ctx)
|
|
{
|
|
/*
|
|
if(ctx->outbuff != NULL)
|
|
free(ctx->outbuff);
|
|
for(int i = 0; i < 10; i++){
|
|
if(ctx->file[i] != NULL)
|
|
free(ctx->file[i]);
|
|
}
|
|
*/
|
|
memset(ctx,0,sizeof(exefs_buildctx));
|
|
free(ctx);
|
|
}
|
|
|
|
int ImportDatatoExeFS(exefs_buildctx *ctx, u8 *outbuff)
|
|
{
|
|
for(int i = 0; i < ctx->fileCount; i++){
|
|
memcpy(outbuff+ctx->fileOffset[i]+0x200,ctx->file[i],ctx->fileSize[i]);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int ImportToExeFSContext(exefs_buildctx *ctx, char *name, u8 *buffer, u32 size)
|
|
{
|
|
if(ctx == NULL || name == NULL || buffer == NULL){
|
|
printf("[!] PTR ERROR\n");
|
|
return PTR_ERROR;
|
|
}
|
|
if(ctx->fileCount >= MAX_EXEFS_SECTIONS){
|
|
printf("[!] Maximum ExeFS Capacity Reached\n");
|
|
return EXEFS_MAX_REACHED;
|
|
}
|
|
if(strlen(name) > 8){
|
|
printf("[!] ExeFS File Name: '%s' is too large\n",name);
|
|
return EXEFS_SECTION_NAME_ERROR;
|
|
}
|
|
|
|
ctx->fileCount++;
|
|
ctx->file[ctx->fileCount - 1] = buffer;
|
|
ctx->fileSize[ctx->fileCount - 1] = size;
|
|
strcpy(ctx->fileName[ctx->fileCount - 1],name);
|
|
return 0;
|
|
}
|
|
|
|
// ExeFs Read Functions
|
|
bool DoesExeFsSectionExist(char *section, u8 *ExeFs)
|
|
{
|
|
exefs_hdr *hdr = (exefs_hdr*) ExeFs;
|
|
for(int i = 0; i < MAX_EXEFS_SECTIONS; i++){
|
|
if(strncmp(hdr->fileHdr[i].name,section,8) == 0) return true;
|
|
}
|
|
return false;
|
|
}
|
|
u8* GetExeFsSection(char *section, u8 *ExeFs)
|
|
{
|
|
exefs_hdr *hdr = (exefs_hdr*) ExeFs;
|
|
for(int i = 0; i < MAX_EXEFS_SECTIONS; i++){
|
|
if(strncmp(hdr->fileHdr[i].name,section,8) == 0){
|
|
u32 offset = u8_to_u32(hdr->fileHdr[i].offset,LE) + sizeof(exefs_hdr);
|
|
return (u8*)(ExeFs+offset);
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
u8* GetExeFsSectionHash(char *section, u8 *ExeFs)
|
|
{
|
|
exefs_hdr *hdr = (exefs_hdr*) ExeFs;
|
|
for(int i = 0; i < MAX_EXEFS_SECTIONS; i++){
|
|
if(strncmp(hdr->fileHdr[i].name,section,8) == 0){
|
|
return (u8*)(hdr->fileHashes[MAX_EXEFS_SECTIONS-1-i]);
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
u32 GetExeFsSectionSize(char *section, u8 *ExeFs)
|
|
{
|
|
exefs_hdr *hdr = (exefs_hdr*) ExeFs;
|
|
for(int i = 0; i < MAX_EXEFS_SECTIONS; i++){
|
|
if(strncmp(hdr->fileHdr[i].name,section,8) == 0){
|
|
return u8_to_u32(hdr->fileHdr[i].size,LE);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
u32 GetExeFsSectionOffset(char *section, u8 *ExeFs)
|
|
{
|
|
exefs_hdr *hdr = (exefs_hdr*) ExeFs;
|
|
for(int i = 0; i < MAX_EXEFS_SECTIONS; i++){
|
|
if(strncmp(hdr->fileHdr[i].name,section,8) == 0){
|
|
return u8_to_u32(hdr->fileHdr[i].offset,LE) + sizeof(exefs_hdr);
|
|
}
|
|
}
|
|
return 0;
|
|
} |