From e7dc460436fcf8fd4a71f1936df1545bea61b993 Mon Sep 17 00:00:00 2001 From: jakcron Date: Wed, 11 Nov 2015 23:20:03 +0800 Subject: [PATCH] [makerom] Fixed makerom ROMFS file limitation. +Several bug fixes. --- makerom/Makefile | 2 +- makerom/cia.c | 23 +++- makerom/code.c | 14 +- makerom/dir.c | 287 +++++++++++++++++++++++----------------- makerom/dir.h | 28 +++- makerom/ncch.c | 19 ++- makerom/ncsd.c | 24 ++++ makerom/romfs.c | 2 +- makerom/romfs.h | 2 + makerom/romfs_gen.c | 127 +++++++----------- makerom/titleid.c | 14 +- makerom/user_settings.c | 43 +++--- makerom/utils.c | 44 +++--- makerom/utils.h | 12 +- 14 files changed, 369 insertions(+), 272 deletions(-) diff --git a/makerom/Makefile b/makerom/Makefile index e68a81c..d15d60f 100644 --- a/makerom/Makefile +++ b/makerom/Makefile @@ -5,7 +5,7 @@ OBJS = $(foreach dir,$(SRC_DIR),$(subst .c,.o,$(wildcard $(dir)/*.c))) # Compiler Settings LIBS = -static-libgcc CXXFLAGS = -I. -CFLAGS = --std=c99 -O2 -flto -Wall -Wno-unused-but-set-variable -Wno-unused-value -I. $(MAKEROM_BUILD_FLAGS) +CFLAGS = --std=c99 -Wall -Wno-unused-but-set-variable -Wno-unused-value -I. $(MAKEROM_BUILD_FLAGS) CC = gcc CXX = g++ diff --git a/makerom/cia.c b/makerom/cia.c index 719c91b..36b54d9 100644 --- a/makerom/cia.c +++ b/makerom/cia.c @@ -571,16 +571,27 @@ u16 SetupVersion(u16 major, u16 minor, u16 micro) void GetContentHashes(cia_settings *ciaset) { - for(int i = 0; i < ciaset->content.count; i++) - ShaCalc(ciaset->ciaSections.content.buffer+ciaset->content.offset[i],ciaset->content.size[i],ciaset->content.hash[i],CTR_SHA_256); + for (int i = 0; i < ciaset->content.count; i++) { + if (ciaset->verbose) + printf("[CIA] Hashing content %d... ", i); + ShaCalc(ciaset->ciaSections.content.buffer + ciaset->content.offset[i], ciaset->content.size[i], ciaset->content.hash[i], CTR_SHA_256); + if (ciaset->verbose) + printf("Done!\n"); + } } void EncryptContent(cia_settings *ciaset) { for(int i = 0; i < ciaset->content.count; i++){ + if (ciaset->verbose) + printf("[CIA] Encrypting content %d... ", i); + ciaset->content.flags[i] |= content_Encrypted; u8 *content = ciaset->ciaSections.content.buffer+ciaset->content.offset[i]; CryptContent(content, content, ciaset->content.size[i], ciaset->common.titleKey, i, ENC); + + if (ciaset->verbose) + printf("Done!\n"); } } @@ -638,12 +649,20 @@ int BuildCiaHdr(cia_settings *ciaset) int WriteCiaToFile(cia_settings *ciaset) { + if (ciaset->verbose) { + printf("[CIA] Writing to file... "); + } WriteBuffer(ciaset->ciaSections.ciaHdr.buffer,ciaset->ciaSections.ciaHdr.size,0,ciaset->out); WriteBuffer(ciaset->ciaSections.certChain.buffer,ciaset->ciaSections.certChain.size,ciaset->ciaSections.certChainOffset,ciaset->out); WriteBuffer(ciaset->ciaSections.tik.buffer,ciaset->ciaSections.tik.size,ciaset->ciaSections.tikOffset,ciaset->out); WriteBuffer(ciaset->ciaSections.tmd.buffer,ciaset->ciaSections.tmd.size,ciaset->ciaSections.tmdOffset,ciaset->out); WriteBuffer(ciaset->ciaSections.content.buffer,ciaset->ciaSections.content.size,ciaset->ciaSections.contentOffset,ciaset->out); WriteBuffer(ciaset->ciaSections.meta.buffer,ciaset->ciaSections.meta.size,ciaset->ciaSections.metaOffset,ciaset->out); + + if (ciaset->verbose) { + printf("Done!\n"); + } + return 0; } diff --git a/makerom/code.c b/makerom/code.c index ea31b2c..07ee74a 100644 --- a/makerom/code.c +++ b/makerom/code.c @@ -41,7 +41,7 @@ int ImportExeFsCodeBinaryFromFile(ncch_settings *set) u32 size = set->componentFilePtrs.codeSize; u8 *buffer = malloc(size); if (!buffer) { - fprintf(stderr, "[ELF ERROR] Not enough memory\n"); + fprintf(stderr, "[CODE ERROR] Not enough memory\n"); return MEM_ERROR; } ReadFile64(buffer, size, 0, set->componentFilePtrs.code); @@ -51,10 +51,14 @@ int ImportExeFsCodeBinaryFromFile(ncch_settings *set) if (!set->exefsSections.code.buffer) { fprintf(stderr, "[ELF ERROR] Not enough memory\n"); return MEM_ERROR; } ReadFile64(set->exefsSections.code.buffer, set->exefsSections.code.size, 0, set->componentFilePtrs.code); if (set->options.CompressCode) { + if (set->options.verbose) + printf("[CODE] Compressing code... "); u32 new_len; set->exefsSections.code.buffer = BLZ_Code(buffer, size, &new_len, BLZ_NORMAL); set->exefsSections.code.size = new_len; free(buffer); + if (set->options.verbose) + printf("Done!\n"); } else { set->exefsSections.code.size = size; @@ -63,12 +67,12 @@ int ImportExeFsCodeBinaryFromFile(ncch_settings *set) size = set->componentFilePtrs.exhdrSize; if (size < sizeof(extended_hdr)) { - fprintf(stderr, "[ELF ERROR] Exheader code info template is too small\n"); + fprintf(stderr, "[CODE ERROR] Exheader code info template is too small\n"); return FAILED_TO_IMPORT_FILE; } extended_hdr *exhdr = malloc(size); if (!exhdr) { - fprintf(stderr, "[ELF ERROR] Not enough memory\n"); + fprintf(stderr, "[CODE ERROR] Not enough memory\n"); return MEM_ERROR; } ReadFile64(exhdr, size, 0, set->componentFilePtrs.exhdr); @@ -245,10 +249,14 @@ int CreateExeFsCode(elf_context *elf, ncch_settings *set) /* Compressing If needed */ if (set->options.CompressCode) { + if (set->options.verbose) + printf("[CODE] Compressing code... "); u32 new_len; set->exefsSections.code.buffer = BLZ_Code(code, size, &new_len, BLZ_NORMAL); set->exefsSections.code.size = new_len; free(code); + if (set->options.verbose) + printf("Done!\n"); } else { set->exefsSections.code.size = size; diff --git a/makerom/dir.c b/makerom/dir.c index 8d8027b..097c44e 100644 --- a/makerom/dir.c +++ b/makerom/dir.c @@ -2,31 +2,125 @@ #include "dir.h" #include "utf.h" +const fs_romfs_char FS_CURRENT_DIR_PATH = 0x2E; +const fs_romfs_char FS_PARENT_DIR_PATH[2] = { 0x2E,0x2E }; + /* This is the FS interface for ROMFS generation */ /* Tested working on Windows/Linux/OSX */ -int fs_InitDir(u16 *path, u32 pathlen, fs_dir *dir); +int fs_InitDir(const fs_entry *entry, fs_dir *dir); int fs_ManageDirSlot(fs_dir *dir); int fs_ManageFileSlot(fs_dir *dir); void fs_chdirUp(void); -fs_entry* fs_GetEntry(fs_DIR *dp); +fs_entry* fs_GetEntry(const fs_char *parent_path, fs_DIR *dp); void fs_FreeEntry(fs_entry *entry); bool fs_EntryIsDirNav(fs_entry *entry); int fs_AddDir(fs_entry *entry, fs_dir *dir); int fs_AddFile(fs_entry *entry, fs_dir *dir); -int fs_RomFsStrLen(fs_romfs_char *str) +u32 fs_romfs_strlen(const fs_romfs_char *str) { - int i; + u32 i; for( i = 0; str[i] != 0x0; i++ ); return i; } -int fs_InitDir(u16 *path, u32 pathlen, fs_dir *dir) +u32 fs_strlen(const fs_char *str) { - dir->name_len = pathlen; - dir->name = calloc(dir->name_len+2,1); - memcpy(dir->name,path,dir->name_len); - + u32 i; + for (i = 0; str[i] != 0x0; i++); + return i; +} + +FILE* fs_fopen(fs_char *path) +{ +#ifdef _WIN32 + return _wfopen(path, L"rb"); +#else + return fopen(path, "rb"); +#endif +} + +u64 fs_fsize(fs_char *path) +{ +#ifdef _WIN32 + return wGetFileSize64(path); +#else + return GetFileSize64(path); +#endif +} + +fs_char* fs_AppendToPath(const fs_char *src, const fs_char *add) +{ + u32 src_len, add_len; + fs_char *new_path; + + src_len = fs_strlen(src); + add_len = fs_strlen(add); + new_path = calloc(src_len + add_len + 0x10, sizeof(fs_char)); + +#ifdef _WIN32 + _snwprintf(new_path, src_len + add_len + 0x10, L"%s%c%s", src, FS_PATH_SEPARATOR, add); +#else + snprintf(new_path, src_len + add_len + 0x10, "%s%c%s", src, FS_PATH_SEPARATOR, add); +#endif + + return new_path; +} + +fs_char* fs_CopyPath(const fs_char *src) +{ + u32 src_len; + fs_char *new_path; + + src_len = fs_strlen(src); + new_path = calloc(src_len + 0x10, sizeof(fs_char)); + + for (u32 i = 0; i < src_len; i++) + new_path[i] = src[i]; + + return new_path; +} + +fs_romfs_char* fs_CopyRomfsName(const fs_romfs_char *src) +{ + u32 src_len; + fs_romfs_char *new_path; + + src_len = fs_strlen(src); + new_path = calloc(src_len + 0x10, sizeof(fs_romfs_char)); + + for (u32 i = 0; i < src_len; i++) + new_path[i] = src[i]; + + return new_path; +} + +void fs_fputs(FILE *out, const fs_char *str) +{ +#ifdef _WIN32 + wprintf(L"%s", str); +#else + printf("%s", str); +#endif +} + +void fs_romfs_fputs(FILE *out, const fs_romfs_char *str) +{ +#ifdef _WIN32 + wprintf(L"%s", str); +#else + const char *name = (const char*)str; + for (u32 i = 0; i < fs_romfs_strlen(str)*2; i += 2) + putchar(name[i]); +#endif +} + +int fs_InitDir(const fs_entry *entry, fs_dir *dir) +{ + dir->fs_path = fs_CopyPath(entry->fs_path); + + dir->name_len = entry->name_len; + dir->name = fs_CopyRomfsName(entry->name); dir->m_child = 10; dir->u_child = 0; @@ -65,16 +159,7 @@ int fs_ManageFileSlot(fs_dir *dir) return 0; } -void fs_chdirUp(void) -{ -#ifdef _WIN32 - fs_chdir(L".."); -#else - fs_chdir(".."); -#endif -} - -fs_entry* fs_GetEntry(fs_DIR *dp) +fs_entry* fs_GetEntry(const fs_char *parent_path, fs_DIR *dp) { // Directory structs struct fs_dirent *tmp_entry; @@ -99,9 +184,9 @@ fs_entry* fs_GetEntry(fs_DIR *dp) memset(entry,0,sizeof(fs_entry)); //Copy FS compatible Entry name - entry->fs_name = malloc(sizeof(fs_char)*(namlen+1)); - memset(entry->fs_name,0,sizeof(fs_char)*(namlen+1)); - memcpy(entry->fs_name,tmp_entry->d_name,sizeof(fs_char)*namlen); + fs_char *fs_name = calloc(sizeof(fs_char)*(namlen+1),1); + memcpy(fs_name,tmp_entry->d_name,sizeof(fs_char)*namlen); + entry->fs_path = fs_AppendToPath(parent_path, fs_name); // Convert Entry name into RomFS u16 char (windows wchar_t, thanks Nintendo) #if _WIN32 @@ -111,45 +196,41 @@ fs_entry* fs_GetEntry(fs_DIR *dp) #endif //printf("get dir entry from dir ptr to check if dir\n"); - tmp_dptr = fs_opendir(entry->fs_name); + tmp_dptr = fs_opendir(entry->fs_path); if(tmp_dptr) { //printf("is dir\n"); fs_closedir(tmp_dptr); entry->IsDir = true; entry->size = 0; - entry->fp = NULL; } else // Open file if it is a file { entry->IsDir = false; -#ifdef _WIN32 - entry->size = wGetFileSize64(entry->fs_name); - entry->fp = _wfopen(entry->fs_name,L"rb"); -#else - entry->size = GetFileSize64(entry->fs_name); - entry->fp = fopen(entry->fs_name,"rb"); -#endif + entry->size = fs_fsize(entry->fs_path); } - //printf("fs_GetEntry() return\n"); + + // Don't bother returning current entry, if it is useless + if (fs_EntryIsDirNav(entry)) { + fs_FreeEntry(entry); + return fs_GetEntry(parent_path, dp); + } + return entry; } void fs_FreeEntry(fs_entry *entry) { - free(entry->fs_name); + free(entry->fs_path); free(entry->name); free(entry); } bool fs_EntryIsDirNav(fs_entry *entry) { - //memdump(stdout,"Entry RomFS Name: ",(u8*)entry->name,entry->name_len); - const fs_romfs_char currentdir = 0x2E; - const fs_romfs_char upperdir[2] = {0x2E,0x2E}; - if(entry->name_len == sizeof(fs_romfs_char)*1 && memcmp(entry->name,¤tdir,sizeof(fs_romfs_char)*1) == 0) + if(entry->name_len == sizeof(fs_romfs_char)*1 && memcmp(entry->name,&FS_CURRENT_DIR_PATH,sizeof(fs_romfs_char)*1) == 0) return true; - if(entry->name_len == sizeof(fs_romfs_char)*2 && memcmp(entry->name,upperdir,sizeof(fs_romfs_char)*2) == 0) + if(entry->name_len == sizeof(fs_romfs_char)*2 && memcmp(entry->name,FS_PARENT_DIR_PATH,sizeof(fs_romfs_char)*2) == 0) return true; return false; @@ -159,84 +240,70 @@ int fs_AddDir(fs_entry *entry, fs_dir *dir) { fs_ManageDirSlot(dir); u32 current_slot = dir->u_child; + dir->u_child++; - return fs_OpenDir(entry->fs_name,entry->name,entry->name_len,&dir->child[current_slot]); + return fs_OpenDir(entry,&dir->child[current_slot]); } int fs_AddFile(fs_entry *entry, fs_dir *dir) { fs_ManageFileSlot(dir); + dir->file[dir->u_file].fs_path = fs_CopyPath(entry->fs_path); dir->file[dir->u_file].name_len = entry->name_len; - dir->file[dir->u_file].name = malloc(entry->name_len+2); - memset(dir->file[dir->u_file].name,0,entry->name_len+2); - memcpy(dir->file[dir->u_file].name,entry->name,entry->name_len); - + dir->file[dir->u_file].name = fs_CopyRomfsName(entry->name); dir->file[dir->u_file].size = entry->size; - dir->file[dir->u_file].fp = entry->fp; dir->u_file++; return 0; } -int fs_OpenDir(fs_char *fs_path, fs_romfs_char *path, u32 pathlen, fs_dir *dir) +int fs_OpenRootDir(const char *path, fs_dir *dir) +{ + fs_entry *root = calloc(1, sizeof(fs_entry)); + u32 nul; + + root->IsDir = true; + root->size = 0; + + str_u16_to_u16(&root->name, &root->name_len, ROMFS_EMPTY_PATH, 0); +#ifdef _WIN32 + str_u8_to_u16(&root->fs_path, &nul, (u8*)path, strlen(path)); +#else + str_u8_to_u8(&root->fs_path, &nul, (u8*)path, strlen(path)); +#endif + + + int ret = fs_OpenDir(root, dir); + + fs_FreeEntry(root); + + return ret; +} + +int fs_OpenDir(fs_entry *curr_dir_entry, fs_dir *dir) { //printf("init open dir\n"); int ret = 0; fs_DIR *dp; fs_entry *entry; + //printf("do some more init\n"); + fs_InitDir(curr_dir_entry, dir); + //wprintf(L" rec: \"%s\" (%d)\n",dir->name,dir->name_len); + //printf("check if path exists\n"); - dp = fs_opendir(fs_path); + dp = fs_opendir(dir->fs_path); if(!dp) { - //wprintf(L"[!] Failed to open directory: \"%s\"\n",path); + wprintf(L"[!] Failed to open directory: \"%s\"\n",dir->fs_path); return -1; } - //printf("do some more init\n"); - fs_InitDir(path,pathlen,dir); - //wprintf(L" rec: \"%s\" (%d)\n",dir->name,dir->name_len); - - //printf("chdir\n"); - fs_chdir(fs_path); - //printf("read entries\n"); - while((entry = fs_GetEntry(dp))) - { - if(!entry) - { - ret = -1; - break; - } - - if(entry->IsDir) - { - //printf("Found Dir "); - if(!fs_EntryIsDirNav(entry)) - { -#ifdef _WIN32 - //wprintf(L"is a dir: \"%s\" (%d)\n",entry->fs_name,entry->name_len); -#else - //printf("is a dir: \"%s\" (%d)\n",entry->fs_name,entry->name_len); -#endif - ret = fs_AddDir(entry,dir); - } - else - { - //printf("Not wanted dir\n"); - ret = 0; - } - } - else - { -#ifdef _WIN32 - //wprintf(L"is a file: \"%s\" (%d)\n",entry->fs_name,entry->name_len); -#else - //printf("is a file: \"%s\" (%d)\n",entry->fs_name,entry->name_len); -#endif - ret = fs_AddFile(entry,dir); - } - + while((entry = fs_GetEntry(dir->fs_path, dp)) != NULL) + { + ret = entry->IsDir? fs_AddDir(entry, dir) : fs_AddFile(entry, dir); + //printf("free entry\n"); fs_FreeEntry(entry); @@ -246,11 +313,7 @@ int fs_OpenDir(fs_char *fs_path, fs_romfs_char *path, u32 pathlen, fs_dir *dir) break; } } - //printf("close dir ptr\n"); fs_closedir(dp); - //printf("return up dir\n"); - fs_chdirUp(); - //printf("return from fs_OpenDir();\n"); return ret; } @@ -260,14 +323,11 @@ void fs_PrintDir(fs_dir *dir, u32 depth) // This is just for simple debugging, p for(u32 i = 0; i < depth; i++) printf(" "); -#ifdef _WIN32 - wprintf(L"%s\n",dir->name); -#else - char *name = (char*)dir->name; - for(u32 i = 0; i < dir->name_len; i+=2) - putchar(name[i]); + if (depth > 0) + fs_romfs_fputs(stdout, dir->name); + else + printf("romfs:"); putchar('\n'); -#endif if(dir->u_file) { @@ -275,15 +335,8 @@ void fs_PrintDir(fs_dir *dir, u32 depth) // This is just for simple debugging, p { for(u32 j = 0; j < depth+1; j++) printf(" "); - -#ifdef _WIN32 - wprintf(L"%s (0x%lx)\n",dir->file[i].name,dir->file[i].size); -#else - name = (char*)dir->file[i].name; - for(u32 j = 0; j < dir->file[i].name_len; j+=2) - putchar(name[j]); - printf(" (0x%llx)\n",dir->file[i].size); -#endif + fs_romfs_fputs(stdout, dir->file[i].name); + printf(" (0x%"PRIx64")\n", dir->file[i].size); } } if(dir->u_child) @@ -298,6 +351,7 @@ void fs_FreeDir(fs_dir *dir) //printf("DIR!! free file names\n"); for(u32 i = 0; i < dir->u_file; i++) { + free(dir->file[i].fs_path); free(dir->file[i].name); } //printf("free file struct\n"); @@ -307,22 +361,11 @@ void fs_FreeDir(fs_dir *dir) //printf("free dir names and\n"); for(u32 i = 0; i < dir->u_child; i++) { + free(dir->child[i].fs_path); free(dir->child[i].name); fs_FreeDir(&dir->child[i]); } //printf("free dir struct\n"); free(dir->child); -} - -void fs_FreeFiles(fs_dir *dir) -{ - for(u32 i = 0; i < dir->u_file; i++) - { - if(dir->file[i].fp) - fclose(dir->file[i].fp); - } - - for(u32 i = 0; i < dir->u_child; i++) - fs_FreeFiles(&dir->child[i]); } \ No newline at end of file diff --git a/makerom/dir.h b/makerom/dir.h index f7c6938..aadd98f 100644 --- a/makerom/dir.h +++ b/makerom/dir.h @@ -9,6 +9,7 @@ #define fs_chdir _wchdir #define fs_opendir _wopendir #define fs_closedir _wclosedir + #define FS_PATH_SEPARATOR '\\' #else #define fs_romfs_char u16 #define fs_char char @@ -18,29 +19,30 @@ #define fs_chdir chdir #define fs_opendir opendir #define fs_closedir closedir + #define FS_PATH_SEPARATOR '/' #endif struct fs_entry { bool IsDir; - fs_char *fs_name; + fs_char *fs_path; fs_romfs_char *name; u32 name_len; u64 size; - FILE *fp; }; struct fs_file { + fs_char *fs_path; fs_romfs_char *name; u32 name_len; u64 size; - FILE *fp; }; struct fs_dir { + fs_char *fs_path; fs_romfs_char *name; u32 name_len; @@ -57,9 +59,21 @@ typedef struct fs_entry fs_entry; typedef struct fs_file fs_file; typedef struct fs_dir fs_dir; -int fs_RomFsStrLen(fs_romfs_char *str); +static const fs_romfs_char ROMFS_EMPTY_PATH[2] = { 0 }; +static const fs_char FS_EMPTY_PATH[2] = { 0 }; -int fs_OpenDir(fs_char *fs_path, fs_romfs_char *path, u32 pathlen, fs_dir *dir); +u32 fs_romfs_strlen(const fs_romfs_char *str); +u32 fs_strlen(const fs_char *str); +FILE* fs_fopen(fs_char *path); +u64 fs_fsize(fs_char *path); + +fs_char* fs_AppendToPath(const fs_char *src, const fs_char *add); +fs_char* fs_CopyPath(const fs_char *src); +fs_romfs_char* fs_CopyRomfsName(const fs_romfs_char *src); +void fs_fputs(FILE *out, const fs_char *str); +void fs_romfs_fputs(FILE *out, const fs_romfs_char *str); + +int fs_OpenRootDir(const char *path, fs_dir *dir); +int fs_OpenDir(fs_entry *entry, fs_dir *dir); void fs_PrintDir(fs_dir *dir, u32 depth); -void fs_FreeDir(fs_dir *dir); -void fs_FreeFiles(fs_dir *dir); \ No newline at end of file +void fs_FreeDir(fs_dir *dir); \ No newline at end of file diff --git a/makerom/ncch.c b/makerom/ncch.c index 69621d4..384c9de 100644 --- a/makerom/ncch.c +++ b/makerom/ncch.c @@ -536,12 +536,19 @@ int FinaliseNcch(ncch_settings *set) // Crypting Exheader/AcexDesc if(set->cryptoDetails.exhdrSize){ + if (set->options.verbose) + printf("[NCCH] Encypting Exheader... "); CryptNcchRegion(exhdr,set->cryptoDetails.exhdrSize,0x0,set->cryptoDetails.titleId,set->keys->aes.ncchKey0,ncch_exhdr); CryptNcchRegion(acexDesc,set->cryptoDetails.acexSize,set->cryptoDetails.exhdrSize,set->cryptoDetails.titleId,set->keys->aes.ncchKey0,ncch_exhdr); + if (set->options.verbose) + printf("Done!\n"); } // Crypting ExeFs Files if(set->cryptoDetails.exefsSize){ + if (set->options.verbose) + printf("[NCCH] Encrypting ExeFS... "); + exefs_hdr *exefsHdr = (exefs_hdr*)exefs; for(int i = 0; i < MAX_EXEFS_SECTIONS; i++){ u8 *key = NULL; @@ -559,11 +566,19 @@ int FinaliseNcch(ncch_settings *set) } // Crypting ExeFs Header CryptNcchRegion(exefs,sizeof(exefs_hdr),0x0,set->cryptoDetails.titleId,set->keys->aes.ncchKey0,ncch_exefs); + + if (set->options.verbose) + printf("Done!\n"); } // Crypting RomFs - if(set->cryptoDetails.romfsSize) - CryptNcchRegion(romfs,set->cryptoDetails.romfsSize,0x0,set->cryptoDetails.titleId,set->keys->aes.ncchKey1,ncch_romfs); + if (set->cryptoDetails.romfsSize) { + if (set->options.verbose) + printf("[NCCH] Encrypting RomFS... "); + CryptNcchRegion(romfs, set->cryptoDetails.romfsSize, 0x0, set->cryptoDetails.titleId, set->keys->aes.ncchKey1, ncch_romfs); + if (set->options.verbose) + printf("Done!\n"); + } } return 0; diff --git a/makerom/ncsd.c b/makerom/ncsd.c index 23d7dfe..29e4f76 100644 --- a/makerom/ncsd.c +++ b/makerom/ncsd.c @@ -615,6 +615,10 @@ int CheckRomConfig(cci_settings *set) void WriteCciDataToOutput(cci_settings *set) { + if (set->options.verbose) { + printf("[CCI] Writing header to file... "); + } + // NCSD Header WriteBuffer(set->headers.ccihdr.buffer, set->headers.ccihdr.size, 0, set->out); // Card Info Header @@ -629,18 +633,34 @@ void WriteCciDataToOutput(cci_settings *set) memset(dummy_data, 0xff, len); WriteBuffer(dummy_data, len, (set->headers.ccihdr.size + set->headers.cardinfohdr.size),set->out); free(dummy_data); + + if (set->options.verbose) { + printf("Done!\n"); + } // NCCH Partitions u8 *ncch; for(int i = 0; i < CCI_MAX_CONTENT; i++){ if(set->content.active[i]){ + if (set->options.verbose) { + printf("[CCI] Writing content %d to file... ", i); + } + ncch = set->content.data + set->content.dOffset[i]; WriteBuffer(ncch, set->content.dSize[i], set->content.cOffset[i], set->out); + + if (set->options.verbose) { + printf("Done!\n"); + } } } // Cci Padding if(set->options.padCci){ + if (set->options.verbose) { + printf("[CCI] Writing padding to file... "); + } + fseek_64(set->out,set->romInfo.usedSize); // Determining Size of Padding @@ -655,6 +675,10 @@ void WriteCciDataToOutput(cci_settings *set) fwrite(pad,set->romInfo.blockSize,1,set->out); free(pad); + + if (set->options.verbose) { + printf("Done!"); + } } return; diff --git a/makerom/romfs.c b/makerom/romfs.c index 9e3956a..bf174fc 100644 --- a/makerom/romfs.c +++ b/makerom/romfs.c @@ -10,6 +10,7 @@ void FreeRomFsCtx(romfs_buildctx *ctx); // RomFs Build Functions int SetupRomFs(ncch_settings *ncchset, romfs_buildctx *ctx) { + ctx->verbose = ncchset->options.verbose; ctx->output = NULL; ctx->romfsSize = 0; @@ -46,7 +47,6 @@ int BuildRomFs(romfs_buildctx *ctx) void FreeRomFsCtx(romfs_buildctx *ctx) { if(ctx->fs){ - fs_FreeFiles(ctx->fs); fs_FreeDir(ctx->fs); free(ctx->fs); } diff --git a/makerom/romfs.h b/makerom/romfs.h index 96ec123..48d5400 100644 --- a/makerom/romfs.h +++ b/makerom/romfs.h @@ -72,6 +72,8 @@ typedef struct typedef struct { + bool verbose; + u8 *output; u64 romfsSize; u64 romfsHeaderSize; diff --git a/makerom/romfs_gen.c b/makerom/romfs_gen.c index 3db457b..8eba46c 100644 --- a/makerom/romfs_gen.c +++ b/makerom/romfs_gen.c @@ -5,7 +5,6 @@ const int ROMFS_BLOCK_SIZE = 0x1000; const unsigned int ROMFS_UNUSED_ENTRY = 0xffffffff; -const fs_romfs_char ROMFS_EMPTY_PATH[2] = {0x0000, 0x0000}; // Build bool IsFileWanted(fs_file *file, void *filter_criteria); @@ -21,60 +20,39 @@ void PopulateRomfs(romfs_buildctx *ctx); void BuildRomfsHeader(romfs_buildctx *ctx); void BuildIvfcHeader(romfs_buildctx *ctx); void GenIvfcHashTree(romfs_buildctx *ctx); -u32 CalcPathHash(u32 parent, fs_romfs_char* path, u32 start, u32 length); +u32 CalcPathHash(u32 parent, const fs_romfs_char* path, u32 start, u32 length); int PrepareBuildRomFsBinary(ncch_settings *ncchset, romfs_buildctx *ctx) { - /* Input Path */ - const int CWD_MAX_LEN = 1024; - char *cwd = calloc(CWD_MAX_LEN,sizeof(char)); - getcwd(cwd,CWD_MAX_LEN); - - char *dir = ncchset->rsfSet->RomFs.RootPath; - - fs_char *fs_path; - fs_romfs_char *path; - u32 path_len; -#ifdef _WIN32 - str_u8_to_u16(&path,&path_len,(u8*)dir,strlen(dir)); - fs_path = path; -#else - str_utf8_to_u16(&path,&path_len,(u8*)dir,strlen(dir)); - fs_path = dir; -#endif - /* FS Structures */ void *filter_criteria = NULL; fs_dir *fs_raw = calloc(1,sizeof(fs_dir)); ctx->fs = calloc(1,sizeof(fs_dir)); /* Import FS and process */ - fs_OpenDir(fs_path,path,path_len,fs_raw); + fs_OpenRootDir(ncchset->rsfSet->RomFs.RootPath,fs_raw); FilterRomFS(fs_raw,ctx->fs,filter_criteria); /* free unfiltered FS */ - fs_FreeFiles(fs_raw); // All important FPs have been moved with FilterRomFS, so only un-wanted FPs are closed here fs_FreeDir(fs_raw); free(fs_raw); /* Abort romfs making, if no wanted files/directories were found */ if(ctx->fs->u_file == 0 && ctx->fs->u_child == 0){ ctx->romfsSize = 0; - goto finish; - } - - - /* Print Filtered FS */ - if(ncchset->options.verbose){ - printf("[ROMFS] File System:\n"); - fs_PrintDir(ctx->fs,0); + return 0; } CalcRomfsSize(ctx); -finish: - chdir(cwd); + if (ctx->verbose) { + printf("[ROMFS] File System:\n"); + printf(" > Size: %"PRIx64"\n", ctx->romfsSize); + printf(" > Directories: %d\n", ctx->dirNum); + printf(" > Files: %d\n", ctx->fileNum); + } + return 0; } @@ -208,9 +186,10 @@ int FilterRomFS(fs_dir *fs_raw, fs_dir *fs_filtered, void *filter_criteria) if(!IsDirWanted(fs_raw,filter_criteria)) return 0; + fs_filtered->fs_path = fs_CopyPath(fs_raw->fs_path); + fs_filtered->name_len = fs_raw->name_len; - fs_filtered->name = calloc(fs_filtered->name_len+2,1); - memcpy(fs_filtered->name,fs_raw->name,fs_filtered->name_len); + fs_filtered->name = fs_CopyRomfsName(fs_raw->name); fs_filtered->u_child = 0; fs_filtered->m_child = fs_raw->u_child; @@ -233,16 +212,13 @@ int FilterRomFS(fs_dir *fs_raw, fs_dir *fs_filtered, void *filter_criteria) { if(IsFileWanted(&fs_raw->file[i],filter_criteria)) { + fs_filtered->file[fs_filtered->u_file].fs_path = fs_CopyPath(fs_raw->file[i].fs_path); + fs_filtered->file[fs_filtered->u_file].name_len = fs_raw->file[i].name_len; - fs_filtered->file[fs_filtered->u_file].name = malloc(fs_filtered->file[fs_filtered->u_file].name_len+2); - memset(fs_filtered->file[fs_filtered->u_file].name,0,fs_filtered->file[fs_filtered->u_file].name_len+2); - memcpy(fs_filtered->file[fs_filtered->u_file].name,fs_raw->file[i].name,fs_filtered->file[fs_filtered->u_file].name_len); + fs_filtered->file[fs_filtered->u_file].name = fs_CopyRomfsName(fs_raw->file[i].name); fs_filtered->file[fs_filtered->u_file].size = fs_raw->file[i].size; - fs_filtered->file[fs_filtered->u_file].fp = fs_raw->file[i].fp; - fs_raw->file[i].fp = NULL; - fs_filtered->u_file++; } } @@ -301,15 +277,15 @@ void BuildRomfsHeader(romfs_buildctx *ctx) } } -u32 GetFileHashTableIndex(romfs_buildctx *ctx, u32 parent, fs_romfs_char *path) +u32 GetFileHashTableIndex(romfs_buildctx *ctx, u32 parent, const fs_romfs_char *path) { - u32 hash = CalcPathHash(parent, path, 0, fs_RomFsStrLen(path)); + u32 hash = CalcPathHash(parent, path, 0, fs_romfs_strlen(path)); return hash % ctx->m_fileHashTable; } -u32 GetDirHashTableIndex(romfs_buildctx *ctx, u32 parent, fs_romfs_char* path) +u32 GetDirHashTableIndex(romfs_buildctx *ctx, u32 parent, const fs_romfs_char* path) { - u32 hash = CalcPathHash(parent, path, 0, fs_RomFsStrLen(path)); + u32 hash = CalcPathHash(parent, path, 0, fs_romfs_strlen(path)); return hash % ctx->m_dirHashTable; } @@ -338,7 +314,21 @@ void AddFileToRomfs(romfs_buildctx *ctx, fs_file *file, u32 parent, u32 sibling) u64_to_u8(entry->dataoffset,ctx->u_dataLen,LE); u64_to_u8(entry->datasize,file->size,LE); u8 *data_pos = (ctx->data + ctx->u_dataLen); - ReadFile64(data_pos,file->size,0,file->fp); + + if (ctx->verbose) { + printf("[ROMFS] Reading \""); + fs_fputs(stdout, file->fs_path); + printf("\"... "); + } + + FILE *fp = fs_fopen(file->fs_path); + fread(data_pos, file->size, 1, fp); + fclose(fp); + + if (ctx->verbose) { + printf("Done!\n"); + } + ctx->u_dataLen += file->size; // adding file size } else @@ -351,7 +341,6 @@ void AddFileToRomfs(romfs_buildctx *ctx, fs_file *file, u32 parent, u32 sibling) void AddDirToRomfs(romfs_buildctx *ctx, fs_dir *fs, u32 parent, u32 sibling) { u32 offset = ctx->u_dirTableLen; - u32 hashindex; romfs_direntry *entry = (romfs_direntry*)(ctx->dirTable + offset); /* Set entry data */ @@ -360,37 +349,19 @@ void AddDirToRomfs(romfs_buildctx *ctx, fs_dir *fs, u32 parent, u32 sibling) u32_to_u8(entry->childoffset, ROMFS_UNUSED_ENTRY, LE); u32_to_u8(entry->fileoffset, ROMFS_UNUSED_ENTRY, LE); - - /* If root dir ... */ - if(offset == 0) - { - /* Import name (root dir has no name) */ - u32_to_u8(entry->namesize,0,LE); - - /* Get hash table index */ - hashindex = GetDirHashTableIndex(ctx, parent, (fs_romfs_char*)ROMFS_EMPTY_PATH); - - /* Increment used dir table length */ - ctx->u_dirTableLen += sizeof(romfs_direntry); - } - else - { - /* Import name */ - u32_to_u8(entry->namesize,fs->name_len,LE); - u8 *name_pos = (u8*)(ctx->dirTable + ctx->u_dirTableLen + sizeof(romfs_direntry)); - memset(name_pos,0,(u32)align(fs->name_len,4)); - memcpy(name_pos,(u8*)fs->name,fs->name_len); - - /* Get hash table index */ - hashindex = GetDirHashTableIndex(ctx, parent, fs->name); - - /* Increment used dir table length */ - ctx->u_dirTableLen += sizeof(romfs_direntry) + (u32)align(fs->name_len,4); - } + /* Import name */ + u32_to_u8(entry->namesize,fs->name_len,LE); + u8 *name_pos = (u8*)(ctx->dirTable + ctx->u_dirTableLen + sizeof(romfs_direntry)); + memset(name_pos,0,(u32)align(fs->name_len,4)); + memcpy(name_pos,(u8*)fs->name,fs->name_len); /* Set hash data */ - u32_to_u8(entry->hashoffset, u8_to_u32(ctx->dirHashTable + hashindex*4, LE), LE); - u32_to_u8(ctx->dirHashTable + hashindex*4, offset, LE); + u32 hashindex = GetDirHashTableIndex(ctx, parent, fs->name); + u32_to_u8(entry->hashoffset, u8_to_u32(ctx->dirHashTable + hashindex * 4, LE), LE); + u32_to_u8(ctx->dirHashTable + hashindex * 4, offset, LE); + + /* Increment used dir table length */ + ctx->u_dirTableLen += sizeof(romfs_direntry) + (u32)align(fs->name_len,4); } void AddDirChildrenToRomfs(romfs_buildctx *ctx, fs_dir *fs, u32 parent, u32 dir) @@ -425,10 +396,10 @@ void AddDirChildrenToRomfs(romfs_buildctx *ctx, fs_dir *fs, u32 parent, u32 dir) u32_to_u8(entry->childoffset, ctx->u_dirTableLen, LE); for (u32 i = 0; i < fs->u_child; i++) { - /* Store address fo child */ + /* Store address for child */ childs[i] = ctx->u_dirTableLen; - + /* If is the last child directory, no more siblings */ u32 dir_sibling = 0; if (i >= fs->u_child - 1) dir_sibling = ROMFS_UNUSED_ENTRY; @@ -488,7 +459,7 @@ void GenIvfcHashTree(romfs_buildctx *ctx) return; } -u32 CalcPathHash(u32 parent, fs_romfs_char* path, u32 start, u32 length) +u32 CalcPathHash(u32 parent, const fs_romfs_char* path, u32 start, u32 length) { u32 hash = parent ^ 123456789; for( u32 index = 0; index < length; index++ ) diff --git a/makerom/titleid.c b/makerom/titleid.c index 9bf8217..33961a4 100644 --- a/makerom/titleid.c +++ b/makerom/titleid.c @@ -2,6 +2,7 @@ #include "ncch_read.h" #include "titleid.h" +const u16 DEFAULT_CATEGORY = PROGRAM_ID_CATEGORY_APPLICATION; const u32 DEFAULT_UNIQUE_ID = 0xff3ff; void SetPIDType(u16 *type); @@ -28,7 +29,7 @@ u32 GetTidUniqueId(u64 titleId) int GetProgramID(u64 *dest, rsf_settings *rsf, bool IsForExheader) { - int ret; + int ret = 0; u32 uniqueId; u16 type,category; u8 variation; @@ -42,12 +43,15 @@ int GetProgramID(u64 *dest, rsf_settings *rsf, bool IsForExheader) SetPIDType(&type); // Getting Category - if(rsf->TitleInfo.Category) - ret = SetPIDCategoryFromName(&category,rsf->TitleInfo.Category); - else if(rsf->TitleInfo.CategoryFlags) - ret = SetPIDCategoryFromFlags(&category,rsf->TitleInfo.CategoryFlags,rsf->TitleInfo.CategoryFlagsNum); if(IsForExheader && rsf->TitleInfo.TargetCategory) ret = SetPIDCategoryFromName(&category,rsf->TitleInfo.TargetCategory); + else if (rsf->TitleInfo.Category) + ret = SetPIDCategoryFromName(&category, rsf->TitleInfo.Category); + else if (rsf->TitleInfo.CategoryFlags) + ret = SetPIDCategoryFromFlags(&category, rsf->TitleInfo.CategoryFlags, rsf->TitleInfo.CategoryFlagsNum); + else + category = DEFAULT_CATEGORY; + if(ret == PID_INVALID_CATEGORY) // Error occured return PID_BAD_RSF_SET; diff --git a/makerom/user_settings.c b/makerom/user_settings.c index aa5bc46..8bfe595 100644 --- a/makerom/user_settings.c +++ b/makerom/user_settings.c @@ -6,6 +6,7 @@ void DisplayExtendedHelp(char *app_name); void SetDefaults(user_settings *set); int SetArgument(int argc, int i, char *argv[], user_settings *set); int CheckArgumentCombination(user_settings *set); +const char* GetOutputExtention(u8 file_type); void PrintNeedsArg(char *arg); void PrintArgInvalid(char *arg); void PrintArgReqParam(char *arg, u32 paramNum); @@ -75,14 +76,7 @@ int ParseArgs(int argc, char *argv[], user_settings *set) source_path = set->common.workingFilePath; else source_path = set->common.contentPath[0]; - u16 outfile_len = strlen(source_path) + 0x10; - set->common.outFileName = calloc(outfile_len, sizeof(char)); - if (!set->common.outFileName) { - fprintf(stderr, "[SETTING ERROR] Not Enough Memory\n"); - return USR_MEM_ERROR; - } - set->common.outFileName_mallocd = true; - append_filextention(set->common.outFileName, outfile_len, source_path, (char*)&output_extention[set->common.outFormat - 1]); + set->common.outFileName = replace_filextention(source_path, GetOutputExtention(set->common.outFormat)); } return 0; } @@ -95,7 +89,7 @@ void SetDefaults(user_settings *set) // Build NCCH Info set->ncch.useSecCrypto = false; - set->ncch.buildNcch0 = false; + set->ncch.buildNcch0 = true; set->ncch.includeExefsLogo = false; set->common.outFormat = NCCH; set->ncch.ncchType = format_not_set; @@ -704,22 +698,18 @@ int SetArgument(int argc, int i, char *argv[], user_settings *set) int CheckArgumentCombination(user_settings *set) { - if (set->ncch.ncchType & (CXI | CFA)) { + if (set->common.contentPath[0] == NULL) { set->ncch.buildNcch0 = true; if (set->ncch.ncchType & CXI) set->ncch.ncchType = CXI; else set->ncch.ncchType = CFA; - } - if (set->common.outFormat == NCCH) { - set->ncch.buildNcch0 = true; - if (set->ncch.ncchType) + if (set->common.outFormat == NCCH) set->common.outFormat = set->ncch.ncchType; - else { - set->ncch.ncchType = CFA; - set->common.outFormat = CFA; - } + } + else { + set->ncch.buildNcch0 = false; } for (int i = 0; i < CIA_MAX_CONTENT; i++) { @@ -733,11 +723,6 @@ int CheckArgumentCombination(user_settings *set) } } - if (set->common.contentPath[0] && set->ncch.buildNcch0) { - fprintf(stderr, "[SETTING ERROR] You cannot both import and build content 0\n"); - return USR_BAD_ARG; - } - if (set->common.outFormat == CIA && set->cci.cverDataPath) { fprintf(stderr, "[SETTING ERROR] You cannot use argument \"-cverinfo\" when generating a CIA\n"); return USR_BAD_ARG; @@ -808,6 +793,18 @@ int CheckArgumentCombination(user_settings *set) return 0; } +const char* GetOutputExtention(u8 file_type) +{ + switch (file_type) { + case(NCCH) : return ".app"; + case(CXI) : return ".cxi"; + case(CFA) : return ".cfa"; + case(CIA) : return ".cia"; + case(CCI) : return ".cci"; + default: return ".bin"; + } +} + void init_UserSettings(user_settings *set) { memset(set, 0, sizeof(user_settings)); diff --git a/makerom/utils.c b/makerom/utils.c index dd08733..2899b77 100644 --- a/makerom/utils.c +++ b/makerom/utils.c @@ -53,27 +53,27 @@ u64 max64(u64 a, u64 b) } // Strings -int append_filextention(char *output, u16 max_outlen, char *input, char extention[]) +char* replace_filextention(const char *input, const char *new_ext) { - if(output == NULL || input == NULL){ - printf("[!] Memory Error\n"); - return Fail; + if(input == NULL || new_ext == NULL) + return NULL; + + char *new_name; + char *ext = strrchr(input, '.'); + + // If there is no existing extention, just append new_ext + if (!ext) { + new_name = calloc(strlen(input) + strlen(new_ext), 1); + sprintf(new_name, "%s%s", input, new_ext); } - memset(output,0,max_outlen); - u16 extention_point = strlen(input)+1; - for(int i = strlen(input)-1; i > 0; i--){ - if(input[i] == '.'){ - extention_point = i; - break; - } + else { + u32 size = ext - input; + new_name = calloc(size + strlen(new_ext), 1); + snprintf(new_name, size, "%s", input); + sprintf(new_name, "%s%s", new_name, new_ext); } - if(extention_point+strlen(extention) >= max_outlen){ - printf("[!] Input File Name Too Large for Output buffer\n"); - return Fail; - } - memcpy(output,input,extention_point); - sprintf(output,"%s%s",output,extention); - return 0; + + return new_name; } void memdump(FILE* fout, const char* prefix, const u8* data, u32 size) @@ -104,7 +104,7 @@ void memdump(FILE* fout, const char* prefix, const u8* data, u32 size) } } -int str_u8_to_u16(u16 **dst, u32 *dst_len, u8 *src, u32 src_len) +int str_u8_to_u16(u16 **dst, u32 *dst_len, const u8 *src, u32 src_len) { *dst_len = src_len*sizeof(u16); *dst = malloc((*dst_len)+sizeof(u16)); @@ -117,7 +117,7 @@ int str_u8_to_u16(u16 **dst, u32 *dst_len, u8 *src, u32 src_len) return 0; } -int str_u16_to_u16(u16 **dst, u32 *dst_len, u16 *src, u32 src_len) +int str_u16_to_u16(u16 **dst, u32 *dst_len, const u16 *src, u32 src_len) { *dst_len = src_len*sizeof(u16); *dst = malloc((*dst_len)+sizeof(u16)); @@ -130,7 +130,7 @@ int str_u16_to_u16(u16 **dst, u32 *dst_len, u16 *src, u32 src_len) return 0; } -int str_u32_to_u16(u16 **dst, u32 *dst_len, u32 *src, u32 src_len) +int str_u32_to_u16(u16 **dst, u32 *dst_len, const u32 *src, u32 src_len) { *dst_len = src_len*sizeof(u16); *dst = malloc((*dst_len)+sizeof(u16)); @@ -144,7 +144,7 @@ int str_u32_to_u16(u16 **dst, u32 *dst_len, u32 *src, u32 src_len) } #ifndef _WIN32 -int str_utf8_to_u16(u16 **dst, u32 *dst_len, u8 *src, u32 src_len) +int str_utf8_to_u16(u16 **dst, u32 *dst_len, const u8 *src, u32 src_len) { *dst_len = src_len*sizeof(u16); *dst = malloc((*dst_len)+sizeof(u16)); diff --git a/makerom/utils.h b/makerom/utils.h index 6d30d51..1a89100 100644 --- a/makerom/utils.h +++ b/makerom/utils.h @@ -18,13 +18,13 @@ u64 min64(u64 a, u64 b); u64 max64(u64 a, u64 b); // Strings -void memdump(FILE* fout, const char* prefix, const u8* data, u32 size); -int append_filextention(char *output, u16 max_outlen, char *input, char extention[]); -int str_u8_to_u16(u16 **dst, u32 *dst_len, u8 *src, u32 src_len); -int str_u16_to_u16(u16 **dst, u32 *dst_len, u16 *src, u32 src_len); -int str_u32_to_u16(u16 **dst, u32 *dst_len, u32 *src, u32 src_len); +void memdump(FILE* fout, const char* prefix, const const u8* data, u32 size); +char* replace_filextention(const char *input, const char *extention); +int str_u8_to_u16(u16 **dst, u32 *dst_len, const u8 *src, u32 src_len); +int str_u16_to_u16(u16 **dst, u32 *dst_len, const u16 *src, u32 src_len); +int str_u32_to_u16(u16 **dst, u32 *dst_len, const u32 *src, u32 src_len); #ifndef _WIN32 -int str_utf8_to_u16(u16 **dst, u32 *dst_len, u8 *src, u32 src_len); +int str_utf8_to_u16(u16 **dst, u32 *dst_len, const u8 *src, u32 src_len); #endif // Base64