mirror of
https://github.com/wiiu-env/haxchi.git
synced 2024-11-16 13:19:16 +01:00
-fixed screen corruption when loading homebrew launcher by properly clearing the screen
-modified IOSU exploit to load from high MEM1 to not run into existing memory and crash -updated homebrew launcher loader to follow dimoks latest commit and be ready for 1.4 .rpx loading
This commit is contained in:
parent
2562624f20
commit
791b2944a7
22
Makefile
22
Makefile
@ -1,5 +1,11 @@
|
||||
.PHONY := all code550.bin
|
||||
|
||||
ifeq ($(Windows_NT), 1)
|
||||
ZIP = zip/zip.exe
|
||||
else
|
||||
ZIP = zip
|
||||
endif
|
||||
|
||||
all: brainage kirby yoshids brainage.zip kirby.zip yoshids.zip brainage_cfw.zip kirby_cfw.zip yoshids_cfw.zip
|
||||
|
||||
brainage: setup_brainage brainage.nds setup_brainage_cfw brainage_cfw.nds
|
||||
@ -71,24 +77,24 @@ yoshids_cfw.nds:
|
||||
cp yoshids_cfw.nds wwtouched_cfw.nds
|
||||
|
||||
brainage.zip:
|
||||
zip -JXjq9 brainage.zip brainage.nds
|
||||
$(ZIP) -JXjq9 brainage.zip brainage.nds
|
||||
|
||||
kirby.zip:
|
||||
zip -JXjq9 kirby.zip kirby.nds
|
||||
$(ZIP) -JXjq9 kirby.zip kirby.nds
|
||||
|
||||
yoshids.zip:
|
||||
zip -JXjq9 yoshids.zip yoshids.nds
|
||||
zip -JXjq9 wwtouched.zip wwtouched.nds
|
||||
$(ZIP) -JXjq9 yoshids.zip yoshids.nds
|
||||
$(ZIP) -JXjq9 wwtouched.zip wwtouched.nds
|
||||
|
||||
brainage_cfw.zip:
|
||||
zip -JXjq9 brainage_cfw.zip brainage_cfw.nds
|
||||
$(ZIP) -JXjq9 brainage_cfw.zip brainage_cfw.nds
|
||||
|
||||
kirby_cfw.zip:
|
||||
zip -JXjq9 kirby_cfw.zip kirby_cfw.nds
|
||||
$(ZIP) -JXjq9 kirby_cfw.zip kirby_cfw.nds
|
||||
|
||||
yoshids_cfw.zip:
|
||||
zip -JXjq9 yoshids_cfw.zip yoshids_cfw.nds
|
||||
zip -JXjq9 wwtouched_cfw.zip wwtouched_cfw.nds
|
||||
$(ZIP) -JXjq9 yoshids_cfw.zip yoshids_cfw.nds
|
||||
$(ZIP) -JXjq9 wwtouched_cfw.zip wwtouched_cfw.nds
|
||||
|
||||
clean:
|
||||
@rm -f *.bin defines.s brainage.nds brainage.zip kirby.nds kirby.zip wwtouched.nds wwtouched.zip yoshids.nds yoshids.zip
|
||||
|
@ -2,7 +2,7 @@ PATH := $(DEVKITPPC)/bin:$(PATH)
|
||||
PREFIX ?= powerpc-eabi-
|
||||
CC = $(PREFIX)gcc
|
||||
AS = $(PREFIX)gcc
|
||||
CFLAGS = -std=gnu99 -O0 -nostdinc -fno-builtin -g
|
||||
CFLAGS = -std=gnu99 -O3 -nostdinc -fno-builtin
|
||||
ASFLAGS = -mregnames -x assembler-with-cpp
|
||||
LD = $(PREFIX)ld
|
||||
OBJCOPY = $(PREFIX)objcopy
|
||||
@ -37,7 +37,7 @@ main: $(CURDIR)/payload/arm_kernel_bin.h
|
||||
cp -r $(root)/*.o $(build)
|
||||
rm $(root)/*.o
|
||||
$(LD) -o code$(FIRMWARE).elf $(build)/crt0.o `find $(build) -name "*.o" ! -name "crt0.o"` $(LDFLAGS) -Map code.map
|
||||
$(OBJCOPY) code$(FIRMWARE).elf -O binary ../code$(FIRMWARE).bin
|
||||
$(OBJCOPY) code$(FIRMWARE).elf -S -O binary ../code$(FIRMWARE).bin
|
||||
|
||||
clean:
|
||||
rm -rf $(build) payload
|
||||
|
@ -70,7 +70,7 @@ int _main()
|
||||
unsigned int control_register = disable_mmu();
|
||||
|
||||
/* Save the request handle so we can reply later */
|
||||
*(volatile u32*)0x0012F000 = *(volatile u32*)0x1016AD18;
|
||||
*(volatile u32*)0x01E10000 = *(volatile u32*)0x1016AD18;
|
||||
|
||||
/* Patch kernel_error_handler to BX LR immediately */
|
||||
*(int*)0x08129A24 = 0xE12FFF1E;
|
||||
@ -84,7 +84,7 @@ int _main()
|
||||
void * pusb_root_thread = (void*)0x10100174;
|
||||
kernel_memcpy(pusb_root_thread, (void*)repairData_usb_root_thread, sizeof(repairData_usb_root_thread));
|
||||
|
||||
void * pUserBinSource = (void*)0x00148000;
|
||||
void * pUserBinSource = (void*)0x01E50000;
|
||||
void * pUserBinDest = (void*)0x101312D0;
|
||||
kernel_memcpy(pUserBinDest, (void*)pUserBinSource, sizeof(arm_user_bin));
|
||||
|
||||
|
@ -9,7 +9,7 @@ void _main()
|
||||
|
||||
int(*reply)(int, int) = (int(*)(int, int))0x1012ED04;
|
||||
|
||||
int saved_handle = *(volatile u32*)0x0012F000;
|
||||
int saved_handle = *(volatile u32*)0x01E10000;
|
||||
int myret = reply(saved_handle, 0);
|
||||
if (myret != 0)
|
||||
ios_shutdown(1);
|
||||
|
@ -4,7 +4,7 @@
|
||||
#define CHAIN_START 0x1016AD40
|
||||
#define SHUTDOWN 0x1012EE4C
|
||||
#define SIMPLE_RETURN 0x101014E4
|
||||
#define SOURCE (0x120000)
|
||||
#define SOURCE 0x01E20000
|
||||
#define IOS_CREATETHREAD 0x1012EABC
|
||||
#define ARM_CODE_BASE 0x08134100
|
||||
#define REPLACE_SYSCALL 0x081298BC
|
||||
@ -217,7 +217,7 @@ static const int final_chain[] = {
|
||||
sizeof(arm_kernel_bin), // 0x1FC our code size
|
||||
0x0, // 0x200
|
||||
0x10123983, // 0x204 POP {R1,R3,R4,R6,PC}
|
||||
0x00140000, // 0x208 our code source location
|
||||
0x01E40000, // 0x208 our code source location
|
||||
0x08131D04, // 0x20C KERNEL_MEMCPY address
|
||||
0x0, // 0x210
|
||||
0x0, // 0x214
|
||||
@ -233,7 +233,7 @@ static const int second_chain[] = {
|
||||
0x0, // 0x08
|
||||
0x0, // 0x0C
|
||||
0x101063db, // 0x10 POP {R1,R2,R5,PC}
|
||||
0x00130000, // 0x14 source
|
||||
0x01E30000, // 0x14 source
|
||||
sizeof(final_chain), // 0x18 length
|
||||
0x0, // 0x1C
|
||||
0x10106D4C, // 0x20 BL MEMCPY; MOV R0, #0; LDMFD SP!, {R4,R5,PC}
|
||||
@ -283,22 +283,8 @@ static const int second_chain[] = {
|
||||
static void uhs_exploit_init(unsigned int coreinit_handle);
|
||||
static int uhs_write32(unsigned int coreinit_handle, int dev_uhs_0_handle, int arm_addr, int val);
|
||||
|
||||
void __main(void) {
|
||||
|
||||
unsigned int sound_handle = 0;
|
||||
OSDynLoad_Acquire("sndcore2.rpl", &sound_handle);
|
||||
if(sound_handle == 0)
|
||||
{
|
||||
/* Quit ongoing menu load music */
|
||||
OSDynLoad_Acquire("snd_core.rpl", &sound_handle);
|
||||
void (* AXInit)();
|
||||
void (* AXQuit)();
|
||||
OSDynLoad_FindExport(sound_handle, 0, "AXInit", &AXInit);
|
||||
OSDynLoad_FindExport(sound_handle, 0, "AXQuit", &AXQuit);
|
||||
AXInit();
|
||||
AXQuit();
|
||||
}
|
||||
|
||||
void __main(void)
|
||||
{
|
||||
unsigned int coreinit_handle;
|
||||
OSDynLoad_Acquire("coreinit.rpl", &coreinit_handle);
|
||||
unsigned int sysapp_handle;
|
||||
@ -337,58 +323,65 @@ void __main(void) {
|
||||
OSExitThread(0);
|
||||
}
|
||||
|
||||
static void uhs_exploit_init(unsigned int coreinit_handle) {
|
||||
void (*DCFlushRange)(const void *addr, uint32_t length);
|
||||
void (*DCInvalidateRange)(const void *addr, uint32_t length);
|
||||
static void uhs_exploit_init(unsigned int coreinit_handle)
|
||||
{
|
||||
void (*DCStoreRange)(const void *addr, uint32_t length);
|
||||
void (*memcpy)(void *dst, const void *src, uint32_t length);
|
||||
OSDynLoad_FindExport(coreinit_handle, 0, "DCFlushRange", &DCFlushRange);
|
||||
OSDynLoad_FindExport(coreinit_handle, 0, "DCInvalidateRange", &DCInvalidateRange);
|
||||
void (*memset)(void *dst, const char val, uint32_t length);
|
||||
OSDynLoad_FindExport(coreinit_handle, 0, "DCStoreRange", &DCStoreRange);
|
||||
OSDynLoad_FindExport(coreinit_handle, 0, "memcpy", &memcpy);
|
||||
OSDynLoad_FindExport(coreinit_handle, 0, "memset", &memset);
|
||||
|
||||
//! Clear out our used MEM1 area
|
||||
memset((void*)0xF5E00000, 0, 0x00070000);
|
||||
DCStoreRange((void*)0xF5E00000, 0x00070000);
|
||||
|
||||
//!------Variables used in exploit------
|
||||
int *pretend_root_hub = (int*)0xF5003ABC;
|
||||
int *ayylmao = (int*)0xF4F00000;
|
||||
int *pretend_root_hub = (int*)0xF5E60640;
|
||||
int *ayylmao = (int*)0xF5E00000;
|
||||
//!-------------------------------------
|
||||
|
||||
ayylmao[5] = 1;
|
||||
ayylmao[8] = 0xF00000;
|
||||
ayylmao[8] = 0x1E00000;
|
||||
|
||||
memcpy((char*)(0xF4120000), second_chain, sizeof(second_chain));
|
||||
memcpy((char*)(0xF4130000), final_chain, sizeof(final_chain));
|
||||
memcpy((char*)(0xF4140000), arm_kernel_bin, sizeof(arm_kernel_bin));
|
||||
memcpy((char*)(0xF4148000), arm_user_bin, sizeof(arm_user_bin));
|
||||
memcpy((char*)(0xF5E20000), second_chain, sizeof(second_chain));
|
||||
memcpy((char*)(0xF5E30000), final_chain, sizeof(final_chain));
|
||||
memcpy((char*)(0xF5E40000), arm_kernel_bin, sizeof(arm_kernel_bin));
|
||||
memcpy((char*)(0xF5E50000), arm_user_bin, sizeof(arm_user_bin));
|
||||
|
||||
pretend_root_hub[33] = 0xF00000;
|
||||
pretend_root_hub[33] = 0x1E00000;
|
||||
pretend_root_hub[78] = 0;
|
||||
|
||||
DCFlushRange(pretend_root_hub + 33, 200); //! |Make CPU fetch new data (with updated vals)
|
||||
DCInvalidateRange(pretend_root_hub + 33, 200); //! |for "pretend_root_hub"
|
||||
//! Store current CPU cache into main memory for IOSU to read
|
||||
DCStoreRange(ayylmao, 0x840);
|
||||
|
||||
DCFlushRange((void*)0xF4120000, sizeof(second_chain)); //! |Make CPU fetch new data (with updated vals)
|
||||
DCFlushRange((void*)0xF4130000, sizeof(final_chain)); //! |Make CPU fetch new data (with updated vals)
|
||||
DCFlushRange((void*)0xF4140000, sizeof(arm_kernel_bin)); //! |Make CPU fetch new data (with updated vals)
|
||||
DCFlushRange((void*)0xF4148000, sizeof(arm_user_bin)); //! |Make CPU fetch new data (with updated vals)
|
||||
DCStoreRange((void*)0xF5E20000, sizeof(second_chain));
|
||||
DCStoreRange((void*)0xF5E30000, sizeof(final_chain));
|
||||
DCStoreRange((void*)0xF5E40000, sizeof(arm_kernel_bin));
|
||||
DCStoreRange((void*)0xF5E50000, sizeof(arm_user_bin));
|
||||
|
||||
DCStoreRange(pretend_root_hub, 0x160);
|
||||
}
|
||||
|
||||
static int uhs_write32(unsigned int coreinit_handle, int dev_uhs_0_handle, int arm_addr, int val) {
|
||||
void (*DCFlushRange)(const void *addr, uint32_t length);
|
||||
void (*DCInvalidateRange)(const void *addr, uint32_t length);
|
||||
static int uhs_write32(unsigned int coreinit_handle, int dev_uhs_0_handle, int arm_addr, int val)
|
||||
{
|
||||
void (*DCStoreRange)(const void *addr, uint32_t length);
|
||||
void (*OSSleepTicks)(uint64_t ticks);
|
||||
int (*IOS_Ioctl)(int fd, uint32_t request, void *input_buffer,uint32_t input_buffer_len, void *output_buffer, uint32_t output_buffer_len);
|
||||
OSDynLoad_FindExport(coreinit_handle, 0, "DCFlushRange", &DCFlushRange);
|
||||
OSDynLoad_FindExport(coreinit_handle, 0, "DCInvalidateRange", &DCInvalidateRange);
|
||||
OSDynLoad_FindExport(coreinit_handle, 0, "DCStoreRange", &DCStoreRange);
|
||||
OSDynLoad_FindExport(coreinit_handle, 0, "OSSleepTicks", &OSSleepTicks);
|
||||
OSDynLoad_FindExport(coreinit_handle, 0, "IOS_Ioctl", &IOS_Ioctl);
|
||||
|
||||
//!------Variables used in exploit------
|
||||
int *ayylmao = (int*)0xF4F00000;
|
||||
int *ayylmao = (int*)0xF5E00000;
|
||||
//!-------------------------------------
|
||||
|
||||
ayylmao[520] = arm_addr - 24; //! The address to be overwritten, minus 24 bytes
|
||||
DCFlushRange(ayylmao, 521 * 4); //! |Make CPU fetch new data (with updated adress)
|
||||
DCInvalidateRange(ayylmao, 521 * 4); //! |for "ayylmao"
|
||||
OSSleepTicks(0x200000); //! Improves stability
|
||||
int request_buffer[] = { -(0xBEA2C), val }; //! -(0xBEA2C) gets IOS_USB to read from the middle of MEM1
|
||||
ayylmao[520] = arm_addr - 24; //! The address to be overwritten, minus 24 bytes
|
||||
DCStoreRange(ayylmao, 0x840); //! Store current CPU cache into main memory for IOSU to read
|
||||
OSSleepTicks(0x200000); //! Wait for caches to refresh over in IOSU
|
||||
//! index 0 is at 0x10149A6C, each index is 0x144 bytes long, so 0x10149A6C - (0x144*0xB349B) = 0x1E60640,
|
||||
//! which is the physical address of 0xF5E60640 for us, right at the end of MEM1
|
||||
int request_buffer[] = { -(0xB349B), val };
|
||||
int output_buffer[32];
|
||||
return IOS_Ioctl(dev_uhs_0_handle, 0x15, request_buffer, sizeof(request_buffer), output_buffer, sizeof(output_buffer));
|
||||
}
|
||||
|
@ -118,8 +118,10 @@ rop_hook_start:
|
||||
.arm.big
|
||||
|
||||
rop_start:
|
||||
; quit out of GX2 so we can re-use it in core 0
|
||||
; do hachihachi cleanups so we can use everything safely
|
||||
call_func HACHI_APPLICATION_SHUTDOWNANDDESTROY, HACHI_APPLICATION_PTR, 0, 0, 0
|
||||
call_func NERD_FASTWIIU_SHUTDOWN, 0, 0, 0, 0
|
||||
call_func CORE_SHUTDOWN, 0, 0, 0, 0
|
||||
|
||||
; set up hbl_loader in core 0
|
||||
call_func_6args NERD_CREATETHREAD, NERD_THREAD0OBJECT, LWZ_R0xAFC_MTLR_R0_ADDI_R1xAF8_BLR, 0x1007E7A8, thread0_param, 0x0, 0x0
|
||||
@ -198,10 +200,6 @@ rop_start:
|
||||
call_func NERD_STARTTHREAD, NERD_THREAD0OBJECT, 0x0, 0x0, 0x0
|
||||
call_func NERD_JOINTHREAD, NERD_THREAD0OBJECT, 0x0, 0x0, 0x0
|
||||
|
||||
; clean up the rest of hachihachi
|
||||
call_func HACHI_APPLICATION_SHUTDOWNANDDESTROY, HACHI_APPLICATION_PTR, 0, 0, 0
|
||||
call_func CORE_SHUTDOWN, 0, 0, 0, 0
|
||||
|
||||
; prepare system for foreground release
|
||||
call_func OSSAVESDONE_READYTORELEASE, 0, 0, 0, 0
|
||||
|
||||
|
@ -2,7 +2,7 @@ PATH := $(DEVKITPPC)/bin:$(PATH)
|
||||
PREFIX ?= powerpc-eabi-
|
||||
CC = $(PREFIX)gcc
|
||||
AS = $(PREFIX)gcc
|
||||
CFLAGS = -std=gnu99 -O0 -nostdinc -fno-builtin -g
|
||||
CFLAGS = -std=gnu99 -O3 -nostdinc -fno-builtin
|
||||
ASFLAGS = -mregnames -x assembler-with-cpp
|
||||
LD = $(PREFIX)ld
|
||||
OBJCOPY = $(PREFIX)objcopy
|
||||
@ -37,7 +37,7 @@ main: sd_loader.h
|
||||
cp -r $(root)/*.o $(build)
|
||||
rm $(root)/*.o
|
||||
$(LD) -o code$(FIRMWARE).elf $(build)/crt0.o `find $(build) -name "*.o" ! -name "crt0.o"` $(LDFLAGS) -Map code.map
|
||||
$(OBJCOPY) code$(FIRMWARE).elf -O binary ../code$(FIRMWARE).bin
|
||||
$(OBJCOPY) code$(FIRMWARE).elf -S -O binary ../code$(FIRMWARE).bin
|
||||
|
||||
clean:
|
||||
rm -rf $(build)
|
||||
|
@ -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
|
||||
|
@ -18,22 +18,13 @@ void run_kexploit(private_data_t *private_data)
|
||||
|
||||
/* Exit functions */
|
||||
void (*__PPCExit)();
|
||||
void (*_Exit)(int);
|
||||
|
||||
OSDynLoad_FindExport(coreinit_handle, 0, "__PPCExit", &__PPCExit);
|
||||
OSDynLoad_FindExport(coreinit_handle, 0, "_Exit", &_Exit);
|
||||
|
||||
/* Memory functions */
|
||||
void (*DCFlushRange)(void *buffer, uint32_t length);
|
||||
void (*DCInvalidateRange)(void *buffer, uint32_t length);
|
||||
void (*DCTouchRange)(void *buffer, uint32_t length);
|
||||
uint32_t (*OSEffectiveToPhysical)(void *vaddr);
|
||||
void* (*OSAllocFromSystem)(uint32_t size, int align);
|
||||
void (*OSFreeToSystem)(void *ptr);
|
||||
OSDynLoad_FindExport(coreinit_handle, 0, "DCFlushRange", &DCFlushRange);
|
||||
OSDynLoad_FindExport(coreinit_handle, 0, "DCInvalidateRange", &DCInvalidateRange);
|
||||
OSDynLoad_FindExport(coreinit_handle, 0, "DCTouchRange", &DCTouchRange);
|
||||
OSDynLoad_FindExport(coreinit_handle, 0, "OSEffectiveToPhysical", &OSEffectiveToPhysical);
|
||||
OSDynLoad_FindExport(coreinit_handle, 0, "OSAllocFromSystem", &OSAllocFromSystem);
|
||||
OSDynLoad_FindExport(coreinit_handle, 0, "OSFreeToSystem", &OSFreeToSystem);
|
||||
|
||||
|
@ -23,9 +23,17 @@
|
||||
#define ROOTRPX_DBAT0L_VAL 0x30000012
|
||||
#define COREINIT_DBAT0L_VAL 0x32000012
|
||||
|
||||
#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
|
||||
|
||||
/* Install functions */
|
||||
static void InstallMain(private_data_t *private_data);
|
||||
static void InstallPatches(private_data_t *private_data);
|
||||
static void PrepareScreen(private_data_t *private_data);
|
||||
static void ExitFailure(private_data_t *private_data, const char *failure);
|
||||
|
||||
static void SetupKernelSyscall(unsigned int addr);
|
||||
@ -41,20 +49,6 @@ extern void KernelPatches(void);
|
||||
/* ****************************************************************** */
|
||||
void __main(void)
|
||||
{
|
||||
unsigned int sound_handle = 0;
|
||||
OSDynLoad_Acquire("sndcore2.rpl", &sound_handle);
|
||||
if(sound_handle == 0)
|
||||
{
|
||||
/* Quit ongoing menu load music */
|
||||
OSDynLoad_Acquire("snd_core.rpl", &sound_handle);
|
||||
void (* AXInit)();
|
||||
void (* AXQuit)();
|
||||
OSDynLoad_FindExport(sound_handle, 0, "AXInit", &AXInit);
|
||||
OSDynLoad_FindExport(sound_handle, 0, "AXQuit", &AXQuit);
|
||||
AXInit();
|
||||
AXQuit();
|
||||
}
|
||||
|
||||
/* Get coreinit handle and keep it in memory */
|
||||
unsigned int coreinit_handle;
|
||||
OSDynLoad_Acquire("coreinit.rpl", &coreinit_handle);
|
||||
@ -86,56 +80,16 @@ void __main(void)
|
||||
if (private_data.OSEffectiveToPhysical((void *)0xa0000000) == (void *)0)
|
||||
run_kexploit(&private_data);
|
||||
|
||||
/* Prepare for _SYSLaunchMiiStudio thread */
|
||||
int (*OSCreateThread)(void *thread, void *entry, int argc, void *args, unsigned int stack, unsigned int stack_size, int priority, unsigned short attr);
|
||||
int (*OSResumeThread)(void *thread);
|
||||
int (*OSIsThreadTerminated)(void *thread);
|
||||
/* Since we inited GX2 without initing the screen before do that now */
|
||||
/* Without this the hbl load will have some screen corruptions */
|
||||
PrepareScreen(&private_data);
|
||||
|
||||
OSDynLoad_FindExport(coreinit_handle, 0, "OSCreateThread", &OSCreateThread);
|
||||
OSDynLoad_FindExport(coreinit_handle, 0, "OSResumeThread", &OSResumeThread);
|
||||
OSDynLoad_FindExport(coreinit_handle, 0, "OSIsThreadTerminated", &OSIsThreadTerminated);
|
||||
|
||||
/* Allocate a stack for the thread */
|
||||
void *stack = private_data.MEMAllocFromDefaultHeapEx(0x1000, 0x20);
|
||||
/* Create the thread variable */
|
||||
void *thread = private_data.MEMAllocFromDefaultHeapEx(0x1000, 8);
|
||||
if(!thread || !stack)
|
||||
ExitFailure(&private_data, "Thread memory allocation failed. Exit and re-enter browser.");
|
||||
|
||||
/* Quickly find _SYSLaunchMiiStudio */
|
||||
/* Do SYSLaunchMiiStudio to boot HBL */
|
||||
unsigned int sysapp_handle;
|
||||
void (*_SYSLaunchMiiStudio)(void) = 0;
|
||||
void (*SYSLaunchMiiStudio)(void) = 0;
|
||||
OSDynLoad_Acquire("sysapp.rpl", &sysapp_handle);
|
||||
OSDynLoad_FindExport(sysapp_handle, 0, "_SYSLaunchMiiStudio", &_SYSLaunchMiiStudio);
|
||||
if(_SYSLaunchMiiStudio == (void*)0)
|
||||
OSFatal("_SYSLaunchMiiStudio is not there?");
|
||||
|
||||
/* Do _SYSLaunchMiiStudio in core 1 */
|
||||
int ret = OSCreateThread(thread, _SYSLaunchMiiStudio, 0, (void*)0, (unsigned int)stack+0x1000, 0x1000, 0, 0x1A);
|
||||
if (ret == 0)
|
||||
ExitFailure(&private_data, "Failed to create thread. Exit and re-enter browser.");
|
||||
|
||||
/* Schedule it for execution */
|
||||
OSResumeThread(thread);
|
||||
|
||||
/* Can not use OSJoinThread, which hangs for some reason, so we use a detached one and wait for it to terminate */
|
||||
while(OSIsThreadTerminated(thread) == 0)
|
||||
{
|
||||
asm volatile (
|
||||
" nop\n"
|
||||
" nop\n"
|
||||
" nop\n"
|
||||
" nop\n"
|
||||
" nop\n"
|
||||
" nop\n"
|
||||
" nop\n"
|
||||
" nop\n"
|
||||
);
|
||||
}
|
||||
|
||||
/* Free thread memory and stack */
|
||||
private_data.MEMFreeToDefaultHeap(thread);
|
||||
private_data.MEMFreeToDefaultHeap(stack);
|
||||
OSDynLoad_FindExport(sysapp_handle, 0, "SYSLaunchMiiStudio", &SYSLaunchMiiStudio);
|
||||
SYSLaunchMiiStudio();
|
||||
|
||||
/* setup kernel copy data syscall */
|
||||
kern_write((void*)(KERN_SYSCALL_TBL_2 + (0x25 * 4)), (unsigned int)KernelCopyData);
|
||||
@ -156,23 +110,20 @@ void __main(void)
|
||||
OSExitThread(0);
|
||||
}
|
||||
|
||||
void ExitFailure(private_data_t *private_data, const char *failure)
|
||||
void PrepareScreen(private_data_t *private_data)
|
||||
{
|
||||
/************************************************************************/
|
||||
// Prepare screen
|
||||
void (*OSScreenInit)();
|
||||
unsigned int (*OSScreenGetBufferSizeEx)(unsigned int bufferNum);
|
||||
unsigned int (*OSScreenSetBufferEx)(unsigned int bufferNum, void * addr);
|
||||
unsigned int (*OSScreenClearBufferEx)(unsigned int bufferNum, unsigned int temp);
|
||||
unsigned int (*OSScreenFlipBuffersEx)(unsigned int bufferNum);
|
||||
unsigned int (*OSScreenPutFontEx)(unsigned int bufferNum, unsigned int posX, unsigned int posY, const char * buffer);
|
||||
|
||||
OSDynLoad_FindExport(private_data->coreinit_handle, 0, "OSScreenInit", &OSScreenInit);
|
||||
OSDynLoad_FindExport(private_data->coreinit_handle, 0, "OSScreenGetBufferSizeEx", &OSScreenGetBufferSizeEx);
|
||||
OSDynLoad_FindExport(private_data->coreinit_handle, 0, "OSScreenSetBufferEx", &OSScreenSetBufferEx);
|
||||
OSDynLoad_FindExport(private_data->coreinit_handle, 0, "OSScreenClearBufferEx", &OSScreenClearBufferEx);
|
||||
OSDynLoad_FindExport(private_data->coreinit_handle, 0, "OSScreenFlipBuffersEx", &OSScreenFlipBuffersEx);
|
||||
OSDynLoad_FindExport(private_data->coreinit_handle, 0, "OSScreenPutFontEx", &OSScreenPutFontEx);
|
||||
|
||||
// Prepare screen
|
||||
int screen_buf0_size = 0;
|
||||
@ -197,6 +148,18 @@ void ExitFailure(private_data_t *private_data, const char *failure)
|
||||
// Flip buffers
|
||||
OSScreenFlipBuffersEx(0);
|
||||
OSScreenFlipBuffersEx(1);
|
||||
}
|
||||
|
||||
void ExitFailure(private_data_t *private_data, const char *failure)
|
||||
{
|
||||
/************************************************************************/
|
||||
unsigned int (*OSScreenClearBufferEx)(unsigned int bufferNum, unsigned int temp);
|
||||
unsigned int (*OSScreenFlipBuffersEx)(unsigned int bufferNum);
|
||||
unsigned int (*OSScreenPutFontEx)(unsigned int bufferNum, unsigned int posX, unsigned int posY, const char * buffer);
|
||||
|
||||
OSDynLoad_FindExport(private_data->coreinit_handle, 0, "OSScreenClearBufferEx", &OSScreenClearBufferEx);
|
||||
OSDynLoad_FindExport(private_data->coreinit_handle, 0, "OSScreenFlipBuffersEx", &OSScreenFlipBuffersEx);
|
||||
OSDynLoad_FindExport(private_data->coreinit_handle, 0, "OSScreenPutFontEx", &OSScreenPutFontEx);
|
||||
|
||||
OSScreenPutFontEx(1, 0, 0, failure);
|
||||
|
||||
@ -404,6 +367,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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -3,13 +3,11 @@
|
||||
#include "../../common.h"
|
||||
#include "../../fs_defs.h"
|
||||
#include "../../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;
|
||||
}
|
||||
|
75
hbl_loader/sd_loader/src/kernel_defs.h
Normal file
75
hbl_loader/sd_loader/src/kernel_defs.h
Normal 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_
|
@ -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
|
||||
|
@ -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.");
|
||||
|
38
hbl_loader/sd_loader/src/loader_defs.h
Normal file
38
hbl_loader/sd_loader/src/loader_defs.h
Normal 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_
|
60
zip/LICENSE
Normal file
60
zip/LICENSE
Normal file
@ -0,0 +1,60 @@
|
||||
This is version 2007-Mar-4 of the Info-ZIP license.
|
||||
The definitive version of this document should be available at
|
||||
ftp://ftp.info-zip.org/pub/infozip/license.html indefinitely and
|
||||
a copy at http://www.info-zip.org/pub/infozip/license.html.
|
||||
|
||||
|
||||
Copyright (c) 1990-2007 Info-ZIP. All rights reserved.
|
||||
|
||||
For the purposes of this copyright and license, "Info-ZIP" is defined as
|
||||
the following set of individuals:
|
||||
|
||||
Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois,
|
||||
Jean-loup Gailly, Hunter Goatley, Ed Gordon, Ian Gorman, Chris Herborth,
|
||||
Dirk Haase, Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz,
|
||||
David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko,
|
||||
Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs,
|
||||
Kai Uwe Rommel, Steve Salisbury, Dave Smith, Steven M. Schweda,
|
||||
Christian Spieler, Cosmin Truta, Antoine Verheijen, Paul von Behren,
|
||||
Rich Wales, Mike White.
|
||||
|
||||
This software is provided "as is," without warranty of any kind, express
|
||||
or implied. In no event shall Info-ZIP or its contributors be held liable
|
||||
for any direct, indirect, incidental, special or consequential damages
|
||||
arising out of the use of or inability to use this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the above disclaimer and the following restrictions:
|
||||
|
||||
1. Redistributions of source code (in whole or in part) must retain
|
||||
the above copyright notice, definition, disclaimer, and this list
|
||||
of conditions.
|
||||
|
||||
2. Redistributions in binary form (compiled executables and libraries)
|
||||
must reproduce the above copyright notice, definition, disclaimer,
|
||||
and this list of conditions in documentation and/or other materials
|
||||
provided with the distribution. The sole exception to this condition
|
||||
is redistribution of a standard UnZipSFX binary (including SFXWiz) as
|
||||
part of a self-extracting archive; that is permitted without inclusion
|
||||
of this license, as long as the normal SFX banner has not been removed
|
||||
from the binary or disabled.
|
||||
|
||||
3. Altered versions--including, but not limited to, ports to new operating
|
||||
systems, existing ports with new graphical interfaces, versions with
|
||||
modified or added functionality, and dynamic, shared, or static library
|
||||
versions not from Info-ZIP--must be plainly marked as such and must not
|
||||
be misrepresented as being the original source or, if binaries,
|
||||
compiled from the original source. Such altered versions also must not
|
||||
be misrepresented as being Info-ZIP releases--including, but not
|
||||
limited to, labeling of the altered versions with the names "Info-ZIP"
|
||||
(or any variation thereof, including, but not limited to, different
|
||||
capitalizations), "Pocket UnZip," "WiZ" or "MacZip" without the
|
||||
explicit permission of Info-ZIP. Such altered versions are further
|
||||
prohibited from misrepresentative use of the Zip-Bugs or Info-ZIP
|
||||
e-mail addresses or the Info-ZIP URL(s), such as to imply Info-ZIP
|
||||
will provide support for the altered versions.
|
||||
|
||||
4. Info-ZIP retains the right to use the names "Info-ZIP," "Zip," "UnZip,"
|
||||
"UnZipSFX," "WiZ," "Pocket UnZip," "Pocket Zip," and "MacZip" for its
|
||||
own source and binary releases.
|
BIN
zip/zip.exe
Normal file
BIN
zip/zip.exe
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user