2.12U
This commit is contained in:
parent
4a13fcfd3c
commit
6d4efb401b
8 changed files with 300 additions and 46 deletions
|
|
@ -9,7 +9,9 @@ IOP_AS = iop-as
|
||||||
IOP_OBJCOPY = iop-objcopy
|
IOP_OBJCOPY = iop-objcopy
|
||||||
IOP_OBJDUMP = iop-objdump
|
IOP_OBJDUMP = iop-objdump
|
||||||
|
|
||||||
IOP_SYMBOLS = -DREAD_SECTORS=$(IOP_READ_SECTORS) -DORIGINAL_RETURN_ADDRESS=$(IOP_ORIGINAL_RETURN_ADDRESS) -DRETURN_ADDRESS_LOCATION=$(IOP_RETURN_ADDRESS_LOCATION)
|
IOP_SYMBOLS = -DREAD_SECTORS_210=$(IOP_READ_SECTORS_210) -DORIGINAL_RETURN_ADDRESS_210=$(IOP_ORIGINAL_RETURN_ADDRESS_210) -DRETURN_ADDRESS_LOCATION_210=$(IOP_RETURN_ADDRESS_LOCATION_210) \
|
||||||
|
-DREAD_SECTORS_212=$(IOP_READ_SECTORS_212) -DORIGINAL_RETURN_ADDRESS_212=$(IOP_ORIGINAL_RETURN_ADDRESS_212) -DRETURN_ADDRESS_LOCATION_212=$(IOP_RETURN_ADDRESS_LOCATION_212)
|
||||||
|
|
||||||
IOP_CFLAGS = -O2 -G 0 -nostartfiles -nostdlib -ffreestanding -g $(IOP_SYMBOLS)
|
IOP_CFLAGS = -O2 -G 0 -nostartfiles -nostdlib -ffreestanding -g $(IOP_SYMBOLS)
|
||||||
|
|
||||||
EE_CFLAGS = -O2 -G 0 -nostartfiles -nostdlib -ffreestanding -Wl,-z,max-page-size=0x1
|
EE_CFLAGS = -O2 -G 0 -nostartfiles -nostdlib -ffreestanding -Wl,-z,max-page-size=0x1
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
STAGE1_LOAD_ADDRESS = 0xa00b7548
|
STAGE1_LOAD_ADDRESS = 0xa00b7548
|
||||||
STAGE1_LOAD_ADDRESS_STRING = '\x48\x75\x0b\xa0'
|
STAGE1_LOAD_ADDRESS_STRING = '\x48\x75\x0b\xa0'
|
||||||
|
|
||||||
IOP_READ_SECTORS = 0xb260c
|
IOP_READ_SECTORS_210 = 0xb260c
|
||||||
IOP_ORIGINAL_RETURN_ADDRESS = 0xb3630
|
IOP_READ_SECTORS_212 = 0xb25f8
|
||||||
IOP_RETURN_ADDRESS_LOCATION = 0x1f62ac
|
IOP_ORIGINAL_RETURN_ADDRESS_210 = 0xb3630
|
||||||
|
IOP_ORIGINAL_RETURN_ADDRESS_212 = 0xB35D8
|
||||||
|
IOP_RETURN_ADDRESS_LOCATION_210 = 0x1f62ac
|
||||||
|
IOP_RETURN_ADDRESS_LOCATION_212 = 0x1f62b4
|
||||||
|
|
||||||
|
|
||||||
#IOP_PAYLOAD_ENTRY = `$(IOP_OBJDUMP) -t ioppayload.iop.elf | grep " _start"`
|
#IOP_PAYLOAD_ENTRY = `$(IOP_OBJDUMP) -t ioppayload.iop.elf | grep " _start"`
|
||||||
|
|
@ -5,6 +5,13 @@ IOP_READ_SECTORS = 0x5DD0C # 0xb260c + 0x5c700 - 0xb1000
|
||||||
IOP_ORIGINAL_RETURN_ADDRESS = 0x5ED30 # 0xb3630 + 0x5c700 - 0xb1000
|
IOP_ORIGINAL_RETURN_ADDRESS = 0x5ED30 # 0xb3630 + 0x5c700 - 0xb1000
|
||||||
IOP_RETURN_ADDRESS_LOCATION = 0x1F30AC # 0x1f62ac + 0x1F3058 - 0x1f6258
|
IOP_RETURN_ADDRESS_LOCATION = 0x1F30AC # 0x1f62ac + 0x1F3058 - 0x1f6258
|
||||||
|
|
||||||
|
IOP_READ_SECTORS_210 = 0x5DD0C # 0xb260c + 0x5c700 - 0xb1000
|
||||||
|
IOP_READ_SECTORS_212 = 0x5DCF8 # 0xb25f8 + 0x5c700 - 0xb1000
|
||||||
|
IOP_ORIGINAL_RETURN_ADDRESS_210 = 0x5ED30 # 0xb3630 + 0x5c700 - 0xb1000
|
||||||
|
IOP_ORIGINAL_RETURN_ADDRESS_212 = 0x5ECD8 # 0xB35D8 + 0x5c700 - 0xb1000
|
||||||
|
IOP_RETURN_ADDRESS_LOCATION_210 = 0x1F30AC # 0x1f62ac + 0x1F3058 - 0x1f6258
|
||||||
|
IOP_RETURN_ADDRESS_LOCATION_212 = 0x1F30B4 # 0x1f62b4 + 0x1F3058 - 0x1f6258
|
||||||
|
|
||||||
|
|
||||||
#IOP_PAYLOAD_ENTRY = `$(IOP_OBJDUMP) -t ioppayload.iop.elf | grep " _start"`
|
#IOP_PAYLOAD_ENTRY = `$(IOP_OBJDUMP) -t ioppayload.iop.elf | grep " _start"`
|
||||||
IOP_PAYLOAD_ENTRY = 0xa00fd178 # Set this manually for now.
|
IOP_PAYLOAD_ENTRY = 0xa00fd178 # Set this manually for now.
|
||||||
|
|
@ -53,25 +53,25 @@ typedef struct {
|
||||||
|
|
||||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
|
|
||||||
/* All of these could be reimplemented here, but I'm lazy so we will use whatever
|
int (*readSectors)(int count, int sector, void *destination);
|
||||||
* the IOP has already loaded. The addresses are hardcoded but should be easy
|
|
||||||
* enough to extract from IOP memory by looking for their module names and magic
|
|
||||||
* number 0x41C00000.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int (*readSectors)(int count, int sector, void *destination) = (void *)READ_SECTORS;
|
//int (*sceSifSetDma)(struct SifDmaTransfer *, int num) = (void *)0x16fc8;
|
||||||
|
//int (*sceSifDmaStat)(int trid) = (void *)0x17170;
|
||||||
|
//void (*flushIcache)(void) = (void*)0x2f40;
|
||||||
|
//void (*flushDcache)(void) = (void*)0x3044;
|
||||||
|
//void (*printf)(char *, ...) = (void *)0x1ab84; // 2.10
|
||||||
|
//void (*printf)(char *, ...) = (void *)0x155f8; // 2.12
|
||||||
|
|
||||||
int (*sceSifSetDma)(struct SifDmaTransfer *, int num) = (void *)0x16fc8;
|
int (*sceSifSetDma)(struct SifDmaTransfer *, int num);
|
||||||
int (*sceSifDmaStat)(int trid) = (void *)0x17170;
|
int (*sceSifDmaStat)(int trid);
|
||||||
void (*flushIcache)(void) = (void*)0x2f40;
|
|
||||||
void (*flushDcache)(void) = (void*)0x3044;
|
|
||||||
void (*printf)(char *, ...) = (void *)0x1ab84;
|
|
||||||
|
|
||||||
static void transfer_to_ee(void *dest, void *src, unsigned int size);
|
static void transfer_to_ee(void *dest, void *src, unsigned int size);
|
||||||
static void *memcpy(void *dest, void *src, unsigned int n);
|
static void *memcpy(void *dest, void *src, unsigned int n);
|
||||||
static void *memset(void *s, int c, unsigned int n);
|
static void *memset(void *s, int c, unsigned int n);
|
||||||
static void memset_ee(void *s, int c, unsigned int n);
|
static void memset_ee(void *s, int c, unsigned int n);
|
||||||
|
|
||||||
|
//#include "iopresolve.h"
|
||||||
|
|
||||||
static void readData(void *dest, unsigned int offset, size_t n) {
|
static void readData(void *dest, unsigned int offset, size_t n) {
|
||||||
//unsigned char buffer[SECTOR_SIZE];
|
//unsigned char buffer[SECTOR_SIZE];
|
||||||
//unsigned char *buffer = (void *)0xfd000;
|
//unsigned char *buffer = (void *)0xfd000;
|
||||||
|
|
@ -110,18 +110,30 @@ static void readDataUnsafe(void *dest, unsigned int offset, size_t n) {
|
||||||
void _start(void) {
|
void _start(void) {
|
||||||
extern unsigned char ee_crt0[];
|
extern unsigned char ee_crt0[];
|
||||||
extern unsigned int ee_crt0_size;
|
extern unsigned int ee_crt0_size;
|
||||||
void *return_address = EE_CRT0_ADDRESS;
|
void *return_address[4] __attribute__ ((aligned (16))) = { EE_CRT0_ADDRESS, 0, 0, 0 };
|
||||||
int one = 1;
|
int one __attribute__ ((aligned (16))) = 1;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
//sceSifSetDma = resolve("sifman", 7);
|
||||||
|
//sceSifDmaStat = resolve("sifman", 8);
|
||||||
|
|
||||||
|
sceSifSetDma = (void *)0x16fc8;
|
||||||
|
sceSifDmaStat = (void *)0x17170;
|
||||||
|
|
||||||
|
if(*(unsigned int *)READ_SECTORS_210 == 0x27bdffc8) // addiu $sp, $sp, -0x38
|
||||||
|
readSectors = (void *)READ_SECTORS_210;
|
||||||
|
else readSectors = (void *)READ_SECTORS_212;
|
||||||
|
|
||||||
transfer_to_ee(EE_CRT0_ADDRESS, ee_crt0, ee_crt0_size);
|
transfer_to_ee(EE_CRT0_ADDRESS, ee_crt0, ee_crt0_size);
|
||||||
|
|
||||||
/* Corrupt all known return addresses in the stack.
|
// Corrupt all known return addresses in the stack, there might be a more universal way for IOP to redirect EE...
|
||||||
*/
|
transfer_to_ee((void *)0x14A5FF0, &return_address, sizeof(return_address)); // 2.10E/A
|
||||||
transfer_to_ee((void *)0x14A5FF0, &return_address, sizeof(return_address)); /* 2.10E/A */
|
transfer_to_ee((void *)0x10007F0, &return_address, sizeof(return_address)); // 2.10J
|
||||||
transfer_to_ee((void *)0x10007F0, &return_address, sizeof(return_address)); /* 2.10J */
|
transfer_to_ee((void *)0x12D1C70, &return_address, sizeof(return_address)); // 2.10U
|
||||||
transfer_to_ee((void *)0x12D1C70, &return_address, sizeof(return_address)); /* 2.10U */
|
|
||||||
|
|
||||||
|
transfer_to_ee((void *)0x12B8CF0, &return_address, sizeof(return_address)); // 2.12U
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Clear bit 0 of 0x208bb710 to make EE exit loop waiting for IOP, and return to our above payload
|
// Clear bit 0 of 0x208bb710 to make EE exit loop waiting for IOP, and return to our above payload
|
||||||
//unsigned int loopValue = 0x010004;
|
//unsigned int loopValue = 0x010004;
|
||||||
|
|
@ -185,17 +197,11 @@ void _start(void) {
|
||||||
copied += k;
|
copied += k;
|
||||||
remaining -= k;
|
remaining -= k;
|
||||||
}
|
}
|
||||||
|
|
||||||
//unsigned char x[] = { 0x08, 0x00, 0xE0, 0x03, 0x01, 0x00, 0x42, 0x30, 0x01 };
|
|
||||||
//memcpy(buffer, &x, sizeof(x));
|
|
||||||
//memset(buffer + sizeof(x), 0, sizeofbuffer - sizeof(x));
|
|
||||||
//transfer_to_ee(eph[i].vaddr + (eph[i].filesz & ~(0x10 - 1)), buffer, (remaining + 0xf) & ~(0x10 - 1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
transfer_to_ee(EE_ENTRYPOINT_ADDRESS, &eh.entry, sizeof(one));
|
transfer_to_ee(EE_ENTRYPOINT_ADDRESS, &eh.entry, sizeof(one));
|
||||||
|
|
||||||
/* Signal EE that the ELF is loaded and ready to execute.
|
// Signal EE that the ELF is loaded and ready to execute.
|
||||||
*/
|
|
||||||
transfer_to_ee(EE_WAIT_ADDRESS, &one, sizeof(one));
|
transfer_to_ee(EE_WAIT_ADDRESS, &one, sizeof(one));
|
||||||
|
|
||||||
//int loopValueJ = 0;
|
//int loopValueJ = 0;
|
||||||
|
|
|
||||||
220
PAYLOADS/1.00-2.13/iopresolve.h
Normal file
220
PAYLOADS/1.00-2.13/iopresolve.h
Normal file
|
|
@ -0,0 +1,220 @@
|
||||||
|
//typedef unsigned char u8;
|
||||||
|
//typedef unsigned short u16;
|
||||||
|
//typedef unsigned int u32;
|
||||||
|
|
||||||
|
typedef void *pointer;
|
||||||
|
|
||||||
|
#define NULL 0
|
||||||
|
|
||||||
|
typedef struct _smod_mod_info {
|
||||||
|
//struct _smod_mod_info *next;
|
||||||
|
pointer next;
|
||||||
|
/** A pointer to the name in IOP RAM, this must be smem_read(). */
|
||||||
|
//char *name;
|
||||||
|
pointer name;
|
||||||
|
u16 version;
|
||||||
|
/** For MODLOAD shipped with games. The old MODLOAD module from boot ROMs do not use a flags field. */
|
||||||
|
u16 newflags;
|
||||||
|
u16 id;
|
||||||
|
u16 unused;
|
||||||
|
/** _start */
|
||||||
|
u32 entry;
|
||||||
|
u32 gp;
|
||||||
|
u32 text_start;
|
||||||
|
u32 text_size;
|
||||||
|
u32 data_size;
|
||||||
|
u32 bss_size;
|
||||||
|
u32 unused1;
|
||||||
|
u32 unused2;
|
||||||
|
} smod_mod_info_t;
|
||||||
|
|
||||||
|
typedef struct _slib_imp_list {
|
||||||
|
u8 magic;
|
||||||
|
//struct _slib_imp_list *next;
|
||||||
|
pointer next;
|
||||||
|
u16 version;
|
||||||
|
u16 flags;
|
||||||
|
u8 name[8];
|
||||||
|
//void *imports[0];
|
||||||
|
pointer imports[0];
|
||||||
|
} slib_imp_list_t;
|
||||||
|
|
||||||
|
typedef struct _slib_exp_lib {
|
||||||
|
//struct _slib_exp_lib *prev;
|
||||||
|
pointer prev;
|
||||||
|
//struct _slib_imp_list *caller;
|
||||||
|
pointer caller;
|
||||||
|
u16 version;
|
||||||
|
u16 flags;
|
||||||
|
u8 name[8];
|
||||||
|
//void *exports[0];
|
||||||
|
pointer exports[0];
|
||||||
|
} slib_exp_lib_t;
|
||||||
|
|
||||||
|
typedef struct _slib_exp_lib_list {
|
||||||
|
//struct _slib_exp_lib *tail;
|
||||||
|
pointer tail;
|
||||||
|
//struct _slib_exp_lib *head;
|
||||||
|
pointer head;
|
||||||
|
} slib_exp_lib_list_t;
|
||||||
|
|
||||||
|
#define SMEM_BUF_SIZE 0x300 //Must be large enough to accommodate all operations.
|
||||||
|
|
||||||
|
struct smem_buf {
|
||||||
|
union {
|
||||||
|
u8 bytes[SMEM_BUF_SIZE / sizeof(u8)];
|
||||||
|
u32 words[SMEM_BUF_SIZE / sizeof(u32)];
|
||||||
|
smod_mod_info_t mod_info;
|
||||||
|
slib_exp_lib_t exp_lib;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
size_t strlen(const char *str) {
|
||||||
|
const char *s;
|
||||||
|
for (s = str; *s; ++s);
|
||||||
|
return (s - str);
|
||||||
|
}
|
||||||
|
|
||||||
|
int memcmp(const char *cs_in, const char *ct_in, size_t n) {
|
||||||
|
size_t i;
|
||||||
|
const unsigned char * cs = (const unsigned char*) cs_in;
|
||||||
|
const unsigned char * ct = (const unsigned char*) ct_in;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++, cs++, ct++)
|
||||||
|
{
|
||||||
|
if (*cs < *ct)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (*cs > *ct)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
slib_exp_lib_list_t _slib_cur_exp_lib_list;
|
||||||
|
|
||||||
|
struct smem_buf smem_buf;
|
||||||
|
|
||||||
|
typedef unsigned int SifRpcReceiveData_t;
|
||||||
|
|
||||||
|
size_t SifRpcGetOtherData(void *a, pointer x, void *dest, size_t s, int z) {
|
||||||
|
memcpy(dest, x, s);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
slib_exp_lib_list_t *slib_exp_lib_list(void) {
|
||||||
|
SifRpcReceiveData_t RData;
|
||||||
|
slib_exp_lib_t *core_exps;
|
||||||
|
slib_exp_lib_list_t *exp_lib_list = NULL;
|
||||||
|
u32 i, addr, core_end, NextMod, *exp_func;
|
||||||
|
void *pGetLoadcoreInternalData;
|
||||||
|
smod_mod_info_t *ModInfo;
|
||||||
|
|
||||||
|
/* Read the start of the global module table - this is where we will search. */
|
||||||
|
if(SifRpcGetOtherData(&RData, (void*)0x800, &smem_buf, sizeof(smod_mod_info_t), 0)>=0){
|
||||||
|
/* The first entry points to LOADCORE's module info. We then use the
|
||||||
|
module info to determine the end of LOADCORE's .text segment (just
|
||||||
|
past the export library we're trying to find. */
|
||||||
|
NextMod = *smem_buf.words;
|
||||||
|
if(SifRpcGetOtherData(&RData, (void*)NextMod, &smem_buf, sizeof(smod_mod_info_t), 0)>=0){
|
||||||
|
ModInfo = &smem_buf.mod_info;
|
||||||
|
core_end = ModInfo->text_start+ModInfo->text_size;
|
||||||
|
|
||||||
|
/* Back up so we position ourselves infront of where the export
|
||||||
|
library will be. */
|
||||||
|
if(SifRpcGetOtherData(&RData, (void*)(core_end - 512), &smem_buf, 512, 0)>=0){
|
||||||
|
/* Search for LOADCORE's export library. */
|
||||||
|
for (i = 0; i < 512; i += 4) {
|
||||||
|
/* SYSMEM's export library sits at 0x830, so it should appear in
|
||||||
|
LOADCORE's prev pointer. */
|
||||||
|
if (smem_buf.words[i / sizeof(u32)] == 0x830) {
|
||||||
|
if (!memcmp(smem_buf.bytes + i + 12, "loadcore", 8))
|
||||||
|
//if(*(unsigned int *)(smem_buf.bytes + i + 12) == 0x64616f6c) // 6c 6f 61 64 == load
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i >= 512)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Get to the start of the export table, and find the address of the
|
||||||
|
routine that will get us the export library list info. */
|
||||||
|
core_exps = (slib_exp_lib_t *)(smem_buf.bytes + i);
|
||||||
|
pGetLoadcoreInternalData = core_exps->exports[3];
|
||||||
|
|
||||||
|
if(SifRpcGetOtherData(&RData, pGetLoadcoreInternalData, &smem_buf, 8, 0)>=0){
|
||||||
|
exp_func = smem_buf.words;
|
||||||
|
|
||||||
|
/* Parse the two instructions that hold the address of the table. */
|
||||||
|
if ((exp_func[0] & 0xffff0000) != 0x3c020000) /* lui v0, XXXX */
|
||||||
|
return NULL;
|
||||||
|
if ((exp_func[1] & 0xffff0000) != 0x24420000) /* addiu v0, v0, XXXX */
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
addr = ((exp_func[0] & 0xffff) << 16) | (exp_func[1] & 0xffff);
|
||||||
|
|
||||||
|
if(SifRpcGetOtherData(&RData, (void*)addr, &smem_buf, 8, 0)>=0){
|
||||||
|
_slib_cur_exp_lib_list.tail = (slib_exp_lib_t *)(smem_buf.words[0]);
|
||||||
|
_slib_cur_exp_lib_list.head = (slib_exp_lib_t *)(smem_buf.words[1]);
|
||||||
|
exp_lib_list = &_slib_cur_exp_lib_list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return exp_lib_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define EXP_LIB_MAX SMEM_BUF_SIZE /* We can even handle CDVDMAN's bloat! */
|
||||||
|
|
||||||
|
int slib_get_exp_lib(const char *name, slib_exp_lib_t *library)
|
||||||
|
{
|
||||||
|
SifRpcReceiveData_t RData;
|
||||||
|
slib_exp_lib_list_t *exp_lib_list = &_slib_cur_exp_lib_list;
|
||||||
|
slib_exp_lib_t *exp_lib = &smem_buf.exp_lib;
|
||||||
|
void *cur_lib;
|
||||||
|
int len = strlen(name), count = 0;
|
||||||
|
|
||||||
|
if (!exp_lib_list->head && !(exp_lib_list = slib_exp_lib_list()))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Read the tail export library to initiate the search. */
|
||||||
|
cur_lib = exp_lib_list->tail;
|
||||||
|
|
||||||
|
while (cur_lib) {
|
||||||
|
if(SifRpcGetOtherData(&RData, cur_lib, exp_lib, EXP_LIB_MAX, 0)>=0){
|
||||||
|
if (!memcmp(exp_lib->name, name, len)) {
|
||||||
|
while (exp_lib->exports[count] != 0)
|
||||||
|
count++;
|
||||||
|
|
||||||
|
if (library)
|
||||||
|
memcpy(library, exp_lib, sizeof(slib_exp_lib_t) + count * 4);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_lib = exp_lib->prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *resolve(char *name, int export) {
|
||||||
|
slib_exp_lib_t *modload_lib = (void *)0x100;
|
||||||
|
|
||||||
|
memset(&_slib_cur_exp_lib_list, 0, sizeof(slib_exp_lib_list_t));
|
||||||
|
|
||||||
|
if (!slib_get_exp_lib(name, modload_lib)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return modload_lib->exports[export];
|
||||||
|
}
|
||||||
|
|
@ -1,14 +1,10 @@
|
||||||
# ElReino & CTurt 2020
|
# ElReino & CTurt 2020
|
||||||
|
|
||||||
readSectors = READ_SECTORS
|
|
||||||
|
|
||||||
flushIcache = 0x00002f40
|
flushIcache = 0x00002f40
|
||||||
flushDcache = 0x0003044
|
flushDcache = 0x0003044
|
||||||
|
|
||||||
#flushDcacheWrapper = 0x0057f1c
|
#flushDcacheWrapper = 0x0057f1c
|
||||||
|
|
||||||
#iop_payload_address = 0x460000
|
|
||||||
#iop_payload_address = 0xa0460000
|
|
||||||
iop_payload_address = 0xa00fd000
|
iop_payload_address = 0xa00fd000
|
||||||
|
|
||||||
.section .text
|
.section .text
|
||||||
|
|
@ -16,11 +12,21 @@ iop_payload_address = 0xa00fd000
|
||||||
.global _start
|
.global _start
|
||||||
_start:
|
_start:
|
||||||
move $fp, $sp # We need to reset $fp as it gets trashed by memcpy
|
move $fp, $sp # We need to reset $fp as it gets trashed by memcpy
|
||||||
|
|
||||||
|
check_210:
|
||||||
|
la $v1, 0x27bdffc8 # addiu $sp, $sp, -0x38
|
||||||
|
la $v0, READ_SECTORS_210
|
||||||
|
lw $t0, 0($v0)
|
||||||
|
beq $t0, $v1, read_iop_payload
|
||||||
|
|
||||||
|
check_212:
|
||||||
|
la $v0, READ_SECTORS_212
|
||||||
|
|
||||||
|
read_iop_payload:
|
||||||
la $a0, (IOP_PAYLOAD_SIZE / 0x800) + 1 # count
|
la $a0, (IOP_PAYLOAD_SIZE / 0x800) + 1 # count
|
||||||
la $a1, 0x700000 / 0x800 # sector
|
la $a1, 0x700000 / 0x800 # sector
|
||||||
la $a2, iop_payload_address # destination
|
la $a2, iop_payload_address # destination
|
||||||
jal readSectors
|
jal $v0
|
||||||
|
|
||||||
#jal flushIcache
|
#jal flushIcache
|
||||||
#jal flushDcache
|
#jal flushDcache
|
||||||
|
|
@ -28,13 +34,21 @@ _start:
|
||||||
#jal ENTRY
|
#jal ENTRY
|
||||||
la $v0, ENTRY
|
la $v0, ENTRY
|
||||||
jalr $v0
|
jalr $v0
|
||||||
|
|
||||||
|
check_210_again:
|
||||||
|
la $v1, 0x27bdffc8 # addiu $sp, $sp, -0x38
|
||||||
|
la $v0, READ_SECTORS_210
|
||||||
|
lw $v0, 0($v0)
|
||||||
|
la $a0, RETURN_ADDRESS_LOCATION_210
|
||||||
|
la $ra, ORIGINAL_RETURN_ADDRESS_210
|
||||||
|
beq $v0, $v1, return
|
||||||
|
|
||||||
|
check_212_again:
|
||||||
|
la $a0, RETURN_ADDRESS_LOCATION_212
|
||||||
|
la $ra, ORIGINAL_RETURN_ADDRESS_212
|
||||||
|
|
||||||
|
return:
|
||||||
# Return gracefully back to original return address
|
# Return gracefully back to original return address
|
||||||
la $a0, RETURN_ADDRESS_LOCATION
|
|
||||||
la $ra, ORIGINAL_RETURN_ADDRESS # hardware
|
|
||||||
|
|
||||||
sw $ra, 0($a0)
|
sw $ra, 0($a0)
|
||||||
|
|
||||||
la $v0, 0
|
la $v0, 0
|
||||||
|
|
||||||
jr $ra
|
jr $ra
|
||||||
|
|
|
||||||
Binary file not shown.
12
README.md
12
README.md
|
|
@ -68,7 +68,9 @@ Boot your PlayStation 2 without any disc inserted, and press Triangle to identif
|
||||||
|
|
||||||
**Currently only support:**
|
**Currently only support:**
|
||||||
|
|
||||||
- 2.10 (all regions and languages),
|
- 2.10 (certain models only?),
|
||||||
|
|
||||||
|
- 2.12 (region U, others to be added soon),
|
||||||
|
|
||||||
- 3.04 (tested only region M in emulator so far, but guess most other regions EUMACDG, except for J will work - with English language set in settings),
|
- 3.04 (tested only region M in emulator so far, but guess most other regions EUMACDG, except for J will work - with English language set in settings),
|
||||||
|
|
||||||
|
|
@ -140,13 +142,13 @@ If you wish to update the loader payload, run `build.sh` inside `PAYLOAD` direct
|
||||||
## DEVELOPMENT: Replacing the loader payload - Phat
|
## DEVELOPMENT: Replacing the loader payload - Phat
|
||||||
Run the following to build a new `dvd.iso`:
|
Run the following to build a new `dvd.iso`:
|
||||||
|
|
||||||
`make -f 2.10.mk`
|
`make -f hardware.mk`
|
||||||
|
|
||||||
If you want to test on PCSX2 using KrHacken's repacked DVD players, it loads `udfio` at a different base address, use the repacked makefile to build an image for testing on the emulator:
|
If you want to test on PCSX2 using KrHacken's repacked DVD players, it loads `udfio` at a different base address, use the repacked Makefile to build an image for testing on the emulator:
|
||||||
|
|
||||||
`make -f 2.10_repacked.mk`
|
`make -f emulator.mk`
|
||||||
|
|
||||||
`clean` before switching between these, or use `-B` flag.
|
`clean` before switching between these different Makefiles, or use `-B` flag.
|
||||||
|
|
||||||
## PORTING:
|
## PORTING:
|
||||||
Please read my technical writeup, to understand how the exploit works. I've also provided some [notes about porting](https://cturt.github.io/FreeDVDBoot/portingnotes.html) in the [`gh-pages`](https://github.com/CTurt/FreeDVDBoot/tree/gh-pages) branch.
|
Please read my technical writeup, to understand how the exploit works. I've also provided some [notes about porting](https://cturt.github.io/FreeDVDBoot/portingnotes.html) in the [`gh-pages`](https://github.com/CTurt/FreeDVDBoot/tree/gh-pages) branch.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue