Merge pull request #5 from jakcron/master

[makerom/ctrtool] fixes + enhancements
This commit is contained in:
profi200
2015-10-09 18:21:01 +02:00
8 changed files with 91 additions and 222 deletions
+1 -1
View File
@@ -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));
+72 -131
View File
@@ -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];
+1
View File
@@ -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
+5 -11
View File
@@ -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)
+8 -4
View File
@@ -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)
-59
View File
@@ -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);
+4 -4
View File
@@ -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)
-12
View File
@@ -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;