- added support to load and launch RPX files directly through SD or wiiload/sendelf

- added error prints in progress window on failures

NOTE:
For this to work you will need to update the code550.bin (or the mp4 file). The old mp4 will still work but not be able to load RPX files, only ELFs.
This commit is contained in:
dimok789 2016-11-12 14:04:23 +01:00
parent c97af74a9d
commit a63171682d
21 changed files with 1256 additions and 106 deletions

View File

@ -16,7 +16,7 @@ sd_loader_elf := ../sd_loader/sd_loader.elf
CFLAGS += -DUSE_SD_LOADER
ASFLAGS += -DUSE_SD_LOADER
all: clean setup main532 main550 main500 main410 main400 main310 main300
all: clean setup main532 main550 main500 main410 main400
sd_loader.h: $(sd_loader_elf)
xxd -i $< | sed "s/unsigned/static const unsigned/g;s/loader/loader/g;s/build_//g" > $@

View File

@ -23,6 +23,14 @@
#define KERN_SYSCALL_TBL_3 0xFFE85470 // works with loader
#define KERN_SYSCALL_TBL_4 0xFFEA9CE0 // works with home menu
#define KERN_SYSCALL_TBL_5 0xFFEAA0E0 // works with browser (previously KERN_SYSCALL_TBL)
#define address_LiWaitIopComplete 0x0100FFA4
#define address_LiWaitIopCompleteWithInterrupts 0x0100FE90
#define address_LiWaitOneChunk 0x010007EC
#define address_PrepareTitle_hook 0xFFF18558
#define address_sgIsLoadingBuffer 0xEFE19D00
#define address_gDynloadInitialized 0xEFE13C3C
#elif ( (VER == 500) || (VER == 510) )
#define ADDRESS_OSTitle_main_entry_ptr 0x1005CB00
#define ADDRESS_main_entry_hook 0x0101C15C
@ -32,6 +40,14 @@
#define KERN_SYSCALL_TBL_3 0xFFE85470 // works with loader
#define KERN_SYSCALL_TBL_4 0xFFEA9120 // works with home menu
#define KERN_SYSCALL_TBL_5 0xFFEA9520 // works with browser (previously KERN_SYSCALL_TBL)
#define address_LiWaitIopComplete 0x0100FBC4
#define address_LiWaitIopCompleteWithInterrupts 0x0100FAB0
#define address_LiWaitOneChunk 0x010007EC
#define address_PrepareTitle_hook 0xFFF18534
#define address_sgIsLoadingBuffer 0xEFE19D00
#define address_gDynloadInitialized 0xEFE13C3C
#elif (VER == 550)
#define ADDRESS_OSTitle_main_entry_ptr 0x1005E040
#define ADDRESS_main_entry_hook 0x0101c56c
@ -41,6 +57,13 @@
#define KERN_SYSCALL_TBL_3 0xFFE85470 // works with loader
#define KERN_SYSCALL_TBL_4 0xFFEAAA60 // works with home menu
#define KERN_SYSCALL_TBL_5 0xFFEAAE60 // works with browser (previously KERN_SYSCALL_TBL)
#define address_LiWaitIopComplete 0x01010180
#define address_LiWaitIopCompleteWithInterrupts 0x0101006C
#define address_LiWaitOneChunk 0x0100080C
#define address_PrepareTitle_hook 0xFFF184E4
#define address_sgIsLoadingBuffer 0xEFE19E80
#define address_gDynloadInitialized 0xEFE13DBC
#elif (VER == 410)
#define ADDRESS_OSTitle_main_entry_ptr 0x1005A8C0
#define ADDRESS_main_entry_hook 0x0101BD4C
@ -50,6 +73,13 @@
#define KERN_SYSCALL_TBL_3 0xFFE85C90
#define KERN_SYSCALL_TBL_4 0xFFE85490
#define KERN_SYSCALL_TBL_5 0xFFE85890 // works with browser
#define address_LiWaitIopComplete 0x0100F78C
#define address_LiWaitIopCompleteWithInterrupts 0x0100F678
#define address_LiWaitOneChunk 0x010007F8
#define address_PrepareTitle_hook 0xFFF166DC
#define address_sgIsLoadingBuffer 0xEFE19CC0
#define address_gDynloadInitialized 0xEFE13BFC
#elif (VER == 400)
#define ADDRESS_OSTitle_main_entry_ptr 0x1005A600
#define ADDRESS_main_entry_hook 0x0101BD4C
@ -59,6 +89,13 @@
#define KERN_SYSCALL_TBL_3 0xFFE85C90
#define KERN_SYSCALL_TBL_4 0xFFE85490
#define KERN_SYSCALL_TBL_5 0xFFE85890 // works with browser
#define address_LiWaitIopComplete 0x0100F78C
#define address_LiWaitIopCompleteWithInterrupts 0x0100F678
#define address_LiWaitOneChunk 0x010007F8
#define address_PrepareTitle_hook 0xFFF15E70
#define address_sgIsLoadingBuffer 0xEFE19CC0
#define address_gDynloadInitialized 0xEFE13BFC
#elif ( (VER == 300) || (VER == 310) )
#define ADDRESS_OSTitle_main_entry_ptr 0x1005BBC0
#define ADDRESS_main_entry_hook 0x0101894C // used OSDynLoad_Acquire 0x01022CBC from libwiiu to calculate
@ -496,6 +533,15 @@ static void InstallPatches(private_data_t *private_data)
osSpecificFunctions.addr_KernSyscallTbl3 = KERN_SYSCALL_TBL_3;
osSpecificFunctions.addr_KernSyscallTbl4 = KERN_SYSCALL_TBL_4;
osSpecificFunctions.addr_KernSyscallTbl5 = KERN_SYSCALL_TBL_5;
osSpecificFunctions.LiWaitIopComplete = (int (*)(int, int *)) address_LiWaitIopComplete;
osSpecificFunctions.LiWaitIopCompleteWithInterrupts = (int (*)(int, int *)) address_LiWaitIopCompleteWithInterrupts;
osSpecificFunctions.addr_LiWaitOneChunk = address_LiWaitOneChunk;
osSpecificFunctions.addr_PrepareTitle_hook = address_PrepareTitle_hook;
osSpecificFunctions.addr_sgIsLoadingBuffer = address_sgIsLoadingBuffer;
osSpecificFunctions.addr_gDynloadInitialized = address_gDynloadInitialized;
osSpecificFunctions.orig_LiWaitOneChunkInstr = *(unsigned int*)address_LiWaitOneChunk;
//! pointer to main entry point of a title
osSpecificFunctions.addr_OSTitle_main_entry = ADDRESS_OSTitle_main_entry_ptr;

View File

@ -3,13 +3,11 @@
#include "../../src/common/common.h"
#include "../../src/common/fs_defs.h"
#include "../../src/common/os_defs.h"
#define CODE_RW_BASE_OFFSET 0
#define DATA_RW_BASE_OFFSET 0
#include "kernel_defs.h"
#include "loader_defs.h"
#define EXPORT_DECL(res, func, ...) res (* func)(__VA_ARGS__);
#define OS_FIND_EXPORT(handle, funcName, func) OSDynLoad_FindExport(handle, 0, funcName, &func)
#define OS_FIND_EXPORT(handle, funcName, func) OSDynLoad_FindExport(handle, 0, funcName, &func)
typedef struct _private_data_t
{
@ -19,10 +17,8 @@ typedef struct _private_data_t
EXPORT_DECL(void*, memcpy, void *p1, const void *p2, unsigned int s);
EXPORT_DECL(void*, memset, void *p1, int val, unsigned int s);
EXPORT_DECL(void, OSFatal, const char* msg);
EXPORT_DECL(void, DCFlushRange, const void *addr, u32 length);
EXPORT_DECL(void, ICInvalidateRange, const void *addr, u32 length);
EXPORT_DECL(int, __os_snprintf, char* s, int n, const char * format, ...);
EXPORT_DECL(void, exit, void);
EXPORT_DECL(unsigned int, OSEffectiveToPhysical, const void*);
EXPORT_DECL(void, exit, int);
EXPORT_DECL(int, FSInit, void);
EXPORT_DECL(int, FSAddClientEx, void *pClient, int unk_zero_param, int errHandling);
@ -39,6 +35,333 @@ typedef struct _private_data_t
EXPORT_DECL(int, SYSRelaunchTitle, int argc, char** argv);
} private_data_t;
static void (*DCFlushRange)(void *addr, unsigned int size);
static void (*DCInvalidateRange)(void *addr, unsigned int size);
static void (*ICInvalidateRange)(void *addr, unsigned int size);
static unsigned int hook_LiWaitOneChunk;
static unsigned int addrphys_LiWaitOneChunk;
extern void SC0x25_KernelCopyData(unsigned int addr, unsigned int src, unsigned int len);
extern void my_PrepareTitle_hook(void);
/* Write a 32-bit word with kernel permissions */
static void __attribute__ ((noinline)) kern_write(void *addr, uint32_t value)
{
asm volatile (
"li 3,1\n"
"li 4,0\n"
"mr 5,%1\n"
"li 6,0\n"
"li 7,0\n"
"lis 8,1\n"
"mr 9,%0\n"
"mr %1,1\n"
"li 0,0x3500\n"
"sc\n"
"nop\n"
"mr 1,%1\n"
:
: "r"(addr), "r"(value)
: "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10",
"11", "12"
);
}
static void KernelCopyData(unsigned int addr, unsigned int src, unsigned int len)
{
/*
* Setup a DBAT access with cache inhibited to write through and read directly from memory
*/
unsigned int dbatu0, dbatl0, dbatu1, dbatl1;
// save the original DBAT value
asm volatile("mfdbatu %0, 0" : "=r" (dbatu0));
asm volatile("mfdbatl %0, 0" : "=r" (dbatl0));
asm volatile("mfdbatu %0, 1" : "=r" (dbatu1));
asm volatile("mfdbatl %0, 1" : "=r" (dbatl1));
unsigned int target_dbatu0 = 0;
unsigned int target_dbatl0 = 0;
unsigned int target_dbatu1 = 0;
unsigned int target_dbatl1 = 0;
unsigned int *dst_p = (unsigned int*)addr;
unsigned int *src_p = (unsigned int*)src;
// we only need DBAT modification for addresses out of our own DBAT range
// as our own DBAT is available everywhere for user and supervisor
// since our own DBAT is on DBAT5 position we don't collide here
if(addr < 0x00800000 || addr >= 0x01000000)
{
target_dbatu0 = (addr & 0x00F00000) | 0xC0000000 | 0x1F;
target_dbatl0 = (addr & 0xFFF00000) | 0x32;
asm volatile("mtdbatu 0, %0" : : "r" (target_dbatu0));
asm volatile("mtdbatl 0, %0" : : "r" (target_dbatl0));
dst_p = (unsigned int*)((addr & 0xFFFFFF) | 0xC0000000);
}
if(src < 0x00800000 || src >= 0x01000000)
{
target_dbatu1 = (src & 0x00F00000) | 0xB0000000 | 0x1F;
target_dbatl1 = (src & 0xFFF00000) | 0x32;
asm volatile("mtdbatu 1, %0" : : "r" (target_dbatu1));
asm volatile("mtdbatl 1, %0" : : "r" (target_dbatl1));
src_p = (unsigned int*)((src & 0xFFFFFF) | 0xB0000000);
}
asm volatile("eieio; isync");
unsigned int i;
for(i = 0; i < len; i += 4)
{
// if we are on the edge to next chunk
if((target_dbatu0 != 0) && (((unsigned int)dst_p & 0x00F00000) != (target_dbatu0 & 0x00F00000)))
{
target_dbatu0 = ((addr + i) & 0x00F00000) | 0xC0000000 | 0x1F;
target_dbatl0 = ((addr + i) & 0xFFF00000) | 0x32;
dst_p = (unsigned int*)(((addr + i) & 0xFFFFFF) | 0xC0000000);
asm volatile("eieio; isync");
asm volatile("mtdbatu 0, %0" : : "r" (target_dbatu0));
asm volatile("mtdbatl 0, %0" : : "r" (target_dbatl0));
asm volatile("eieio; isync");
}
if((target_dbatu1 != 0) && (((unsigned int)src_p & 0x00F00000) != (target_dbatu1 & 0x00F00000)))
{
target_dbatu1 = ((src + i) & 0x00F00000) | 0xB0000000 | 0x1F;
target_dbatl1 = ((src + i) & 0xFFF00000) | 0x32;
src_p = (unsigned int*)(((src + i) & 0xFFFFFF) | 0xB0000000);
asm volatile("eieio; isync");
asm volatile("mtdbatu 1, %0" : : "r" (target_dbatu1));
asm volatile("mtdbatl 1, %0" : : "r" (target_dbatl1));
asm volatile("eieio; isync");
}
*dst_p = *src_p;
++dst_p;
++src_p;
}
/*
* Restore original DBAT value
*/
asm volatile("eieio; isync");
asm volatile("mtdbatu 0, %0" : : "r" (dbatu0));
asm volatile("mtdbatl 0, %0" : : "r" (dbatl0));
asm volatile("mtdbatu 1, %0" : : "r" (dbatu1));
asm volatile("mtdbatl 1, %0" : : "r" (dbatl1));
asm volatile("eieio; isync");
}
// This function is called every time after LiBounceOneChunk.
// It waits for the asynchronous call of LiLoadAsync for the IOSU to fill data to the RPX/RPL address
// and return the still remaining bytes to load.
// We override it and replace the loaded date from LiLoadAsync with our data and our remaining bytes to load.
static int LiWaitOneChunk(unsigned int * iRemainingBytes, const char *filename, int fileType)
{
unsigned int result;
register int core_id;
int remaining_bytes = 0;
int sgFileOffset;
int sgBufferNumber;
int *sgBounceError;
int *sgGotBytes;
int *sgTotalBytes;
int *sgIsLoadingBuffer;
int *sgFinishedLoadingBuffer;
// get the current core
asm volatile("mfspr %0, 0x3EF" : "=r" (core_id));
// get the offset of per core global variable for dynload initialized (just a simple address + (core_id * 4))
unsigned int gDynloadInitialized = *(volatile unsigned int*)(OS_SPECIFICS->addr_gDynloadInitialized + (core_id << 2));
// Comment (Dimok):
// time measurement at this position for logger -> we don't need it right now except maybe for debugging
//unsigned long long systemTime1 = Loader_GetSystemTime();
if(OS_FIRMWARE == 550)
{
// pointer to global variables of the loader
loader_globals_550_t *loader_globals = (loader_globals_550_t*)(0xEFE19E80);
sgBufferNumber = loader_globals->sgBufferNumber;
sgFileOffset = loader_globals->sgFileOffset;
sgBounceError = &loader_globals->sgBounceError;
sgGotBytes = &loader_globals->sgGotBytes;
sgTotalBytes = &loader_globals->sgTotalBytes;
sgFinishedLoadingBuffer = &loader_globals->sgFinishedLoadingBuffer;
// not available on 5.5.x
sgIsLoadingBuffer = NULL;
}
else
{
// pointer to global variables of the loader
loader_globals_t *loader_globals = (loader_globals_t*)(OS_SPECIFICS->addr_sgIsLoadingBuffer);
sgBufferNumber = loader_globals->sgBufferNumber;
sgFileOffset = loader_globals->sgFileOffset;
sgBounceError = &loader_globals->sgBounceError;
sgGotBytes = &loader_globals->sgGotBytes;
sgIsLoadingBuffer = &loader_globals->sgIsLoadingBuffer;
// not available on < 5.5.x
sgTotalBytes = NULL;
sgFinishedLoadingBuffer = NULL;
}
// the data loading was started in LiBounceOneChunk() and here it waits for IOSU to finish copy the data
if(gDynloadInitialized != 0) {
result = OS_SPECIFICS->LiWaitIopCompleteWithInterrupts(0x2160EC0, &remaining_bytes);
}
else {
result = OS_SPECIFICS->LiWaitIopComplete(0x2160EC0, &remaining_bytes);
}
// Comment (Dimok):
// time measurement at this position for logger -> we don't need it right now except maybe for debugging
//unsigned long long systemTime2 = Loader_GetSystemTime();
//------------------------------------------------------------------------------------------------------------------
// Start of our function intrusion:
// After IOSU is done writing the data into the 0xF6000000/0xF6400000 address,
// we overwrite it with our data before setting the global flag for IsLoadingBuffer to 0
// Do this only if we are in the game that was launched by our method
s_mem_area *mem_area = MEM_AREA_TABLE;
if((ELF_DATA_ADDR == mem_area->address) && (fileType == 0))
{
unsigned int load_address = (sgBufferNumber == 1) ? 0xF6000000 : (0xF6000000 + 0x00400000);
unsigned int load_addressPhys = (sgBufferNumber == 1) ? 0x1B000000 : (0x1B000000 + 0x00400000); // virtual 0xF6000000 and 0xF6400000
remaining_bytes = ELF_DATA_SIZE - sgFileOffset;
if (remaining_bytes > 0x400000)
// truncate size
remaining_bytes = 0x400000;
DCFlushRange((void*)load_address, remaining_bytes);
u32 rpxBlockPos = 0;
u32 done = 0;
u32 mapOffset = 0;
while((done < (u32)sgFileOffset) && mem_area)
{
if((done + mem_area->size) > (u32)sgFileOffset)
{
mapOffset = sgFileOffset - done;
done = sgFileOffset;
}
else
{
done += mem_area->size;
mem_area = mem_area->next;
}
}
while((done < ELF_DATA_SIZE) && (rpxBlockPos < 0x400000) && mem_area)
{
u32 address = mem_area->address + mapOffset;
u32 blockSize = ELF_DATA_SIZE - done;
if(blockSize > (0x400000 - rpxBlockPos))
{
blockSize = 0x400000 - rpxBlockPos;
}
if((mapOffset + blockSize) >= mem_area->size)
{
blockSize = mem_area->size - mapOffset;
mem_area = mem_area->next;
mapOffset = 0;
}
SC0x25_KernelCopyData(load_addressPhys + rpxBlockPos, address, blockSize);
done += blockSize;
rpxBlockPos += blockSize;
mapOffset += blockSize;
}
DCInvalidateRange((void*)load_address, remaining_bytes);
if((u32)(sgFileOffset + remaining_bytes) == ELF_DATA_SIZE)
{
ELF_DATA_ADDR = 0xDEADC0DE;
ELF_DATA_SIZE = 0;
MAIN_ENTRY_ADDR = 0xC001C0DE;
}
// set result to 0 -> "everything OK"
result = 0;
}
// end of our little intrusion into this function
//------------------------------------------------------------------------------------------------------------------
// set the result to the global bounce error variable
if(sgBounceError) {
*sgBounceError = result;
}
// disable global flag that buffer is still loaded by IOSU
if(sgFinishedLoadingBuffer)
{
unsigned int zeroBitCount = 0;
asm volatile("cntlzw %0, %0" : "=r" (zeroBitCount) : "r"(*sgFinishedLoadingBuffer));
*sgFinishedLoadingBuffer = zeroBitCount >> 5;
}
else if(sgIsLoadingBuffer)
{
*sgIsLoadingBuffer = 0;
}
// check result for errors
if(result == 0)
{
// the remaining size is set globally and in stack variable only
// if a pointer was passed to this function
if(iRemainingBytes) {
if(sgGotBytes) {
*sgGotBytes = remaining_bytes;
}
*iRemainingBytes = remaining_bytes;
// on 5.5.x a new variable for total loaded bytes was added
if(sgTotalBytes) {
*sgTotalBytes += remaining_bytes;
}
}
// Comment (Dimok):
// calculate time difference and print it on logging how long the wait for asynchronous data load took
// something like (systemTime2 - systemTime1) * constant / bus speed, did not look deeper into it as we don't need that crap
}
else {
// Comment (Dimok):
// a lot of error handling here. depending on error code sometimes calls Loader_Panic() -> we don't make errors so we can skip that part ;-P
}
return result;
}
void my_PrepareTitle(CosAppXmlInfo *xmlKernelInfo)
{
if(ELF_DATA_ADDR == MEM_AREA_TABLE->address)
{
xmlKernelInfo->max_size = RPX_MAX_SIZE;
xmlKernelInfo->max_codesize = RPX_MAX_CODE_SIZE;
//! setup our hook to LiWaitOneChunk for RPX loading
hook_LiWaitOneChunk = ((u32)LiWaitOneChunk) | 0x48000002;
KernelCopyData(addrphys_LiWaitOneChunk, (u32) &hook_LiWaitOneChunk, 4);
asm volatile("icbi 0, %0" : : "r" (OS_SPECIFICS->addr_LiWaitOneChunk & ~31));
}
else if((MAIN_ENTRY_ADDR == 0xC001C0DE) && (*(u32*)xmlKernelInfo->rpx_name == 0x66666c5f)) // ffl_
{
//! restore original LiWaitOneChunk instruction as our RPX is done
MAIN_ENTRY_ADDR = 0xDEADC0DE;
KernelCopyData(addrphys_LiWaitOneChunk, (u32)&OS_SPECIFICS->orig_LiWaitOneChunkInstr, 4);
asm volatile("icbi 0, %0" : : "r" (OS_SPECIFICS->addr_LiWaitOneChunk & ~31));
}
}
static int LoadFileToMem(private_data_t *private_data, const char *filepath, unsigned char **fileOut, unsigned int * sizeOut)
{
int iFd = -1;
@ -66,19 +389,15 @@ static int LoadFileToMem(private_data_t *private_data, const char *filepath, uns
int status = private_data->FSGetMountSource(pClient, pCmd, 0, tempPath, -1);
if (status != 0) {
private_data->OSFatal("FSGetMountSource failed.");
break;
}
status = private_data->FSMount(pClient, pCmd, tempPath, mountPath, FS_MAX_MOUNTPATH_SIZE, -1);
if(status != 0) {
private_data->OSFatal("SD mount failed.");
break;
}
status = private_data->FSOpenFile(pClient, pCmd, filepath, "r", &iFd, -1);
if(status != 0)
{
private_data->FSUnmount(pClient, pCmd, mountPath, -1);
break;
if(status != 0) {
private_data->OSFatal("FSOpenFile failed.");
}
FSStat stat;
@ -90,9 +409,8 @@ static int LoadFileToMem(private_data_t *private_data, const char *filepath, uns
if(stat.size > 0)
pBuffer = private_data->MEMAllocFromDefaultHeapEx((stat.size + 0x3F) & ~0x3F, 0x40);
if(!pBuffer)
private_data->OSFatal("Not enough memory for ELF file.");
else
private_data->OSFatal("ELF file empty.");
unsigned int done = 0;
@ -150,25 +468,19 @@ static unsigned int load_elf_image (private_data_t *private_data, unsigned char
continue;
if(phdrs[i].p_filesz > phdrs[i].p_memsz)
return 0;
continue;
if(!phdrs[i].p_filesz)
continue;
unsigned int p_paddr = phdrs[i].p_paddr;
// use correct offset address for executables and data access
if(phdrs[i].p_flags & PF_X)
p_paddr += CODE_RW_BASE_OFFSET;
else
p_paddr += DATA_RW_BASE_OFFSET;
image = (unsigned char *) (elfstart + phdrs[i].p_offset);
private_data->memcpy ((void *) p_paddr, image, phdrs[i].p_filesz);
private_data->DCFlushRange((void*)p_paddr, phdrs[i].p_filesz);
private_data->memcpy ((void *) p_paddr, image, phdrs[i].p_filesz);
DCFlushRange((void*)p_paddr, phdrs[i].p_filesz);
if(phdrs[i].p_flags & PF_X)
private_data->ICInvalidateRange ((void *) phdrs[i].p_paddr, phdrs[i].p_memsz);
ICInvalidateRange ((void *) p_paddr, phdrs[i].p_memsz);
}
//! clear BSS
@ -179,15 +491,31 @@ static unsigned int load_elf_image (private_data_t *private_data, unsigned char
if(section_name[0] == '.' && section_name[1] == 'b' && section_name[2] == 's' && section_name[3] == 's')
{
private_data->memset((void*)shdr[i].sh_addr, 0, shdr[i].sh_size);
private_data->DCFlushRange((void*)shdr[i].sh_addr, shdr[i].sh_size);
DCFlushRange((void*)shdr[i].sh_addr, shdr[i].sh_size);
}
else if(section_name[0] == '.' && section_name[1] == 's' && section_name[2] == 'b' && section_name[3] == 's' && section_name[4] == 's')
{
private_data->memset((void*)shdr[i].sh_addr, 0, shdr[i].sh_size);
private_data->DCFlushRange((void*)shdr[i].sh_addr, shdr[i].sh_size);
DCFlushRange((void*)shdr[i].sh_addr, shdr[i].sh_size);
}
}
//! setup hooks
kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl1 + (0x25 * 4)), (unsigned int)KernelCopyData);
kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl2 + (0x25 * 4)), (unsigned int)KernelCopyData);
kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl3 + (0x25 * 4)), (unsigned int)KernelCopyData);
kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl4 + (0x25 * 4)), (unsigned int)KernelCopyData);
kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl5 + (0x25 * 4)), (unsigned int)KernelCopyData);
//! store physical address for later use
addrphys_LiWaitOneChunk = private_data->OSEffectiveToPhysical((void*)OS_SPECIFICS->addr_LiWaitOneChunk);
u32 addr_my_PrepareTitle_hook = ((u32)my_PrepareTitle_hook) | 0x48000003;
DCFlushRange(&addr_my_PrepareTitle_hook, 4);
//! create our copy syscall
SC0x25_KernelCopyData(OS_SPECIFICS->addr_PrepareTitle_hook, private_data->OSEffectiveToPhysical(&addr_my_PrepareTitle_hook), 4);
return ehdr->e_entry;
}
@ -213,9 +541,10 @@ static void loadFunctionPointers(private_data_t * private_data)
OS_FIND_EXPORT(coreinit_handle, "memcpy", private_data->memcpy);
OS_FIND_EXPORT(coreinit_handle, "memset", private_data->memset);
OS_FIND_EXPORT(coreinit_handle, "OSFatal", private_data->OSFatal);
OS_FIND_EXPORT(coreinit_handle, "DCFlushRange", private_data->DCFlushRange);
OS_FIND_EXPORT(coreinit_handle, "ICInvalidateRange", private_data->ICInvalidateRange);
OS_FIND_EXPORT(coreinit_handle, "__os_snprintf", private_data->__os_snprintf);
OS_FIND_EXPORT(coreinit_handle, "DCFlushRange", DCFlushRange);
OS_FIND_EXPORT(coreinit_handle, "DCInvalidateRange", DCInvalidateRange);
OS_FIND_EXPORT(coreinit_handle, "ICInvalidateRange", ICInvalidateRange);
OS_FIND_EXPORT(coreinit_handle, "OSEffectiveToPhysical", private_data->OSEffectiveToPhysical);
OS_FIND_EXPORT(coreinit_handle, "exit", private_data->exit);
OS_FIND_EXPORT(coreinit_handle, "FSInit", private_data->FSInit);
@ -237,8 +566,10 @@ static void loadFunctionPointers(private_data_t * private_data)
int _start(int argc, char **argv)
{
private_data_t private_data;
if(MAIN_ENTRY_ADDR != 0xC001C0DE)
{
private_data_t private_data;
loadFunctionPointers(&private_data);
while(1)
@ -252,6 +583,7 @@ int _start(int argc, char **argv)
private_data.memcpy(pElfBuffer, (unsigned char*)ELF_DATA_ADDR, ELF_DATA_SIZE);
MAIN_ENTRY_ADDR = load_elf_image(&private_data, pElfBuffer);
private_data.MEMFreeToDefaultHeap(pElfBuffer);
}
ELF_DATA_ADDR = 0xDEADC0DE;
ELF_DATA_SIZE = 0;
@ -259,30 +591,38 @@ int _start(int argc, char **argv)
if(MAIN_ENTRY_ADDR == 0xDEADC0DE || MAIN_ENTRY_ADDR == 0)
{
unsigned char *pElfBuffer = NULL;
unsigned int uiElfSize = 0;
LoadFileToMem(&private_data, CAFE_OS_SD_PATH WIIU_PATH "/apps/homebrew_launcher/homebrew_launcher.elf", &pElfBuffer, &uiElfSize);
if(!pElfBuffer)
if(HBL_CHANNEL)
{
private_data.OSFatal("Could not load file " WIIU_PATH "/apps/homebrew_launcher/homebrew_launcher.elf");
break;
}
else
{
MAIN_ENTRY_ADDR = load_elf_image(&private_data, pElfBuffer);
private_data.MEMFreeToDefaultHeap(pElfBuffer);
unsigned char *pElfBuffer = NULL;
unsigned int uiElfSize = 0;
if(MAIN_ENTRY_ADDR == 0)
LoadFileToMem(&private_data, CAFE_OS_SD_PATH WIIU_PATH "/apps/homebrew_launcher/homebrew_launcher.elf", &pElfBuffer, &uiElfSize);
if(!pElfBuffer)
{
private_data.OSFatal("Failed to load ELF " WIIU_PATH "/apps/homebrew_launcher/homebrew_launcher.elf");
private_data.OSFatal("Failed to load homebrew_launcher.elf");
}
else
{
MAIN_ENTRY_ADDR = load_elf_image(&private_data, pElfBuffer);
if(MAIN_ENTRY_ADDR == 0)
{
private_data.OSFatal("Failed to load homebrew_launcher.elf");
}
else
{
private_data.MEMFreeToDefaultHeap(pElfBuffer);
}
}
}
}
else
{
int returnVal = ((int (*)(int, char **))MAIN_ENTRY_ADDR)(argc, argv);
//! exit to miimaker and restart application on re-enter of another application
if(returnVal == (int)EXIT_RELAUNCH_ON_LOAD)
{
@ -293,12 +633,20 @@ int _start(int argc, char **argv)
{
MAIN_ENTRY_ADDR = 0xDEADC0DE;
private_data.SYSRelaunchTitle(0, 0);
private_data.exit();
private_data.exit(0);
break;
}
}
}
}
return ( (int (*)(int, char **))(*(unsigned int*)OS_SPECIFICS->addr_OSTitle_main_entry) )(argc, argv);
int ret = ( (int (*)(int, char **))(*(unsigned int*)OS_SPECIFICS->addr_OSTitle_main_entry) )(argc, argv);
//! if an application returns and was an RPX launch then launch HBL again
if(MAIN_ENTRY_ADDR == 0xC001C0DE)
{
private_data.SYSRelaunchTitle(0, 0);
private_data.exit(0);
}
return ret;
}

View File

@ -0,0 +1,75 @@
#ifndef __KERNEL_DEFS_H_
#define __KERNEL_DEFS_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
// original structure in the kernel that is originally 0x1270 long
typedef struct
{
uint32_t version_cos_xml; // version tag from cos.xml
uint64_t os_version; // os_version from app.xml
uint64_t title_id; // title_id tag from app.xml
uint32_t app_type; // app_type tag from app.xml
uint32_t cmdFlags; // unknown tag as it is always 0 (might be cmdFlags from cos.xml but i am not sure)
char rpx_name[0x1000]; // rpx name from cos.xml
uint32_t unknown2; // 0x050B8304 in mii maker and system menu (looks a bit like permissions complex that got masked!?)
uint32_t unknown3[63]; // those were all zeros, but its probably connected with unknown2
uint32_t max_size; // max_size in cos.xml which defines the maximum amount of memory reserved for the app
uint32_t avail_size; // avail_size or codegen_size in cos.xml (seems to mostly be 0?)
uint32_t codegen_size; // codegen_size or avail_size in cos.xml (seems to mostly be 0?)
uint32_t codegen_core; // codegen_core in cos.xml (seems to mostly be 1?)
uint32_t max_codesize; // max_codesize in cos.xml
uint32_t overlay_arena; // overlay_arena in cos.xml
uint32_t unknown4[59]; // all zeros it seems
uint32_t default_stack0_size; // not sure because always 0 but very likely
uint32_t default_stack1_size; // not sure because always 0 but very likely
uint32_t default_stack2_size; // not sure because always 0 but very likely
uint32_t default_redzone0_size; // not sure because always 0 but very likely
uint32_t default_redzone1_size; // not sure because always 0 but very likely
uint32_t default_redzone2_size; // not sure because always 0 but very likely
uint32_t exception_stack0_size; // from cos.xml, 0x1000 on mii maker
uint32_t exception_stack1_size; // from cos.xml, 0x1000 on mii maker
uint32_t exception_stack2_size; // from cos.xml, 0x1000 on mii maker
uint32_t sdk_version; // from app.xml, 20909 (0x51AD) on mii maker
uint32_t title_version; // from app.xml, 0x32 on mii maker
/*
// ---------------------------------------------------------------------------------------------------------------------------------------------
// the next part might be changing from title to title?! I don't think its important but nice to know maybe....
// ---------------------------------------------------------------------------------------------------------------------------------------------
char mlc[4]; // string "mlc" on mii maker and sysmenu
uint32_t unknown5[7]; // all zeros on mii maker and sysmenu
uint32_t unknown6_one; // 0x01 on mii maker and sysmenu
// ---------------------------------------------------------------------------------------------------------------------------------------------
char ACP[4]; // string "ACP" on mii maker and sysmenu
uint32_t unknown7[15]; // all zeros on mii maker and sysmenu
uint32_t unknown8_5; // 0x05 on mii maker and sysmenu
uint32_t unknown9_zero; // 0x00 on mii maker and sysmenu
uint32_t unknown10_ptr; // 0xFF23DD0C pointer on mii maker and sysmenu
// ---------------------------------------------------------------------------------------------------------------------------------------------
char UVD[4]; // string "UVD" on mii maker and sysmenu
uint32_t unknown11[15]; // all zeros on mii maker and sysmenu
uint32_t unknown12_5; // 0x05 on mii maker and sysmenu
uint32_t unknown13_zero; // 0x00 on mii maker and sysmenu
uint32_t unknown14_ptr; // 0xFF23EFC8 pointer on mii maker and sysmenu
// ---------------------------------------------------------------------------------------------------------------------------------------------
char SND[4]; // string "SND" on mii maker and sysmenu
uint32_t unknown15[15]; // all zeros on mii maker and sysmenu
uint32_t unknown16_5; // 0x05 on mii maker and sysmenu
uint32_t unknown17_zero; // 0x00 on mii maker and sysmenu
uint32_t unknown18_ptr; // 0xFF23F014 pointer on mii maker and sysmenu
// ---------------------------------------------------------------------------------------------------------------------------------------------
uint32_t unknown19; // 0x02 on miimaker, 0x0F on system menu
*/
// after that only zeros follow
} __attribute__((packed)) CosAppXmlInfo;
#ifdef __cplusplus
}
#endif
#endif // __KERNEL_DEFS_H_

View File

@ -27,3 +27,43 @@ SaveAndResetDataBATs_And_SRs_hook:
mtsr 7, r5
# jump back to the position in kernel after our patch (from LR)
bctr
.extern my_PrepareTitle
.globl my_PrepareTitle_hook
my_PrepareTitle_hook:
# store all registers on stack to avoid issues with the call to C functions
stwu r1, -0x90(r1)
# registers for our own usage
# just store everything
stmw r3, 0x10(r1)
# save the LR from where we came
mflr r31
# the cos.xml/app.xml structure is at the location 0x68 of r11
# there are actually many places that can be hooked for it
# e.g. 0xFFF16130 and r27 points to this structure
addi r3, r11, 0x68
bl my_PrepareTitle
# setup LR to jump back to kernel code
mtlr r31
# restore all original values of registers from stack
lmw r3, 0x10(r1)
# restore the stack
addi r1, r1, 0x90
# restore original instruction that we replaced in the kernel
clrlwi r7, r12, 0
# jump back
blr
.globl SC0x25_KernelCopyData
SC0x25_KernelCopyData:
li r0, 0x2500
sc
blr

View File

@ -13,10 +13,11 @@ SECTIONS {
.data : {
*(.rodata*);
*(.data*);
*(.bss*);
}
/DISCARD/ : {
*(*);
}
}
ASSERT((SIZEOF(.text) + SIZEOF(.data)) < 0x1000, "Memory overlapping with main elf.");
ASSERT((SIZEOF(.text) + SIZEOF(.data)) < 0x1300, "Memory overlapping with main elf.");

View File

@ -0,0 +1,38 @@
#ifndef __LOADER_DEFS_H_
#define __LOADER_DEFS_H_
#ifdef __cplusplus
extern "C" {
#endif
// struct holding the globals of the loader (there are actually more but we don't need others)
typedef struct _loader_globals_t
{
int sgIsLoadingBuffer;
int sgFileType;
int sgProcId;
int sgGotBytes;
int sgFileOffset;
int sgBufferNumber;
int sgBounceError;
char sgLoadName[0x1000];
} __attribute__((packed)) loader_globals_t;
typedef struct _loader_globals_550_t
{
int sgFinishedLoadingBuffer;
int sgFileType;
int sgProcId;
int sgGotBytes;
int sgTotalBytes;
int sgFileOffset;
int sgBufferNumber;
int sgBounceError;
char sgLoadName[0x1000];
} __attribute__((packed)) loader_globals_550_t;
#ifdef __cplusplus
}
#endif
#endif // __LOADER_DEFS_H_

View File

@ -7,7 +7,7 @@ extern "C" {
#include "os_defs.h"
#define HBL_VERSION "v1.3"
#define HBL_VERSION "v1.4"
#define CAFE_OS_SD_PATH "/vol/external01"
#define SD_PATH "sd:"
@ -19,11 +19,16 @@ extern "C" {
#define ELF_DATA_ADDR (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x00))
#define ELF_DATA_SIZE (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x04))
#define HBL_CHANNEL (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x08))
#define RPX_MAX_SIZE (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x0C))
#define RPX_MAX_CODE_SIZE (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x10))
#define MAIN_ENTRY_ADDR (*(volatile unsigned int*)(MEM_BASE + 0x1400 + 0x00))
#define OS_FIRMWARE (*(volatile unsigned int*)(MEM_BASE + 0x1400 + 0x04))
#define OS_SPECIFICS ((OsSpecifics*)(MEM_BASE + 0x1500))
#define MEM_AREA_TABLE ((s_mem_area*)(MEM_BASE + 0x1600))
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#endif

View File

@ -16,8 +16,23 @@ typedef struct _OsSpecifics
unsigned int addr_KernSyscallTbl3;
unsigned int addr_KernSyscallTbl4;
unsigned int addr_KernSyscallTbl5;
int (*LiWaitIopComplete)(int, int *);
int (*LiWaitIopCompleteWithInterrupts)(int, int *);
unsigned int addr_LiWaitOneChunk;
unsigned int addr_PrepareTitle_hook;
unsigned int addr_sgIsLoadingBuffer;
unsigned int addr_gDynloadInitialized;
unsigned int orig_LiWaitOneChunkInstr;
} OsSpecifics;
typedef struct _s_mem_area
{
unsigned int address;
unsigned int size;
struct _s_mem_area* next;
} s_mem_area;
#ifdef __cplusplus
}
#endif

View File

@ -167,10 +167,6 @@ void HomebrewLaunchWindow::OnFileLoadFinish(GuiElement *element, const std::stri
if(result > 0)
{
u32 ApplicationMemoryEnd = getApplicationEndAddr();
ELF_DATA_ADDR = ApplicationMemoryEnd;
ELF_DATA_SIZE = result;
Application::instance()->quit(EXIT_SUCCESS);
}
}
@ -181,9 +177,7 @@ void HomebrewLaunchWindow::OnLoadButtonClick(GuiButton *button, const GuiControl
backBtn.setState(GuiElement::STATE_DISABLED);
loadBtn.setState(GuiElement::STATE_DISABLED);
u32 ApplicationMemoryEnd = getApplicationEndAddr();
HomebrewLoader * loader = HomebrewLoader::loadToMemoryAsync(homebrewLaunchPath, (unsigned char*)ApplicationMemoryEnd);
HomebrewLoader * loader = HomebrewLoader::loadToMemoryAsync(homebrewLaunchPath);
loader->setEffect(EFFECT_FADE, 15, 255);
loader->effectFinished.connect(this, &HomebrewLaunchWindow::OnOpenEffectFinish);
loader->asyncLoadFinished.connect(this, &HomebrewLaunchWindow::OnFileLoadFinish);

View File

@ -3,13 +3,14 @@
#include <string.h>
#include "HomebrewLoader.h"
#include "HomebrewMemory.h"
#include "fs/CFile.hpp"
#include "utils/logger.h"
#include "utils/StringTools.h"
HomebrewLoader * HomebrewLoader::loadToMemoryAsync(const std::string & file, unsigned char *address)
HomebrewLoader * HomebrewLoader::loadToMemoryAsync(const std::string & file)
{
HomebrewLoader * loader = new HomebrewLoader(file, address);
HomebrewLoader * loader = new HomebrewLoader(file);
loader->resumeThread();
return loader;
}
@ -29,13 +30,25 @@ int HomebrewLoader::loadToMemory()
CFile file(filepath, CFile::ReadOnly);
if(!file.isOpen())
{
progressWindow.setTitle(strfmt("Failed to open file %s", FullpathToFilename(filepath.c_str())));
sleep(1);
return FILE_OPEN_FAILURE;
}
u32 bytesRead = 0;
u32 fileSize = file.size();
progressWindow.setTitle(strfmt("Loading file %s", FullpathToFilename(filepath.c_str())));
unsigned char *buffer = (unsigned char*) memalign(0x40, (fileSize + 0x3F) & ~0x3F);
if(!buffer)
{
progressWindow.setTitle("Not enough memory");
sleep(1);
return NOT_ENOUGH_MEMORY;
}
// Copy rpl in memory
while(bytesRead < fileSize)
{
@ -45,13 +58,7 @@ int HomebrewLoader::loadToMemory()
if(blockSize > (fileSize - bytesRead))
blockSize = fileSize - bytesRead;
if((u32)(loadAddress + bytesRead + blockSize) > 0x01000000)
{
log_printf("File ist too big\n");
return NOT_ENOUGH_MEMORY;
}
int ret = file.read(loadAddress + bytesRead, blockSize);
int ret = file.read(buffer + bytesRead, blockSize);
if(ret <= 0)
{
log_printf("Failure on reading file %s\n", filepath.c_str());
@ -65,9 +72,25 @@ int HomebrewLoader::loadToMemory()
if(bytesRead != fileSize)
{
free(buffer);
log_printf("File loading not finished for file %s, finished %i of %i bytes\n", filepath.c_str(), bytesRead, fileSize);
progressWindow.setTitle("File read failure");
sleep(1);
return FILE_READ_ERROR;
}
HomebrewInitMemory();
int ret = HomebrewCopyMemory(buffer, bytesRead);
free(buffer);
if(ret < 0)
{
progressWindow.setTitle("Not enough memory");
sleep(1);
return NOT_ENOUGH_MEMORY;
}
return fileSize;
}

View File

@ -22,15 +22,14 @@ public:
};
static HomebrewLoader * loadToMemoryAsync(const std::string & filepath, unsigned char *address);
static HomebrewLoader * loadToMemoryAsync(const std::string & filepath);
sigslot::signal3<GuiElement *, const std::string &, int> asyncLoadFinished;
private:
HomebrewLoader(const std::string & file, unsigned char *address)
HomebrewLoader(const std::string & file)
: GuiFrame(0, 0)
, CThread(CThread::eAttributeAffCore0 | CThread::eAttributePinnedAff)
, filepath(file)
, loadAddress(address)
, progressWindow("Loading file...")
{
append(&progressWindow);
@ -45,7 +44,6 @@ private:
static void loadCallback(CThread *thread, void *arg);
const std::string filepath;
unsigned char *loadAddress;
ProgressWindow progressWindow;
};

View File

@ -0,0 +1,84 @@
#include <string.h>
#include "common/common.h"
#include "dynamic_libs/os_functions.h"
#include "system/memory_area_table.h"
#include "utils/utils.h"
#include "utils/logger.h"
static s_mem_area *mem_map = 0;
static u32 mapPosition = 0;
void HomebrewInitMemory(void)
{
memoryInitAreaTable();
mem_map = MEM_AREA_TABLE;
mapPosition = 0;
ELF_DATA_ADDR = 0;
ELF_DATA_SIZE = 0;
RPX_MAX_SIZE = 0x40000000;
RPX_MAX_CODE_SIZE = 0x03000000;
}
int HomebrewCopyMemory(u8 *address, u32 bytes)
{
if(ELF_DATA_SIZE == 0)
{
// check if we load an RPX or an ELF
if(*(u16*)&address[7] != 0xCAFE)
{
// assume ELF
ELF_DATA_ADDR = getApplicationEndAddr();
}
else
{
// RPX
ELF_DATA_ADDR = MEM_AREA_TABLE->address;
}
}
//! if we load an ELF file
if(ELF_DATA_ADDR < 0x01000000)
{
u32 targetAddress = ELF_DATA_ADDR + ELF_DATA_SIZE;
if((targetAddress + bytes) > 0x01000000)
return -1;
memcpy((void*)(targetAddress + ELF_DATA_SIZE), address, bytes);
ELF_DATA_SIZE += bytes;
}
else
{
DCFlushRange(address, bytes);
u32 done = 0;
u32 addressPhysical = (u32)OSEffectiveToPhysical(address);
while((done < bytes) && mem_map)
{
if(mapPosition >= mem_map->size)
{
mem_map = mem_map->next;
if(!mem_map)
return -1;
mapPosition = 0;
}
u32 blockSize = bytes - done;
if((mapPosition + blockSize) > mem_map->size)
{
blockSize = mem_map->size - mapPosition;
}
SC0x25_KernelCopyData(mem_map->address + mapPosition, (addressPhysical + done), blockSize);
mapPosition += blockSize;
done += blockSize;
}
ELF_DATA_SIZE += done;
}
return bytes;
}

View File

@ -0,0 +1,7 @@
#ifndef HOMEBREW_MEMORY_H_
#define HOMEBREW_MEMORY_H_
void HomebrewInitMemory(void);
int HomebrewCopyMemory(u8 *address, u32 bytes);
#endif

View File

@ -52,7 +52,7 @@ HomebrewWindow::HomebrewWindow(int w, int h)
currentLeftPosition = 0;
listOffset = 0;
DirList dirList("sd:/wiiu/apps", ".elf", DirList::Files | DirList::CheckSubfolders, 1);
DirList dirList("sd:/wiiu/apps", ".elf,.rpx", DirList::Files | DirList::CheckSubfolders, 1);
dirList.SortList();
@ -314,8 +314,6 @@ void HomebrewWindow::OnCloseTcpReceiverFinish(GuiElement *element)
void HomebrewWindow::OnTcpReceiveStart(GuiElement *element, u32 ip)
{
setState(STATE_DISABLED);
element->setEffect(EFFECT_FADE, 15, 255);
element->effectFinished.connect(this, &HomebrewWindow::OnOpenEffectFinish);
append(element);
@ -329,10 +327,7 @@ void HomebrewWindow::OnTcpReceiveFinish(GuiElement *element, u32 ip, int result)
if(result > 0)
{
u32 ApplicationMemoryEnd = getApplicationEndAddr();
ELF_DATA_ADDR = ApplicationMemoryEnd;
ELF_DATA_SIZE = result;
log_printf("Launching homebrew, loaded to address %08X size %08X\n", ELF_DATA_ADDR, ELF_DATA_SIZE);
Application::instance()->quit(EXIT_SUCCESS);
}
}

View File

@ -4,6 +4,7 @@
#include <zlib.h>
#include "TcpReceiver.h"
#include "HomebrewMemory.h"
#include "dynamic_libs/os_functions.h"
#include "dynamic_libs/socket_functions.h"
#include "fs/CFile.hpp"
@ -15,7 +16,6 @@ TcpReceiver::TcpReceiver(int port)
: GuiFrame(0, 0)
, CThread(CThread::eAttributeAffCore0 | CThread::eAttributePinnedAff)
, exitRequested(false)
, loadAddress(0)
, serverPort(port)
, serverSocket(-1)
, progressWindow("Receiving file...")
@ -23,10 +23,6 @@ TcpReceiver::TcpReceiver(int port)
width = progressWindow.getWidth();
height = progressWindow.getHeight();
append(&progressWindow);
u32 ApplicationMemoryEnd = getApplicationEndAddr();
loadAddress = (unsigned char*)ApplicationMemoryEnd;
resumeThread();
}
@ -116,32 +112,30 @@ int TcpReceiver::loadToMemory(s32 clientSocket, u32 ipAddress)
log_printf("transfer start\n");
std::string strBuffer;
strBuffer.resize(0x1000);
unsigned char* loadAddress = (unsigned char*)memalign(0x40, fileSize);
if(!loadAddress)
{
progressWindow.setTitle("Not enough memory");
sleep(1);
return NOT_ENOUGH_MEMORY;
}
// Copy rpl in memory
while(bytesRead < fileSize)
{
progressWindow.setProgress(100.0f * (f32)bytesRead / (f32)fileSize);
u32 blockSize = strBuffer.size();
u32 blockSize = 0x1000;
if(blockSize > (fileSize - bytesRead))
blockSize = fileSize - bytesRead;
if((u32)(loadAddress + bytesRead + blockSize) > 0x01000000)
{
log_printf("File ist too big\n");
return NOT_ENOUGH_MEMORY;
}
int ret = recv(clientSocket, &strBuffer[0], blockSize, 0);
int ret = recv(clientSocket, loadAddress + bytesRead, blockSize, 0);
if(ret <= 0)
{
log_printf("Failure on reading file\n");
break;
}
memcpy(loadAddress + bytesRead, &strBuffer[0], ret);
bytesRead += ret;
}
@ -149,13 +143,20 @@ int TcpReceiver::loadToMemory(s32 clientSocket, u32 ipAddress)
if(bytesRead != fileSize)
{
free(loadAddress);
log_printf("File loading not finished, %i of %i bytes received\n", bytesRead, fileSize);
progressWindow.setTitle("Receive incomplete");
sleep(1);
return FILE_READ_ERROR;
}
int res = -1;
// Do we need to unzip this thing?
if (haxx[4] > 0 || haxx[5] > 4)
{
unsigned char* inflatedData = NULL;
// We need to unzip...
if (loadAddress[0] == 'P' && loadAddress[1] == 'K' && loadAddress[2] == 0x03 && loadAddress[3] == 0x04)
{
@ -163,8 +164,14 @@ int TcpReceiver::loadToMemory(s32 clientSocket, u32 ipAddress)
//! mhmm this is incorrect, it has to parse the zip
// Section is compressed, inflate
std::string inflatedData;
inflatedData.resize(fileSizeUnc);
inflatedData = (unsigned char*)malloc(fileSizeUnc);
if(!inflatedData)
{
free(loadAddress);
progressWindow.setTitle("Not enough memory");
sleep(1);
return NOT_ENOUGH_MEMORY;
}
int ret = 0;
z_stream s;
@ -176,7 +183,13 @@ int TcpReceiver::loadToMemory(s32 clientSocket, u32 ipAddress)
ret = inflateInit(&s);
if (ret != Z_OK)
{
free(loadAddress);
free(inflatedData);
progressWindow.setTitle("Uncompress failure");
sleep(1);
return FILE_READ_ERROR;
}
s.avail_in = fileSize;
s.next_in = (Bytef *)(&loadAddress[0]);
@ -186,34 +199,62 @@ int TcpReceiver::loadToMemory(s32 clientSocket, u32 ipAddress)
ret = inflate(&s, Z_FINISH);
if (ret != Z_OK && ret != Z_STREAM_END)
{
free(loadAddress);
free(inflatedData);
progressWindow.setTitle("Uncompress failure");
sleep(1);
return FILE_READ_ERROR;
}
inflateEnd(&s);
if(fileSizeUnc > (0x01000000 - (u32)loadAddress))
return FILE_READ_ERROR;
memcpy(loadAddress, &inflatedData[0], fileSizeUnc);
fileSize = fileSizeUnc;
}
else
{
// Section is compressed, inflate
std::string inflatedData;
inflatedData.resize(fileSizeUnc);
inflatedData = (unsigned char*)malloc(fileSizeUnc);
if(!inflatedData)
{
free(loadAddress);
progressWindow.setTitle("Not enough memory");
sleep(1);
return NOT_ENOUGH_MEMORY;
}
uLongf f = fileSizeUnc;
int result = uncompress((Bytef*)&inflatedData[0], &f, (Bytef*)loadAddress, fileSize);
if(result != Z_OK)
{
log_printf("uncompress failed %i\n", result);
progressWindow.setTitle("Uncompress failure");
sleep(1);
return FILE_READ_ERROR;
}
fileSizeUnc = f;
memcpy(loadAddress, &inflatedData[0], fileSizeUnc);
fileSize = fileSizeUnc;
}
free(loadAddress);
HomebrewInitMemory();
res = HomebrewCopyMemory(inflatedData, fileSize);
free(inflatedData);
}
else
{
HomebrewInitMemory();
res = HomebrewCopyMemory(loadAddress, fileSize);
free(loadAddress);
}
if(res < 0)
{
progressWindow.setTitle("Not enough memory");
sleep(1);
return NOT_ENOUGH_MEMORY;
}
return fileSize;
}

View File

@ -33,7 +33,6 @@ private:
int loadToMemory(s32 clientSocket, u32 ipAddress);
bool exitRequested;
unsigned char *loadAddress;
s32 serverPort;
s32 serverSocket;
ProgressWindow progressWindow;

View File

@ -0,0 +1,400 @@
/****************************************************************************
* Copyright (C) 2015 Dimok
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include <malloc.h>
#include <string.h>
#include <gctypes.h>
#include "common/common.h"
#include "utils/utils.h"
#include "memory_area_table.h"
typedef struct _memory_values_t
{
unsigned int start_address;
unsigned int end_address;
} memory_values_t;
static const memory_values_t mem_vals_400[] =
{
{ 0x2E573BFC, 0x2FF8F83C }, // 26735 kB
{ 0x2D86D318, 0x2DFFFFFC }, // 7755 kB
{ 0x2CE59830, 0x2D3794D8 }, // 5247 kB
{ 0x2D3795AC, 0x2D854300 }, // 4971 kB
{ 0x28FEC800, 0x293B29D0 }, // 3864 kB
{ 0x29BC200C, 0x29D79B94 }, // 1758 kB
{ 0x2A517A68, 0x2A6794B8 }, // 1414 kB
{ 0x288C1D80, 0x28A69FA0 }, // 1696 kB
{ 0, 0 }
};
static const memory_values_t mem_vals_410[] =
{
// { 0x28041760, 0x28049D0C } // 33 kB
// { 0x280608F4, 0x2806C97C } // 48 kB
// { 0x280953C8, 0x280A1324 } // 47 kB
// { 0x280A1358, 0x280AD388 } // 48 kB
// { 0x280C9040, 0x280D0ABC } // 30 kB
// { 0x280D0AD8, 0x28113FBC } // 269 kB
// { 0x2812575C, 0x2817A53C } // 339 kB
// { 0x2817A6A0, 0x281BA53C } // 255 kB
// { 0x281D571C, 0x2820253C } // 179 kB
// { 0x28234D00, 0x2824B33C } // 89 kB
// { 0x2824E300, 0x2828D7BC } // 253 kB
// { 0x282A8DF0, 0x282B63FC } // 53 kB
// { 0x282BC524, 0x282C62FC } // 39 kB
// { 0x2835A988, 0x28366804 } // 47 kB
// { 0x2836E05C, 0x28378DBC } // 43 kB
// { 0x283A735C, 0x284D2A64 } // 1197 kB (1 MB)
// { 0x284D76B0, 0x285021FC } // 170 kB
// { 0x285766A4, 0x28583E4C } // 53 kB
// { 0x28590E5C, 0x2859B248 } // 40 kB
// { 0x2859B288, 0x285AE06C } // 75 kB
// { 0x285B7108, 0x285C0A7C } // 38 kB
// { 0x285C38A0, 0x285D089C } // 52 kB
// { 0x285D0A84, 0x285DC63C } // 46 kB
// { 0x285E0A84, 0x285F089C } // 63 kB
// { 0x285F7FD0, 0x286037D8 } // 46 kB
// { 0x2860E3E4, 0x28621B00 } // 77 kB
// { 0x286287B0, 0x28638BC0 } // 65 kB
// { 0x2863F4A0, 0x2864DE00 } // 58 kB
// { 0x2864F1FC, 0x28656EE0 } // 31 kB
// { 0x2865AF44, 0x286635A0 } // 33 kB
// { 0x2866F774, 0x2867C680 } // 51 kB
// { 0x2867FAC0, 0x286A2CA0 } // 140 kB
// { 0x286B3540, 0x286C1900 } // 56 kB
// { 0x286C64A4, 0x286DDB80 } // 93 kB
// { 0x286E640C, 0x286F1DC0 } // 46 kB
// { 0x286F3884, 0x2870D3C0 } // 102 kB
// { 0x28710824, 0x28719D80 } // 37 kB
// { 0x2872A674, 0x2873B180 } // 66 kB
// { 0x287402F0, 0x28758780 } // 97 kB
// { 0x287652F0, 0x28771C00 } // 50 kB
// { 0x287F878C, 0x2880A680 } // 71 kB
// { 0x2880F4AC, 0x2881E6E0 } // 60 kB
// { 0x28821488, 0x28829A40 } // 33 kB
// { 0x2882A5D0, 0x288385BC } // 55 kB
// { 0x288385D8, 0x28854780 } // 112 kB
// { 0x28857984, 0x28864F80 } // 53 kB
// { 0x28870AC0, 0x2887CAC0 } // 48 kB
// { 0x2887CAC8, 0x28888CC8 } // 48 kB
// { 0x28888CD0, 0x28894ED0 } // 48 kB
// { 0x28894ED8, 0x288BE0DC } // 164 kB
// { 0x288C1C70, 0x28AD9ED4 } // 2144 kB (2 MB)
// { 0x28AD9F04, 0x28B66100 } // 560 kB
// { 0x28B748A8, 0x28B952E0 } // 130 kB
// { 0x28B9AB58, 0x28BA2480 } // 30 kB
// { 0x28BA3D00, 0x28BC21C0 } // 121 kB
// { 0x28BC2F08, 0x28BD9860 } // 90 kB
// { 0x28BED09C, 0x28BFDD00 } // 67 kB
// { 0x28C068F0, 0x28C2E220 } // 158 kB
// { 0x28CC4C6C, 0x28CF6834 } // 198 kB
// { 0x28D3DD64, 0x28D4BF8C } // 56 kB
// { 0x28D83C4C, 0x28DD0284 } // 305 kB
// { 0x28DDDED4, 0x28E84294 } // 664 kB
// { 0x28E99C7C, 0x28F382A4 } // 633 kB
// { 0x28F45EF4, 0x28FEC2B4 } // 664 kB
// { 0x28FEC800, 0x293B2A18 } // 3864 kB (3 MB)
// { 0x293E187C, 0x293EC7FC } // 43 kB
// { 0x295C7240, 0x295D523C } // 56 kB
// { 0x295DA8DC, 0x295E323C } // 34 kB
// { 0x295ED6C0, 0x295F6FDC } // 38 kB
// { 0x29606340, 0x2960FC5C } // 38 kB
// { 0x2964F040, 0x29657C3C } // 35 kB
// { 0x296E0EBC, 0x296EBDBC } // 43 kB
// { 0x2998DFB4, 0x2999DEE4 } // 63 kB
// { 0x2999E6A8, 0x299BE9C4 } // 128 kB
// { 0x29B8DF40, 0x29BA09DC } // 74 kB
// { 0x29BC200C, 0x29D79B94 } // 1758 kB (1 MB)
// { 0x29DA9694, 0x29DB1694 } // 32 kB
// { 0x2A3D7558, 0x2A427558 } // 320 kB
// { 0x2A42769C, 0x2A47769C } // 320 kB
// { 0x2A4777E0, 0x2A4C77E0 } // 320 kB
// { 0x2A4C7924, 0x2A517924 } // 320 kB
// { 0x2A517A68, 0x2A6794B8 } // 1414 kB (1 MB)
// { 0x2AD17528, 0x2AD4EA24 } // 221 kB
// { 0x2B038C4C, 0x2B1794C8 } // 1282 kB (1 MB)
// { 0x2BBA990C, 0x2BBB983C } // 63 kB
// { 0x2BBBA160, 0x2BC82164 } // 800 kB
// { 0x2BD0000C, 0x2BD71638 } // 453 kB
// { 0x2BD7170C, 0x2BD83B0C } // 73 kB
// { 0x2BDBA000, 0x2BDCA028 } // 64 kB
// { 0x2BDCE000, 0x2BDDE028 } // 64 kB
// { 0x2BDE2E34, 0x2BDF2D64 } // 63 kB
// { 0x2BDF35E8, 0x2BE031BC } // 62 kB
// { 0x2BE052A4, 0x2BE151D4 } // 63 kB
// { 0x2BE174AC, 0x2BE27244 } // 63 kB
// { 0x2BE3AC80, 0x2BE48C80 } // 56 kB
// { 0x2BE49EDC, 0x2BE56C7C } // 51 kB
// { 0x2BE82F70, 0x2BE92E9C } // 63 kB
// { 0x2BE9ADBC, 0x2BEA8DBC } // 56 kB
// { 0x2BEAAB7C, 0x2BEB6DBC } // 48 kB
// { 0x2BEC0F3C, 0x2BECEF3C } // 56 kB
// { 0x2BED45DC, 0x2BEDCF3C } // 34 kB
// { 0x2BEE73C0, 0x2BEF0CDC } // 38 kB
// { 0x2BF00040, 0x2BF0995C } // 38 kB
// { 0x2BF48D40, 0x2BF5193C } // 35 kB
// { 0x2BFDABBC, 0x2BFE5ABC } // 43 kB
// { 0x2C03DA40, 0x2C045D7C } // 32 kB
// { 0x2C179450, 0x2C18937C } // 63 kB
// { 0x2C1DC940, 0x2C1EA93C } // 56 kB
// { 0x2C1EABDC, 0x2C1F893C } // 55 kB
// { 0x2C239A80, 0x2C243D3C } // 40 kB
// { 0x2CE10224, 0x2CE3683C } // 153 kB
// { 0x2CE374F4, 0x2CE473A4 } // 63 kB
// { 0x2CE49830, 0x2D3794D8 } // 5311 kB (5 MB)
// { 0x2D3795AC, 0x2D854300 } // 4971 kB (4 MB)
// { 0x2D8546B0, 0x2D8602C4 } // 47 kB
// { 0x2D86D318, 0x2DFFFFFC } // 7755 kB (7 MB)
// { 0x2E2DCD60, 0x2E2E4D7C } // 32 kB
// { 0x2E33F160, 0x2E365AFC } // 154 kB
// { 0x2E37AC40, 0x2E39BB3C } // 131 kB
// { 0x2E3A6EF0, 0x2E3CA2FC } // 141 kB
// { 0x2E3D9EE0, 0x2E400B3C } // 155 kB
// { 0x2E43A8F0, 0x2E442BBC } // 32 kB
// { 0x2E46EC90, 0x2E48E27C } // 125 kB
// { 0x2E497F90, 0x2E4A147C } // 37 kB
// { 0x2E4A5B40, 0x2E4C67BC } // 131 kB
// { 0x2E4FBEF0, 0x2E52697C } // 170 kB
// { 0x2E550750, 0x2E57333C } // 138 kB
// { 0x2E573F3C, 0x2FF8F07C } // 226732 kB (26 MB)
// { 0x31000000, 0x31E1FFFC } // 614464 kB (14 MB)
// { 0x320A5D80, 0x320AEA3C } // 35 kB
// { 0x320E8670, 0x3210017C } // 94 kB
// { 0x3212609C, 0x3213187C } // 45 kB
// { 0x3219DF08, 0x321B72BC } // 100 kB
// { 0x3300ED34, 0x3301AD3C } // 48 kB
// { 0x33041760, 0x33049D0C } // 33 kB
// { 0x330608F8, 0x3306C97C } // 48 kB
// { 0x33089D80, 0x33095284 } // 45 kB
// { 0x33095470, 0x330A1324 } // 47 kB
// { 0x330A1358, 0x330ADC10 } // 50 kB
// { 0x330C9040, 0x330D0ABC } // 30 kB
// { 0x330D0AD8, 0x3311F9CC } // 315 kB
// { 0x3312575C, 0x3320A63C } // 915 kB
// { 0x33234D00, 0x3324B33C } // 89 kB
// { 0x3324E300, 0x3328D7BC } // 253 kB
// { 0x3329D134, 0x332CA324 } // 180 kB
// { 0x3332B200, 0x33340C88 } // 86 kB
// { 0x3335A440, 0x335021FC } // 1695 kB (1 MB)
// { 0x3350A778, 0x3391680C } // 4144 kB (4 MB)
// { 0x3391A444, 0x3392A25C } // 63 kB
// { 0x3392A444, 0x33939EB4 } // 62 kB
// { 0x3393A444, 0x3394A25C } // 63 kB
// { 0x339587C0, 0x33976C80 } // 121 kB
// { 0x339779C8, 0x3398E320 } // 90 kB
// { 0x3399AE74, 0x339A7D80 } // 51 kB
// { 0x339AB1C0, 0x339CE3A0 } // 140 kB
// { 0x339CEB28, 0x339DEC38 } // 64 kB
// { 0x339DEC40, 0x339ED000 } // 56 kB
// { 0x339F1BA4, 0x33A09280 } // 93 kB
// { 0x33A0C6E4, 0x33A15C40 } // 37 kB
// { 0x33A15D64, 0x33EBFFFC } // 4776 kB (4 MB)
// { 0x33F01380, 0x33F21FFC } // 131 kB
// { 0x33F44820, 0x33F6B1BC } // 154 kB
// { 0x33F80300, 0x33FA11FC } // 131 kB
// { 0x33FA4D3C, 0x33FEDAFC } // 291 kB
// { 0x33FFFFD4, 0x38FFFFFC } // 81920 kB (80 MB)
{0, 0}
};
static const memory_values_t mem_vals_500[] =
{
{ 0x2E605CBC, 0x2FF849BC }, // size 26733828 (26107 kB) (25 MB)
{ 0x2CAE7878, 0x2D207DB4 }, // size 7472448 (7297 kB) (7 MB)
{ 0x2D3B966C, 0x2D8943C0 }, // size 5090648 (4971 kB) (4 MB)
{ 0x2D8AD3D8, 0x2DFFFFFC }, // size 7679016 (7499 kB) (7 MB)
// TODO: Check which of those areas are usable
// { 0x283A73DC, 0x284D2AE4 } // size 1226508 (1197 kB) (1 MB)
// { 0x29030800, 0x293F69FC } // size 3957248 (3864 kB) (3 MB)
// { 0x2970200C, 0x298B9C54 } // size 1801292 (1759 kB) (1 MB)
// { 0x2A057B68, 0x2A1B9578 } // size 1448468 (1414 kB) (1 MB)
// { 0x29030800, 0x293F69FC } // size 3957248 (3864 kB) (3 MB)
// { 0x2970200C, 0x298B9C54 } // size 1801292 (1759 kB) (1 MB)
// { 0x2A057B68, 0x2A1B9578 } // size 1448468 (1414 kB) (1 MB)
// { 0x288EEC30, 0x28B06E94 } // size 2196072 (2144 kB) (2 MB)
// { 0x283A73DC, 0x284D2AE4 } // size 1226508 (1197 kB) (1 MB)
// { 0x3335A4C0, 0x335021FC } // size 1736000 (1695 kB) (1 MB)
// { 0x3350C1D4, 0x339182CC } // size 4243708 (4144 kB) (4 MB)
// { 0x33A14094, 0x33EBFFFC } // size 4898668 (4783 kB) (4 MB)
// { 0x33FFFFD4, 0x38FFFFFC } // size 83886124 (81920 kB) (80 MB)
{0, 0}
};
static const memory_values_t mem_vals_532[] =
{
// TODO: Check which of those areas are usable
// {0x28000000 + 0x000DCC9C, 0x28000000 + 0x00174F80}, // 608 kB
// {0x28000000 + 0x00180B60, 0x28000000 + 0x001C0A00}, // 255 kB
// {0x28000000 + 0x001ECE9C, 0x28000000 + 0x00208CC0}, // 111 kB
// {0x28000000 + 0x00234180, 0x28000000 + 0x0024B444}, // 92 kB
// {0x28000000 + 0x0024D8C0, 0x28000000 + 0x0028D884}, // 255 kB
// {0x28000000 + 0x003A745C, 0x28000000 + 0x004D2B68}, // 1197 kB
// {0x28000000 + 0x004D77B0, 0x28000000 + 0x00502200}, // 170 kB
// {0x28000000 + 0x005B3A88, 0x28000000 + 0x005C6870}, // 75 kB
// {0x28000000 + 0x0061F3E4, 0x28000000 + 0x00632B04}, // 77 kB
// {0x28000000 + 0x00639790, 0x28000000 + 0x00649BC4}, // 65 kB
// {0x28000000 + 0x00691490, 0x28000000 + 0x006B3CA4}, // 138 kB
// {0x28000000 + 0x006D7BCC, 0x28000000 + 0x006EEB84}, // 91 kB
// {0x28000000 + 0x00704E44, 0x28000000 + 0x0071E3C4}, // 101 kB
// {0x28000000 + 0x0073B684, 0x28000000 + 0x0074C184}, // 66 kB
// {0x28000000 + 0x00751354, 0x28000000 + 0x00769784}, // 97 kB
// {0x28000000 + 0x008627DC, 0x28000000 + 0x00872904}, // 64 kB
// {0x28000000 + 0x008C1E98, 0x28000000 + 0x008EB0A0}, // 164 kB
// {0x28000000 + 0x008EEC30, 0x28000000 + 0x00B06E98}, // 2144 kB
// {0x28000000 + 0x00B06EC4, 0x28000000 + 0x00B930C4}, // 560 kB
// {0x28000000 + 0x00BA1868, 0x28000000 + 0x00BC22A4}, // 130 kB
// {0x28000000 + 0x00BC48F8, 0x28000000 + 0x00BDEC84}, // 104 kB
// {0x28000000 + 0x00BE3DC0, 0x28000000 + 0x00C02284}, // 121 kB
// {0x28000000 + 0x00C02FC8, 0x28000000 + 0x00C19924}, // 90 kB
// {0x28000000 + 0x00C2D35C, 0x28000000 + 0x00C3DDC4}, // 66 kB
// {0x28000000 + 0x00C48654, 0x28000000 + 0x00C6E2E4}, // 151 kB
// {0x28000000 + 0x00D04E04, 0x28000000 + 0x00D36938}, // 198 kB
// {0x28000000 + 0x00DC88AC, 0x28000000 + 0x00E14288}, // 302 kB
// {0x28000000 + 0x00E21ED4, 0x28000000 + 0x00EC8298}, // 664 kB
// {0x28000000 + 0x00EDDC7C, 0x28000000 + 0x00F7C2A8}, // 633 kB
// {0x28000000 + 0x00F89EF4, 0x28000000 + 0x010302B8}, // 664 kB
// {0x28000000 + 0x01030800, 0x28000000 + 0x013F69A0}, // 3864 kB
// {0x28000000 + 0x016CE000, 0x28000000 + 0x016E0AA0}, // 74 kB
// {0x28000000 + 0x0170200C, 0x28000000 + 0x018B9C58}, // 1759 kB
// {0x28000000 + 0x01F17658, 0x28000000 + 0x01F6765C}, // 320 kB
// {0x28000000 + 0x01F6779C, 0x28000000 + 0x01FB77A0}, // 320 kB
// {0x28000000 + 0x01FB78E0, 0x28000000 + 0x020078E4}, // 320 kB
// {0x28000000 + 0x02007A24, 0x28000000 + 0x02057A28}, // 320 kB
// {0x28000000 + 0x02057B68, 0x28000000 + 0x021B957C}, // 1414 kB
// {0x28000000 + 0x02891528, 0x28000000 + 0x028C8A28}, // 221 kB
// {0x28000000 + 0x02BBCC4C, 0x28000000 + 0x02CB958C}, // 1010 kB
// {0x28000000 + 0x0378D45C, 0x28000000 + 0x03855464}, // 800 kB
// {0x28000000 + 0x0387800C, 0x28000000 + 0x03944938}, // 818 kB
// {0x28000000 + 0x03944A08, 0x28000000 + 0x03956E0C}, // 73 kB
// {0x28000000 + 0x04A944A4, 0x28000000 + 0x04ABAAC0}, // 153 kB
// {0x28000000 + 0x04ADE370, 0x28000000 + 0x0520EAB8}, // 7361 kB // ok
// {0x28000000 + 0x053B966C, 0x28000000 + 0x058943C4}, // 4971 kB // ok
// {0x28000000 + 0x058AD3D8, 0x28000000 + 0x06000000}, // 7499 kB
// {0x28000000 + 0x0638D320, 0x28000000 + 0x063B0280}, // 139 kB
// {0x28000000 + 0x063C39E0, 0x28000000 + 0x063E62C0}, // 138 kB
// {0x28000000 + 0x063F52A0, 0x28000000 + 0x06414A80}, // 125 kB
// {0x28000000 + 0x06422810, 0x28000000 + 0x0644B2C0}, // 162 kB
// {0x28000000 + 0x064E48D0, 0x28000000 + 0x06503EC0}, // 125 kB
// {0x28000000 + 0x0650E360, 0x28000000 + 0x06537080}, // 163 kB
// {0x28000000 + 0x0653A460, 0x28000000 + 0x0655C300}, // 135 kB
// {0x28000000 + 0x0658AA40, 0x28000000 + 0x065BC4C0}, // 198 kB // ok
// {0x28000000 + 0x065E51A0, 0x28000000 + 0x06608E80}, // 143 kB // ok
// {0x28000000 + 0x06609ABC, 0x28000000 + 0x07F82C00}, // 26084 kB // ok
// {0x30000000 + 0x000DCC9C, 0x30000000 + 0x00180A00}, // 655 kB
// {0x30000000 + 0x00180B60, 0x30000000 + 0x001C0A00}, // 255 kB
// {0x30000000 + 0x001F5EF0, 0x30000000 + 0x00208CC0}, // 75 kB
// {0x30000000 + 0x00234180, 0x30000000 + 0x0024B444}, // 92 kB
// {0x30000000 + 0x0024D8C0, 0x30000000 + 0x0028D884}, // 255 kB
// {0x30000000 + 0x003A745C, 0x30000000 + 0x004D2B68}, // 1197 kB
// {0x30000000 + 0x006D3334, 0x30000000 + 0x00772204}, // 635 kB
// {0x30000000 + 0x00789C60, 0x30000000 + 0x007C6000}, // 240 kB
// {0x30000000 + 0x00800000, 0x30000000 + 0x01E20000}, // 22876 kB // ok
{ 0x2E609ABC, 0x2FF82C00 }, // 26084 kB
{ 0x29030800, 0x293F69A0 }, // 3864 kB
{ 0x288EEC30, 0x28B06E98 }, // 2144 kB
{ 0x2D3B966C, 0x2D8943C4 }, // 4971 kB
{ 0x2CAE0370, 0x2D20EAB8 }, // 7361 kB
{ 0x2D8AD3D8, 0x2E000000 }, // 7499 kB
{0, 0}
}; // total : 66mB + 25mB
static const memory_values_t mem_vals_540[] =
{
{ 0x2E609EFC, 0x2FF82000 }, // 26083 kB
{ 0x29030800, 0x293F6000 }, // 3864 kB
{ 0x288EEC30, 0x28B06800 }, // 2144 kB
{ 0x2D3B966C, 0x2D894000 }, // 4971 kB
{ 0x2CB56370, 0x2D1EF000 }, // 6756 kB
{ 0x2D8AD3D8, 0x2E000000 }, // 7499 kB
{ 0x2970200C, 0x298B9800 }, // 1759 kB
{ 0x2A057B68, 0x2A1B9000 }, // 1414 kB
{ 0x2ABBCC4C, 0x2ACB9000 }, // 1010 kB
{0, 0}
};
s_mem_area * memoryGetAreaTable(void)
{
return MEM_AREA_TABLE;
}
static inline void memoryAddArea(int start, int end, int cur_index)
{
// Create and copy new memory area
s_mem_area * mem_area = memoryGetAreaTable();
mem_area[cur_index].address = start;
mem_area[cur_index].size = end - start;
mem_area[cur_index].next = 0;
// Fill pointer to this area in the previous area
if (cur_index > 0)
{
mem_area[cur_index - 1].next = &mem_area[cur_index];
}
}
/* Create memory areas arrays */
void memoryInitAreaTable()
{
u32 ApplicationMemoryEnd = getApplicationEndAddr();
if(ApplicationMemoryEnd >= 0x01000000)
ApplicationMemoryEnd = 0x00800000;
// This one seems to be available on every firmware and therefore its our code area but also our main RPX area behind our code
// 22876 kB - our application // ok
if(OS_FIRMWARE <= 400) {
memoryAddArea(ApplicationMemoryEnd + 0x4B000000, 0x4B000000 + 0x01E20000, 0);
}
else {
memoryAddArea(ApplicationMemoryEnd + 0x30000000, 0x30000000 + 0x01E20000, 0);
}
const memory_values_t * mem_vals = NULL;
switch(OS_FIRMWARE)
{
case 400: {
mem_vals = mem_vals_400;
break;
}
case 500: {
mem_vals = mem_vals_500;
break;
}
case 532: {
mem_vals = mem_vals_532;
break;
}
case 540:
case 550: {
mem_vals = mem_vals_540;
break;
}
default:
return; // no known values
}
// Fill entries
int i = 0;
while (mem_vals[i].start_address)
{
memoryAddArea(mem_vals[i].start_address, mem_vals[i].end_address, i + 1);
i++;
}
}

View File

@ -0,0 +1,34 @@
/****************************************************************************
* Copyright (C) 2015 Dimok
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef _MEMORY_AREA_TABLE_H_
#define _MEMORY_AREA_TABLE_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "common/common.h"
void memoryInitAreaTable();
s_mem_area * memoryGetAreaTable(void);
#ifdef __cplusplus
}
#endif
#endif // _MEMORY_AREA_TABLE_H_

View File

@ -3,3 +3,9 @@ getApplicationEndAddr:
lis r3, __CODE_END@h
ori r3, r3, __CODE_END@l
blr
.globl SC0x25_KernelCopyData
SC0x25_KernelCopyData:
li r0, 0x2500
sc
blr

View File

@ -41,6 +41,7 @@ extern "C" {
#define le64(i) ((((u64)le32((i) & 0xFFFFFFFFLL)) << 32) | ((u64)le32(((i) & 0xFFFFFFFF00000000LL) >> 32)))
unsigned int getApplicationEndAddr(void);
void SC0x25_KernelCopyData(unsigned int addr, unsigned int src, unsigned int len);
#ifdef __cplusplus
}