Added ARM9 payload launching

This commit is contained in:
Wolf 2017-01-25 16:13:50 -03:00 committed by d0k3
parent d9dbf14f8b
commit af32ca3ac5
5 changed files with 97 additions and 21 deletions

View File

@ -0,0 +1,7 @@
#pragma once
#include "common.h"
#define PAYLOAD_MAX_SIZE 0xFFFE0
void Chainload(u8 *source, size_t size);

52
source/common/chainload.s Normal file
View File

@ -0,0 +1,52 @@
@ Wolfvak - 25/01/2017
@ TODO: ELF launcher
@ void Chainload(u8 *source, size_t size)
@ Wrapper around chainload_itcm
.arm
.global Chainload
.type Chainload, %function
Chainload:
ldr r2, =0x1FF8100 @ ITCM + 0x100 bytes
mov r3, r2
ldr r4, =chainload_itcm
ldr r5, =chainload_itcm_end
.copy_chainloader:
cmp r4, r5
ldrlt r6, [r4], #4
strlt r6, [r3], #4
blt .copy_chainloader
bx r2 @ Branch to the real chainloader in ITCM
@ void chainload_itcm(void)
@ Note: Uses unprotected bootrom functions
.arm
.type chainload_itcm, %function
.align 4
chainload_itcm:
mov r2, r1
ldr r1, =0x23F00000
mov r4, r1 @ memcpy256 and clean_flush_cache mess with the registers
ldr r3, =0xFFFF03F0 @ memcpy256(u32 *src, u32 *ddest, size_t size)
blx r3
ldr r3, =0xFFFF0830 @ void clean_flush_cache(void)
blx r3
mov r3, r4
mov r0, #0 @ Clear argc
mov r1, #0 @ Same for argv
mov r2, #0
mov lr, #0
bx r3
.pool
chainload_itcm_end:

View File

@ -2,6 +2,7 @@
#include "fsutil.h"
#include "fatmbr.h"
#include "game.h"
#include "chainload.h"
u32 IdentifyFileType(const char* path) {
const u8 romfs_magic[] = { ROMFS_MAGIC };
@ -9,9 +10,9 @@ u32 IdentifyFileType(const char* path) {
u8 header[0x200] __attribute__((aligned(32))); // minimum required size
size_t fsize = FileGetSize(path);
char* fname = strrchr(path, '/');
if (fname == NULL) return 0; // not a proper path
fname++;
if (FileGetData(path, header, 0x200, 0) < fsize) return 0;
char* ext = (fname) ? strrchr(++fname, '.') : NULL;
if (ext) ext++;
if (FileGetData(path, header, 0x200, 0) < ((fsize > 0x200) ? 0x200 : fsize)) return 0;
if (fsize >= 0x200) {
if ((getbe32(header + 0x100) == 0x4E435344) && (getbe64(header + 0x110) == (u64) 0x0104030301000000) &&
@ -51,8 +52,12 @@ u32 IdentifyFileType(const char* path) {
}
if ((fsize > sizeof(NcchInfoHeader)) &&
(GetNcchInfoVersion((NcchInfoHeader*) (void*) header)) &&
(strncasecmp(fname, NCCHINFO_NAME, 32) == 0)) {
return MISC_NINFO; // ncchinfo.bin file
fname && (strncasecmp(fname, NCCHINFO_NAME, 32) == 0)) {
return BIN_NCCHNFO; // ncchinfo.bin file
#if PAYLOAD_MAX_SIZE <= TEMP_BUFFER_SIZE
} else if ((fsize <= PAYLOAD_MAX_SIZE) && (strncasecmp(ext, "bin", 4) == 0)) {
return BIN_LAUNCH; // assume it's an ARM9 payload
#endif
}
return 0;

View File

@ -2,19 +2,17 @@
#include "common.h"
#define IMG_FAT (1<<0)
#define IMG_NAND (1<<1)
#define GAME_CIA (1<<2)
#define GAME_NCSD (1<<3)
#define GAME_NCCH (1<<4)
#define GAME_TMD (1<<5)
#define GAME_EXEFS (1<<6)
#define GAME_ROMFS (1<<7)
#define SYS_FIRM (1<<8)
#define MISC_NINFO (1<<9)
#define IMG_FAT (1<<0)
#define IMG_NAND (1<<1)
#define GAME_CIA (1<<2)
#define GAME_NCSD (1<<3)
#define GAME_NCCH (1<<4)
#define GAME_TMD (1<<5)
#define GAME_EXEFS (1<<6)
#define GAME_ROMFS (1<<7)
#define SYS_FIRM (1<<8)
#define BIN_NCCHNFO (1<<9)
#define BIN_LAUNCH (1<<10)
#define FTYPE_MOUNTABLE (IMG_FAT|IMG_NAND|GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_EXEFS|GAME_ROMFS|SYS_FIRM)
#define FYTPE_VERIFICABLE (IMG_NAND|GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_TMD|SYS_FIRM)
@ -22,6 +20,7 @@
#define FTYPE_BUILDABLE (GAME_NCSD|GAME_NCCH|GAME_TMD)
#define FTYPE_BUILDABLE_L (FTYPE_BUILDABLE&(GAME_TMD))
#define FTYPE_RESTORABLE (IMG_NAND)
#define FTYPE_XORPAD (MISC_NINFO)
#define FTYPE_XORPAD (BIN_NCCHNFO)
#define FTYPE_PAYLOAD (BIN_LAUNCH)
u32 IdentifyFileType(const char* path);

View File

@ -14,6 +14,7 @@
#include "vcart.h"
#include "ncchinfo.h"
#include "image.h"
#include "chainload.h"
#define N_PANES 2
@ -589,8 +590,9 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur
bool buildable_legit = (filetype & FTYPE_BUILDABLE_L);
bool restorable = (CheckA9lh() && (filetype & FTYPE_RESTORABLE) && !(drvtype & DRV_SYSNAND));
bool xorpadable = (filetype & FTYPE_XORPAD);
bool launchable = ((filetype & FTYPE_PAYLOAD) && (drvtype & DRV_FAT));
bool special_opt = mountable || verificable || decryptable || decryptable_inplace ||
buildable || buildable_legit || restorable || xorpadable;
buildable || buildable_legit || restorable || xorpadable || launchable;
char pathstr[32 + 1];
TruncateString(pathstr, curr_entry->path, 32, 8);
@ -623,7 +625,8 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur
(filetype == GAME_ROMFS) ? "Mount as ROMFS image" :
(filetype == GAME_TMD) ? "TMD file options..." :
(filetype == SYS_FIRM) ? "FIRM image options..." :
(filetype == MISC_NINFO) ? "NCCHinfo options..." : "???";
(filetype == BIN_NCCHNFO) ? "NCCHinfo options..." :
(filetype == BIN_LAUNCH) ? "Launch as arm9 payload" : "???";
optionstr[hexviewer-1] = "Show in Hexeditor";
optionstr[calcsha-1] = "Calculate SHA-256";
if (copystd > 0) optionstr[copystd-1] = "Copy to " OUTPUT_PATH;
@ -698,6 +701,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur
int verify = (verificable) ? ++n_opt : -1;
int xorpad = (xorpadable) ? ++n_opt : -1;
int xorpad_inplace = (xorpadable) ? ++n_opt : -1;
int launch = (launchable) ? ++n_opt : -1;
if (mount > 0) optionstr[mount-1] = "Mount image to drive";
if (restore > 0) optionstr[restore-1] = "Restore SysNAND (safe)";
if (decrypt > 0) optionstr[decrypt-1] = "Decrypt file (SD output)";
@ -707,6 +711,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur
if (verify > 0) optionstr[verify-1] = "Verify file";
if (xorpad > 0) optionstr[xorpad-1] = "Build XORpads (SD output)";
if (xorpad_inplace > 0) optionstr[xorpad_inplace-1] = "Build XORpads (inplace)";
if (launch > 0) optionstr[launch-1] = "Launch as ARM9 payload";
// auto select when there is only one option
user_select = (n_opt > 1) ? (int) ShowSelectPrompt(n_opt, optionstr, pathstr) : n_opt;
@ -858,6 +863,14 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur
*scroll = 0;
*cursor = 1;
}
} else if ((user_select == launch)) {
size_t payload_size = FileGetSize(curr_entry->path);
if (ShowPrompt(true, "%s (%dkB)\nLaunch as arm9 payload?", pathstr, payload_size / 1024)) {
if (FileGetData(curr_entry->path, TEMP_BUFFER, payload_size, 0) == payload_size) {
Chainload(TEMP_BUFFER, payload_size);
while(1);
} // failed load is basically impossible here
}
}
return 1;