On error return to system menu instead of crashing.

This commit is contained in:
orboditilt 2019-07-25 10:32:52 +02:00
parent 234c180659
commit f4e393a885
8 changed files with 177 additions and 20 deletions

View File

@ -9,12 +9,14 @@ static int32_t LoadFileToMem(private_data_t *private_data, const char *filepath,
int32_t iFd = -1;
void *pClient = private_data->MEMAllocFromDefaultHeapEx(FS_CLIENT_SIZE, 4);
if(!pClient) {
ExitFailure(private_data, "Failed to allocate pClient.");
return 0;
}
void *pCmd = private_data->MEMAllocFromDefaultHeapEx(FS_CMD_BLOCK_SIZE, 4);
if(!pCmd) {
private_data->MEMFreeToDefaultHeap(pClient);
ExitFailure(private_data, "Failed to allocate pCmd.");
return 0;
}
@ -29,18 +31,21 @@ static int32_t LoadFileToMem(private_data_t *private_data, const char *filepath,
int32_t status = private_data->FSGetMountSource(pClient, pCmd, 0, tempPath, -1);
if (status != 0) {
OSFatal("FSGetMountSource failed. Please insert a FAT32 formatted sd card.");
ExitFailure(private_data, "FSGetMountSource failed. Please insert a FAT32 formatted sd card.");
return 0;
}
status = private_data->FSMount(pClient, pCmd, tempPath, mountPath, FS_MAX_MOUNTPATH_SIZE, -1);
if(status != 0) {
OSFatal("SD mount failed. Please insert a FAT32 formatted sd card.");
ExitFailure(private_data, "SD mount failed. Please insert a FAT32 formatted sd card.");
return 0;
}
status = private_data->FSOpenFile(pClient, pCmd, filepath, "r", &iFd, -1);
if(status != 0) {
char buf[0x255];
__os_snprintf(buf,0x254,"FSOpenFile failed. File missing %s",filepath);
OSFatal(buf);
__os_snprintf(buf,0x254,"FSOpenFile failed. File missing %s",filepath);
ExitFailure(private_data, buf);
return 0;
}
FSStat stat;
@ -50,10 +55,12 @@ static int32_t LoadFileToMem(private_data_t *private_data, const char *filepath,
private_data->FSGetStatFile(pClient, pCmd, iFd, &stat, -1);
if(stat.size > 0)
if(stat.size > 0) {
pBuffer = private_data->MEMAllocFromDefaultHeapEx((stat.size + 0x3F) & ~0x3F, 0x40);
else
OSFatal("ELF file empty.");
} else {
ExitFailure(private_data, "ELF file empty.");
return 0;
}
uint32_t done = 0;
@ -66,6 +73,7 @@ static int32_t LoadFileToMem(private_data_t *private_data, const char *filepath,
}
if(done != stat.size) {
ExitFailure(private_data, "Loaded file size was not as expected");
private_data->MEMFreeToDefaultHeap(pBuffer);
} else {
*fileOut = (uint8_t*)pBuffer;
@ -92,10 +100,12 @@ static uint32_t load_elf_image_to_mem (private_data_t *private_data, uint8_t *el
ehdr = (Elf32_Ehdr *) elfstart;
if(ehdr->e_phoff == 0 || ehdr->e_phnum == 0) {
ExitFailure(private_data, "e_phoff or e_phnum were NULL");
return 0;
}
if(ehdr->e_phentsize != sizeof(Elf32_Phdr)) {
ExitFailure(private_data, "wrong e_phentsize");
return 0;
}
@ -141,24 +151,25 @@ static uint32_t load_elf_image_to_mem (private_data_t *private_data, uint8_t *el
return ehdr->e_entry;
}
uint32_t LoadAndCopyFile(const char *filepath) {
private_data_t private_data;
loadFunctionPointers(&private_data);
uint32_t LoadAndCopyFile(const char *filepath, private_data_t * private_data) {
unsigned char *pElfBuffer = NULL;
unsigned int uiElfSize = 0;
LoadFileToMem(&private_data, filepath, &pElfBuffer, &uiElfSize);
if(!LoadFileToMem(private_data, filepath, &pElfBuffer, &uiElfSize)){
// Error messages are set inside the function
return 0;
}
if(!pElfBuffer) {
OSFatal("Failed to load homebrew_launcher.elf");
ExitFailure(private_data, "Failed to load homebrew_launcher.elf");
return 0;
}
unsigned int newEntry = load_elf_image_to_mem(&private_data, pElfBuffer);
unsigned int newEntry = load_elf_image_to_mem(private_data, pElfBuffer);
if(newEntry == 0) {
OSFatal("failed to load .elf");
// Error messages are set inside the function
return 0;
}
private_data.MEMFreeToDefaultHeap(pElfBuffer);
private_data->MEMFreeToDefaultHeap(pElfBuffer);
return newEntry;
}

View File

@ -6,8 +6,9 @@
#ifdef __cplusplus
extern "C" {
#endif
#include "structs.h"
uint32_t LoadAndCopyFile(const char *filepath);
uint32_t LoadAndCopyFile(const char *filepath, private_data_t * private_data);
#ifdef __cplusplus
}

View File

@ -9,7 +9,17 @@
int _start(int argc, char **argv) {
setup_memory();
uint32_t newEntry = LoadAndCopyFile(CAFE_OS_SD_PATH WIIU_PATH "/payload.elf");
private_data_t private_data;
loadFunctionPointers(&private_data);
uint32_t newEntry = LoadAndCopyFile(CAFE_OS_SD_PATH WIIU_PATH "/payload.elf", &private_data);
if(newEntry == 0) {
// When loading the payload failed, wait 1 second to display the error and return back to System Menu.
revertMainHook(&private_data);
private_data.OSSleepTicks(SECS_TO_TICKS(1));
private_data._SYSLaunchTitleWithStdArgsInNoSplash(private_data.sysmenuTitleID, 0);
return ( (int (*)(int, char **))(*(unsigned int*)ADDRESS_OSTitle_main_entry_ptr) )(argc, argv);
}
return ((int (*)(int, char **))newEntry)(argc, argv);
}

View File

@ -9,3 +9,31 @@ SC_0x36_SETBATS:
li r0, 0x3600
sc
blr
.global SCKernelCopyData
SCKernelCopyData:
// Disable data address translation
mfmsr %r6
li %r7, 0x10
andc %r6, %r6, %r7
mtmsr %r6
// Copy data
addi %r3, %r3, -1
addi %r4, %r4, -1
mtctr %r5
SCKernelCopyData_loop:
lbzu %r5, 1(%r4)
stbu %r5, 1(%r3)
bdnz SCKernelCopyData_loop
// Enable data address translation
ori %r6, %r6, 0x10
mtmsr %r6
blr
.global SC_0x25_KernelCopyData
SC_0x25_KernelCopyData:
li %r0, 0x2500
sc
blr

View File

@ -100,7 +100,7 @@ void setup_memory() {
int ret = OSCreateThread(thread, thread_callback, 0, (void*)0, (unsigned int)stack+0x4000, 0x4000, 0, 0x8 + (1 << i));
if (ret == 0) {
OSFatal("Failed to create thread. Exit and re-enter browser.");
OSFatal("Failed to create thread.");
}
// Schedule it for execution

View File

@ -8,6 +8,11 @@
extern "C" {
#endif
#include <stdint.h>
#define BUS_SPEED 248625000
#define SECS_TO_TICKS(sec) (((unsigned long long)(sec)) * (BUS_SPEED/4))
typedef struct _private_data_t {
EXPORT_DECL(void *, MEMAllocFromDefaultHeapEx,int size, int align);
EXPORT_DECL(void, MEMFreeToDefaultHeap,void *ptr);
@ -33,7 +38,22 @@ typedef struct _private_data_t {
EXPORT_DECL(int, FSReadFile, void *pClient, void *pCmd, void *buffer, int size, int count, int fd, int flag, int errHandling);
EXPORT_DECL(int, FSCloseFile, void *pClient, void *pCmd, int fd, int errHandling);
EXPORT_DECL(unsigned int, OSScreenPutFontEx, unsigned int bufferNum, unsigned int posX, unsigned int posY, const char * buffer);
EXPORT_DECL(void, OSScreenInit, void);
EXPORT_DECL(void, OSForceFullRelaunch, void);
EXPORT_DECL(unsigned int, OSScreenGetBufferSizeEx, unsigned int bufferNum);
EXPORT_DECL(unsigned int, OSScreenSetBufferEx, unsigned int bufferNum, void * addr);
EXPORT_DECL(unsigned int, OSScreenClearBufferEx, unsigned int bufferNum, unsigned int temp);
EXPORT_DECL(unsigned int, OSScreenFlipBuffersEx, unsigned int bufferNum);
EXPORT_DECL(unsigned int, OSSleepTicks, uint64_t ticks);
EXPORT_DECL(int, SYSRelaunchTitle, int argc, char** argv);
EXPORT_DECL(void, SYSLaunchMenu, void);
EXPORT_DECL(void, _SYSLaunchMiiStudio, void);
EXPORT_DECL(int, _SYSLaunchTitleWithStdArgsInNoSplash, unsigned long long tid, void *ptr);
EXPORT_DECL(unsigned long long, _SYSGetSystemApplicationTitleId, int sysApp);
uint64_t sysmenuTitleID;
} private_data_t;
#ifdef __cplusplus

View File

@ -1,5 +1,69 @@
#include "utils.h"
extern void SCKernelCopyData(unsigned int addr, unsigned int src, unsigned int len);
extern void SC_0x25_KernelCopyData(unsigned int addr, unsigned int src, unsigned int len);
static void KernelWriteU32(uint32_t addr, uint32_t value, private_data_t * pdata) {
pdata->ICInvalidateRange(&value, 4);
pdata->DCFlushRange(&value, 4);
uint32_t dst = (uint32_t) pdata->OSEffectiveToPhysical((void *)addr);
uint32_t src = (uint32_t) pdata->OSEffectiveToPhysical((void *)&value);
SC_0x25_KernelCopyData(dst, src, 4);
pdata->DCFlushRange((void *)addr, 4);
pdata->ICInvalidateRange((void *)addr, 4);
}
void revertMainHook(private_data_t * private_data) {
kern_write((void*)(KERN_SYSCALL_TBL_1 + (0x25 * 4)), (unsigned int)SCKernelCopyData);
kern_write((void*)(KERN_SYSCALL_TBL_2 + (0x25 * 4)), (unsigned int)SCKernelCopyData);
kern_write((void*)(KERN_SYSCALL_TBL_3 + (0x25 * 4)), (unsigned int)SCKernelCopyData);
kern_write((void*)(KERN_SYSCALL_TBL_4 + (0x25 * 4)), (unsigned int)SCKernelCopyData);
kern_write((void*)(KERN_SYSCALL_TBL_5 + (0x25 * 4)), (unsigned int)SCKernelCopyData);
unsigned int repl_addr = ADDRESS_main_entry_hook;
unsigned int bufferU32 = 0x4E800421;
KernelWriteU32(repl_addr,bufferU32,private_data);
}
void PrepareScreen(private_data_t *private_data) {
// Prepare screen
int screen_buf0_size = 0;
int screen_buf1_size = 0;
unsigned int screen_color = 0; // (r << 24) | (g << 16) | (b << 8) | a;
// Init screen and screen buffers
private_data->OSScreenInit();
screen_buf0_size = private_data->OSScreenGetBufferSizeEx(0);
screen_buf1_size = private_data->OSScreenGetBufferSizeEx(1);
private_data->OSScreenSetBufferEx(0, (void *)0xF4000000);
private_data->OSScreenSetBufferEx(1, (void *)0xF4000000 + screen_buf0_size);
// Clear screens
private_data->OSScreenClearBufferEx(0, screen_color);
private_data->OSScreenClearBufferEx(1, screen_color);
// Flush the cache
private_data->DCFlushRange((void *)0xF4000000, screen_buf0_size);
private_data->DCFlushRange((void *)0xF4000000 + screen_buf0_size, screen_buf1_size);
// Flip buffers
private_data->OSScreenFlipBuffersEx(0);
private_data->OSScreenFlipBuffersEx(1);
}
void ExitFailure(private_data_t *private_data, const char *failure) {
PrepareScreen(private_data);
private_data->OSScreenClearBufferEx(1,0);
private_data->OSScreenPutFontEx(1, 0, 0, failure);
private_data->OSScreenFlipBuffersEx(1);
private_data->OSScreenClearBufferEx(1,0);
private_data->OSScreenPutFontEx(1, 0, 0, failure);
private_data->OSScreenFlipBuffersEx(1);
}
void loadFunctionPointers(private_data_t * private_data) {
unsigned int coreinit_handle;
@ -32,9 +96,26 @@ void loadFunctionPointers(private_data_t * private_data) {
OS_FIND_EXPORT(coreinit_handle, "FSReadFile", private_data->FSReadFile);
OS_FIND_EXPORT(coreinit_handle, "FSCloseFile", private_data->FSCloseFile);
OS_FIND_EXPORT(coreinit_handle, "OSSleepTicks", private_data->OSSleepTicks);
OS_FIND_EXPORT(coreinit_handle, "OSScreenPutFontEx", private_data->OSScreenPutFontEx);
OS_FIND_EXPORT(coreinit_handle, "OSScreenInit", private_data->OSScreenInit);
OS_FIND_EXPORT(coreinit_handle, "OSScreenGetBufferSizeEx", private_data->OSScreenGetBufferSizeEx);
OS_FIND_EXPORT(coreinit_handle, "OSScreenSetBufferEx", private_data->OSScreenSetBufferEx);
OS_FIND_EXPORT(coreinit_handle, "OSScreenClearBufferEx", private_data->OSScreenClearBufferEx);
OS_FIND_EXPORT(coreinit_handle, "OSScreenFlipBuffersEx", private_data->OSScreenFlipBuffersEx);
OS_FIND_EXPORT(coreinit_handle, "OSForceFullRelaunch", private_data->OSForceFullRelaunch);
unsigned int sysapp_handle;
OSDynLoad_Acquire("sysapp.rpl", &sysapp_handle);
OS_FIND_EXPORT(sysapp_handle, "SYSRelaunchTitle", private_data->SYSRelaunchTitle);
OS_FIND_EXPORT(sysapp_handle, "SYSLaunchMenu", private_data->SYSLaunchMenu);
OS_FIND_EXPORT(sysapp_handle, "_SYSLaunchMiiStudio", private_data->_SYSLaunchMiiStudio);
OS_FIND_EXPORT(sysapp_handle, "_SYSGetSystemApplicationTitleId", private_data->_SYSGetSystemApplicationTitleId);
OS_FIND_EXPORT(sysapp_handle, "_SYSLaunchTitleWithStdArgsInNoSplash", private_data->_SYSLaunchTitleWithStdArgsInNoSplash);
private_data->sysmenuTitleID = private_data->_SYSGetSystemApplicationTitleId(0);
}
/* Read a 32-bit word with kernel permissions */

View File

@ -8,8 +8,14 @@
extern "C" {
#endif
void revertMainHook();
void loadFunctionPointers(private_data_t * private_data);
void PrepareScreen(private_data_t *private_data);
void ExitFailure(private_data_t *private_data, const char *failure);
/* Read a 32-bit word with kernel permissions */
uint32_t __attribute__ ((noinline)) kern_read(const void *addr);