mirror of
https://github.com/DarkStore-3DS/Project_CTR.git
synced 2026-07-05 16:59:02 +00:00
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
# Makerom Sources
|
# Makerom Sources
|
||||||
UTILS_OBJS = utils.o ctr_utils.o dir.o utf.o keyset.o titleid.o
|
UTILS_OBJS = utils.o ctr_utils.o dir.o utf.o keyset.o titleid.o
|
||||||
CIA_OBJS = cia.o certs.o tik.o tmd.o
|
CIA_OBJS = cia.o certs.o tik.o tmd.o
|
||||||
NCCH_OBJS = ncch.o exheader.o accessdesc.o exefs.o elf.o romfs.o romfs_import.o romfs_gen.o
|
NCCH_OBJS = ncch.o exheader.o accessdesc.o exefs.o elf.o romfs.o romfs_import.o romfs_gen.o
|
||||||
NCSD_OBJS = ncsd.o cardinfo.o
|
NCSD_OBJS = ncsd.o cardinfo.o
|
||||||
SETTINGS_OBJS = user_settings.o rsf_settings.o
|
SETTINGS_OBJS = user_settings.o rsf_settings.o
|
||||||
LIB_API_OBJS = crypto.o yaml_parser.o blz.o
|
LIB_API_OBJS = crypto.o yaml_parser.o blz.o
|
||||||
@@ -21,7 +21,7 @@ CC = gcc
|
|||||||
# MAKEROM Build Settings
|
# MAKEROM Build Settings
|
||||||
MAKEROM_BUILD_FLAGS = #-DDEBUG
|
MAKEROM_BUILD_FLAGS = #-DDEBUG
|
||||||
VER_MAJOR = 0
|
VER_MAJOR = 0
|
||||||
VER_MINOR = 11
|
VER_MINOR = 12
|
||||||
OUTPUT = makerom
|
OUTPUT = makerom
|
||||||
|
|
||||||
main: build
|
main: build
|
||||||
|
|||||||
+3
-18
@@ -443,7 +443,7 @@ int ImportNcchContent(cia_settings *ciaset)
|
|||||||
return MEM_ERROR;
|
return MEM_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ncch_hdr *ncch0hdr = (ncch_hdr*)(ciaset->ciaSections.content.buffer+0x100);
|
ncch_hdr *ncch0hdr = (ncch_hdr*)ciaset->ciaSections.content.buffer;
|
||||||
for(int i = 1; i < ciaset->content.count; i++){
|
for(int i = 1; i < ciaset->content.count; i++){
|
||||||
// Import
|
// Import
|
||||||
u8 *ncchpos = (u8*)(ciaset->ciaSections.content.buffer+ciaset->content.offset[i]);
|
u8 *ncchpos = (u8*)(ciaset->ciaSections.content.buffer+ciaset->content.offset[i]);
|
||||||
@@ -629,24 +629,9 @@ int BuildCiaHdr(cia_settings *ciaset)
|
|||||||
ciaset->ciaSections.contentOffset = align(ciaset->ciaSections.tmdOffset+ciaset->ciaSections.tmd.size,0x40);
|
ciaset->ciaSections.contentOffset = align(ciaset->ciaSections.tmdOffset+ciaset->ciaSections.tmd.size,0x40);
|
||||||
ciaset->ciaSections.metaOffset = align(ciaset->ciaSections.contentOffset+ciaset->content.totalSize,0x40);
|
ciaset->ciaSections.metaOffset = align(ciaset->ciaSections.contentOffset+ciaset->content.totalSize,0x40);
|
||||||
|
|
||||||
for(int i = 0; i < ciaset->content.count; i++){
|
for(int i = 0; i < ciaset->content.count; i++)
|
||||||
// This works by treating the 0x2000 byte index array as an array of 2048 u32 values
|
hdr->contentIndex[ciaset->content.index[i]/8] |= 1 << (7 - (ciaset->content.index[i] & 7));
|
||||||
|
|
||||||
// Used for determining which u32 chunk to write the value to
|
|
||||||
u16 section = ciaset->content.index[i]/32;
|
|
||||||
|
|
||||||
// Calculating the value added to the u32
|
|
||||||
u32 value = 1 << (0x1F-ciaset->content.index[i]);
|
|
||||||
|
|
||||||
// Retrieving current u32 block
|
|
||||||
u32 cur_content_index_section = u8_to_u32(hdr->contentIndex+(sizeof(u32)*section),BE);
|
|
||||||
|
|
||||||
// Adding value to block
|
|
||||||
cur_content_index_section += value;
|
|
||||||
|
|
||||||
// Returning block
|
|
||||||
u32_to_u8(hdr->contentIndex+(sizeof(u32)*section),cur_content_index_section,BE);
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+43
-4
@@ -1,5 +1,6 @@
|
|||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "ncch_build.h"
|
#include "ncch_build.h"
|
||||||
|
#include "exheader_read.h"
|
||||||
#include "elf_hdr.h"
|
#include "elf_hdr.h"
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
#include "blz.h"
|
#include "blz.h"
|
||||||
@@ -113,7 +114,8 @@ finish:
|
|||||||
if(result == NOT_ELF_FILE) fprintf(stderr,"[ELF ERROR] Not ELF File\n");
|
if(result == NOT_ELF_FILE) fprintf(stderr,"[ELF ERROR] Not ELF File\n");
|
||||||
else if(result == NOT_ARM_ELF) fprintf(stderr,"[ELF ERROR] Not ARM ELF\n");
|
else if(result == NOT_ARM_ELF) fprintf(stderr,"[ELF ERROR] Not ARM ELF\n");
|
||||||
else if(result == NON_EXECUTABLE_ELF) fprintf(stderr,"[ELF ERROR] Not Executeable ELF\n");
|
else if(result == NON_EXECUTABLE_ELF) fprintf(stderr,"[ELF ERROR] Not Executeable ELF\n");
|
||||||
else if(result == NOT_FIND_CODE_SECTIONS) fprintf(stderr,"[ELF ERROR] Failed to retrieve code sections from ELF\n");
|
else if(result == NOT_FIND_TEXT_SEGMENT) fprintf(stderr,"[ELF ERROR] Failed to retrieve text sections from ELF\n");
|
||||||
|
else if(result == NOT_FIND_DATA_SEGMENT) fprintf(stderr,"[ELF ERROR] Failed to retrieve data sections from ELF\n");
|
||||||
else fprintf(stderr,"[ELF ERROR] Failed to process ELF file (%d)\n",result);
|
else fprintf(stderr,"[ELF ERROR] Failed to process ELF file (%d)\n",result);
|
||||||
}
|
}
|
||||||
for(int i = 0; i < elf->activeSegments; i++)
|
for(int i = 0; i < elf->activeSegments; i++)
|
||||||
@@ -139,7 +141,10 @@ int ImportExeFsCodeBinaryFromFile(ncch_settings *set)
|
|||||||
{
|
{
|
||||||
u32 size = set->componentFilePtrs.codeSize;
|
u32 size = set->componentFilePtrs.codeSize;
|
||||||
u8 *buffer = malloc(size);
|
u8 *buffer = malloc(size);
|
||||||
if(!buffer) {fprintf(stderr,"[ELF ERROR] Not enough memory\n"); return MEM_ERROR;}
|
if(!buffer) {
|
||||||
|
fprintf(stderr,"[ELF ERROR] Not enough memory\n");
|
||||||
|
return MEM_ERROR;
|
||||||
|
}
|
||||||
ReadFile64(buffer,size,0,set->componentFilePtrs.code);
|
ReadFile64(buffer,size,0,set->componentFilePtrs.code);
|
||||||
|
|
||||||
set->exefsSections.code.size = set->componentFilePtrs.codeSize;
|
set->exefsSections.code.size = set->componentFilePtrs.codeSize;
|
||||||
@@ -156,6 +161,36 @@ int ImportExeFsCodeBinaryFromFile(ncch_settings *set)
|
|||||||
set->exefsSections.code.size = size;
|
set->exefsSections.code.size = size;
|
||||||
set->exefsSections.code.buffer = buffer;
|
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);
|
||||||
|
|
||||||
|
free(exhdr);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,9 +274,13 @@ int CreateExeFsCode(elf_context *elf, u8 *elfFile, ncch_settings *set)
|
|||||||
result = CreateCodeSegmentFromElf(&rwdata,elf,elfFile,set->rsfSet->ExeFs.ReadWrite,set->rsfSet->ExeFs.ReadWriteNum);
|
result = CreateCodeSegmentFromElf(&rwdata,elf,elfFile,set->rsfSet->ExeFs.ReadWrite,set->rsfSet->ExeFs.ReadWriteNum);
|
||||||
if(result) return result;
|
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 */
|
/* Allocating Buffer for ExeFs Code */
|
||||||
u32 size = (text.maxPageNum + rodata.maxPageNum + rwdata.maxPageNum)*elf->pageSize;
|
u32 size = (text.maxPageNum + rodata.maxPageNum + rwdata.maxPageNum)*elf->pageSize;
|
||||||
u8 *code = malloc(size);
|
u8 *code = calloc(1,size);
|
||||||
|
|
||||||
/* Writing Code into Buffer */
|
/* Writing Code into Buffer */
|
||||||
u8 *textPos = (code + 0);
|
u8 *textPos = (code + 0);
|
||||||
@@ -264,7 +303,7 @@ int CreateExeFsCode(elf_context *elf, u8 *elfFile, ncch_settings *set)
|
|||||||
set->exefsSections.code.buffer = code;
|
set->exefsSections.code.buffer = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Setting code_segment rwdata and freeing original buffers */
|
/* Setting code_segment data and freeing original buffers */
|
||||||
set->codeDetails.textAddress = text.address;
|
set->codeDetails.textAddress = text.address;
|
||||||
set->codeDetails.textMaxPages = text.maxPageNum;
|
set->codeDetails.textMaxPages = text.maxPageNum;
|
||||||
set->codeDetails.textSize = text.size;
|
set->codeDetails.textSize = text.size;
|
||||||
|
|||||||
+5
-4
@@ -6,10 +6,11 @@ typedef enum
|
|||||||
NOT_ARM_ELF = -11,
|
NOT_ARM_ELF = -11,
|
||||||
NON_EXECUTABLE_ELF = -12,
|
NON_EXECUTABLE_ELF = -12,
|
||||||
ELF_SECTION_NOT_FOUND = -13,
|
ELF_SECTION_NOT_FOUND = -13,
|
||||||
NOT_FIND_CODE_SECTIONS = -14,
|
NOT_FIND_TEXT_SEGMENT = -14,
|
||||||
ELF_SEGMENT_SECTION_SIZE_MISMATCH = -15,
|
NOT_FIND_DATA_SEGMENT = -15,
|
||||||
ELF_SEGMENTS_NOT_CONTINUOUS = -16,
|
ELF_SEGMENT_SECTION_SIZE_MISMATCH = -16,
|
||||||
ELF_SEGMENTS_NOT_FOUND = -17,
|
ELF_SEGMENTS_NOT_CONTINUOUS = -17,
|
||||||
|
ELF_SEGMENTS_NOT_FOUND = -18,
|
||||||
} elf_errors;
|
} elf_errors;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|||||||
+9
-20
@@ -121,17 +121,6 @@ int get_ExHeaderSettingsFromNcchset(exheader_settings *exhdrset, ncch_settings *
|
|||||||
fprintf(stderr,"[EXHEADER ERROR] Not enough memory\n");
|
fprintf(stderr,"[EXHEADER ERROR] Not enough memory\n");
|
||||||
return MEM_ERROR;
|
return MEM_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Import ExHeader Code Section template */
|
|
||||||
if(ncchset->componentFilePtrs.exhdrSize){
|
|
||||||
u32 import_size = 0x30; //min64(0x30,ncchset->componentFilePtrs.exhdrSize);
|
|
||||||
u32 import_offset = 0x10;
|
|
||||||
if((import_size+import_offset) > ncchset->componentFilePtrs.exhdrSize){
|
|
||||||
fprintf(stderr,"[EXHEADER ERROR] Exheader Template is too small\n");
|
|
||||||
return FAILED_TO_IMPORT_FILE;
|
|
||||||
}
|
|
||||||
ReadFile64((ncchset->sections.exhdr.buffer+import_offset),import_size,import_offset,ncchset->componentFilePtrs.exhdr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create ExHeader Struct for output */
|
/* Create ExHeader Struct for output */
|
||||||
exhdrset->exHdr = (extended_hdr*)ncchset->sections.exhdr.buffer;
|
exhdrset->exHdr = (extended_hdr*)ncchset->sections.exhdr.buffer;
|
||||||
@@ -142,17 +131,17 @@ int get_ExHeaderSettingsFromNcchset(exheader_settings *exhdrset, ncch_settings *
|
|||||||
/* BSS Size */
|
/* BSS Size */
|
||||||
u32_to_u8(exhdrset->exHdr->codeSetInfo.bssSize,ncchset->codeDetails.bssSize,LE);
|
u32_to_u8(exhdrset->exHdr->codeSetInfo.bssSize,ncchset->codeDetails.bssSize,LE);
|
||||||
/* Data */
|
/* Data */
|
||||||
u32_to_u8(exhdrset->exHdr->codeSetInfo.dataSectionInfo.address,ncchset->codeDetails.rwAddress,LE);
|
u32_to_u8(exhdrset->exHdr->codeSetInfo.data.address,ncchset->codeDetails.rwAddress,LE);
|
||||||
u32_to_u8(exhdrset->exHdr->codeSetInfo.dataSectionInfo.codeSize,ncchset->codeDetails.rwSize,LE);
|
u32_to_u8(exhdrset->exHdr->codeSetInfo.data.codeSize,ncchset->codeDetails.rwSize,LE);
|
||||||
u32_to_u8(exhdrset->exHdr->codeSetInfo.dataSectionInfo.numMaxPages,ncchset->codeDetails.rwMaxPages,LE);
|
u32_to_u8(exhdrset->exHdr->codeSetInfo.data.numMaxPages,ncchset->codeDetails.rwMaxPages,LE);
|
||||||
/* RO */
|
/* RO */
|
||||||
u32_to_u8(exhdrset->exHdr->codeSetInfo.readOnlySectionInfo.address,ncchset->codeDetails.roAddress,LE);
|
u32_to_u8(exhdrset->exHdr->codeSetInfo.rodata.address,ncchset->codeDetails.roAddress,LE);
|
||||||
u32_to_u8(exhdrset->exHdr->codeSetInfo.readOnlySectionInfo.codeSize,ncchset->codeDetails.roSize,LE);
|
u32_to_u8(exhdrset->exHdr->codeSetInfo.rodata.codeSize,ncchset->codeDetails.roSize,LE);
|
||||||
u32_to_u8(exhdrset->exHdr->codeSetInfo.readOnlySectionInfo.numMaxPages,ncchset->codeDetails.roMaxPages,LE);
|
u32_to_u8(exhdrset->exHdr->codeSetInfo.rodata.numMaxPages,ncchset->codeDetails.roMaxPages,LE);
|
||||||
/* Text */
|
/* Text */
|
||||||
u32_to_u8(exhdrset->exHdr->codeSetInfo.textSectionInfo.address,ncchset->codeDetails.textAddress,LE);
|
u32_to_u8(exhdrset->exHdr->codeSetInfo.text.address,ncchset->codeDetails.textAddress,LE);
|
||||||
u32_to_u8(exhdrset->exHdr->codeSetInfo.textSectionInfo.codeSize,ncchset->codeDetails.textSize,LE);
|
u32_to_u8(exhdrset->exHdr->codeSetInfo.text.codeSize,ncchset->codeDetails.textSize,LE);
|
||||||
u32_to_u8(exhdrset->exHdr->codeSetInfo.textSectionInfo.numMaxPages,ncchset->codeDetails.textMaxPages,LE);
|
u32_to_u8(exhdrset->exHdr->codeSetInfo.text.numMaxPages,ncchset->codeDetails.textMaxPages,LE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set Simple Flags */
|
/* Set Simple Flags */
|
||||||
|
|||||||
+3
-3
@@ -99,11 +99,11 @@ typedef struct
|
|||||||
u8 padding0[5];
|
u8 padding0[5];
|
||||||
u8 flag;
|
u8 flag;
|
||||||
u8 remasterVersion[2]; // le u16
|
u8 remasterVersion[2]; // le u16
|
||||||
exhdr_CodeSegmentInfo textSectionInfo;
|
exhdr_CodeSegmentInfo text;
|
||||||
u8 stackSize[4]; // le u32
|
u8 stackSize[4]; // le u32
|
||||||
exhdr_CodeSegmentInfo readOnlySectionInfo;
|
exhdr_CodeSegmentInfo rodata;
|
||||||
u8 padding1[4];
|
u8 padding1[4];
|
||||||
exhdr_CodeSegmentInfo dataSectionInfo;
|
exhdr_CodeSegmentInfo data;
|
||||||
u8 bssSize[4]; // le u32
|
u8 bssSize[4]; // le u32
|
||||||
} exhdr_CodeSetInfo;
|
} exhdr_CodeSetInfo;
|
||||||
|
|
||||||
|
|||||||
+4
-5
@@ -858,17 +858,16 @@ int ModifyNcchIds(u8 *ncch, u8 *titleId, u8 *programId, keys_struct *keys)
|
|||||||
|
|
||||||
ncch_hdr *hdr = (ncch_hdr*)ncch;
|
ncch_hdr *hdr = (ncch_hdr*)ncch;
|
||||||
|
|
||||||
if(/*keys->rsa.requiresPresignedDesc && */!IsCfa(hdr)){
|
|
||||||
fprintf(stderr,"[NCCH ERROR] CXI's ID cannot be modified without the ability to resign the AccessDesc\n"); // Not yet yet, requires AccessDesc Privk, may implement anyway later
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool titleIdMatches = titleId == NULL? true : memcmp(titleId,hdr->titleId,8) == 0;
|
bool titleIdMatches = titleId == NULL? true : memcmp(titleId,hdr->titleId,8) == 0;
|
||||||
bool programIdMatches = programId == NULL? true : memcmp(programId,hdr->programId,8) == 0;
|
bool programIdMatches = programId == NULL? true : memcmp(programId,hdr->programId,8) == 0;
|
||||||
|
|
||||||
if(titleIdMatches && programIdMatches)
|
if(titleIdMatches && programIdMatches)
|
||||||
return 0;// if no modification is required don't do anything
|
return 0;// if no modification is required don't do anything
|
||||||
|
|
||||||
|
if(/*keys->rsa.requiresPresignedDesc && */!IsCfa(hdr)){
|
||||||
|
fprintf(stderr,"[NCCH ERROR] CXI's ID cannot be modified without the ability to resign the AccessDesc\n"); // Not yet yet, requires AccessDesc Privk, may implement anyway later
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
ncch_info ncchInfo;
|
ncch_info ncchInfo;
|
||||||
u8 *romfs = NULL;
|
u8 *romfs = NULL;
|
||||||
|
|||||||
+88
-22
@@ -3,32 +3,42 @@
|
|||||||
#include "tik_build.h"
|
#include "tik_build.h"
|
||||||
|
|
||||||
// Private Prototypes
|
// Private Prototypes
|
||||||
int SetupTicketBuffer(buffer_struct *tik);
|
int SetupTicketBuffer(cia_settings *set);
|
||||||
int SetupTicketHeader(tik_hdr *hdr, cia_settings *ciaset);
|
void SetupTicketHeader(tik_hdr *hdr, cia_settings *ciaset);
|
||||||
int SignTicketHeader(tik_hdr *hdr, tik_signature *sig, keys_struct *keys);
|
int SignTicketHeader(buffer_struct *tik, keys_struct *keys);
|
||||||
void SetLimits(tik_hdr *hdr, cia_settings *ciaset);
|
void SetLimits(tik_hdr *hdr, cia_settings *ciaset);
|
||||||
void SetContentIndexData(tik_hdr *hdr, cia_settings *ciaset);
|
u32 GetContentIndexSegNum(cia_settings *set);
|
||||||
|
void SetContentIndexHeader(tik_content_index_hdr *hdr, cia_settings *set);
|
||||||
|
void SetContentIndexData(tik_content_index_struct *data, cia_settings *set);
|
||||||
|
|
||||||
|
|
||||||
int BuildTicket(cia_settings *ciaset)
|
int BuildTicket(cia_settings *set)
|
||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
result = SetupTicketBuffer(&ciaset->ciaSections.tik);
|
result = SetupTicketBuffer(set);
|
||||||
if(result) return result;
|
if(result) return result;
|
||||||
|
|
||||||
// Setting Ticket Struct Ptrs
|
// Setting Ticket Struct Ptrs
|
||||||
tik_signature *sig = (tik_signature*)ciaset->ciaSections.tik.buffer;
|
buffer_struct *tik = &set->ciaSections.tik;
|
||||||
tik_hdr *hdr = (tik_hdr*)(ciaset->ciaSections.tik.buffer+sizeof(tik_signature));
|
|
||||||
|
tik_hdr *hdr = (tik_hdr*) (tik->buffer + sizeof(tik_signature));
|
||||||
result = SetupTicketHeader(hdr,ciaset);
|
tik_content_index_hdr *idxHdr = (tik_content_index_hdr*) (tik->buffer + sizeof(tik_signature) + sizeof(tik_hdr));
|
||||||
if(result) return result;
|
tik_content_index_struct *idxData = (tik_content_index_struct*) (tik->buffer + sizeof(tik_signature) + sizeof(tik_hdr) + sizeof(tik_content_index_hdr));
|
||||||
result = SignTicketHeader(hdr,sig,ciaset->keys);
|
|
||||||
|
|
||||||
|
SetupTicketHeader(hdr,set);
|
||||||
|
SetContentIndexHeader(idxHdr,set);
|
||||||
|
SetContentIndexData(idxData,set);
|
||||||
|
|
||||||
|
result = SignTicketHeader(tik,set->keys);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SetupTicketBuffer(buffer_struct *tik)
|
int SetupTicketBuffer(cia_settings *set)
|
||||||
{
|
{
|
||||||
tik->size = sizeof(tik_signature) + sizeof(tik_hdr);
|
buffer_struct *tik = &set->ciaSections.tik;
|
||||||
|
|
||||||
|
tik->size = sizeof(tik_signature) + sizeof(tik_hdr) + sizeof(tik_content_index_hdr) + sizeof(tik_content_index_struct)*GetContentIndexSegNum(set);
|
||||||
tik->buffer = calloc(1,tik->size);
|
tik->buffer = calloc(1,tik->size);
|
||||||
if(!tik->buffer) {
|
if(!tik->buffer) {
|
||||||
fprintf(stderr,"[TIK ERROR] Not enough memory\n");
|
fprintf(stderr,"[TIK ERROR] Not enough memory\n");
|
||||||
@@ -37,7 +47,7 @@ int SetupTicketBuffer(buffer_struct *tik)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SetupTicketHeader(tik_hdr *hdr, cia_settings *ciaset)
|
void SetupTicketHeader(tik_hdr *hdr, cia_settings *ciaset)
|
||||||
{
|
{
|
||||||
clrmem(hdr,sizeof(tik_hdr));
|
clrmem(hdr,sizeof(tik_hdr));
|
||||||
|
|
||||||
@@ -58,15 +68,19 @@ int SetupTicketHeader(tik_hdr *hdr, cia_settings *ciaset)
|
|||||||
memcpy(hdr->eshopAccId,ciaset->tik.eshopAccId,4);
|
memcpy(hdr->eshopAccId,ciaset->tik.eshopAccId,4);
|
||||||
hdr->audit = ciaset->tik.audit;
|
hdr->audit = ciaset->tik.audit;
|
||||||
SetLimits(hdr,ciaset);
|
SetLimits(hdr,ciaset);
|
||||||
SetContentIndexData(hdr,ciaset);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SignTicketHeader(tik_hdr *hdr, tik_signature *sig, keys_struct *keys)
|
int SignTicketHeader(buffer_struct *tik, keys_struct *keys)
|
||||||
{
|
{
|
||||||
|
tik_signature *sig = (tik_signature*)tik->buffer;
|
||||||
|
u8 *data = tik->buffer + sizeof(tik_signature);
|
||||||
|
u32 len = tik->size - sizeof(tik_signature);
|
||||||
|
|
||||||
|
|
||||||
clrmem(sig,sizeof(tik_signature));
|
clrmem(sig,sizeof(tik_signature));
|
||||||
u32_to_u8(sig->sigType,RSA_2048_SHA256,BE);
|
u32_to_u8(sig->sigType,RSA_2048_SHA256,BE);
|
||||||
return ctr_sig((u8*)hdr,sizeof(tik_hdr),sig->data,keys->rsa.xsPub,keys->rsa.xsPvt,RSA_2048_SHA256,CTR_RSA_SIGN);
|
|
||||||
|
return ctr_sig(data,len,sig->data,keys->rsa.xsPub,keys->rsa.xsPvt,RSA_2048_SHA256,CTR_RSA_SIGN);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CryptTitleKey(u8 *EncTitleKey, u8 *DecTitleKey, u8 *TitleID, keys_struct *keys, u8 mode)
|
int CryptTitleKey(u8 *EncTitleKey, u8 *DecTitleKey, u8 *TitleID, keys_struct *keys, u8 mode)
|
||||||
@@ -94,10 +108,62 @@ void SetLimits(tik_hdr *hdr, cia_settings *ciaset) // TODO?
|
|||||||
memset(hdr->limits,0,0x40);
|
memset(hdr->limits,0,0x40);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetContentIndexData(tik_hdr *hdr, cia_settings *ciaset) // TODO?
|
u32 GetContentIndexSegNum(cia_settings *set)
|
||||||
{
|
{
|
||||||
memset(hdr->contentIndex,0,0xAC);
|
u32 num, level, i;
|
||||||
memcpy(hdr->contentIndex,default_contentIndex,0x30);
|
|
||||||
|
num = level = 0;
|
||||||
|
|
||||||
|
for( i = 0; i < set->content.count; i++)
|
||||||
|
{
|
||||||
|
if(set->content.index[i] >= level)
|
||||||
|
{
|
||||||
|
level = roundup(set->content.index[i],0x400);
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetContentIndexHeader(tik_content_index_hdr *hdr, cia_settings *set)
|
||||||
|
{
|
||||||
|
u32 hdrSize = sizeof(tik_content_index_hdr);
|
||||||
|
u32 segNum = GetContentIndexSegNum(set);
|
||||||
|
u32 segSize = sizeof(tik_content_index_struct);
|
||||||
|
u32 segTotalSize = segSize * segNum;
|
||||||
|
u32 totalSize = hdrSize + segTotalSize;
|
||||||
|
|
||||||
|
u32_to_u8(hdr->unk0,0x00010014,BE);
|
||||||
|
u32_to_u8(hdr->totalSize,totalSize,BE);
|
||||||
|
u32_to_u8(hdr->unk1,0x00000014,BE);
|
||||||
|
u32_to_u8(hdr->unk2,0x00010014,BE);
|
||||||
|
u32_to_u8(hdr->unk3,0x00000000,BE);
|
||||||
|
u32_to_u8(hdr->hdrSize,hdrSize,BE);
|
||||||
|
u32_to_u8(hdr->segNum,segNum,BE);
|
||||||
|
u32_to_u8(hdr->segSize,segSize,BE);
|
||||||
|
u32_to_u8(hdr->segTotalSize,segTotalSize,BE);
|
||||||
|
u32_to_u8(hdr->unk4,0x00030000,BE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetContentIndexData(tik_content_index_struct *data, cia_settings *set)
|
||||||
|
{
|
||||||
|
u32 level, i;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
j = -1;
|
||||||
|
level = 0;
|
||||||
|
|
||||||
|
for( i = 0; i < set->content.count; i++)
|
||||||
|
{
|
||||||
|
if(set->content.index[i] >= level)
|
||||||
|
{
|
||||||
|
level = roundup(set->content.index[i],0x400);
|
||||||
|
j++;
|
||||||
|
u32_to_u8(data[j].level,(set->content.index[i]/0x400)*0x400,BE);
|
||||||
|
}
|
||||||
|
data[j].index[(set->content.index[i] & 0x3ff)/8] |= 1 << (set->content.index[i] & 0x7);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tik_hdr *GetTikHdr(u8 *tik)
|
tik_hdr *GetTikHdr(u8 *tik)
|
||||||
|
|||||||
+20
-1
@@ -20,6 +20,26 @@ typedef enum
|
|||||||
right_AccessTitle = 5
|
right_AccessTitle = 5
|
||||||
} tik_item_rights;
|
} tik_item_rights;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u8 unk0[4];
|
||||||
|
u8 totalSize[4];
|
||||||
|
u8 unk1[4];
|
||||||
|
u8 unk2[4];
|
||||||
|
u8 unk3[4];
|
||||||
|
u8 hdrSize[4];
|
||||||
|
u8 segNum[4];
|
||||||
|
u8 segSize[4];
|
||||||
|
u8 segTotalSize[4];
|
||||||
|
u8 unk4[4];
|
||||||
|
} tik_content_index_hdr;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u8 level[4];
|
||||||
|
u8 index[0x80];
|
||||||
|
} tik_content_index_struct;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
u8 sigType[4];
|
u8 sigType[4];
|
||||||
@@ -50,7 +70,6 @@ typedef struct
|
|||||||
u8 audit;
|
u8 audit;
|
||||||
u8 padding5[0x42];
|
u8 padding5[0x42];
|
||||||
u8 limits[0x40];
|
u8 limits[0x40];
|
||||||
u8 contentIndex[0xAC];
|
|
||||||
} tik_hdr;
|
} tik_hdr;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ int SetArgument(int argc, int i, char *argv[], user_settings *set)
|
|||||||
PrintArgReqParam(argv[i],1);
|
PrintArgReqParam(argv[i],1);
|
||||||
return USR_ARG_REQ_PARAM;
|
return USR_ARG_REQ_PARAM;
|
||||||
}
|
}
|
||||||
if(strcasecmp(argv[i+1],"ncch") == 0)
|
if(strcasecmp(argv[i+1],"ncch") == 0 || strcasecmp(argv[i+1],"cxi") == 0 || strcasecmp(argv[i+1],"cfa") == 0)
|
||||||
set->common.outFormat = NCCH;
|
set->common.outFormat = NCCH;
|
||||||
else if(strcasecmp(argv[i+1],"cci") == 0)
|
else if(strcasecmp(argv[i+1],"cci") == 0)
|
||||||
set->common.outFormat = CCI;
|
set->common.outFormat = CCI;
|
||||||
|
|||||||
+6
-1
@@ -41,10 +41,15 @@ void clrmem(void *ptr, u64 num)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Misc
|
// Misc
|
||||||
|
u64 roundup(u64 value, u64 alignment)
|
||||||
|
{
|
||||||
|
return value + alignment - value % alignment;
|
||||||
|
}
|
||||||
|
|
||||||
u64 align(u64 value, u64 alignment)
|
u64 align(u64 value, u64 alignment)
|
||||||
{
|
{
|
||||||
if(value % alignment != 0)
|
if(value % alignment != 0)
|
||||||
return value + alignment - value % alignment;
|
return roundup(value,alignment);
|
||||||
else
|
else
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ void rndset(void *ptr, u64 num);
|
|||||||
void clrmem(void *ptr, u64 num);
|
void clrmem(void *ptr, u64 num);
|
||||||
|
|
||||||
// MISC
|
// MISC
|
||||||
|
u64 roundup(u64 value, u64 alignment);
|
||||||
u64 align(u64 value, u64 alignment);
|
u64 align(u64 value, u64 alignment);
|
||||||
u64 min64(u64 a, u64 b);
|
u64 min64(u64 a, u64 b);
|
||||||
u64 max64(u64 a, u64 b);
|
u64 max64(u64 a, u64 b);
|
||||||
|
|||||||
Reference in New Issue
Block a user