2.10 support, using new bug
This commit is contained in:
parent
e3b92c3c55
commit
a53803d59c
20 changed files with 526 additions and 5 deletions
BIN
Filesystems/2.10/BOOT.ELF
Normal file
BIN
Filesystems/2.10/BOOT.ELF
Normal file
Binary file not shown.
BIN
Filesystems/2.10/VIDEO_TS/VIDEO_TS.IFO
Normal file
BIN
Filesystems/2.10/VIDEO_TS/VIDEO_TS.IFO
Normal file
Binary file not shown.
BIN
Filesystems/2.10/VIDEO_TS/VTS_01_0.IFO
Normal file
BIN
Filesystems/2.10/VIDEO_TS/VTS_01_0.IFO
Normal file
Binary file not shown.
81
PAYLOADS/2.10/Makefile
Normal file
81
PAYLOADS/2.10/Makefile
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
#STAGE1_LOAD_ADDRESS = 0x1f62b0
|
||||||
|
#STAGE1_LOAD_ADDRESS = 0xa01f62b0 # repacked
|
||||||
|
#STAGE1_LOAD_ADDRESS = 0xA01F30B0 # (0xa0000000 + 0x01f62b0 + 0x1F3058 - 0x1f6258) # hardware
|
||||||
|
|
||||||
|
# (0xb7548 + 0x5c700 - 0xb1000) = 0x62C48
|
||||||
|
STAGE1_LOAD_ADDRESS = 0xa0062C48 # hardware
|
||||||
|
|
||||||
|
EE_CC = ee-gcc
|
||||||
|
EE_LD = ee-ld
|
||||||
|
EE_AS = ee-as
|
||||||
|
EE_OBJCOPY = ee-objcopy
|
||||||
|
|
||||||
|
IOP_CC = iop-gcc
|
||||||
|
IOP_LD = iop-ld
|
||||||
|
IOP_AS = iop-as
|
||||||
|
IOP_OBJCOPY = iop-objcopy
|
||||||
|
IOP_OBJDUMP = iop-objdump
|
||||||
|
|
||||||
|
IOP_CFLAGS = -O2 -G 0 -nostartfiles -nostdlib -ffreestanding -g
|
||||||
|
|
||||||
|
EE_CFLAGS = -O2 -G 0 -nostartfiles -nostdlib -ffreestanding -Wl,-z,max-page-size=0x1
|
||||||
|
|
||||||
|
#IOP_PAYLOAD_ENTRY = `$(IOP_OBJDUMP) -t ioppayload.iop.elf | grep " _start"`
|
||||||
|
#IOP_PAYLOAD_ENTRY = 0xa0460178 # Set this manually for now.
|
||||||
|
IOP_PAYLOAD_ENTRY = 0xa00fd178 # Set this manually for now.
|
||||||
|
|
||||||
|
IOP_STAGE1_SIZE = `stat -c '%s' stage1.iop.bin`
|
||||||
|
IOP_PAYLOAD_SIZE = `stat -c '%s' ioppayload.iop.bin`
|
||||||
|
#IOP_PAYLOAD_ADDRESS = 0x460000
|
||||||
|
#IOP_PAYLOAD_ADDRESS = 0xa0460000
|
||||||
|
IOP_PAYLOAD_ADDRESS = 0xa00fd000
|
||||||
|
|
||||||
|
EE_PAYLOAD_ADDRESS = 0x01fff800
|
||||||
|
|
||||||
|
#isoinfo -l -i dvd.iso | grep "BOOT.ELF"
|
||||||
|
#var=`isoinfo -l -i dvd.iso | grep "BOOT.ELF" | grep -o -P "[0-9]*? -"`
|
||||||
|
# LOAD_ELF_FROM_OFFSET =
|
||||||
|
LOAD_ELF_FROM_OFFSET = 0x5BB000 # Set this manually for now
|
||||||
|
|
||||||
|
all: dvd.iso
|
||||||
|
|
||||||
|
dvd.iso: dvd.base.iso stage1.iop.bin ioppayload.iop.bin
|
||||||
|
cp dvd.base.iso dvd.iso
|
||||||
|
|
||||||
|
#genisoimage -udf -o dvd.iso udf/
|
||||||
|
# @echo Insert 0x00000048 to offset 0x0818AC in dvd.iso
|
||||||
|
# @echo Insert 0x00004000 to offset 0x0818B0 in dvd.iso
|
||||||
|
# @echo Insert 0x000B7548 to offset 0x0818F4 in dvd.iso
|
||||||
|
|
||||||
|
# bs=4096 iflag=skip_bytes,count_bytes
|
||||||
|
|
||||||
|
# 0x820f8 = 532728
|
||||||
|
dd if=stage1.iop.bin of=dvd.iso bs=1 seek=532728 count=$(IOP_STAGE1_SIZE) conv=notrunc
|
||||||
|
# 0x700000 = 7340032
|
||||||
|
dd if=ioppayload.iop.bin of=dvd.iso bs=1 seek=7340032 count=$(IOP_PAYLOAD_SIZE) conv=notrunc
|
||||||
|
|
||||||
|
%.iop.bin: %.iop.elf
|
||||||
|
$(IOP_OBJCOPY) -O binary $< $@
|
||||||
|
|
||||||
|
%.iop.o: %.iop.S
|
||||||
|
$(IOP_AS) $< -o $@
|
||||||
|
|
||||||
|
stage1.iop.elf: stage1.iop.S ioppayload.iop.bin
|
||||||
|
$(IOP_OBJDUMP) -t ioppayload.iop.elf | grep " _start"
|
||||||
|
$(IOP_CC) -Ttext=$(STAGE1_LOAD_ADDRESS) $< -DENTRY=$(IOP_PAYLOAD_ENTRY) -DIOP_PAYLOAD_SIZE=$(IOP_PAYLOAD_SIZE) $(IOP_CFLAGS) -o $@
|
||||||
|
|
||||||
|
ioppayload.iop.elf: ioppayload.iop.c eepayload.ee.bin
|
||||||
|
$(IOP_CC) -Ttext=$(IOP_PAYLOAD_ADDRESS) -DLOAD_ELF_FROM_OFFSET=$(LOAD_ELF_FROM_OFFSET) ioppayload.iop.c $(IOP_CFLAGS) -o $@
|
||||||
|
|
||||||
|
|
||||||
|
%.ee.bin: %.ee.elf
|
||||||
|
$(EE_OBJCOPY) -O binary $< $@ -Wl,-z,max-page-size=0x1
|
||||||
|
|
||||||
|
%.ee.o: %.ee.S
|
||||||
|
$(EE_AS) $< -o $@
|
||||||
|
|
||||||
|
eepayload.ee.elf: eecrt0.ee.o syscalls.ee.o eepayload.ee.c
|
||||||
|
$(EE_CC) -Ttext=$(EE_PAYLOAD_ADDRESS) $^ $(EE_CFLAGS) -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf *.elf *.bin *.o dvd.iso
|
||||||
BIN
PAYLOADS/2.10/dvd.base.iso
Normal file
BIN
PAYLOADS/2.10/dvd.base.iso
Normal file
Binary file not shown.
27
PAYLOADS/2.10/eecrt0.ee.S
Normal file
27
PAYLOADS/2.10/eecrt0.ee.S
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
# ElReino & CTurt 2020
|
||||||
|
|
||||||
|
.section .text.startup
|
||||||
|
|
||||||
|
.global _start
|
||||||
|
_start:
|
||||||
|
# Point stack to end of scratchpad RAM
|
||||||
|
#la $sp, 0x70004000
|
||||||
|
|
||||||
|
la $v0, 0x01FFF7D0
|
||||||
|
sw $v0, 0($v0)
|
||||||
|
|
||||||
|
.global main
|
||||||
|
#la $v1, 0x01
|
||||||
|
#la $a0, 0x7f
|
||||||
|
#syscall 0x01 # ResetEE
|
||||||
|
|
||||||
|
la $a0, main
|
||||||
|
la $a1, 0
|
||||||
|
la $a2, 0
|
||||||
|
la $a3, 0
|
||||||
|
|
||||||
|
jr $a0
|
||||||
|
|
||||||
|
#ExecPS2:
|
||||||
|
#la $v1, 0x07
|
||||||
|
#syscall 0x07 # ExecPS2
|
||||||
BIN
PAYLOADS/2.10/eecrt0.ee.o
Normal file
BIN
PAYLOADS/2.10/eecrt0.ee.o
Normal file
Binary file not shown.
BIN
PAYLOADS/2.10/eepayload.ee.bin
Normal file
BIN
PAYLOADS/2.10/eepayload.ee.bin
Normal file
Binary file not shown.
37
PAYLOADS/2.10/eepayload.ee.c
Normal file
37
PAYLOADS/2.10/eepayload.ee.c
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
// ElReino & CTurt 2020
|
||||||
|
|
||||||
|
int (*SifIopReset)(char *, int) = (void *)0x85360;
|
||||||
|
void (*SifInitRpc)(int) = (void *)0x84500;
|
||||||
|
void (*SifExitRpc)(void) = (void *)0x84690;
|
||||||
|
|
||||||
|
extern void SifWriteBackDCache(void *ptr, int size);
|
||||||
|
extern int SifSetReg(unsigned int register_num, unsigned int register_value);
|
||||||
|
extern int SifGetReg(unsigned int register_num);
|
||||||
|
|
||||||
|
static int SifIopSync(void) {
|
||||||
|
#define SIF_REG_SMFLAG 4
|
||||||
|
#define SIF_STAT_BOOTEND 0x40000
|
||||||
|
return((SifGetReg(SIF_REG_SMFLAG) & SIF_STAT_BOOTEND) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flush(void) {
|
||||||
|
asm volatile("la $v1, 0x64; la $a0, 0; syscall 0x64"); /* FlushCache data writeback */
|
||||||
|
asm volatile("la $v1, 0x64; la $a0, 2; syscall 0x64"); /* FlushCache instruction invalidate */
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
volatile int *waitAddress = (void *)0x21FFF7F0;
|
||||||
|
while(!*waitAddress);
|
||||||
|
|
||||||
|
flush();
|
||||||
|
|
||||||
|
SifInitRpc(0);
|
||||||
|
SifExitRpc();
|
||||||
|
while(!SifIopReset("", 0));
|
||||||
|
while(!SifIopSync()){};
|
||||||
|
|
||||||
|
//SifInitRpc(0);
|
||||||
|
|
||||||
|
volatile void **entry_point_address = (void *)0x01FFF7E0;
|
||||||
|
ExecPS2(*entry_point_address, 0, 0, 0);
|
||||||
|
}
|
||||||
BIN
PAYLOADS/2.10/eepayload.ee.elf
Normal file
BIN
PAYLOADS/2.10/eepayload.ee.elf
Normal file
Binary file not shown.
BIN
PAYLOADS/2.10/ioppayload.iop.bin
Normal file
BIN
PAYLOADS/2.10/ioppayload.iop.bin
Normal file
Binary file not shown.
247
PAYLOADS/2.10/ioppayload.iop.c
Normal file
247
PAYLOADS/2.10/ioppayload.iop.c
Normal file
|
|
@ -0,0 +1,247 @@
|
||||||
|
// ElReino & CTurt
|
||||||
|
|
||||||
|
/* Todo: seperate these settings to an include file.
|
||||||
|
*/
|
||||||
|
#define EE_CRT0_ADDRESS ((void*)0x21FFF800)
|
||||||
|
#define EE_WAIT_ADDRESS ((void*)0x01FFF7F0)
|
||||||
|
#define EE_ENTRYPOINT_ADDRESS ((void *)0x01FFF7E0)
|
||||||
|
//#define EE_DEBUG_ADDRESS ((void *)0x01FFF7D0)
|
||||||
|
|
||||||
|
struct SifDmaTransfer {
|
||||||
|
void *src,
|
||||||
|
*dest;
|
||||||
|
int size;
|
||||||
|
int attr;
|
||||||
|
} __attribute__ ((aligned(8)));
|
||||||
|
|
||||||
|
#define ELF_PT_LOAD 1
|
||||||
|
|
||||||
|
typedef unsigned char u8;
|
||||||
|
typedef unsigned short u16;
|
||||||
|
typedef unsigned int u32;
|
||||||
|
typedef unsigned int size_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u8 ident[16];
|
||||||
|
u16 type;
|
||||||
|
u16 machine;
|
||||||
|
u32 version;
|
||||||
|
u32 entry;
|
||||||
|
u32 phoff;
|
||||||
|
u32 shoff;
|
||||||
|
u32 flags;
|
||||||
|
u16 ehsize;
|
||||||
|
u16 phentsize;
|
||||||
|
u16 phnum;
|
||||||
|
u16 shentsize;
|
||||||
|
u16 shnum;
|
||||||
|
u16 shstrndx;
|
||||||
|
} elf_header_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u32 type;
|
||||||
|
u32 offset;
|
||||||
|
void *vaddr;
|
||||||
|
u32 paddr;
|
||||||
|
u32 filesz;
|
||||||
|
u32 memsz;
|
||||||
|
u32 flags;
|
||||||
|
u32 align;
|
||||||
|
} elf_pheader_t;
|
||||||
|
|
||||||
|
#define SECTOR_SIZE 0x800
|
||||||
|
|
||||||
|
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
|
|
||||||
|
/* All of these could be reimplemented here, but I'm lazy so we will use whatever
|
||||||
|
* 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 *)0xb260c; // repacked ELF
|
||||||
|
int (*readSectors)(int count, int sector, void *destination) = (void *)(0xb260c + 0x5c700 - 0xb1000); // real hardware
|
||||||
|
|
||||||
|
int (*sceSifSetDma)(struct SifDmaTransfer *, int num) = (void *)0x16fc8;
|
||||||
|
int (*sceSifDmaStat)(int trid) = (void *)0x17170;
|
||||||
|
void (*flushIcache)(void) = (void*)0x2f40;
|
||||||
|
void (*flushDcache)(void) = (void*)0x3148;
|
||||||
|
void (*printf)(char *, ...) = (void *)0x1ab84;
|
||||||
|
|
||||||
|
static void transfer_to_ee(void *dest, void *src, unsigned int size);
|
||||||
|
static void *memcpy(void *dest, void *src, 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 readData(void *dest, unsigned int offset, size_t n) {
|
||||||
|
//unsigned char buffer[SECTOR_SIZE];
|
||||||
|
//unsigned char *buffer = (void *)0xfd000;
|
||||||
|
unsigned char *buffer = (void *)0xba000; // single
|
||||||
|
|
||||||
|
unsigned int copied = 0;
|
||||||
|
#define remaining (n - copied)
|
||||||
|
|
||||||
|
if(offset % SECTOR_SIZE) {
|
||||||
|
readSectors(1, offset / SECTOR_SIZE, buffer);
|
||||||
|
memcpy(dest, buffer + offset % SECTOR_SIZE, min(SECTOR_SIZE - (offset % SECTOR_SIZE), n));
|
||||||
|
copied += min(SECTOR_SIZE - (offset % SECTOR_SIZE), n);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(remaining >= SECTOR_SIZE) {
|
||||||
|
readSectors(remaining / SECTOR_SIZE, (offset + copied) / SECTOR_SIZE, dest + copied);
|
||||||
|
copied += (remaining / SECTOR_SIZE) * SECTOR_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(remaining > 0) {
|
||||||
|
readSectors(1, (offset + copied) / SECTOR_SIZE, buffer);
|
||||||
|
memcpy(dest + copied, buffer, remaining);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef remaining
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read data but don't care about over/under writing to dest
|
||||||
|
static void readDataUnsafe(void *dest, unsigned int offset, size_t n) {
|
||||||
|
unsigned int sectorAlignedOffset = offset & ~(SECTOR_SIZE - 1);
|
||||||
|
unsigned int underflow = offset - sectorAlignedOffset;
|
||||||
|
|
||||||
|
readSectors((n + underflow + SECTOR_SIZE - 1) / SECTOR_SIZE, sectorAlignedOffset / SECTOR_SIZE, dest - underflow);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _start(void) {
|
||||||
|
extern unsigned char ee_crt0[];
|
||||||
|
extern unsigned int ee_crt0_size;
|
||||||
|
void *return_address = EE_CRT0_ADDRESS;
|
||||||
|
int one = 1;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
transfer_to_ee(EE_CRT0_ADDRESS, ee_crt0, ee_crt0_size);
|
||||||
|
|
||||||
|
/* Corrupt all known return addresses in the stack.
|
||||||
|
*/
|
||||||
|
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 *)0x12D1C70, &return_address, sizeof(return_address)); /* 2.10U */
|
||||||
|
|
||||||
|
|
||||||
|
// Clear bit 0 of 0x208bb710 to make EE exit loop waiting for IOP, and return to our above payload
|
||||||
|
//unsigned int loopValue = 0x010004;
|
||||||
|
//transfer_to_ee((void *)0x208bb710, &loopValue, sizeof(loopValue)); // 2.10E
|
||||||
|
|
||||||
|
|
||||||
|
//unsigned char *buffer = (void *)0xfe000;
|
||||||
|
unsigned char *buffer = (void *)0xBB800;
|
||||||
|
size_t sizeofbuffer = 2 * SECTOR_SIZE; // todo: find a nice large space 4 sectors maybe
|
||||||
|
|
||||||
|
elf_header_t eh;
|
||||||
|
readData(&eh, LOAD_ELF_FROM_OFFSET, sizeof(elf_header_t));
|
||||||
|
|
||||||
|
elf_pheader_t eph[eh.phnum];
|
||||||
|
readData(&eph, LOAD_ELF_FROM_OFFSET + eh.phoff, sizeof(elf_pheader_t) * eh.phnum);
|
||||||
|
|
||||||
|
for (i = 0; i < eh.phnum; i++) {
|
||||||
|
if (eph[i].type != ELF_PT_LOAD)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// TODO: handle non-16byte aligned transfers
|
||||||
|
|
||||||
|
unsigned int copied = 0;
|
||||||
|
int remaining = eph[i].filesz;
|
||||||
|
while(remaining > 0) {
|
||||||
|
unsigned int k = min(remaining, sizeofbuffer);
|
||||||
|
k = (k + 0xf) & ~0xf;
|
||||||
|
|
||||||
|
// If offset is not aligned to a sector, start with a smaller transfer to get it aligned for future reads
|
||||||
|
if((eph[i].offset + copied) & (SECTOR_SIZE - 1)) k = SECTOR_SIZE - (eph[i].offset + copied) & (SECTOR_SIZE - 1);
|
||||||
|
|
||||||
|
//readData(buffer, LOAD_ELF_FROM_OFFSET + eph[i].offset + copied, k);
|
||||||
|
readDataUnsafe(buffer, LOAD_ELF_FROM_OFFSET + eph[i].offset + copied, k);
|
||||||
|
|
||||||
|
transfer_to_ee(eph[i].vaddr + copied, buffer, k);
|
||||||
|
copied += k;
|
||||||
|
remaining -= k;
|
||||||
|
}
|
||||||
|
|
||||||
|
copied = 0;
|
||||||
|
remaining = eph[i].memsz - eph[i].filesz;
|
||||||
|
|
||||||
|
if(remaining > 0) {
|
||||||
|
// First transfer needs to respect if load size isn't multiple of 16 bytes and not memset 0 over the final eph[i].filesz % 16 bytes
|
||||||
|
if(eph[i].filesz % 16) {
|
||||||
|
readData(buffer, LOAD_ELF_FROM_OFFSET + eph[i].offset + eph[i].filesz - (eph[i].filesz % 16), eph[i].filesz % 16);
|
||||||
|
memset(buffer + (eph[i].filesz % 16), 0, 16 - (eph[i].filesz % 16));
|
||||||
|
transfer_to_ee(eph[i].vaddr + eph[i].filesz - (eph[i].filesz % 16), buffer, 16);
|
||||||
|
|
||||||
|
copied += 16 - (eph[i].filesz % 16);
|
||||||
|
remaining -= 16 - (eph[i].filesz % 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(buffer, 0, sizeofbuffer);
|
||||||
|
}
|
||||||
|
while(remaining > 0) {
|
||||||
|
unsigned int k = min(remaining, sizeofbuffer);
|
||||||
|
k = (k + 0xf) & ~0xf;
|
||||||
|
|
||||||
|
transfer_to_ee(eph[i].vaddr + eph[i].filesz + copied, buffer, k);
|
||||||
|
copied += 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));
|
||||||
|
|
||||||
|
/* Signal EE that the ELF is loaded and ready to execute.
|
||||||
|
*/
|
||||||
|
transfer_to_ee(EE_WAIT_ADDRESS, &one, sizeof(one));
|
||||||
|
|
||||||
|
//int loopValueJ = 0;
|
||||||
|
//transfer_to_ee((void *)0x205ea210, &loopValueJ, sizeof(loopValueJ)); // 2.10J
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dest and src should be aligned to 16 byte boundary
|
||||||
|
*/
|
||||||
|
static void transfer_to_ee(void *dest, void *src, unsigned int size)
|
||||||
|
{
|
||||||
|
int trid;
|
||||||
|
|
||||||
|
size = size & 0x3FFFFFFF;
|
||||||
|
struct SifDmaTransfer t = { src, dest, size, 0 };
|
||||||
|
|
||||||
|
/* These could be sent in parallel, but is it really worth it?
|
||||||
|
*/
|
||||||
|
trid = sceSifSetDma(&t, 1);
|
||||||
|
while(sceSifDmaStat(trid) > -1){};
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *memcpy(void *dest, void *src, unsigned int n)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; i < n; i++)
|
||||||
|
((unsigned char *)dest)[i] = ((unsigned char *)src)[i];
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *memset(void *s, int c, unsigned int n)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; i < n; i++)
|
||||||
|
((unsigned char *)s)[i] = c;
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
asm("\n\
|
||||||
|
.global ee_crt0\n\
|
||||||
|
ee_crt0:\n\
|
||||||
|
.align 8\n\
|
||||||
|
.incbin \"eepayload.ee.bin\"\n\
|
||||||
|
ee_crt0_size: .word . - ee_crt0\n\
|
||||||
|
");
|
||||||
BIN
PAYLOADS/2.10/ioppayload.iop.elf
Normal file
BIN
PAYLOADS/2.10/ioppayload.iop.elf
Normal file
Binary file not shown.
48
PAYLOADS/2.10/stage1.iop.S
Normal file
48
PAYLOADS/2.10/stage1.iop.S
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
# ElReino & CTurt 2020
|
||||||
|
|
||||||
|
# entry 0xb7548 # repacked
|
||||||
|
# entry (0xb7548 + 0x5c700 - 0xb1000) = 0x62C48 (0xa0062C48) # hardware
|
||||||
|
|
||||||
|
|
||||||
|
#readSector = 0xb260c # repacked
|
||||||
|
readSector = (0xb260c + 0x5c700 - 0xb1000) # real hardware
|
||||||
|
|
||||||
|
flushIcache = 0x00002f40
|
||||||
|
flushDcache = 0x0003044
|
||||||
|
|
||||||
|
flushDcacheWrapper = 0x0057f1c
|
||||||
|
|
||||||
|
#iop_payload_address = 0x460000
|
||||||
|
#iop_payload_address = 0xa0460000
|
||||||
|
iop_payload_address = 0xa00fd000
|
||||||
|
|
||||||
|
.section .text
|
||||||
|
|
||||||
|
.global _start
|
||||||
|
_start:
|
||||||
|
move $fp, $sp # We need to reset $fp as it gets trashed by memcpy
|
||||||
|
|
||||||
|
la $a0, (IOP_PAYLOAD_SIZE / 0x800) + 1 # count
|
||||||
|
la $a1, 0x700000 / 0x800 # sector
|
||||||
|
la $a2, iop_payload_address # destination
|
||||||
|
jal readSector
|
||||||
|
|
||||||
|
#jal flushIcache
|
||||||
|
#jal flushDcache
|
||||||
|
|
||||||
|
#jal ENTRY
|
||||||
|
la $v0, ENTRY
|
||||||
|
jalr $v0
|
||||||
|
|
||||||
|
# Return gracefully back to original return address
|
||||||
|
#la $a0, 0x1f62ac # repacked
|
||||||
|
la $a0, (0x1f62ac + 0x1F3058 - 0x1f6258) # hardware
|
||||||
|
|
||||||
|
#la $ra, 0xb3630 # repacked
|
||||||
|
la $ra, (0xb3630 + 0x5c700 - 0xb1000) # hardware
|
||||||
|
|
||||||
|
sw $ra, 0($a0)
|
||||||
|
|
||||||
|
la $v0, 0
|
||||||
|
|
||||||
|
jr $ra
|
||||||
BIN
PAYLOADS/2.10/stage1.iop.bin
Normal file
BIN
PAYLOADS/2.10/stage1.iop.bin
Normal file
Binary file not shown.
BIN
PAYLOADS/2.10/stage1.iop.elf
Normal file
BIN
PAYLOADS/2.10/stage1.iop.elf
Normal file
Binary file not shown.
69
PAYLOADS/2.10/syscalls.ee.S
Normal file
69
PAYLOADS/2.10/syscalls.ee.S
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
# ElReino 2020
|
||||||
|
|
||||||
|
# Since GCC does something strange, we can't write syscall thunks directly in C
|
||||||
|
# as GCC adds move $v1, $v0 directly after jr $ra, effectively trashing $v0.
|
||||||
|
# I don't know why this happens, but I do know enough about GCC that this
|
||||||
|
# approach will most probably be easier. But feel free to try fixing it.
|
||||||
|
|
||||||
|
.global SifGetReg
|
||||||
|
SifGetReg:
|
||||||
|
la $v1, 0x7a
|
||||||
|
syscall 0x7a
|
||||||
|
jr $ra
|
||||||
|
|
||||||
|
.global ExecPS2
|
||||||
|
ExecPS2:
|
||||||
|
la $v1, 0x07
|
||||||
|
syscall 0x07 # BTW why do we put the number here also?
|
||||||
|
|
||||||
|
# Not a syscall, but it might as well be.
|
||||||
|
|
||||||
|
.global SifWriteBackDCache
|
||||||
|
SifWriteBackDCache:
|
||||||
|
lui $25, 0xffff
|
||||||
|
ori $25, $25, 0xffc0
|
||||||
|
blez $5, last
|
||||||
|
addu $10, $4, $5
|
||||||
|
and $8, $4, $25
|
||||||
|
addiu $10, $10, -1
|
||||||
|
and $9, $10, $25
|
||||||
|
subu $10, $9, $8
|
||||||
|
srl $11, $10, 0x6
|
||||||
|
addiu $11, $11, 1
|
||||||
|
andi $9, $11, 0x7
|
||||||
|
beqz $9, eight
|
||||||
|
srl $10, $11, 0x3
|
||||||
|
loop1:
|
||||||
|
sync
|
||||||
|
cache 0x18, 0($8)
|
||||||
|
sync
|
||||||
|
addiu $9, $9, -1
|
||||||
|
nop
|
||||||
|
bgtz $9, loop1
|
||||||
|
addiu $8, $8, 64
|
||||||
|
eight:
|
||||||
|
beqz $10, last
|
||||||
|
loop8:
|
||||||
|
addiu $10, $10, -1
|
||||||
|
sync
|
||||||
|
cache 0x18, 0($8)
|
||||||
|
sync
|
||||||
|
cache 0x18, 64($8)
|
||||||
|
sync
|
||||||
|
cache 0x18, 128($8)
|
||||||
|
sync
|
||||||
|
cache 0x18, 192($8)
|
||||||
|
sync
|
||||||
|
cache 0x18, 256($8)
|
||||||
|
sync
|
||||||
|
cache 0x18, 320($8)
|
||||||
|
sync
|
||||||
|
cache 0x18, 384($8)
|
||||||
|
sync
|
||||||
|
cache 0x18, 448($8)
|
||||||
|
sync
|
||||||
|
bgtz $10, loop8
|
||||||
|
addiu $8, $8, 512
|
||||||
|
last:
|
||||||
|
jr $31
|
||||||
|
nop
|
||||||
BIN
PAYLOADS/2.10/syscalls.ee.o
Normal file
BIN
PAYLOADS/2.10/syscalls.ee.o
Normal file
Binary file not shown.
BIN
PREBUILT ISOs/2.10.iso
Normal file
BIN
PREBUILT ISOs/2.10.iso
Normal file
Binary file not shown.
22
README.md
22
README.md
|
|
@ -3,6 +3,10 @@ PlayStation 2 DVD Player Exploit. This allows you to burn your own PlayStation 2
|
||||||
|
|
||||||
For technical details please refer to my [blog post](https://cturt.github.io/freedvdboot.html).
|
For technical details please refer to my [blog post](https://cturt.github.io/freedvdboot.html).
|
||||||
|
|
||||||
|
Read from [here](#easy-setup-for-all-ps2-slim-consoles--bravia-tv) if you have a Slim PS2.
|
||||||
|
|
||||||
|
Read from [here](#phat-consoles) if you have a Phat PS2.
|
||||||
|
|
||||||
## Easy setup for all PS2 Slim consoles / Bravia TV
|
## Easy setup for all PS2 Slim consoles / Bravia TV
|
||||||
All you need is:
|
All you need is:
|
||||||
|
|
||||||
|
|
@ -57,13 +61,15 @@ Other suggestions that worked for others:
|
||||||
## Phat consoles
|
## Phat consoles
|
||||||
Phat consoles have many different firmware version revisions, which makes them harder to add support for. It also means you will need to identify your firmware version, and burn the matching ISO file.
|
Phat consoles have many different firmware version revisions, which makes them harder to add support for. It also means you will need to identify your firmware version, and burn the matching ISO file.
|
||||||
|
|
||||||
It's still early in terms of support for different versions, check back here later. Hopefully over time other developers from the scene will also contribute support for additional DVD Player versions.
|
It's still early in terms of support for different versions, check back here later. Hopefully over time other developers from the scene will also contribute support for additional DVD Player versions. The new exploit for 2.10 should be possible to port to all firmwares between 1.00 - 2.13 (Sony actually patched this one in 2.14 lol).
|
||||||
|
|
||||||
### Step 1: Identify your DVD Player Version
|
### Step 1: Identify your DVD Player Version
|
||||||
Boot your PlayStation 2 without any disc inserted, and press Triangle to identify which DVD Player version your console has.
|
Boot your PlayStation 2 without any disc inserted, and press Triangle to identify which DVD Player version your console has.
|
||||||
|
|
||||||
**Currently only support:**
|
**Currently only support:**
|
||||||
|
|
||||||
|
- 2.10 (tested on U and J regions on real hardware, any language works),
|
||||||
|
|
||||||
- 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),
|
||||||
|
|
||||||
### Step 2: Download the ISO
|
### Step 2: Download the ISO
|
||||||
|
|
@ -71,12 +77,12 @@ Download the ISO that corresponds to your firmware version.
|
||||||
|
|
||||||
**Please don't bother trying on a non-supported firmware/language configuration, it won't work...**
|
**Please don't bother trying on a non-supported firmware/language configuration, it won't work...**
|
||||||
|
|
||||||
For example, if your DVD Player version is 3.04M, you would want to burn `PREBUILT ISOs/3.04 only - M+maybe other regions except J - English language.iso`.
|
For example, if your DVD Player version is 2.10J, you would want to download `PREBUILT ISOs/2.10.iso`.
|
||||||
|
|
||||||
### Step 3, 4, 5 - Burn the ISO, set console language to English, and boot!
|
### Step 3, 4, 5 - Burn the ISO, set console language to English, and boot!
|
||||||
These steps are the same as described for slim above.
|
These steps are the same as described for slim above.
|
||||||
|
|
||||||
## Custom disc setup
|
## Custom disc setup - Slim
|
||||||
If you intend to make your own image containing additional homebrew / modified initial loader, please read on.
|
If you intend to make your own image containing additional homebrew / modified initial loader, please read on.
|
||||||
|
|
||||||
### Step 1: Copy your homebrew
|
### Step 1: Copy your homebrew
|
||||||
|
|
@ -94,7 +100,10 @@ On Linux the easiest way is probably to use `genisoimage` as it comes pre-instal
|
||||||
### Step 3: Test and burn
|
### Step 3: Test and burn
|
||||||
I would recommend you test in PCSX2 first, but since [PCSX2 doesn't support loading the DVD Player](https://github.com/PCSX2/pcsx2/issues/1981), you have to decrypt and repack it yourself, which is beyond the scope of this README. With that said, if you aren't touching anything in `VIDEO_TS`, there shouldn't really be any reason for the exploit to fail.
|
I would recommend you test in PCSX2 first, but since [PCSX2 doesn't support loading the DVD Player](https://github.com/PCSX2/pcsx2/issues/1981), you have to decrypt and repack it yourself, which is beyond the scope of this README. With that said, if you aren't touching anything in `VIDEO_TS`, there shouldn't really be any reason for the exploit to fail.
|
||||||
|
|
||||||
## Replacing the initial program
|
## Custom disc setup - Phat
|
||||||
|
Instructions for building the phat exploit coming soon.
|
||||||
|
|
||||||
|
## Replacing the initial program - Slim
|
||||||
I've included uLaunchELF recompiled with [DVD support](https://github.com/ps2dev/ps2sdk/pull/130) as the default initial program. It presents a menu which allows you to select any of the homebrew programs you chose to include on the disc (and also allows booting from USB).
|
I've included uLaunchELF recompiled with [DVD support](https://github.com/ps2dev/ps2sdk/pull/130) as the default initial program. It presents a menu which allows you to select any of the homebrew programs you chose to include on the disc (and also allows booting from USB).
|
||||||
|
|
||||||
Alternatively, if you would rather just boot into a single homebrew application, the initial program the exploit attempts to boot is located at `VIDEO_TS/VTS_02_0.IFO`, replace it with your desired `ELF` file, with the below caveat that compatibility might be lower than if you booted a program through uLaunchELF:
|
Alternatively, if you would rather just boot into a single homebrew application, the initial program the exploit attempts to boot is located at `VIDEO_TS/VTS_02_0.IFO`, replace it with your desired `ELF` file, with the below caveat that compatibility might be lower than if you booted a program through uLaunchELF:
|
||||||
|
|
@ -117,10 +126,13 @@ You can run `readelf -l` to verify your executable satisfies this requirement. F
|
||||||
Segment Sections...
|
Segment Sections...
|
||||||
00 .text .ctors .dtors .rodata .data .jcr .sdata .sbss .bss
|
00 .text .ctors .dtors .rodata .data .jcr .sdata .sbss .bss
|
||||||
|
|
||||||
|
## Replacing the initial program - Phat
|
||||||
|
The ELF is read from `0x5bb000` in the ISO file.
|
||||||
|
|
||||||
## Loading backups
|
## Loading backups
|
||||||
It's possible to patch backup images of commercial games to make them bootable using this exploit. I didn't want to maintain this tool, so it's not included in this repository, but can be found by searching for something like FreeDVDBoot ESR auto patcher.
|
It's possible to patch backup images of commercial games to make them bootable using this exploit. I didn't want to maintain this tool, so it's not included in this repository, but can be found by searching for something like FreeDVDBoot ESR auto patcher.
|
||||||
|
|
||||||
## DEVELOPMENT: Replacing the loader payload
|
## DEVELOPMENT: Replacing the loader payload - Slim
|
||||||
The default payload will boot `VIDEO_TS/VTS_02_0.IFO` as an ELF file, but tweaks might be desired to improve compatibility, or maybe changing the behaviour to boot `BOOT.ELF` instead for instance.
|
The default payload will boot `VIDEO_TS/VTS_02_0.IFO` as an ELF file, but tweaks might be desired to improve compatibility, or maybe changing the behaviour to boot `BOOT.ELF` instead for instance.
|
||||||
|
|
||||||
If you wish to update the loader payload, run `build.sh` inside `PAYLOAD` directory, and copy the output `.bin` files into `VIDEO_TS/VIDEO_TS.IFO` at the offsets displayed by the output of the command.
|
If you wish to update the loader payload, run `build.sh` inside `PAYLOAD` directory, and copy the output `.bin` files into `VIDEO_TS/VIDEO_TS.IFO` at the offsets displayed by the output of the command.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue