From 3cb804ee6a2dc58829206ded1ddf606d9b1f7e3b Mon Sep 17 00:00:00 2001 From: jakcron Date: Tue, 3 Nov 2015 16:18:01 +0800 Subject: [PATCH] [makerom] Separated ELF processing from code segment construction. StackSize now read from exheader template. --- makerom/accessdesc.c | 10 +- makerom/code.c | 388 +++++++++++++ makerom/code.h | 3 + makerom/elf.c | 929 +++++--------------------------- makerom/elf.h | 139 +++-- makerom/elf_hdr.h | 192 ------- makerom/exheader.c | 91 ++-- makerom/exheader.h | 27 +- makerom/makerom.vcxproj | 3 +- makerom/makerom.vcxproj.filters | 9 +- makerom/ncch.c | 2 +- makerom/ncch_build.h | 1 + makerom/utils.c | 6 +- makerom/utils.h | 6 +- 14 files changed, 722 insertions(+), 1084 deletions(-) create mode 100644 makerom/code.c create mode 100644 makerom/code.h delete mode 100644 makerom/elf_hdr.h diff --git a/makerom/accessdesc.c b/makerom/accessdesc.c index fcb17be..dde1b58 100644 --- a/makerom/accessdesc.c +++ b/makerom/accessdesc.c @@ -44,12 +44,10 @@ int accessdesc_SignWithKey(exheader_settings *exhdrset) memcpy(&exhdrset->acexDesc->arm9AccessControlInfo,&exhdrset->exHdr->arm9AccessControlInfo,sizeof(exhdr_ARM9AccessControlInfo)); /* Adjust Data */ - u8 *flag = &exhdrset->acexDesc->arm11SystemLocalCapabilities.flag[2]; - u8 SystemMode = (*flag>>4)&0xF; - u8 AffinityMask = (*flag>>2)&0x3; - u8 IdealProcessor = 1<<((*flag>>0)&0x3); - *flag = (u8)(SystemMode << 4 | AffinityMask << 2 | IdealProcessor); - exhdrset->acexDesc->arm11SystemLocalCapabilities.flag[3] /= 2; + exhdr_ARM11SystemLocalCapabilities *arm11 = &exhdrset->acexDesc->arm11SystemLocalCapabilities; + + arm11->idealProcessor = 1 << arm11->idealProcessor; + arm11->threadPriority /= 2; /* Sign AccessDesc */ return SignAccessDesc(exhdrset->acexDesc,exhdrset->keys); diff --git a/makerom/code.c b/makerom/code.c new file mode 100644 index 0000000..ea31b2c --- /dev/null +++ b/makerom/code.c @@ -0,0 +1,388 @@ +#include "lib.h" +#include "elf.h" +#include "blz.h" +#include "ncch_build.h" +#include "exheader_read.h" +#include "code.h" + +const char *SDK_PLAINREGION_SEGMENT_NAME = ".module_id"; + +typedef struct code_segment +{ + u32 address; + u32 size; + u32 maxPageNum; + u8 *data; +} code_segment; + +u32 GetPageSize(ncch_settings *set) +{ + if (set->rsfSet->Option.PageSize) + return strtoul(set->rsfSet->Option.PageSize, NULL, 10); + return 0x1000; +} + +u32 SizeToPage(u32 memorySize, elf_context *elf) +{ + return align(memorySize, elf->pageSize) / elf->pageSize; +} + +int ImportPlainRegionFromFile(ncch_settings *set) +{ + set->sections.plainRegion.size = align(set->componentFilePtrs.plainregionSize, 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; } + ReadFile64(set->sections.plainRegion.buffer, set->componentFilePtrs.plainregionSize, 0, set->componentFilePtrs.plainregion); + return 0; +} + +int ImportExeFsCodeBinaryFromFile(ncch_settings *set) +{ + u32 size = set->componentFilePtrs.codeSize; + u8 *buffer = malloc(size); + if (!buffer) { + fprintf(stderr, "[ELF ERROR] Not enough memory\n"); + return MEM_ERROR; + } + ReadFile64(buffer, size, 0, set->componentFilePtrs.code); + + set->exefsSections.code.size = set->componentFilePtrs.codeSize; + set->exefsSections.code.buffer = malloc(set->exefsSections.code.size); + 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) { + u32 new_len; + set->exefsSections.code.buffer = BLZ_Code(buffer, size, &new_len, BLZ_NORMAL); + set->exefsSections.code.size = new_len; + free(buffer); + } + else { + set->exefsSections.code.size = size; + set->exefsSections.code.buffer = buffer; + } + + size = set->componentFilePtrs.exhdrSize; + if (size < sizeof(extended_hdr)) { + fprintf(stderr, "[ELF 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"); + return MEM_ERROR; + } + ReadFile64(exhdr, size, 0, set->componentFilePtrs.exhdr); + + /* Setting code_segment data */ + set->codeDetails.textAddress = u8_to_u32(exhdr->codeSetInfo.text.address, LE); + set->codeDetails.textMaxPages = u8_to_u32(exhdr->codeSetInfo.text.numMaxPages, LE); + set->codeDetails.textSize = u8_to_u32(exhdr->codeSetInfo.text.codeSize, LE); + + set->codeDetails.roAddress = u8_to_u32(exhdr->codeSetInfo.rodata.address, LE); + set->codeDetails.roMaxPages = u8_to_u32(exhdr->codeSetInfo.rodata.numMaxPages, LE); + set->codeDetails.roSize = u8_to_u32(exhdr->codeSetInfo.rodata.codeSize, LE); + + set->codeDetails.rwAddress = u8_to_u32(exhdr->codeSetInfo.data.address, LE); + set->codeDetails.rwMaxPages = u8_to_u32(exhdr->codeSetInfo.data.numMaxPages, LE); + set->codeDetails.rwSize = u8_to_u32(exhdr->codeSetInfo.data.codeSize, LE); + + set->codeDetails.bssSize = u8_to_u32(exhdr->codeSetInfo.bssSize, LE); + + set->codeDetails.stackSize = u8_to_u32(exhdr->codeSetInfo.stackSize, LE); + + free(exhdr); + + return 0; +} + +int GetBSSFromElf(elf_context *elf, ncch_settings *set) +{ + set->codeDetails.bssSize = 0; + + for (int i = 0; i < elf->sectionTableEntryCount; i++) { + if (IsBss(&elf->sections[i])) + set->codeDetails.bssSize = elf->sections[i].size; + } + + return 0; +} + +int ImportPlainRegionFromElf(elf_context *elf, ncch_settings *set) // Doesn't work same as N makerom +{ + 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; + } + } + + + 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); + + /* Copy Plain Region */ + memcpy(set->sections.plainRegion.buffer, elf->file + offset, size); + } + + return 0; +} + +int CreateCodeSegmentFromElf(code_segment *out, elf_context *elf, u64 segment_flags) +{ + 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++; + } + } + } + + /* Return if there are no applicable segment */ + if (seg_num == 0) + return 0; + + /* Getting Segment Size/Settings */ + u32 vAddr = 0; + u32 memorySize = 0; + for (u16 i = 0; i < seg_num; i++) { + if (i == 0) { + vAddr = seg[i]->vAddr; + } + else { // Add rounded size from previous segment + u32 padding = seg[i]->vAddr - (vAddr + memorySize); + memorySize += padding; + } + + memorySize += seg[i]->header->sizeInMemory; + + 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); +#endif + + out->address = vAddr; + out->size = memorySize; + out->maxPageNum = SizeToPage(memorySize, elf); + out->data = malloc(memorySize); + + /* Writing Segment to Buffer */ + for (int i = 0; i < seg_num; i++) { + + 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; + } + } + } + + free(seg); + return 0; +} + +int CreateExeFsCode(elf_context *elf, ncch_settings *set) +{ + /* Getting Code Segments */ + code_segment text; + memset(&text, 0, sizeof(code_segment)); + code_segment rodata; + memset(&rodata, 0, sizeof(code_segment)); + code_segment rwdata; + memset(&rwdata, 0, sizeof(code_segment)); + + int result = CreateCodeSegmentFromElf(&text, elf, PF_TEXT); + if (result) return result; + result = CreateCodeSegmentFromElf(&rodata, elf, PF_RODATA); + if (result) return result; + result = CreateCodeSegmentFromElf(&rwdata, elf, PF_DATA); + if (result) return result; + + /* Checking the existence of essential ELF Segments */ + if (!text.size) return NOT_FIND_TEXT_SEGMENT; + if (!rwdata.size) return NOT_FIND_DATA_SEGMENT; + + /* Allocating Buffer for ExeFs Code */ + u32 size = (text.maxPageNum + rodata.maxPageNum + rwdata.maxPageNum)*elf->pageSize; + u8 *code = calloc(1, size); + + /* Writing Code into Buffer */ + u8 *textPos = (code + 0); + u8 *rodataPos = (code + text.maxPageNum*elf->pageSize); + u8 *rwdataPos = (code + (text.maxPageNum + rodata.maxPageNum)*elf->pageSize); + if (text.size) memcpy(textPos, text.data, text.size); + if (rodata.size) memcpy(rodataPos, rodata.data, rodata.size); + if (rwdata.size) memcpy(rwdataPos, rwdata.data, rwdata.size); + + + /* Compressing If needed */ + if (set->options.CompressCode) { + u32 new_len; + set->exefsSections.code.buffer = BLZ_Code(code, size, &new_len, BLZ_NORMAL); + set->exefsSections.code.size = new_len; + free(code); + } + else { + set->exefsSections.code.size = size; + set->exefsSections.code.buffer = code; + } + + /* Setting code_segment data and freeing original buffers */ + set->codeDetails.textAddress = text.address; + set->codeDetails.textMaxPages = text.maxPageNum; + set->codeDetails.textSize = text.size; + if (text.size) free(text.data); + + set->codeDetails.roAddress = rodata.address; + set->codeDetails.roMaxPages = rodata.maxPageNum; + set->codeDetails.roSize = rodata.size; + if (rodata.size) free(rodata.data); + + set->codeDetails.rwAddress = rwdata.address; + set->codeDetails.rwMaxPages = rwdata.maxPageNum; + set->codeDetails.rwSize = rwdata.size; + if (rwdata.size) free(rwdata.data); + + if (set->rsfSet->SystemControlInfo.StackSize) + set->codeDetails.stackSize = strtoul(set->rsfSet->SystemControlInfo.StackSize, NULL, 0); + else { + fprintf(stderr, "[CODE ERROR] RSF Parameter Not Found: \"SystemControlInfo/StackSize\"\n"); + return 1; + } + + /* Return */ + return 0; +} + +void PrintElfContext(elf_context *elf) +{ + printf("[ELF] Program Table Data\n"); + printf(" Offset: 0x%x\n", elf->programTableOffset); + printf(" Size: 0x%x\n", elf->programTableEntrySize); + printf(" Count: 0x%x\n", elf->programTableEntryCount); + printf("[ELF] Section Table Data\n"); + printf(" Offset: 0x%x\n", elf->sectionTableOffset); + printf(" Size: 0x%x\n", elf->sectionTableEntrySize); + printf(" Count: 0x%x\n", elf->sectionTableEntryCount); + printf(" Label index: 0x%x\n", elf->sectionHeaderNameEntryIndex); + for (int i = 0; i < elf->activeSegments; i++) { + printf(" Segment [%d][%s]\n", i, elf->segments[i].name); + printf(" > Size : 0x%x\n", elf->segments[i].header->sizeInFile); + printf(" > Address : 0x%x\n", elf->segments[i].vAddr); + printf(" > Flags: 0x%x\n", elf->segments[i].header->flags); + printf(" > Type: 0x%x\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][0x%x][0x%x]\n", j, elf->segments[i].sections[j].name, elf->segments[i].sections[j].flags, elf->segments[i].sections[j].type); + + /* + char outpath[100]; + memset(&outpath,0,100); + sprintf(outpath,"%s.bin",elf->sections[i].name); + chdir("elfsections"); + FILE *tmp = fopen(outpath,"wb"); + WriteBuffer(elf->sections[i].ptr,elf->sections[i].size,0,tmp); + fclose(tmp); + chdir(".."); + */ + } + +} + +int BuildExeFsCode(ncch_settings *set) +{ + int result = 0; + if (set->options.IsCfa) + return result; + + if (set->componentFilePtrs.plainregion) // Import PlainRegion from file + if ((result = ImportPlainRegionFromFile(set))) return result; + if (!set->options.IsBuildingCodeSection) // Import ExeFs Code from file and return + return ImportExeFsCodeBinaryFromFile(set); + + /* Import ELF */ + u8 *elfFile = malloc(set->componentFilePtrs.elfSize); + if (!elfFile) { + fprintf(stderr, "[CODE ERROR] Not enough memory\n"); + return MEM_ERROR; + } + ReadFile64(elfFile, set->componentFilePtrs.elfSize, 0, set->componentFilePtrs.elf); + + /* Create ELF Context */ + elf_context *elf = calloc(1, sizeof(elf_context)); + if (!elf) { + fprintf(stderr, "[CODE ERROR] Not enough memory\n"); + free(elfFile); + return MEM_ERROR; + } + + if ((result = GetElfContext(elf, elfFile))) goto finish; + + /* Setting Page Size */ + elf->pageSize = GetPageSize(set); + + if (!set->componentFilePtrs.plainregion) + if ((result = ImportPlainRegionFromElf(elf, set))) goto finish; + + if (set->options.verbose) + PrintElfContext(elf); + + if ((result = CreateExeFsCode(elf, set))) goto finish; + if ((result = GetBSSFromElf(elf, set))) goto finish; + +finish: + switch (result) { + case (0) : + break; + case (NOT_ELF_FILE) : + fprintf(stderr, "[CODE ERROR] Not ELF File\n"); + break; + case (NOT_CTR_ARM_ELF) : + fprintf(stderr, "[CODE ERROR] Not CTR ARM ELF\n"); + break; + case (NON_EXECUTABLE_ELF) : + fprintf(stderr, "[CODE ERROR] Not Executeable ELF\n"); + break; + case (NOT_FIND_TEXT_SEGMENT) : + fprintf(stderr, "[CODE ERROR] Failed to retrieve text sections from ELF\n"); + break; + case (NOT_FIND_DATA_SEGMENT) : + fprintf(stderr, "[CODE ERROR] Failed to retrieve data sections from ELF\n"); + break; + default: + fprintf(stderr, "[CODE ERROR] Failed to process ELF file (%d)\n", result); + } + + FreeElfContext(elf); + free(elfFile); + free(elf); + return result; +} diff --git a/makerom/code.h b/makerom/code.h new file mode 100644 index 0000000..fdad049 --- /dev/null +++ b/makerom/code.h @@ -0,0 +1,3 @@ +#pragma once + +int BuildExeFsCode(ncch_settings *ncchset); \ No newline at end of file diff --git a/makerom/elf.c b/makerom/elf.c index aae3539..6aad3ef 100644 --- a/makerom/elf.c +++ b/makerom/elf.c @@ -1,430 +1,149 @@ #include "lib.h" -#include "ncch_build.h" -#include "exheader_read.h" -#include "elf_hdr.h" #include "elf.h" -#include "blz.h" -const char *SDK_PLAINREGION_SEGMENT_NAME = ".module_id"; +static const u32 ELF_MAGIC = 0x7f454c46; -int ImportPlainRegionFromFile(ncch_settings *set); -int ImportExeFsCodeBinaryFromFile(ncch_settings *set); +typedef enum elf_bit_format_types +{ + elf_32_bit = 1, + elf_64_bit = 2, +} elf_bit_format_types; -u32 GetPageSize(ncch_settings *set); -u32 SizeToPage(u32 memorySize, elf_context *elf); +typedef enum elf_endianness +{ + elf_little_endian = 1, + elf_big_endian = 2, +} elf_endianness; -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, u64 segment_flags); +typedef enum elf_type +{ + elf_relocatable = 1, + elf_executeable = 2, + elf_shared = 3, + elf_core = 4, +} elf_type; + +typedef enum elf_target_architecture +{ + elf_arm = 0x28, +} elf_target_architecture; + +typedef struct elf_hdr +{ + u8 magic[4]; + u8 bitFormat; + u8 endianness; + u8 elfVersion; + u8 os; + u8 padding0[8]; + u8 type[2]; + u8 targetArchitecture[2]; + u8 version[4]; + u8 entryPoint[4]; + u8 programHeaderTableOffset[4]; + u8 sectionHeaderTableOffset[4]; + u8 flags[4]; + u8 headerSize[2]; + u8 programHeaderEntrySize[2]; + u8 programHeaderEntryCount[2]; + u8 sectionTableEntrySize[2]; + u8 sectionHeaderEntryCount[2]; + u8 sectionHeaderNameEntryIndex[2]; +} elf_hdr; + +/* taken from elf specs, will not follow global style */ + +/* Section header. */ +typedef struct elf_shdr +{ + u8 name[4]; /* Section name (string tbl index) */ + u8 type[4]; /* Section type */ + u8 flags[4]; /* Section flags */ + u8 addr[4]; /* Section virtual addr at execution */ + u8 offset[4]; /* Section file offset */ + u8 size[4]; /* Section size in bytes */ + u8 link[4]; /* Link to another section */ + u8 info[4]; /* Additional section information */ + u8 addralign[4]; /* Section alignment */ + u8 entsize[4]; /* Entry size if section holds table */ +} elf_shdr; + +/* Program segment header. */ +typedef struct elf_phdr +{ + u8 type[4]; /* Segment type */ + u8 offset[4]; /* Segment file offset */ + u8 vaddr[4]; /* Segment virtual address */ + u8 paddr[4]; /* Segment physical address */ + u8 filesz[4]; /* Segment size in file */ + u8 memsz[4]; /* Segment size in memory */ + u8 flags[4]; /* Segment flags */ + u8 align[4]; /* Segment alignment */ +} elf_phdr; // ELF Functions -int GetElfContext(elf_context *elf, u8 *elfFile); -int GetElfSectionEntries(elf_context *elf, u8 *elfFile); -int GetElfProgramEntries(elf_context *elf, u8 *elfFile); -void PrintElfContext(elf_context *elf, u8 *elfFile); -int ReadElfHdr(elf_context *elf, u8 *elfFile); +int GetElfSectionEntries(elf_context *elf); +int GetElfProgramEntries(elf_context *elf); +void PrintElfContext(elf_context *elf); +int ReadElfHdr(elf_context *elf); -int CreateElfSegments(elf_context *elf, u8 *elfFile); +int CreateElfSegments(elf_context *elf); bool IsIgnoreSection(elf_section_entry info); -/* ELF Section Entry Functions */ -u8* GetELFSectionHeader(u16 index, elf_context *elf, u8 *elfFile); -u8* GetELFSectionEntry(u16 index, elf_context *elf, u8 *elfFile); -char* GetELFSectionEntryName(u16 index, elf_context *elf, u8 *elfFile); -u64 GetELFSectionEntryType(u16 index, elf_context *elf, u8 *elfFile); -u64 GetELFSectionEntryFlags(u16 index, elf_context *elf, u8 *elfFile); -u64 GetELFSectionEntryAddress(u16 index, elf_context *elf, u8 *elfFile); -u64 GetELFSectionEntryFileOffset(u16 index, elf_context *elf, u8 *elfFile); -u64 GetELFSectionEntrySize(u16 index, elf_context *elf, u8 *elfFile); -u64 GetELFSectionEntryAlignment(u16 index, elf_context *elf, u8 *elfFile); +// ELF Functions -u16 GetElfSectionIndexFromName(char *name, elf_context *elf, u8 *elfFile); - -bool IsBss(elf_section_entry *section); -bool IsData(elf_section_entry *section); -bool IsRoData(elf_section_entry *section); -bool IsText(elf_section_entry *section); - -/* ELF Program Entry Functions */ -u8* GetELFProgramHeader(u16 index, elf_context *elf, u8 *elfFile); -u8* GetELFProgramEntry(u16 index, elf_context *elf, u8 *elfFile); -u64 GetELFProgramEntryType(u16 index, elf_context *elf, u8 *elfFile); -u64 GetELFProgramEntryFlags(u16 index, elf_context *elf, u8 *elfFile); -u64 GetELFProgramEntryFileSize(u16 index, elf_context *elf, u8 *elfFile); -u64 GetELFProgramEntryFileOffset(u16 index, elf_context *elf, u8 *elfFile); -u64 GetELFProgramEntryMemorySize(u16 index, elf_context *elf, u8 *elfFile); -u64 GetELFProgramEntryVAddress(u16 index, elf_context *elf, u8 *elfFile); -u64 GetELFProgramEntryPAddress(u16 index, elf_context *elf, u8 *elfFile); -u64 GetELFProgramEntryAlignment(u16 index, elf_context *elf, u8 *elfFile); - - -int BuildExeFsCode(ncch_settings *set) +int GetElfContext(elf_context *elf, const u8 *elfFile) { - int result = 0; - if(set->options.IsCfa) - return result; - if(set->componentFilePtrs.plainregion){ // Import PlainRegion from file - result = ImportPlainRegionFromFile(set); - if(result) return result; - } - if(!set->options.IsBuildingCodeSection){ // Import ExeFs Code from file and return - result = ImportExeFsCodeBinaryFromFile(set); - return result; - } - - /* Import ELF */ - u8 *elfFile = malloc(set->componentFilePtrs.elfSize); - if(!elfFile) { - fprintf(stderr,"[ELF ERROR] Not enough memory\n"); - return MEM_ERROR; - } - ReadFile64(elfFile,set->componentFilePtrs.elfSize,0,set->componentFilePtrs.elf); - - /* Create ELF Context */ - elf_context *elf = calloc(1,sizeof(elf_context)); - if(!elf) { - fprintf(stderr,"[ELF ERROR] Not enough memory\n"); - free(elfFile); - return MEM_ERROR; - } + elf->file = elfFile; - result = GetElfContext(elf,elfFile); - if(result) goto finish; + int result; - /* Setting Page Size */ - elf->pageSize = GetPageSize(set); + if((result = ReadElfHdr(elf))) return result; + if((result = GetElfSectionEntries(elf))) return result; + if((result = GetElfProgramEntries(elf))) return result; + if((result = CreateElfSegments(elf))) return result; - if(!set->componentFilePtrs.plainregion){ - result = ImportPlainRegionFromElf(elf,elfFile,set); - if(result) goto finish; - } + return 0; +} - if(set->options.verbose) - PrintElfContext(elf,elfFile); - - result = CreateExeFsCode(elf,elfFile,set); - if(result) goto finish; - - result = GetBSSFromElf(elf,elfFile,set); - if(result) goto finish; - -finish: - switch (result) { - case (0) : - break; - case (NOT_ELF_FILE) : - fprintf(stderr, "[ELF ERROR] Not ELF File\n"); - break; - case (NOT_ARM_ELF) : - fprintf(stderr, "[ELF ERROR] Not ARM ELF\n"); - break; - case (NON_EXECUTABLE_ELF) : - fprintf(stderr, "[ELF ERROR] Not Executeable ELF\n"); - break; - case (NOT_FIND_TEXT_SEGMENT) : - fprintf(stderr, "[ELF ERROR] Failed to retrieve text sections from ELF\n"); - break; - case (NOT_FIND_DATA_SEGMENT) : - fprintf(stderr, "[ELF ERROR] Failed to retrieve data sections from ELF\n"); - break; - default: - fprintf(stderr, "[ELF ERROR] Failed to process ELF file (%d)\n", result); - } - for(int i = 0; i < elf->activeSegments; i++) +void FreeElfContext(elf_context *elf) +{ + for (int i = 0; i < elf->activeSegments; i++) free(elf->segments[i].sections); - free(elfFile); free(elf->sections); free(elf->programHeaders); free(elf->segments); - free(elf); - return result; } -int ImportPlainRegionFromFile(ncch_settings *set) +int ReadElfHdr(elf_context *elf) { - set->sections.plainRegion.size = align(set->componentFilePtrs.plainregionSize,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;} - ReadFile64(set->sections.plainRegion.buffer,set->componentFilePtrs.plainregionSize,0,set->componentFilePtrs.plainregion); - return 0; -} + const elf_hdr *hdr = (const elf_hdr*)elf->file; -int ImportExeFsCodeBinaryFromFile(ncch_settings *set) -{ - u32 size = set->componentFilePtrs.codeSize; - u8 *buffer = malloc(size); - if(!buffer) { - fprintf(stderr,"[ELF ERROR] Not enough memory\n"); - return MEM_ERROR; - } - ReadFile64(buffer,size,0,set->componentFilePtrs.code); + if (u8_to_u32(hdr->magic, BE) != ELF_MAGIC) + return NOT_ELF_FILE; + if (hdr->bitFormat != elf_32_bit) + return NOT_CTR_ARM_ELF; + if (hdr->endianness != elf_little_endian) + return NOT_CTR_ARM_ELF; + if (u8_to_u16(hdr->targetArchitecture, LE) != elf_arm) + return NOT_CTR_ARM_ELF; + if (u8_to_u16(hdr->type, LE) != elf_executeable) + return NON_EXECUTABLE_ELF; - set->exefsSections.code.size = set->componentFilePtrs.codeSize; - set->exefsSections.code.buffer = malloc(set->exefsSections.code.size); - 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){ - u32 new_len; - set->exefsSections.code.buffer = BLZ_Code(buffer,size,&new_len,BLZ_NORMAL); - set->exefsSections.code.size = new_len; - free(buffer); - } - else{ - set->exefsSections.code.size = size; - set->exefsSections.code.buffer = buffer; - } - - size = set->componentFilePtrs.exhdrSize; - if(size < sizeof(extended_hdr)){ - fprintf(stderr,"[ELF 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"); - return MEM_ERROR; - } - ReadFile64(exhdr,size,0,set->componentFilePtrs.exhdr); - - /* Setting code_segment data */ - set->codeDetails.textAddress = u8_to_u32(exhdr->codeSetInfo.text.address,LE); - set->codeDetails.textMaxPages = u8_to_u32(exhdr->codeSetInfo.text.numMaxPages,LE); - set->codeDetails.textSize = u8_to_u32(exhdr->codeSetInfo.text.codeSize,LE); + elf->programTableOffset = u8_to_u32(hdr->programHeaderTableOffset, LE); + elf->programTableEntrySize = u8_to_u16(hdr->programHeaderEntrySize, LE); + elf->programTableEntryCount = u8_to_u16(hdr->programHeaderEntryCount, LE); - set->codeDetails.roAddress = u8_to_u32(exhdr->codeSetInfo.rodata.address,LE); - set->codeDetails.roMaxPages = u8_to_u32(exhdr->codeSetInfo.rodata.numMaxPages,LE); - set->codeDetails.roSize = u8_to_u32(exhdr->codeSetInfo.rodata.codeSize,LE); + elf->sectionTableOffset = u8_to_u32(hdr->sectionHeaderTableOffset, LE); + elf->sectionTableEntrySize = u8_to_u16(hdr->sectionTableEntrySize, LE); + elf->sectionTableEntryCount = u8_to_u16(hdr->sectionHeaderEntryCount, LE); - set->codeDetails.rwAddress = u8_to_u32(exhdr->codeSetInfo.data.address,LE); - set->codeDetails.rwMaxPages = u8_to_u32(exhdr->codeSetInfo.data.numMaxPages,LE); - set->codeDetails.rwSize = u8_to_u32(exhdr->codeSetInfo.data.codeSize,LE); - - set->codeDetails.bssSize = u8_to_u32(exhdr->codeSetInfo.bssSize,LE); - - free(exhdr); - - return 0; -} - -u32 GetPageSize(ncch_settings *set) -{ - if(set->rsfSet->Option.PageSize) - return strtoul(set->rsfSet->Option.PageSize,NULL,10); - return 0x1000; -} - -u32 SizeToPage(u32 memorySize, elf_context *elf) -{ - return align(memorySize,elf->pageSize)/elf->pageSize; -} - - -int GetBSSFromElf(elf_context *elf, u8 *elfFile, ncch_settings *set) -{ - set->codeDetails.bssSize = 0; - - for(int i = 0; i < elf->sectionTableEntryCount; i++){ - if(IsBss(&elf->sections[i])) - set->codeDetails.bssSize = elf->sections[i].size; - } - - return 0; -} - -int ImportPlainRegionFromElf(elf_context *elf, u8 *elfFile, ncch_settings *set) // Doesn't work same as N makerom -{ - 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; - } - } - - - 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); - - /* Copy Plain Region */ - memcpy(set->sections.plainRegion.buffer, elfFile+offset, size); - } + elf->sectionHeaderNameEntryIndex = u8_to_u16(hdr->sectionHeaderNameEntryIndex, LE); return 0; } -int CreateExeFsCode(elf_context *elf, u8 *elfFile, ncch_settings *set) -{ - /* Getting Code Segments */ - code_segment text; - memset(&text,0,sizeof(code_segment)); - code_segment rodata; - memset(&rodata,0,sizeof(code_segment)); - code_segment rwdata; - memset(&rwdata,0,sizeof(code_segment)); - - int result = CreateCodeSegmentFromElf(&text,elf,elfFile,(PF_R|PF_X)); - if(result) return result; - result = CreateCodeSegmentFromElf(&rodata,elf,elfFile,(PF_R)); - if(result) return result; - result = CreateCodeSegmentFromElf(&rwdata,elf,elfFile,(PF_R | PF_W)); - if(result) return result; - - /* Checking the existence of essential ELF Segments */ - if(!text.size) return NOT_FIND_TEXT_SEGMENT; - if(!rwdata.size) return NOT_FIND_DATA_SEGMENT; - - /* Allocating Buffer for ExeFs Code */ - u32 size = (text.maxPageNum + rodata.maxPageNum + rwdata.maxPageNum)*elf->pageSize; - u8 *code = calloc(1,size); - - /* Writing Code into Buffer */ - u8 *textPos = (code + 0); - u8 *rodataPos = (code + text.maxPageNum*elf->pageSize); - u8 *rwdataPos = (code + (text.maxPageNum + rodata.maxPageNum)*elf->pageSize); - if(text.size) memcpy(textPos,text.data,text.size); - if(rodata.size) memcpy(rodataPos,rodata.data,rodata.size); - if(rwdata.size) memcpy(rwdataPos,rwdata.data,rwdata.size); - - - /* Compressing If needed */ - if(set->options.CompressCode){ - u32 new_len; - set->exefsSections.code.buffer = BLZ_Code(code,size,&new_len,BLZ_NORMAL); - set->exefsSections.code.size = new_len; - free(code); - } - else{ - set->exefsSections.code.size = size; - set->exefsSections.code.buffer = code; - } - - /* Setting code_segment data and freeing original buffers */ - set->codeDetails.textAddress = text.address; - set->codeDetails.textMaxPages = text.maxPageNum; - set->codeDetails.textSize = text.size; - if(text.size) free(text.data); - - set->codeDetails.roAddress = rodata.address; - set->codeDetails.roMaxPages = rodata.maxPageNum; - set->codeDetails.roSize = rodata.size; - if(rodata.size) free(rodata.data); - - set->codeDetails.rwAddress = rwdata.address; - set->codeDetails.rwMaxPages = rwdata.maxPageNum; - set->codeDetails.rwSize = rwdata.size; - if(rwdata.size) free(rwdata.data); - - /* Return */ - return 0; -} - -int CreateCodeSegmentFromElf(code_segment *out, elf_context *elf, u8 *elfFile, u64 segment_flags) -{ - 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++; - } - } - } - - /* Return if there are no applicable segment */ - if (seg_num == 0) - return 0; - - /* Getting Segment Size/Settings */ - u32 vAddr = 0; - u32 memorySize = 0; - for (u16 i = 0; i < seg_num; i++) { - if (i == 0) { - vAddr = seg[i]->vAddr; - } - else { // Add rounded size from previous segment - u32 padding = seg[i]->vAddr - (vAddr + memorySize); - memorySize += padding; - } - - memorySize += seg[i]->header->sizeInMemory; - - 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); -#endif - - out->address = vAddr; - out->size = memorySize; - out->maxPageNum = SizeToPage(memorySize, elf); - out->data = malloc(memorySize); - - /* Writing Segment to Buffer */ - for (int i = 0; i < seg_num; i++) { - - 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; - } - } - } - - free(seg); - return 0; -} - -// ELF Functions - -int GetElfContext(elf_context *elf, u8 *elfFile) -{ - if(u8_to_u32(elfFile,BE) != ELF_MAGIC) return NOT_ELF_FILE; - - elf->Is64bit = (elfFile[4] == elf_64_bit); - elf->IsLittleEndian = (elfFile[5] == elf_little_endian); - - int result = ReadElfHdr(elf,elfFile); - if(result) return result; - - result = GetElfSectionEntries(elf,elfFile); - if(result) return result; - - result = GetElfProgramEntries(elf,elfFile); - if(result) return result; - - result = CreateElfSegments(elf,elfFile); - if(result) return result; - - return 0; -} - -int GetElfSectionEntries(elf_context *elf, u8 *elfFile) +int GetElfSectionEntries(elf_context *elf) { elf->sections = calloc(elf->sectionTableEntryCount,sizeof(elf_section_entry)); if(!elf->sections) { @@ -432,20 +151,23 @@ int GetElfSectionEntries(elf_context *elf, u8 *elfFile) return MEM_ERROR; } + const elf_shdr *shdr = (const elf_shdr *)(elf->file + elf->sectionTableOffset); + const char *nameTable = (const char*)(elf->file + u8_to_u32(shdr[elf->sectionHeaderNameEntryIndex].offset, LE)); + for(int i = 0; i < elf->sectionTableEntryCount; i++){ - elf->sections[i].name = GetELFSectionEntryName(i,elf,elfFile); - elf->sections[i].type = GetELFSectionEntryType(i,elf,elfFile); - elf->sections[i].flags = GetELFSectionEntryFlags(i,elf,elfFile); - elf->sections[i].ptr = GetELFSectionEntry(i,elf,elfFile); - elf->sections[i].offsetInFile = GetELFSectionEntryFileOffset(i,elf,elfFile); - elf->sections[i].size = GetELFSectionEntrySize(i,elf,elfFile); - elf->sections[i].address = GetELFSectionEntryAddress(i,elf,elfFile); - elf->sections[i].alignment = GetELFSectionEntryAlignment(i,elf,elfFile); + elf->sections[i].name = nameTable + u8_to_u32(shdr[i].name, LE); + elf->sections[i].type = u8_to_u32(shdr[i].type, LE); + elf->sections[i].flags = u8_to_u32(shdr[i].flags, LE); + elf->sections[i].offsetInFile = u8_to_u32(shdr[i].offset, LE); + elf->sections[i].size = u8_to_u32(shdr[i].size, LE); + elf->sections[i].ptr = elf->file + elf->sections[i].offsetInFile; + elf->sections[i].address = u8_to_u32(shdr[i].addr, LE); + elf->sections[i].alignment = u8_to_u32(shdr[i].addralign, LE); } return 0; } -int GetElfProgramEntries(elf_context *elf, u8 *elfFile) +int GetElfProgramEntries(elf_context *elf) { elf->programHeaders = calloc(elf->programTableEntryCount,sizeof(elf_program_entry)); if(!elf->programHeaders) { @@ -453,240 +175,25 @@ int GetElfProgramEntries(elf_context *elf, u8 *elfFile) return MEM_ERROR; } + const elf_phdr *phdr = (const elf_phdr*)(elf->file + elf->programTableOffset); + for(int i = 0; i < elf->programTableEntryCount; i++){ - elf->programHeaders[i].type = GetELFProgramEntryType(i,elf,elfFile); - elf->programHeaders[i].flags = GetELFProgramEntryFlags(i,elf,elfFile); - elf->programHeaders[i].ptr = GetELFProgramEntry(i,elf,elfFile); - elf->programHeaders[i].offsetInFile = GetELFProgramEntryFileOffset(i,elf,elfFile); - elf->programHeaders[i].sizeInFile = GetELFProgramEntryFileSize(i,elf,elfFile); - elf->programHeaders[i].physicalAddress = GetELFProgramEntryPAddress(i,elf,elfFile); - elf->programHeaders[i].virtualAddress = GetELFProgramEntryVAddress(i,elf,elfFile); - elf->programHeaders[i].sizeInMemory = GetELFProgramEntryMemorySize(i,elf,elfFile); - elf->programHeaders[i].alignment = GetELFProgramEntryAlignment(i,elf,elfFile); + elf->programHeaders[i].type = u8_to_u32(phdr[i].type, LE); + elf->programHeaders[i].flags = u8_to_u32(phdr[i].flags, LE); + elf->programHeaders[i].offsetInFile = u8_to_u32(phdr[i].offset, LE); + elf->programHeaders[i].sizeInFile = u8_to_u32(phdr[i].filesz, LE); + elf->programHeaders[i].ptr = elf->file + elf->programHeaders[i].offsetInFile; + elf->programHeaders[i].physicalAddress = u8_to_u32(phdr[i].paddr, LE); + elf->programHeaders[i].virtualAddress = u8_to_u32(phdr[i].vaddr, LE); + elf->programHeaders[i].sizeInMemory = u8_to_u32(phdr[i].memsz, LE); + elf->programHeaders[i].alignment = u8_to_u32(phdr[i].align, LE); } return 0; } -void PrintElfContext(elf_context *elf, u8 *elfFile) -{ - printf("[ELF] Basic Details\n"); - printf(" Class: %s\n",elf->Is64bit ? "64-bit" : "32-bit"); - printf(" Data: %s\n",elf->IsLittleEndian ? "Little Endian" : "Big Endian"); - printf("[ELF] Program Table Data\n"); - printf(" Offset: 0x%"PRIx64"\n",elf->programTableOffset); - printf(" Size: 0x%x\n",elf->programTableEntrySize); - printf(" Count: 0x%x\n",elf->programTableEntryCount); - printf("[ELF] Section Table Data\n"); - printf(" Offset: 0x%"PRIx64"\n",elf->sectionTableOffset); - printf(" Size: 0x%x\n",elf->sectionTableEntrySize); - printf(" Count: 0x%x\n",elf->sectionTableEntryCount); - printf(" Label index: 0x%x\n",elf->sectionHeaderNameEntryIndex); - for(int i = 0; i < elf->activeSegments; i++){ - 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][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]; - memset(&outpath,0,100); - sprintf(outpath,"%s.bin",elf->sections[i].name); - chdir("elfsections"); - FILE *tmp = fopen(outpath,"wb"); - WriteBuffer(elf->sections[i].ptr,elf->sections[i].size,0,tmp); - fclose(tmp); - chdir(".."); - */ - } - -} - -int ReadElfHdr(elf_context *elf, u8 *elfFile) -{ - if(elf->Is64bit){ - elf_64_hdr *hdr = (elf_64_hdr*)elfFile; - - u16 Architecture = u8_to_u16(hdr->targetArchitecture,elf->IsLittleEndian); - u16 Type = u8_to_u16(hdr->type,elf->IsLittleEndian); - if(Architecture != elf_arm) return NOT_ARM_ELF; - if(Type != elf_executeable) return NON_EXECUTABLE_ELF; - - elf->programTableOffset = u8_to_u64(hdr->programHeaderTableOffset,elf->IsLittleEndian); - elf->programTableEntrySize = u8_to_u16(hdr->programHeaderEntrySize,elf->IsLittleEndian); - elf->programTableEntryCount = u8_to_u16(hdr->programHeaderEntryCount,elf->IsLittleEndian); - - elf->sectionTableOffset = u8_to_u64(hdr->sectionHeaderTableOffset,elf->IsLittleEndian); - elf->sectionTableEntrySize = u8_to_u16(hdr->sectionTableEntrySize,elf->IsLittleEndian); - elf->sectionTableEntryCount = u8_to_u16(hdr->sectionHeaderEntryCount,elf->IsLittleEndian); - - elf->sectionHeaderNameEntryIndex = u8_to_u16(hdr->sectionHeaderNameEntryIndex,elf->IsLittleEndian); - } - else{ - elf_32_hdr *hdr = (elf_32_hdr*)elfFile; - - u16 Architecture = u8_to_u16(hdr->targetArchitecture,elf->IsLittleEndian); - u16 Type = u8_to_u16(hdr->type,elf->IsLittleEndian); - if(Architecture != elf_arm) return NOT_ARM_ELF; - if(Type != elf_executeable) return NON_EXECUTABLE_ELF; - - elf->programTableOffset = u8_to_u32(hdr->programHeaderTableOffset,elf->IsLittleEndian); - elf->programTableEntrySize = u8_to_u16(hdr->programHeaderEntrySize,elf->IsLittleEndian); - elf->programTableEntryCount = u8_to_u16(hdr->programHeaderEntryCount,elf->IsLittleEndian); - - elf->sectionTableOffset = u8_to_u32(hdr->sectionHeaderTableOffset,elf->IsLittleEndian); - elf->sectionTableEntrySize = u8_to_u16(hdr->sectionTableEntrySize,elf->IsLittleEndian); - elf->sectionTableEntryCount = u8_to_u16(hdr->sectionHeaderEntryCount,elf->IsLittleEndian); - - elf->sectionHeaderNameEntryIndex = u8_to_u16(hdr->sectionHeaderNameEntryIndex,elf->IsLittleEndian); - } - return 0; -} - /* Section Hdr Functions */ -u8* GetELFSectionHeader(u16 index, elf_context *elf, u8 *elfFile) -{ - if(index >= elf->sectionTableEntryCount) return NULL; - - return (elfFile + elf->sectionTableOffset + elf->sectionTableEntrySize*index); -} - -u8* GetELFSectionEntry(u16 index, elf_context *elf, u8 *elfFile) -{ - if(index >= elf->sectionTableEntryCount) return NULL; - - return (u8*) (elfFile + GetELFSectionEntryFileOffset(index,elf,elfFile)); -} - -char* GetELFSectionEntryName(u16 index, elf_context *elf, u8 *elfFile) -{ - if(index >= elf->sectionTableEntryCount) return 0; - - u64 NameIndex = 0; - if(elf->Is64bit){ - elf_64_shdr *shdr = (elf_64_shdr*)GetELFSectionHeader(index,elf,elfFile); - NameIndex = u8_to_u64(shdr->sh_name,elf->IsLittleEndian); - } - else{ - elf_32_shdr *shdr = (elf_32_shdr*)GetELFSectionHeader(index,elf,elfFile); - NameIndex = u8_to_u32(shdr->sh_name,elf->IsLittleEndian); - } - - u8 *NameTable = GetELFSectionEntry(elf->sectionHeaderNameEntryIndex,elf,elfFile); - - return (char*)(NameTable+NameIndex); -} - -u64 GetELFSectionEntryType(u16 index, elf_context *elf, u8 *elfFile) -{ - if(index >= elf->sectionTableEntryCount) return 0; - - if(elf->Is64bit){ - elf_64_shdr *shdr = (elf_64_shdr*)GetELFSectionHeader(index,elf,elfFile); - return u8_to_u64(shdr->sh_type,elf->IsLittleEndian); - } - else{ - elf_32_shdr *shdr = (elf_32_shdr*)GetELFSectionHeader(index,elf,elfFile); - return u8_to_u32(shdr->sh_type,elf->IsLittleEndian); - } - - return 0; -} - -u64 GetELFSectionEntryFlags(u16 index, elf_context *elf, u8 *elfFile) -{ - if(index >= elf->sectionTableEntryCount) return 0; - - if(elf->Is64bit){ - elf_64_shdr *shdr = (elf_64_shdr*)GetELFSectionHeader(index,elf,elfFile); - return u8_to_u64(shdr->sh_flags,elf->IsLittleEndian); - } - else{ - elf_32_shdr *shdr = (elf_32_shdr*)GetELFSectionHeader(index,elf,elfFile); - return u8_to_u32(shdr->sh_flags,elf->IsLittleEndian); - } - - return 0; -} - -u64 GetELFSectionEntryAddress(u16 index, elf_context *elf, u8 *elfFile) -{ - if(index >= elf->sectionTableEntryCount) return 0; - - if(elf->Is64bit){ - elf_64_shdr *shdr = (elf_64_shdr*)GetELFSectionHeader(index,elf,elfFile); - return u8_to_u64(shdr->sh_addr,elf->IsLittleEndian); - } - else{ - elf_32_shdr *shdr = (elf_32_shdr*)GetELFSectionHeader(index,elf,elfFile); - return u8_to_u32(shdr->sh_addr,elf->IsLittleEndian); - } - - return 0; -} - -u64 GetELFSectionEntryFileOffset(u16 index, elf_context *elf, u8 *elfFile) -{ - if(index >= elf->sectionTableEntryCount) return 0; - - if(elf->Is64bit){ - elf_64_shdr *shdr = (elf_64_shdr*)GetELFSectionHeader(index,elf,elfFile); - return u8_to_u64(shdr->sh_offset,elf->IsLittleEndian); - } - else{ - elf_32_shdr *shdr = (elf_32_shdr*)GetELFSectionHeader(index,elf,elfFile); - return u8_to_u32(shdr->sh_offset,elf->IsLittleEndian); - } - - return 0; -} - -u64 GetELFSectionEntrySize(u16 index, elf_context *elf, u8 *elfFile) -{ - if(index >= elf->sectionTableEntryCount) return 0; - - if(elf->Is64bit){ - elf_64_shdr *shdr = (elf_64_shdr*)GetELFSectionHeader(index,elf,elfFile); - return u8_to_u64(shdr->sh_size,elf->IsLittleEndian); - } - else{ - elf_32_shdr *shdr = (elf_32_shdr*)GetELFSectionHeader(index,elf,elfFile); - return u8_to_u32(shdr->sh_size,elf->IsLittleEndian); - } - - return 0; -} - -u64 GetELFSectionEntryAlignment(u16 index, elf_context *elf, u8 *elfFile) -{ - if(index >= elf->sectionTableEntryCount) return 0; - - if(elf->Is64bit){ - elf_64_shdr *shdr = (elf_64_shdr*)GetELFSectionHeader(index,elf,elfFile); - return u8_to_u64(shdr->sh_addralign,elf->IsLittleEndian); - } - else{ - elf_32_shdr *shdr = (elf_32_shdr*)GetELFSectionHeader(index,elf,elfFile); - return u8_to_u32(shdr->sh_addralign,elf->IsLittleEndian); - } - - return 0; -} - - -u16 GetElfSectionIndexFromName(char *name, elf_context *elf, u8 *elfFile) -{ - for(int i = 0; i < elf->sectionTableEntryCount; i++){ - if(strcmp(name,elf->sections[i].name) == 0) return i; - } - return 0; // Assuming 0 is always empty -} - bool IsBss(elf_section_entry *section) { return (section->type == SHT_NOBITS && section->flags == (SHF_WRITE | SHF_ALLOC)); @@ -707,153 +214,7 @@ bool IsText(elf_section_entry *section) return (section->type == SHT_PROGBITS && section->flags == (SHF_ALLOC | SHF_EXECINSTR)); } -/* ProgramHeader Functions */ - -u8* GetELFProgramHeader(u16 index, elf_context *elf, u8 *elfFile) -{ - if(index >= elf->programTableEntryCount) return NULL; - - return (elfFile + elf->programTableOffset + elf->programTableEntrySize*index); -} - -u8* GetELFProgramEntry(u16 index, elf_context *elf, u8 *elfFile) -{ - if(index >= elf->programTableEntryCount) return NULL; - - return (u8*) (elfFile + GetELFProgramEntryFileOffset(index,elf,elfFile)); - - return NULL; -} - -u64 GetELFProgramEntryType(u16 index, elf_context *elf, u8 *elfFile) -{ - if(index >= elf->programTableEntryCount) return 0; - - if(elf->Is64bit){ - elf_64_phdr *phdr = (elf_64_phdr*)GetELFProgramHeader(index,elf,elfFile); - return u8_to_u64(phdr->p_type,elf->IsLittleEndian); - } - else{ - elf_32_phdr *phdr = (elf_32_phdr*)GetELFProgramHeader(index,elf,elfFile); - return u8_to_u32(phdr->p_type,elf->IsLittleEndian); - } - - return 0; -} - -u64 GetELFProgramEntryFlags(u16 index, elf_context *elf, u8 *elfFile) -{ - if(index >= elf->programTableEntryCount) return 0; - - if(elf->Is64bit){ - elf_64_phdr *phdr = (elf_64_phdr*)GetELFProgramHeader(index,elf,elfFile); - return u8_to_u64(phdr->p_flags,elf->IsLittleEndian); - } - else{ - elf_32_phdr *phdr = (elf_32_phdr*)GetELFProgramHeader(index,elf,elfFile); - return u8_to_u32(phdr->p_flags,elf->IsLittleEndian); - } - - return 0; -} - -u64 GetELFProgramEntryFileSize(u16 index, elf_context *elf, u8 *elfFile) -{ - if(index >= elf->programTableEntryCount) return 0; - - if(elf->Is64bit){ - elf_64_phdr *phdr = (elf_64_phdr*)GetELFProgramHeader(index,elf,elfFile); - return u8_to_u64(phdr->p_filesz,elf->IsLittleEndian); - } - else{ - elf_32_phdr *phdr = (elf_32_phdr*)GetELFProgramHeader(index,elf,elfFile); - return u8_to_u32(phdr->p_filesz,elf->IsLittleEndian); - } - - return 0; -} - -u64 GetELFProgramEntryFileOffset(u16 index, elf_context *elf, u8 *elfFile) -{ - if(index >= elf->programTableEntryCount) return 0; - - if(elf->Is64bit){ - elf_64_phdr *phdr = (elf_64_phdr*)GetELFProgramHeader(index,elf,elfFile); - return u8_to_u64(phdr->p_offset,elf->IsLittleEndian); - } - else{ - elf_32_phdr *phdr = (elf_32_phdr*)GetELFProgramHeader(index,elf,elfFile); - return u8_to_u32(phdr->p_offset,elf->IsLittleEndian); - } - - return 0; -} - -u64 GetELFProgramEntryMemorySize(u16 index, elf_context *elf, u8 *elfFile) -{ - if(index >= elf->programTableEntryCount) return 0; - - if(elf->Is64bit){ - elf_64_phdr *phdr = (elf_64_phdr*)GetELFProgramHeader(index,elf,elfFile); - return u8_to_u64(phdr->p_memsz,elf->IsLittleEndian); - } - else{ - elf_32_phdr *phdr = (elf_32_phdr*)GetELFProgramHeader(index,elf,elfFile); - return u8_to_u32(phdr->p_memsz,elf->IsLittleEndian); - } - - return 0; -} - -u64 GetELFProgramEntryVAddress(u16 index, elf_context *elf, u8 *elfFile) -{ - if(index >= elf->programTableEntryCount) return 0; - - if(elf->Is64bit){ - elf_64_phdr *phdr = (elf_64_phdr*)GetELFProgramHeader(index,elf,elfFile); - return u8_to_u64(phdr->p_vaddr,elf->IsLittleEndian); - } - else{ - elf_32_phdr *phdr = (elf_32_phdr*)GetELFProgramHeader(index,elf,elfFile); - return u8_to_u32(phdr->p_vaddr,elf->IsLittleEndian); - } - - return 0; -} - -u64 GetELFProgramEntryPAddress(u16 index, elf_context *elf, u8 *elfFile) -{ - if(index >= elf->programTableEntryCount) return 0; - - if(elf->Is64bit){ - elf_64_phdr *phdr = (elf_64_phdr*)GetELFProgramHeader(index,elf,elfFile); - return u8_to_u64(phdr->p_paddr,elf->IsLittleEndian); - } - else{ - elf_32_phdr *phdr = (elf_32_phdr*)GetELFProgramHeader(index,elf,elfFile); - return u8_to_u32(phdr->p_paddr,elf->IsLittleEndian); - } - - return 0; -} - - -u64 GetELFProgramEntryAlignment(u16 index, elf_context *elf, u8 *elfFile) -{ - if(index >= elf->programTableEntryCount) return 0; - - if(elf->Is64bit){ - elf_64_phdr *phdr = (elf_64_phdr*)GetELFProgramHeader(index,elf,elfFile); - return u8_to_u64(phdr->p_align,elf->IsLittleEndian); - } - else{ - elf_32_phdr *phdr = (elf_32_phdr*)GetELFProgramHeader(index,elf,elfFile); - return u8_to_u32(phdr->p_align,elf->IsLittleEndian); - } - - return 0; -} - +/* Program Segment Functions */ void InitSegment(elf_segment *segment) { memset(segment, 0, sizeof(elf_segment)); @@ -880,7 +241,12 @@ void AddSegmentSection(elf_segment *segment, elf_section_entry *section) segment->sectionNum++; } -int CreateElfSegments(elf_context *elf, u8 *elfFile) +bool IsIgnoreSection(elf_section_entry info) +{ + return !(info.flags & SHF_ALLOC);//(info.type != SHT_PROGBITS && info.type != SHT_NOBITS && info.type != SHT_INIT_ARRAY && info.type != SHT_FINI_ARRAY && info.type != SHT_ARM_EXIDX); +} + +int CreateElfSegments(elf_context *elf) { // Interate through Each Program Header elf->activeSegments = 0; @@ -945,9 +311,4 @@ int CreateElfSegments(elf_context *elf, u8 *elfFile) } return 0; -} - -bool IsIgnoreSection(elf_section_entry info) -{ - return (info.type != SHT_PROGBITS && info.type != SHT_NOBITS && info.type != SHT_INIT_ARRAY && info.type != SHT_FINI_ARRAY && info.type != SHT_ARM_EXIDX); -} +} \ No newline at end of file diff --git a/makerom/elf.h b/makerom/elf.h index a6b856a..c568a5b 100644 --- a/makerom/elf.h +++ b/makerom/elf.h @@ -1,9 +1,9 @@ #pragma once -typedef enum +typedef enum elf_errors { NOT_ELF_FILE = -10, - NOT_ARM_ELF = -11, + NOT_CTR_ARM_ELF = -11, NON_EXECUTABLE_ELF = -12, ELF_SECTION_NOT_FOUND = -13, NOT_FIND_TEXT_SEGMENT = -14, @@ -13,35 +13,101 @@ typedef enum ELF_SEGMENTS_NOT_FOUND = -18, } elf_errors; -typedef struct +typedef enum elf_section_type { - char *name; - u64 type; - u64 flags; - u8 *ptr; - u64 offsetInFile; - u64 size; - u64 address; - u64 alignment; + SHT_NULL, + SHT_PROGBITS, + SHT_SYMTAB, + SHT_STRTAB, + SHT_RELA, + SHT_HASH, + SHT_DYNAMIC, + SHT_NOTE, + SHT_NOBITS, + SHT_REL, + SHT_SHLIB, + SHT_DYNSYM, + SHT_UNKNOWN12, + SHT_UNKNOWN13, + SHT_INIT_ARRAY, + SHT_FINI_ARRAY, + SHT_PREINIT_ARRAY, + SHT_GROUP, + SHT_SYMTAB_SHNDX, + SHT_NUM, + SHT_ARM_EXIDX = 0x70000001, + SHT_ARM_PREEMPTMAP, + SHT_ARM_ATTRIBUTES, + SHT_ARM_DEBUGOVERLAY, + SHT_ARM_OVERLAYSECTION +} elf_section_type; + +typedef enum elf_section_flag +{ + SHF_WRITE = 0x1, + SHF_ALLOC = 0x2, + SHF_EXECINSTR = 0x4, + SHF_MERGE = 0x10, + SHF_STRINGS = 0x20, + SHF_INFO_LINK = 0x40, + SHF_LINK_ORDER = 0x80, + SHF_OS_NONCONFORMING = 0x100, + SHF_GROUP = 0x200, + SHF_TLS = 0x400 +} elf_section_flag; + +typedef struct elf_section_entry +{ + const char *name; + u32 type; + u32 flags; + const u8 *ptr; + u32 offsetInFile; + u32 size; + u32 address; + u32 alignment; } elf_section_entry; -typedef struct +typedef enum elf_program_type { - u64 type; - u64 flags; - u8 *ptr; - u64 offsetInFile; - u64 sizeInFile; - u64 virtualAddress; - u64 physicalAddress; - u64 sizeInMemory; - u64 alignment; + PT_NULL, + PT_LOAD, + PT_DYNAMIC, + PT_INTERP, + PT_NOTE, + PT_SHLIB, + PT_PHDR, +} elf_program_type; + +typedef enum elf_program_flag +{ + PF_X = 0x1, + PF_W = 0x2, + PF_R = 0x4, + PF_CTRSDK = 0x80000000, + + PF_TEXT = (PF_R|PF_X), + PF_DATA = (PF_R|PF_W), + PF_RODATA = PF_R +} elf_program_flag; + +typedef struct elf_program_entry +{ + u32 type; + u32 flags; + const u8 *ptr; + u32 offsetInFile; + u32 sizeInFile; + u32 virtualAddress; + u32 physicalAddress; + u32 sizeInMemory; + u32 alignment; } elf_program_entry; -typedef struct +typedef struct elf_segment { - char *name; - u64 vAddr; + const char *name; + u32 vAddr; elf_program_entry *header; u32 sectionNum; @@ -49,25 +115,17 @@ typedef struct elf_section_entry *sections; } elf_segment; -typedef struct +typedef struct elf_context { - u32 address; - u32 size; - u32 maxPageNum; - u8 *data; -} code_segment; + const u8 *file; -typedef struct -{ u32 pageSize; - bool IsLittleEndian; - bool Is64bit; - u64 programTableOffset; + u32 programTableOffset; u16 programTableEntrySize; u16 programTableEntryCount; - u64 sectionTableOffset; + u32 sectionTableOffset; u16 sectionTableEntrySize; u16 sectionTableEntryCount; @@ -78,7 +136,12 @@ typedef struct u16 activeSegments; elf_segment *segments; - } elf_context; -int BuildExeFsCode(ncch_settings *ncchset); \ No newline at end of file +bool IsBss(elf_section_entry *section); +bool IsData(elf_section_entry *section); +bool IsRoData(elf_section_entry *section); +bool IsText(elf_section_entry *section); + +int GetElfContext(elf_context *elf, const u8 *elfFile); +void FreeElfContext(elf_context *elf); \ No newline at end of file diff --git a/makerom/elf_hdr.h b/makerom/elf_hdr.h deleted file mode 100644 index 4fb772d..0000000 --- a/makerom/elf_hdr.h +++ /dev/null @@ -1,192 +0,0 @@ -#pragma once - -static const u32 ELF_MAGIC = 0x7f454c46; - -typedef enum -{ - elf_32_bit = 1, - elf_64_bit = 2, -} elf_bit_format_types; - -typedef enum -{ - elf_little_endian = 1, - elf_big_endian = 2, -} elf_endianness; - -typedef enum -{ - elf_relocatable = 1, - elf_executeable = 2, - elf_shared = 3, - elf_core = 4, -} elf_type; - -typedef enum -{ - elf_arm = 0x28, -} elf_target_architecture; - -typedef struct -{ - u8 magic[4]; - u8 bitFormat; - u8 endianness; - u8 elfVersion; - u8 os; - u8 padding0[8]; - u8 type[2]; - u8 targetArchitecture[2]; - u8 version[4]; - u8 entryPoint[4]; - u8 programHeaderTableOffset[4]; - u8 sectionHeaderTableOffset[4]; - u8 flags[4]; - u8 headerSize[2]; - u8 programHeaderEntrySize[2]; - u8 programHeaderEntryCount[2]; - u8 sectionTableEntrySize[2]; - u8 sectionHeaderEntryCount[2]; - u8 sectionHeaderNameEntryIndex[2]; -} elf_32_hdr; - -typedef struct -{ - u8 magic[4]; - u8 bitFormat; - u8 endianness; - u8 elfVersion; - u8 os; - u8 padding0[8]; - u8 type[2]; - u8 targetArchitecture[2]; - u8 version[4]; - u8 entryPoint[8]; - u8 programHeaderTableOffset[8]; - u8 sectionHeaderTableOffset[8]; - u8 flags[4]; - u8 headerSize[2]; - u8 programHeaderEntrySize[2]; - u8 programHeaderEntryCount[2]; - u8 sectionTableEntrySize[2]; - u8 sectionHeaderEntryCount[2]; - u8 sectionHeaderNameEntryIndex[2]; -} elf_64_hdr; - -/* taken from elf specs, will not follow global style */ - -/* Section header. */ - -/* Legal values for sh_type (section type). */ - -#define SHT_NULL 0 /* Section header table entry unused */ -#define SHT_PROGBITS 1 /* Program data */ -#define SHT_SYMTAB 2 /* Symbol table */ -#define SHT_STRTAB 3 /* String table */ -#define SHT_RELA 4 /* Relocation entries with addends */ -#define SHT_HASH 5 /* Symbol hash table */ -#define SHT_DYNAMIC 6 /* Dynamic linking information */ -#define SHT_NOTE 7 /* Notes */ -#define SHT_NOBITS 8 /* Program space with no data (bss) */ -#define SHT_REL 9 /* Relocation entries, no addends */ -#define SHT_SHLIB 10 /* Reserved */ -#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ -#define SHT_UNKNOWN12 12 -#define SHT_UNKNOWN13 13 -#define SHT_INIT_ARRAY 14 -#define SHT_FINI_ARRAY 15 -#define SHT_PREINIT_ARRAY 16 -#define SHT_GROUP 17 -#define SHT_SYMTAB_SHNDX 18 -#define SHT_NUM 19 -#define SHT_ARM_EXIDX 0x70000001 /* Exception Index table */ -#define SHT_ARM_PREEMPTMAP 0x70000002 /* BPABI DLL dynamic linking pre-emption map*/ -#define SHT_ARM_ATTRIBUTES 0x70000003 /* Object file compatibility attributes */ -#define SHT_ARM_DEBUGOVERLAY 0x70000004 -#define SHT_ARM_OVERLAYSECTION 0x70000005 - -#define SHF_WRITE 0x01 /* sh_flags */ -#define SHF_ALLOC 0x02 -#define SHF_EXECINSTR 0x04 -#define SHF_MERGE 0x10 -#define SHF_STRINGS 0x20 -#define SHF_INFO_LINK 0x40 -#define SHF_LINK_ORDER 0x80 -#define SHF_OS_NONCONFORMING 0x100 -#define SHF_GROUP 0x200 -#define SHF_TLS 0x400 - - -typedef struct -{ - u8 sh_name[4]; /* Section name (string tbl index) */ - u8 sh_type[4]; /* Section type */ - u8 sh_flags[4]; /* Section flags */ - u8 sh_addr[4]; /* Section virtual addr at execution */ - u8 sh_offset[4]; /* Section file offset */ - u8 sh_size[4]; /* Section size in bytes */ - u8 sh_link[4]; /* Link to another section */ - u8 sh_info[4]; /* Additional section information */ - u8 sh_addralign[4]; /* Section alignment */ - u8 sh_entsize[4]; /* Entry size if section holds table */ -} elf_32_shdr; - -typedef struct -{ - u8 sh_name[8]; /* Section name (string tbl index) */ - u8 sh_type[8]; /* Section type */ - u8 sh_flags[8]; /* Section flags */ - u8 sh_addr[8]; /* Section virtual addr at execution */ - u8 sh_offset[8]; /* Section file offset */ - u8 sh_size[8]; /* Section size in bytes */ - u8 sh_link[8]; /* Link to another section */ - u8 sh_info[8]; /* Additional section information */ - u8 sh_addralign[8]; /* Section alignment */ - u8 sh_entsize[8]; /* Entry size if section holds table */ -} elf_64_shdr; - -/* Program segment header. */ - -/* p_type legal values */ -#define PT_NULL 0 /* Program header table entry unused */ -#define PT_LOAD 1 /* Loadable program segment */ -#define PT_DYNAMIC 2 /* Dynamic linking information */ -#define PT_INTERP 3 /* Program interpreter */ -#define PT_NOTE 4 /* Auxiliary information */ -#define PT_SHLIB 5 /* Reserved */ -#define PT_PHDR 6 /* Entry for header table itself */ -#define PT_NUM 7 /* Number of defined types. */ -#define PT_LOOS 0x60000000 /* Start of OS-specific */ -#define PT_HIOS 0x6fffffff /* End of OS-specific */ -#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 - - -typedef struct -{ - u8 p_type[4]; /* Segment type */ - u8 p_offset[4]; /* Segment file offset */ - u8 p_vaddr[4]; /* Segment virtual address */ - u8 p_paddr[4]; /* Segment physical address */ - u8 p_filesz[4]; /* Segment size in file */ - u8 p_memsz[4]; /* Segment size in memory */ - u8 p_flags[4]; /* Segment flags */ - u8 p_align[4]; /* Segment alignment */ -} elf_32_phdr; - -typedef struct -{ - u8 p_type[8]; /* Segment type */ - u8 p_flags[8]; /* Segment flags */ - u8 p_offset[8]; /* Segment file offset */ - u8 p_vaddr[8]; /* Segment virtual address */ - u8 p_paddr[8]; /* Segment physical address */ - u8 p_filesz[8]; /* Segment size in file */ - u8 p_memsz[8]; /* Segment size in memory */ - u8 p_align[8]; /* Segment alignment */ -} elf_64_phdr; \ No newline at end of file diff --git a/makerom/exheader.c b/makerom/exheader.c index 0d4b0bf..0d8065b 100644 --- a/makerom/exheader.c +++ b/makerom/exheader.c @@ -129,8 +129,6 @@ int get_ExHeaderSettingsFromNcchset(exheader_settings *exhdrset, ncch_settings * exhdrset->exHdr = (extended_hdr*)ncchset->sections.exhdr.buffer; exhdrset->acexDesc = (access_descriptor*)ncchset->sections.acexDesc.buffer; - /* BSS Size */ - u32_to_u8(exhdrset->exHdr->codeSetInfo.bssSize,ncchset->codeDetails.bssSize,LE); /* Data */ u32_to_u8(exhdrset->exHdr->codeSetInfo.data.address,ncchset->codeDetails.rwAddress,LE); u32_to_u8(exhdrset->exHdr->codeSetInfo.data.codeSize,ncchset->codeDetails.rwSize,LE); @@ -143,12 +141,16 @@ int get_ExHeaderSettingsFromNcchset(exheader_settings *exhdrset, ncch_settings * u32_to_u8(exhdrset->exHdr->codeSetInfo.text.address,ncchset->codeDetails.textAddress,LE); u32_to_u8(exhdrset->exHdr->codeSetInfo.text.codeSize,ncchset->codeDetails.textSize,LE); u32_to_u8(exhdrset->exHdr->codeSetInfo.text.numMaxPages,ncchset->codeDetails.textMaxPages,LE); + /* BSS Size */ + u32_to_u8(exhdrset->exHdr->codeSetInfo.bssSize, ncchset->codeDetails.bssSize, LE); + /* Stack Size */ + u32_to_u8(exhdrset->exHdr->codeSetInfo.stackSize, ncchset->codeDetails.stackSize, LE); /* Set Simple Flags */ if(ncchset->options.CompressCode) - exhdrset->exHdr->codeSetInfo.flag |= infoflag_COMPRESS_EXEFS_0; - if(ncchset->options.UseOnSD) - exhdrset->exHdr->codeSetInfo.flag |= infoflag_SD_APPLICATION; + exhdrset->exHdr->codeSetInfo.compressExeFs0 = true; + if (ncchset->options.UseOnSD) + exhdrset->exHdr->codeSetInfo.useOnSd = true; if(!ncchset->options.UseRomFS) exhdrset->exHdr->arm11SystemLocalCapabilities.storageInfo.otherAttributes |= attribute_NOT_USE_ROMFS; @@ -195,13 +197,6 @@ int get_ExHeaderCodeSetInfo(exhdr_CodeSetInfo *CodeSetInfo, rsf_settings *rsf) else strncpy((char*)CodeSetInfo->name, DEFAULT_EXHEADER_NAME, 8); - /* Stack Size */ - if(rsf->SystemControlInfo.StackSize) - u32_to_u8(CodeSetInfo->stackSize, strtoul(rsf->SystemControlInfo.StackSize,NULL,0), LE); - else{ - ErrorParamNotFound("SystemControlInfo/StackSize"); - return EXHDR_BAD_RSF_OPT; - } /* Remaster Version */ if(rsf->SystemControlInfo.RemasterVersion) u16_to_u8(CodeSetInfo->remasterVersion, strtol(rsf->SystemControlInfo.RemasterVersion,NULL,0), LE); @@ -311,93 +306,87 @@ int SetARM11SystemLocalInfoFlags(exhdr_ARM11SystemLocalCapabilities *arm11, rsf_ return EXHDR_BAD_RSF_OPT; } - /* Flag[0] */ - arm11->flag[0] |= rsf->AccessControlInfo.EnableL2Cache; + /* Defaults */ + arm11->enableL2Cache = false; + arm11->cpuSpeed = cpuspeed_268MHz; + arm11->systemModeExt = sysmode_ext_LEGACY; + arm11->affinityMask = 0; + arm11->idealProcessor = 0; + arm11->systemMode = sysmode_64MB; + + /* flag[0] */ + arm11->enableL2Cache |= rsf->AccessControlInfo.EnableL2Cache; if (rsf->AccessControlInfo.CpuSpeed) { if(strcasecmp(rsf->AccessControlInfo.CpuSpeed, "268mhz") == 0) - arm11->flag[0] |= cpuspeed_268MHz << 1; + arm11->cpuSpeed |= cpuspeed_268MHz; else if(strcasecmp(rsf->AccessControlInfo.CpuSpeed, "804mhz") == 0) - arm11->flag[0] |= cpuspeed_804MHz << 1; + arm11->cpuSpeed |= cpuspeed_804MHz; else { fprintf(stderr, "[EXHEADER ERROR] Invalid cpu speed: 0x%s\n", rsf->AccessControlInfo.CpuSpeed); return EXHDR_BAD_RSF_OPT; } } - else - arm11->flag[0] |= cpuspeed_268MHz << 1; - /* Flag[1] (SystemModeExt) */ + /* flag[1] (SystemModeExt) */ if (rsf->AccessControlInfo.SystemModeExt) { if (strcasecmp(rsf->AccessControlInfo.SystemModeExt, "Legacy") == 0) - arm11->flag[1] = sysmode_ext_LEGACY; + arm11->systemModeExt = sysmode_ext_LEGACY; else if (strcasecmp(rsf->AccessControlInfo.SystemModeExt, "124MB") == 0) - arm11->flag[1] = sysmode_ext_124MB; + arm11->systemModeExt = sysmode_ext_124MB; else if (strcasecmp(rsf->AccessControlInfo.SystemModeExt, "178MB") == 0) - arm11->flag[1] = sysmode_ext_178MB; + arm11->systemModeExt = sysmode_ext_178MB; else { fprintf(stderr, "[EXHEADER ERROR] Unexpected SystemModeExt: %s\n", rsf->AccessControlInfo.SystemModeExt); return EXHDR_BAD_RSF_OPT; } } - else { - arm11->flag[1] = sysmode_ext_LEGACY; - } - /* Flag[2] */ - u8 affinityMask = 0; - u8 idealProcessor = 0; - u8 systemMode = 0; - + /* flag[2] */ if(rsf->AccessControlInfo.AffinityMask){ - affinityMask = strtol(rsf->AccessControlInfo.AffinityMask,NULL,0); - if(affinityMask > 1){ - fprintf(stderr,"[EXHEADER ERROR] Unexpected AffinityMask: %d. Expected range: 0x0 - 0x1\n",affinityMask); + arm11->affinityMask = strtol(rsf->AccessControlInfo.AffinityMask,NULL,0); + if(arm11->affinityMask > 1){ + fprintf(stderr,"[EXHEADER ERROR] Unexpected AffinityMask: %d. Expected range: 0x0 - 0x1\n", arm11->affinityMask); return EXHDR_BAD_RSF_OPT; } } if(rsf->AccessControlInfo.IdealProcessor){ - idealProcessor = strtol(rsf->AccessControlInfo.IdealProcessor,NULL,0); - if(idealProcessor > 1){ - fprintf(stderr,"[EXHEADER ERROR] Unexpected IdealProcessor: %d. Expected range: 0x0 - 0x1\n",idealProcessor); + arm11->idealProcessor = strtol(rsf->AccessControlInfo.IdealProcessor,NULL,0); + if(arm11->idealProcessor > 1){ + fprintf(stderr,"[EXHEADER ERROR] Unexpected IdealProcessor: %d. Expected range: 0x0 - 0x1\n", arm11->idealProcessor); return EXHDR_BAD_RSF_OPT; } } if(rsf->AccessControlInfo.SystemMode){ if (strcasecmp(rsf->AccessControlInfo.SystemMode, "64MB") == 0 || strcasecmp(rsf->AccessControlInfo.SystemMode, "prod") == 0) - systemMode = sysmode_64MB; + arm11->systemMode = sysmode_64MB; //else if (strcasecmp(rsf->AccessControlInfo.SystemMode, "UNK") == 0 || strcasecmp(rsf->AccessControlInfo.SystemMode, "null") == 0) - // systemMode = sysmode_UNK; + // arm11->systemMode = sysmode_UNK; else if (strcasecmp(rsf->AccessControlInfo.SystemMode, "96MB") == 0 || strcasecmp(rsf->AccessControlInfo.SystemMode, "dev1") == 0) - systemMode = sysmode_96MB; + arm11->systemMode = sysmode_96MB; else if (strcasecmp(rsf->AccessControlInfo.SystemMode, "80MB") == 0 || strcasecmp(rsf->AccessControlInfo.SystemMode, "dev2") == 0) - systemMode = sysmode_80MB; + arm11->systemMode = sysmode_80MB; else if (strcasecmp(rsf->AccessControlInfo.SystemMode, "72MB") == 0 || strcasecmp(rsf->AccessControlInfo.SystemMode, "dev3") == 0) - systemMode = sysmode_72MB; + arm11->systemMode = sysmode_72MB; else if (strcasecmp(rsf->AccessControlInfo.SystemMode, "32MB") == 0 || strcasecmp(rsf->AccessControlInfo.SystemMode, "dev4") == 0) - systemMode = sysmode_32MB; + arm11->systemMode = sysmode_32MB; else { fprintf(stderr, "[EXHEADER ERROR] Unexpected SystemMode: %s\n", rsf->AccessControlInfo.SystemMode); return EXHDR_BAD_RSF_OPT; } } - else { - systemMode = sysmode_64MB; - } - arm11->flag[2] = (u8)(systemMode << 4 | affinityMask << 2 | idealProcessor); /* flag[3] (Thread Priority) */ if(rsf->AccessControlInfo.Priority){ - u8 priority = strtoul(rsf->AccessControlInfo.Priority,NULL,0); + arm11->threadPriority = strtoul(rsf->AccessControlInfo.Priority,NULL,0); if(GetAppType(rsf) == processtype_APPLICATION) - priority += 32; - if(priority > 127){ - fprintf(stderr,"[EXHEADER ERROR] Invalid Priority: %d\n",priority); + arm11->threadPriority += 32; + if(arm11->threadPriority < 0){ + fprintf(stderr,"[EXHEADER ERROR] Invalid Priority: %d\n", arm11->threadPriority); return EXHDR_BAD_RSF_OPT; } - arm11->flag[3] = priority; } else{ ErrorParamNotFound("AccessControlInfo/Priority"); diff --git a/makerom/exheader.h b/makerom/exheader.h index 8d91e56..d3ef983 100644 --- a/makerom/exheader.h +++ b/makerom/exheader.h @@ -121,7 +121,14 @@ typedef struct { u8 name[8]; u8 padding0[5]; - u8 flag; + union { + u8 flag; + struct { + u8 compressExeFs0 : 1; + u8 useOnSd : 1; + }; + }; + u8 remasterVersion[2]; // le u16 exhdr_CodeSegmentInfo text; u8 stackSize[4]; // le u32 @@ -151,7 +158,23 @@ typedef struct { u8 programId[8]; u8 coreVersion[4]; - u8 flag[4]; + union { + u8 flag[4]; + struct { + u8 enableL2Cache : 1; + u8 cpuSpeed : 1; + u8: 6; + + u8 systemModeExt : 4; + u8: 4; + + u8 idealProcessor : 2; + u8 affinityMask : 2; + u8 systemMode : 4; + + s8 threadPriority; + }; + }; u8 resourceLimitDescriptor[16][2]; exhdr_StorageInfo storageInfo; u8 serviceAccessControl[34][8]; // Those char[8] server names diff --git a/makerom/makerom.vcxproj b/makerom/makerom.vcxproj index 472d5b4..ecc931c 100644 --- a/makerom/makerom.vcxproj +++ b/makerom/makerom.vcxproj @@ -97,6 +97,7 @@ + @@ -105,7 +106,6 @@ - @@ -198,6 +198,7 @@ + diff --git a/makerom/makerom.vcxproj.filters b/makerom/makerom.vcxproj.filters index 5fb196a..049b9f8 100644 --- a/makerom/makerom.vcxproj.filters +++ b/makerom/makerom.vcxproj.filters @@ -72,9 +72,6 @@ Header Files - - Header Files - Header Files @@ -339,6 +336,9 @@ Resource Files\DESC + + Header Files + @@ -470,6 +470,9 @@ Source Files\polarssl + + Source Files + diff --git a/makerom/ncch.c b/makerom/ncch.c index 4a8d00e..69621d4 100644 --- a/makerom/ncch.c +++ b/makerom/ncch.c @@ -3,7 +3,7 @@ #include "ncch_build.h" #include "exheader_build.h" #include "exheader_read.h" -#include "elf.h" +#include "code.h" #include "exefs_build.h" #include "exefs_read.h" #include "romfs.h" diff --git a/makerom/ncch_build.h b/makerom/ncch_build.h index 96f47c4..d97ab7b 100644 --- a/makerom/ncch_build.h +++ b/makerom/ncch_build.h @@ -70,6 +70,7 @@ typedef struct u32 rwSize; u32 rwMaxPages; u32 bssSize; + u32 stackSize; } codeDetails; struct diff --git a/makerom/utils.c b/makerom/utils.c index 5a97fb6..dd08733 100644 --- a/makerom/utils.c +++ b/makerom/utils.c @@ -368,7 +368,7 @@ int fseek_64(FILE *fp, u64 file_pos) } //Data Size conversion -u16 u8_to_u16(u8 *value, u8 endianness) +u16 u8_to_u16(const u8 *value, u8 endianness) { u16 new_value; switch(endianness){ @@ -378,7 +378,7 @@ u16 u8_to_u16(u8 *value, u8 endianness) return new_value; } -u32 u8_to_u32(u8 *value, u8 endianness) +u32 u8_to_u32(const u8 *value, u8 endianness) { u32 new_value; switch(endianness){ @@ -389,7 +389,7 @@ u32 u8_to_u32(u8 *value, u8 endianness) } -u64 u8_to_u64(u8 *value, u8 endianness) +u64 u8_to_u64(const u8 *value, u8 endianness) { u64 ret = 0; switch(endianness){ diff --git a/makerom/utils.h b/makerom/utils.h index c479f11..6d30d51 100644 --- a/makerom/utils.h +++ b/makerom/utils.h @@ -59,9 +59,9 @@ void ReadFile64(void *outbuff, u64 size, u64 offset, FILE *file); int fseek_64(FILE *fp, u64 file_pos); //Data Size conversion -u16 u8_to_u16(u8 *value, u8 endianness); -u32 u8_to_u32(u8 *value, u8 endianness); -u64 u8_to_u64(u8 *value, u8 endianness); +u16 u8_to_u16(const u8 *value, u8 endianness); +u32 u8_to_u32(const u8 *value, u8 endianness); +u64 u8_to_u64(const u8 *value, u8 endianness); int u16_to_u8(u8 *out_value, u16 in_value, u8 endianness); int u32_to_u8(u8 *out_value, u32 in_value, u8 endianness); int u64_to_u8(u8 *out_value, u64 in_value, u8 endianness);