diff --git a/ctrtool/ncch.c b/ctrtool/ncch.c index 07f8755..5de61ce 100644 --- a/ctrtool/ncch.c +++ b/ctrtool/ncch.c @@ -575,7 +575,7 @@ void ncch_print(ncch_context* ctx) memdump(stdout, "Signature (FAIL): ", header->signature, 0x100); fprintf(stdout, "Content size: 0x%08x\n", getle32(header->contentsize)*mediaunitsize); fprintf(stdout, "Partition id: %016"PRIx64"\n", getle64(header->partitionid)); - fprintf(stdout, "Maker code: %04x\n", getle16(header->makercode)); + fprintf(stdout, "Maker code: %.2s\n", header->makercode); fprintf(stdout, "Version: %04x\n", getle16(header->version)); fprintf(stdout, "Title seed check: %08x\n", getle32(header->seedcheck)); fprintf(stdout, "Program id: %016"PRIx64"\n", getle64(header->programid)); diff --git a/makerom/elf.c b/makerom/elf.c index 17168e2..aae3539 100644 --- a/makerom/elf.c +++ b/makerom/elf.c @@ -5,6 +5,8 @@ #include "elf.h" #include "blz.h" +const char *SDK_PLAINREGION_SEGMENT_NAME = ".module_id"; + int ImportPlainRegionFromFile(ncch_settings *set); int ImportExeFsCodeBinaryFromFile(ncch_settings *set); @@ -14,9 +16,7 @@ u32 SizeToPage(u32 memorySize, elf_context *elf); int GetBSSFromElf(elf_context *elf, u8 *elfFile, ncch_settings *set); int ImportPlainRegionFromElf(elf_context *elf, u8 *elfFile, ncch_settings *set); int CreateExeFsCode(elf_context *elf, u8 *elfFile, ncch_settings *set); -int CreateCodeSegmentFromElf(code_segment *out, elf_context *elf, u8 *elfFile, char **names, u32 nameNum); -elf_segment** GetContinuousSegments(u16 *ContinuousSegmentNum, elf_context *elf, char **names, u32 nameNum); -elf_segment** GetSegments(u16 *SegmentNum, elf_context *elf, char **names, u32 nameNum); +int CreateCodeSegmentFromElf(code_segment *out, elf_context *elf, u8 *elfFile, u64 segment_flags); // ELF Functions int GetElfContext(elf_context *elf, u8 *elfFile); @@ -234,39 +234,28 @@ int GetBSSFromElf(elf_context *elf, u8 *elfFile, ncch_settings *set) int ImportPlainRegionFromElf(elf_context *elf, u8 *elfFile, ncch_settings *set) // Doesn't work same as N makerom { - if(!set->rsfSet->PlainRegionNum) return 0; - u16 *index = calloc(set->rsfSet->PlainRegionNum,sizeof(u16)); - - /* Getting index Values for each section */ - for(int i = 0; i < set->rsfSet->PlainRegionNum; i++){ - index[i] = GetElfSectionIndexFromName(set->rsfSet->PlainRegion[i],elf,elfFile); - } - - // Eliminating Duplicated Sections - for(int i = set->rsfSet->PlainRegionNum - 1; i >= 0; i--){ - for(int j = i-1; j >= 0; j--){ - if(index[i] == index[j]) index[i] = 0; + u64 size = 0; + u64 offset = 0; + for (u16 i = 0; i < elf->activeSegments; i++) { + if (strcmp(elf->segments[i].name, SDK_PLAINREGION_SEGMENT_NAME) == 0) { + size = elf->segments[i].header->sizeInFile; + offset = elf->segments[i].header->offsetInFile; + break; } } - - /* Calculating Total Size of Data */ - u64 totalSize = 0; - for(int i = 0; i < set->rsfSet->PlainRegionNum; i++){ - totalSize += elf->sections[index[i]].size; - } - /* Creating Output Buffer */ - set->sections.plainRegion.size = align(totalSize,set->options.blockSize); - set->sections.plainRegion.buffer = malloc(set->sections.plainRegion.size); - if(!set->sections.plainRegion.buffer) {fprintf(stderr,"[ELF ERROR] Not enough memory\n"); return MEM_ERROR;} - memset(set->sections.plainRegion.buffer,0,set->sections.plainRegion.size); + + if (size > 0) { + /* Creating Output Buffer */ + set->sections.plainRegion.size = align(size, set->options.blockSize); + set->sections.plainRegion.buffer = malloc(set->sections.plainRegion.size); + if (!set->sections.plainRegion.buffer) { fprintf(stderr, "[ELF ERROR] Not enough memory\n"); return MEM_ERROR; } + memset(set->sections.plainRegion.buffer, 0, set->sections.plainRegion.size); - /* Storing Sections */ - u64 pos = 0; - for(int i = 0; i < set->rsfSet->PlainRegionNum; i++){ - memcpy((set->sections.plainRegion.buffer+pos),elf->sections[index[i]].ptr,elf->sections[index[i]].size); - pos += elf->sections[index[i]].size; + /* Copy Plain Region */ + memcpy(set->sections.plainRegion.buffer, elfFile+offset, size); } + return 0; } @@ -280,11 +269,11 @@ int CreateExeFsCode(elf_context *elf, u8 *elfFile, ncch_settings *set) code_segment rwdata; memset(&rwdata,0,sizeof(code_segment)); - int result = CreateCodeSegmentFromElf(&text,elf,elfFile,set->rsfSet->ExeFs.Text,set->rsfSet->ExeFs.TextNum); + int result = CreateCodeSegmentFromElf(&text,elf,elfFile,(PF_R|PF_X)); if(result) return result; - result = CreateCodeSegmentFromElf(&rodata,elf,elfFile,set->rsfSet->ExeFs.ReadOnly,set->rsfSet->ExeFs.ReadOnlyNum); + result = CreateCodeSegmentFromElf(&rodata,elf,elfFile,(PF_R)); if(result) return result; - result = CreateCodeSegmentFromElf(&rwdata,elf,elfFile,set->rsfSet->ExeFs.ReadWrite,set->rsfSet->ExeFs.ReadWriteNum); + result = CreateCodeSegmentFromElf(&rwdata,elf,elfFile,(PF_R | PF_W)); if(result) return result; /* Checking the existence of essential ELF Segments */ @@ -336,131 +325,81 @@ int CreateExeFsCode(elf_context *elf, u8 *elfFile, ncch_settings *set) return 0; } -int CreateCodeSegmentFromElf(code_segment *out, elf_context *elf, u8 *elfFile, char **names, u32 nameNum) +int CreateCodeSegmentFromElf(code_segment *out, elf_context *elf, u8 *elfFile, u64 segment_flags) { - u16 ContinuousSegmentNum = 0; - memset(out,0,sizeof(code_segment)); - elf_segment **ContinuousSegments = GetContinuousSegments(&ContinuousSegmentNum,elf,names,nameNum); - if (ContinuousSegments == NULL){ - if(!ContinuousSegmentNum){// Nothing Was Found - //printf("Nothing was found\n"); - return 0; + memset(out, 0, sizeof(code_segment)); + + u16 seg_num = 0; + elf_segment **seg = calloc(elf->activeSegments, sizeof(elf_segment*)); + + for (u16 i = 0; i < elf->activeSegments; i++) { + // Skip SDK ELF plain region + if (strcmp(elf->segments[i].name, SDK_PLAINREGION_SEGMENT_NAME) == 0) + continue; + + //printf("SegName: %s (flags: %x)\n", elf->segments[i].name, elf->segments[i].header->flags); + if ((elf->segments[i].header->flags & ~PF_CTRSDK) == segment_flags) { + if (seg_num == 0) { + seg[seg_num] = &elf->segments[i]; + seg_num++; + } + else if (elf->segments[i].vAddr == (u32)align(seg[seg_num - 1]->vAddr, seg[seg_num-1]->header->alignment)) { + seg[seg_num] = &elf->segments[i]; + seg_num++; + } } - else // Error with found segments - return ELF_SEGMENTS_NOT_CONTINUOUS; } - + + /* Return if there are no applicable segment */ + if (seg_num == 0) + return 0; + /* Getting Segment Size/Settings */ u32 vAddr = 0; u32 memorySize = 0; - for(int i = 0; i < ContinuousSegmentNum; i++){ - if (i==0){ - vAddr = ContinuousSegments[i]->vAddr; + for (u16 i = 0; i < seg_num; i++) { + if (i == 0) { + vAddr = seg[i]->vAddr; } - else{ // Add rounded size from previous segment - u32 padding = ContinuousSegments[i]->vAddr - (vAddr + memorySize); + else { // Add rounded size from previous segment + u32 padding = seg[i]->vAddr - (vAddr + memorySize); memorySize += padding; } - memorySize += ContinuousSegments[i]->header->sizeInMemory; + memorySize += seg[i]->header->sizeInMemory; - if(IsBss(&ContinuousSegments[i]->sections[ContinuousSegments[i]->sectionNum-1])) - memorySize -= ContinuousSegments[i]->sections[ContinuousSegments[i]->sectionNum-1].size; + if (IsBss(&seg[i]->sections[seg[i]->sectionNum - 1])) + memorySize -= seg[i]->sections[seg[i]->sectionNum - 1].size; } - + // For Check #ifdef DEBUG - printf("Address: 0x%x\n",vAddr); - printf("Size: 0x%x\n",memorySize); + printf("Address: 0x%x\n", vAddr); + printf("Size: 0x%x\n", memorySize); #endif out->address = vAddr; out->size = memorySize; - out->maxPageNum = SizeToPage(memorySize,elf); + out->maxPageNum = SizeToPage(memorySize, elf); out->data = malloc(memorySize); - + /* Writing Segment to Buffer */ - //vAddr = 0; - //memorySize = 0; - for(int i = 0; i < ContinuousSegmentNum; i++){ - /* - if (i==0) - vAddr = ContinuousSegments[i]->vAddr; + for (int i = 0; i < seg_num; i++) { - else{ - u32 num = ContinuousSegments[i]->vAddr - (vAddr + memorySize); - memorySize += num; - } - */ - //u32 size = 0; - for (int j = 0; j < ContinuousSegments[i]->sectionNum; j++){ - elf_section_entry *section = &ContinuousSegments[i]->sections[j]; - if (!IsBss(section)){ - u8 *pos = (out->data + (section->address - ContinuousSegments[i]->vAddr)); - memcpy(pos,section->ptr,section->size); + for (int j = 0; j < seg[i]->sectionNum; j++) { + elf_section_entry *section = &seg[i]->sections[j]; + if (!IsBss(section)) { + u8 *pos = (out->data + (section->address - seg[i]->vAddr)); + memcpy(pos, section->ptr, section->size); //size += section->size; } - - //else if (j == (ContinuousSegments[i]->sectionNum-1)) - //memorySize -= section->size; - //'else - //size += section->size; } } - free(ContinuousSegments); + free(seg); return 0; } - -elf_segment** GetContinuousSegments(u16 *ContinuousSegmentNum, elf_context *elf, char **names, u32 nameNum) -{ - u16 SegmentNum = 0; - elf_segment **Segments = GetSegments(&SegmentNum, elf, names, nameNum); - if (Segments == NULL || SegmentNum == 0){ // No Segments for the names were found - //printf("Not Found Segment\n"); - return NULL; - } - - if (SegmentNum == 1){ //Return as there is no need to check - *ContinuousSegmentNum = SegmentNum; - return Segments; - } - - u32 vAddr = Segments[0]->vAddr + Segments[0]->header->sizeInMemory; - for (int i = 1; i < SegmentNum; i++){ - if (Segments[i]->vAddr != (u32)align(vAddr,Segments[i]->header->alignment)){ //Each Segment must start after each other - fprintf(stderr,"[ELF ERROR] %s segment and %s segment are not continuous\n", Segments[i]->name, Segments[i - 1]->name); - free(Segments); - *ContinuousSegmentNum = 0xffff; // Signify to function that an error occured - return NULL; - } - } - *ContinuousSegmentNum = SegmentNum; - return Segments; -} - - -elf_segment** GetSegments(u16 *SegmentNum, elf_context *elf, char **names, u32 nameNum) -{ - if (names == NULL) - { - return NULL; - } - - elf_segment **Segments = calloc(nameNum,sizeof(elf_segment*)); - *SegmentNum = 0; // There can be a max of nameNum Segments, however, they might not all exist - for (int i = 0; i < nameNum; i++){ - for(int j = 0; j < elf->activeSegments; j++){ - if(strcmp(names[i],elf->segments[j].name) == 0){ // If there is a match, store Segment data pointer & increment index - Segments[*SegmentNum] = &elf->segments[j]; - *SegmentNum = *SegmentNum + 1; - } - } - } - return Segments; -} - // ELF Functions int GetElfContext(elf_context *elf, u8 *elfFile) @@ -547,9 +486,11 @@ void PrintElfContext(elf_context *elf, u8 *elfFile) printf(" Segment [%d][%s]\n",i,elf->segments[i].name); printf(" > Size : 0x%"PRIx64"\n",elf->segments[i].header->sizeInFile); printf(" > Address : 0x%"PRIx64"\n",elf->segments[i].vAddr); + printf(" > Flags: 0x%"PRIx64"\n", elf->segments[i].header->flags); + printf(" > Type: 0x%"PRIx64"\n", elf->segments[i].header->type); printf(" > Sections : %d\n",elf->segments[i].sectionNum); for(int j = 0; j < elf->segments[i].sectionNum; j++) - printf(" > Section [%d][%s]\n",j,elf->segments[i].sections[j].name); + printf(" > Section [%d][%s][0x%"PRIx64"][0x%"PRIx64"]\n",j,elf->segments[i].sections[j].name, elf->segments[i].sections[j].flags, elf->segments[i].sections[j].type); /* char outpath[100]; diff --git a/makerom/elf_hdr.h b/makerom/elf_hdr.h index eac9d64..4fb772d 100644 --- a/makerom/elf_hdr.h +++ b/makerom/elf_hdr.h @@ -161,6 +161,7 @@ typedef struct #define PT_LOPROC 0x70000000 /* Start of processor-specific */ #define PT_HIPROC 0x7fffffff /* End of processor-specific */ +#define PF_CTRSDK 0x80000000 #define PF_R 0x4 /* p_flags */ #define PF_W 0x2 #define PF_X 0x1 diff --git a/makerom/exheader.c b/makerom/exheader.c index d994c1e..a52fa42 100644 --- a/makerom/exheader.c +++ b/makerom/exheader.c @@ -4,6 +4,7 @@ #include "accessdesc.h" #include "titleid.h" +const char *DEFAULT_EXHEADER_NAME = "CtrApp"; /* Prototypes */ void free_ExHeaderSettings(exheader_settings *exhdrset); @@ -189,17 +190,10 @@ finish: int get_ExHeaderCodeSetInfo(exhdr_CodeSetInfo *CodeSetInfo, rsf_settings *rsf) { /* Name */ - if(rsf->BasicInfo.Title){ - //if(strlen(rsf->BasicInfo.Title) > 8){ - // fprintf(stderr,"[EXHEADER ERROR] Parameter Too Long \"BasicInfo/Title\"\n"); - // return EXHDR_BAD_RSF_OPT; - //} - strncpy((char*)CodeSetInfo->name,rsf->BasicInfo.Title,8); - } - else{ - ErrorParamNotFound("BasicInfo/Title"); - return EXHDR_BAD_RSF_OPT; - } + if (rsf->BasicInfo.Title) + strncpy((char*)CodeSetInfo->name, rsf->BasicInfo.Title, 8); + else + strncpy((char*)CodeSetInfo->name, DEFAULT_EXHEADER_NAME, 8); /* Stack Size */ if(rsf->SystemControlInfo.StackSize) diff --git a/makerom/ncch.c b/makerom/ncch.c index 0cc87ec..4a8d00e 100644 --- a/makerom/ncch.c +++ b/makerom/ncch.c @@ -12,6 +12,8 @@ #include "ncch_logo.h" // Contains Logos const u32 NCCH_BLOCK_SIZE = 0x200; +const char *DEFAULT_PRODUCT_CODE = "CTR-P-CTAP"; +const char *DEFAULT_MAKER_CODE = "00"; // Private Prototypes int SignCFA(ncch_hdr *hdr, keys_struct *keys); @@ -591,18 +593,20 @@ int SetCommonHeaderBasicData(ncch_settings *set, ncch_hdr *hdr) fprintf(stderr,"[NCCH ERROR] Invalid Product Code\n"); return NCCH_BAD_RSF_SET; } - memcpy(hdr->productCode,set->rsfSet->BasicInfo.ProductCode,strlen((char*)set->rsfSet->BasicInfo.ProductCode)); + strncpy((char*)hdr->productCode,set->rsfSet->BasicInfo.ProductCode, 16); } - else memcpy(hdr->productCode,"CTR-P-CTAP",10); + else + strncpy((char*)hdr->productCode, DEFAULT_PRODUCT_CODE, 16); if(set->rsfSet->BasicInfo.CompanyCode){ if(strlen((char*)set->rsfSet->BasicInfo.CompanyCode) != 2){ fprintf(stderr,"[NCCH ERROR] CompanyCode length must be 2\n"); return NCCH_BAD_RSF_SET; } - memcpy(hdr->makerCode,set->rsfSet->BasicInfo.CompanyCode,2); + strncpy((char*)hdr->makerCode, set->rsfSet->BasicInfo.CompanyCode, 2); } - else memcpy(hdr->makerCode,"00",2); + else + strncpy((char*)hdr->makerCode, DEFAULT_MAKER_CODE, 2); // Setting Encryption Settings if(!set->options.Encrypt) diff --git a/makerom/rsf_settings.c b/makerom/rsf_settings.c index ede105d..66fcc0f 100644 --- a/makerom/rsf_settings.c +++ b/makerom/rsf_settings.c @@ -5,8 +5,6 @@ void GET_AccessControlInfo(ctr_yaml_context *ctx, rsf_settings *rsf); void GET_SystemControlInfo(ctr_yaml_context *ctx, rsf_settings *rsf); void GET_BasicInfo(ctr_yaml_context *ctx, rsf_settings *rsf); void GET_RomFs(ctr_yaml_context *ctx, rsf_settings *rsf); -void GET_ExeFs(ctr_yaml_context *ctx, rsf_settings *rsf); -void GET_PlainRegion(ctr_yaml_context *ctx, rsf_settings *rsf); void GET_TitleInfo(ctr_yaml_context *ctx, rsf_settings *rsf); void GET_CardInfo(ctr_yaml_context *ctx, rsf_settings *rsf); void GET_CommonHeaderKey(ctr_yaml_context *ctx, rsf_settings *rsf); @@ -23,8 +21,6 @@ void EvaluateRSF(rsf_settings *rsf, ctr_yaml_context *ctx) else if(cmpYamlValue("SystemControlInfo",ctx)) {FinishEvent(ctx); GET_SystemControlInfo(ctx,rsf); goto GET_NextGroup;} else if(cmpYamlValue("BasicInfo",ctx)) {FinishEvent(ctx); GET_BasicInfo(ctx,rsf); goto GET_NextGroup;} else if(cmpYamlValue("RomFs",ctx)) {FinishEvent(ctx); GET_RomFs(ctx,rsf); goto GET_NextGroup;} - else if(cmpYamlValue("ExeFs",ctx)) {FinishEvent(ctx); GET_ExeFs(ctx,rsf); goto GET_NextGroup;} - else if(cmpYamlValue("PlainRegion",ctx)) {FinishEvent(ctx); GET_PlainRegion(ctx,rsf); goto GET_NextGroup;} else if(cmpYamlValue("TitleInfo",ctx)) {FinishEvent(ctx); GET_TitleInfo(ctx,rsf); goto GET_NextGroup;} else if(cmpYamlValue("CardInfo",ctx)) {FinishEvent(ctx); GET_CardInfo(ctx,rsf); goto GET_NextGroup;} else if(cmpYamlValue("CommonHeaderKey",ctx)) {FinishEvent(ctx); GET_CommonHeaderKey(ctx,rsf); goto GET_NextGroup;} @@ -240,39 +236,6 @@ void GET_RomFs(ctr_yaml_context *ctx, rsf_settings *rsf) FinishEvent(ctx); } -void GET_ExeFs(ctr_yaml_context *ctx, rsf_settings *rsf) -{ - /* Checking That Group is in a map */ - if(!CheckMappingEvent(ctx)) return; - u32 InitLevel = ctx->Level; - /* Checking each child */ - GetEvent(ctx); - while(ctx->Level == InitLevel){ - if(ctx->error || ctx->done) return; - // Handle childs - - if(cmpYamlValue("Text",ctx)) rsf->ExeFs.TextNum = SetYAMLSequence(&rsf->ExeFs.Text,"Text",ctx); - else if(cmpYamlValue("ReadOnly",ctx)) rsf->ExeFs.ReadOnlyNum = SetYAMLSequence(&rsf->ExeFs.ReadOnly,"ReadOnly",ctx); - else if(cmpYamlValue("ReadWrite",ctx)) rsf->ExeFs.ReadWriteNum = SetYAMLSequence(&rsf->ExeFs.ReadWrite,"ReadWrite",ctx); - - else{ - fprintf(stderr,"[RSF ERROR] Unrecognised key '%s'\n",GetYamlString(ctx)); - ctx->error = YAML_UNKNOWN_KEY; - FinishEvent(ctx); - return; - } - // Finish event start next - FinishEvent(ctx); - GetEvent(ctx); - } - FinishEvent(ctx); -} - -void GET_PlainRegion(ctr_yaml_context *ctx, rsf_settings *rsf) -{ - rsf->PlainRegionNum = SetYAMLSequence(&rsf->PlainRegion,"PlainRegion",ctx); -} - void GET_TitleInfo(ctr_yaml_context *ctx, rsf_settings *rsf) { /* Checking That Group is in a map */ @@ -487,28 +450,6 @@ void free_RsfSettings(rsf_settings *set) } free(set->RomFs.File); - //ExeFs - for(u32 i = 0; i < set->ExeFs.TextNum; i++){ - free(set->ExeFs.Text[i]); - } - free(set->ExeFs.Text); - - for(u32 i = 0; i < set->ExeFs.ReadOnlyNum; i++){ - free(set->ExeFs.ReadOnly[i]); - } - free(set->ExeFs.ReadOnly); - - for(u32 i = 0; i < set->ExeFs.ReadWriteNum; i++){ - free(set->ExeFs.ReadWrite[i]); - } - free(set->ExeFs.ReadWrite); - - //PlainRegion - for(u32 i = 0; i < set->PlainRegionNum; i++){ - free(set->PlainRegion[i]); - } - free(set->PlainRegion); - //TitleInfo free(set->TitleInfo.Platform); free(set->TitleInfo.Category); diff --git a/makerom/titleid.c b/makerom/titleid.c index b904534..9bf8217 100644 --- a/makerom/titleid.c +++ b/makerom/titleid.c @@ -2,6 +2,8 @@ #include "ncch_read.h" #include "titleid.h" +const u32 DEFAULT_UNIQUE_ID = 0xff3ff; + void SetPIDType(u16 *type); int SetPIDCategoryFromName(u16 *cat, char *CategoryStr); int SetPIDCategoryFromFlags(u16 *cat, char **CategoryFlags, u32 FlagNum); @@ -52,10 +54,8 @@ int GetProgramID(u64 *dest, rsf_settings *rsf, bool IsForExheader) // Getting UniqueId if(rsf->TitleInfo.UniqueId) GetUniqueID(&uniqueId,rsf); - else{ - fprintf(stderr,"[ID ERROR] ParameterNotFound: \"TitleInfo/UniqueId\"\n"); - return PID_BAD_RSF_SET; - } + else + uniqueId = DEFAULT_UNIQUE_ID; // Getting Variation if(SetTitleVariation(&variation,category,rsf) == PID_INVALID_VARIATION) diff --git a/makerom/user_settings.h b/makerom/user_settings.h index a2cacb8..6e18c98 100644 --- a/makerom/user_settings.h +++ b/makerom/user_settings.h @@ -169,18 +169,6 @@ typedef struct char **File; } RomFs; - struct{ - u32 TextNum; - char **Text; - u32 ReadOnlyNum; - char **ReadOnly; - u32 ReadWriteNum; - char **ReadWrite; - } ExeFs; - - u32 PlainRegionNum; - char **PlainRegion; - struct{ // Strings char *Platform;