From badb624e2c182362b1306fec48bd5396942e6b52 Mon Sep 17 00:00:00 2001 From: CTurt Date: Sun, 14 Jun 2020 16:40:36 +0100 Subject: [PATCH] Add payload --- PAYLOAD/build.sh | 14 ++++ PAYLOAD/crt0.S | 63 ++++++++++++++++++ PAYLOAD/fullpayload.bin | Bin 0 -> 2044 bytes PAYLOAD/fullpayload.elf | Bin 0 -> 8454 bytes PAYLOAD/payload.bin | Bin 0 -> 944 bytes PAYLOAD/payload.c | 142 ++++++++++++++++++++++++++++++++++++++++ PAYLOAD/payload.elf | Bin 0 -> 5374 bytes README.md | 5 ++ 8 files changed, 224 insertions(+) create mode 100644 PAYLOAD/build.sh create mode 100644 PAYLOAD/crt0.S create mode 100644 PAYLOAD/fullpayload.bin create mode 100644 PAYLOAD/fullpayload.elf create mode 100644 PAYLOAD/payload.bin create mode 100644 PAYLOAD/payload.c create mode 100644 PAYLOAD/payload.elf diff --git a/PAYLOAD/build.sh b/PAYLOAD/build.sh new file mode 100644 index 0000000..f1ba774 --- /dev/null +++ b/PAYLOAD/build.sh @@ -0,0 +1,14 @@ +echo "Building payload" + +ee-gcc -Ttext=0x01FFF800 payload.c -o payload.elf -nostartfiles -nostdlib -ffreestanding -Os -Wl,-z,max-page-size=0x1 # 2048 +ee-objcopy -O binary payload.elf payload.bin -Wl,-z,max-page-size=0x1 + +ENTRY=`ee-objdump -t payload.elf | grep " _start"` +ENTRY=0x`grep -o "^\S*" <<< $ENTRY` + +echo "Building crt0" + +ee-gcc -Ttext=0x01500014 -DENTRY=$ENTRY crt0.S -o fullpayload.elf -nostartfiles -nostdlib -ffreestanding -Wl,-z,max-page-size=0x1 +ee-objcopy -O binary fullpayload.elf fullpayload.bin -Wl,-z,max-page-size=0x1 + +echo "Done. Insert fullpayload.bin into VIDEO_TS.IFO at offset 0x2bb4" diff --git a/PAYLOAD/crt0.S b/PAYLOAD/crt0.S new file mode 100644 index 0000000..88ab446 --- /dev/null +++ b/PAYLOAD/crt0.S @@ -0,0 +1,63 @@ +.set noreorder # If we're writing assembly, why would we want this? + +.section .text.startup + +.equ memcpy, 0x225668 +.equ getBufferInternal, 0x2986a0 +.equ payload, (0x2000000 - 0x800) # End of RAM + +.global _start +_start: + #la $a0, 0x7f + #la $v1, 0x01 + #syscall 0x01 # ResetEE + + #la $a0, relo + la $a0, load + la $a1, 0 + la $a2, 0 + la $a3, 0 + +.global ExecPS2 +ExecPS2: + la $v1, 7 + syscall 7 # ExecPS2 + +load: + la $a0, 0 + la $a1, 0 # 0 = VIDEO_TS.IFO, 1 = VTS_01_0.IFO + la $a2, 0x3000 / 0x800 # lba offset in file + la $a3, payload # Destination + la $t0, 0x800 / 0x800 # Count + la $t1, 0 + la $v0, getBufferInternal + jalr $v0 + nop + +#relo: + # Relocate payload to end of RAM +# la $a0, (0x2000000 - 1024) +# la $a1, payload +# la $a2, 2048 +# la $v0, memcpy +# jalr $v0 + +boot: + la $v1, 0x64; la $a0, 0; syscall 0x64 # FlushCache data writeback + la $v1, 0x64; la $a0, 2; syscall 0x64 # FlushCache instruction invalidate + + # Point stack to end of scratchpad RAM + la $sp, 0x70004000 + + # Execute from relocated place + la $v0, ENTRY + j $v0 + nop + +.space (_start + 0x2faa - 0x2bb4) - . +fpIndex: + .byte 0x7e + .byte 0xe0 + +.space (_start + 0x3000 - 0x2bb4) - . +.incbin "payload.bin" diff --git a/PAYLOAD/fullpayload.bin b/PAYLOAD/fullpayload.bin new file mode 100644 index 0000000000000000000000000000000000000000..b8dfce968e0daf1b16238a723a3d3ab8fe7fe86c GIT binary patch literal 2044 zcmeHIzfTlF6#jPhehf%4oWw|s$*#9@hcL-{xkO^FSU4~i1h6o%urNeBj2Hg^-2|dk z2eH9&W25DXwkMYh8Z{R77Dp_^l1>PT<9oYDkiybv!6v&qGw=J}`{vup+c_&$@v-Cq zX}U9XXT2cb^`|DHgOo=H<*k?cZ}NE z3WDY(V-bFDqAZc%W76^C*nwjQ{(%Dzw*E%ZgT5iLWpjQVgy=y_=`p}n&*3^*>MGS$ z3)|j^`bLPwXwL)#jAf2iu(AjE(~oh8yA$mn!G(x^Gz;xq8cM!2dMvW_a)dy>HjZ33 zItpR3r4j`7Hu=iLJxex>e%ivE+%WnoD0kY^et;MIOWr7gQ#u6lswQ0D7wsnk%!Qm7 zb;njkj3rLHl!@_!2$T*2;VM6gQGKp)0<|3HW^TJAFbs=&q)R>0iFvNGDs(ZjQ$HW} z<^7rZgJfnQ746V zLeU$}3$CMmh>yhKy*Z{?pgBHc!*G9Y;f>KnpaJr5C$b|n%z4rrzE3pkWl*U#wq;5uFRWZb5j1 zm{%4q4srZ~Iw$xXI8Z}>{Ev{QTuYLct=UA2q;JP_buF254LT=rEqcW76w-BtOr7;e zq-bo{2O#Qszlsqxj}GCJys3IWVO(bsU&t@k#ks@r?!KL*wyGZ1VlQuCbA``0x?Zq` d`}gkpm#0d%Zx9{!j*lR&Tp)G{6 z1FL!8d*8fy^X6$rXwMIf999$svZ>I)s2O8Q7xlkB4=9PtW*1D-x1k@u8iXD3uT+w{*I_sr6l9qYqYjOjNVYmolur1Q>-Cvfe-LbL;kXRI>N zVieR!Jg%-?R>5PT_jW`MR#cZuW7axrUH%><3@edPBSu`KzN&FvU7KlZ(^$JwPx<2bt+GvZp)Dy;qkE7x6uh#Z?JpbqRIURP#{Ng%Ba~B~ zi~h0h-Z&~^(P{4(8*d5Bb5NbQbJ2&}hfuR*pmvGl(Gen9TWW^7)DrK*0V9od;tRi_ zrAFdJ%nSH|^2Kqn?{bf~Zd1%{^li_@xjccJm$<&+<$_}<&g9~+AMYO>FBFRmv*J8>`dr4B7awxkdN{_1{rnroQ7jsx<1ad;P** zpowsWdiSRd$-_49sc5~M4xJO*@-7n3yt5CiCl|0Uw!3l%Q|>tm>-n9@b$v{E|E}Y_ zM)LQbe2Ca6i&BGbKzEhVq&0S#*!jSVA&MWKSMAn;joJ)`?_R49(^<#AaviJ1Mz-x%PVhx~pW#buS*D zjo(?x{2nJg`>5tfI{WbZF{Oce_9Nq9KTp&1C_i+2Jkk%DTpM!$$Kg-*-A^^dxR$U% zb+quCzzq`rF0fm}Z1?!P$zCCR^A}+^J>2i%Ru3~7>jrh`@+hKQ{QWc)}+vx&n z{q~VgHn|S&MXd_U!i&HLDeDOG4>$HlsdBO3U&aKkl3q6HPhx-1`DU!SD-d}VSj^1% z6Ijf!jeQGq$J5GvP2-IDnkL>_Z)vox6IrMcI9&mHkQ;{-_E=-bXuclz(ljA7=1oF$+dL2gbER{*u*q}^du8?h)@TYw1}Z~@R}8?|4NxVH?{k7m{{bHCyZhez-n-|o0Nej)0TO#Q=+R+> z2@I5O0-kyX&n-~3)wS@=udA#2Gg78NQ5A=`a+Y3Pv^3XN_a%l(;u@hYf+Vu;!D8 z-rU4bH{*G3SLj+|JHPKwRf3KnFDZFW$zw{sQ@Tq^K2y%(rtDY$>( z40(>;jXdiOAS4{0?Y|$N)dqHm-Rd0j{weNH{58DYx`8*FVKI-&_op`Jn$_IIUc+!} zlJa8zI!b6R?AU_v%V;YL=V!QnPMsD!2QJjiEt(;a=2RKrHT&c>XUbZVyzH%xyh!?Y zyjNF8d)A;i$+YN|eI4Xtg?!9@Bph1X@iatS30kPDHd4Zm`Z{ruFrK@P&y*MY;@;81 x_}=bFTeS|gILqtU-Q@YkI1Bc0@9v%8!nMVfWj9+bEiJDuEVfoIaqWM4{s0s7y{rHL literal 0 HcmV?d00001 diff --git a/PAYLOAD/payload.c b/PAYLOAD/payload.c new file mode 100644 index 0000000..88b061d --- /dev/null +++ b/PAYLOAD/payload.c @@ -0,0 +1,142 @@ +#include + +#define min(a, b) (((a) < (b)) ? (a) : (b)) + +#define pointToIFO ((void (*)(unsigned int index, unsigned int lba, unsigned int offset))0x25c880) +#define getDiscData ((void (*)(unsigned int s, void *d))0x25c9f0) +#define getDiscBuffer ((void (*)(void))0x25c678) + +#define sceCdSync ((void (*)(int mode))0x2a69c8) + +typedef struct { + unsigned int lsn; + unsigned int size; + char name[16]; + unsigned char date[8]; +} sceCdlFILE; +#define sceCdSearchFile ((int (*)(sceCdlFILE *, char *, int))0x2a6488) + +#define SifIopReset ((int (*)(char *, int))0x84fe0) +#define SifIopSync ((int (*)(void))0x85110) +#define SifInitRpc ((void (*)(int))0x84180) +#define SifExitRpc ((void (*)(void))0x84310) + +#define getBufferInternal ((int (*)(void *filename, int type, int currentSector, void *dest, unsigned int sectorsRemaining, int curReadPos))0x002986a0) + +#define ELF_PT_LOAD 1 + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; + +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; + +__attribute__((noreturn)) void ExecPS2(void *entry, void *gp, int argc, char **argv) { + asm volatile("la $v1, 7; syscall 7"); + //__builtin_unreachable(); +} + +void *memcpy_(void *dest, void *src, size_t n) { + int i; + for(i = 0; i < n; i++) ((unsigned char *)dest)[i] = ((unsigned char *)src)[i]; + return dest; +} + +void *memset(void *dest, int c, size_t n) { + int i; + for(i = 0; i < n; i++) ((unsigned char *)dest)[i] = c; + return dest; +} + +static void readData(void *dest, unsigned int offset, size_t n) { + unsigned char buffer[0x800]; + + unsigned int copied = 0; + #define remaining (n - copied) + + if(offset % 0x800) { + getBufferInternal("", 1, offset / 0x800, buffer, 1, 0); + memcpy_(dest, buffer + offset % 0x800, min(0x800 - offset, n)); + copied += min(0x800 - offset, n); + } + + if(remaining >= 0x800) { + getBufferInternal("", 1, (offset + copied) / 0x800, dest + copied, remaining / 0x800, 0); + copied += (remaining / 0x800) * 0x800; + } + + if(remaining > 0) { + getBufferInternal("", 1, (offset + copied) / 0x800, buffer, 1, 0); + memcpy_(dest + copied, buffer, remaining); + } +} + +__attribute__((noreturn)) void _start(void) { + //Exit(0); + //asm volatile("la $v1, 0x04; la $a0, 0; syscall 0x04"); + + int i; + + // point to VTS_02_0.IFO + pointToIFO(2, 0, 0); + + // Force a read from VTS_02_0.IFO + char head[64]; + getDiscData(64, &head); + + // Based on https://github.com/AKuHAK/uLaunchELF/blob/master/loader/loader.c + elf_header_t eh; + readData(&eh, 0, sizeof(elf_header_t)); + + elf_pheader_t eph[eh.phnum]; + readData(&eph, eh.phoff, sizeof(elf_pheader_t) * eh.phnum); + + for (i = 0; i < eh.phnum; i++) { + if (eph[i].type != ELF_PT_LOAD) + continue; + + readData(eph[i].vaddr, eph[i].offset, eph[i].filesz); + if(eph[i].memsz > eph[i].filesz) memset(eph[i].vaddr + eph[i].filesz, 0, eph[i].memsz - eph[i].filesz); + } + + 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 + + //while(!SifIopReset("", 0)); + //while(!SifIopSync()); + + //while(!SifIopReset("rom0:UDNL rom0:EELOADCNF", 0)); + SifIopReset("rom0:UDNL rom0:EELOADCNF", 0); + while(!SifIopSync()); + + SifInitRpc(0); + SifExitRpc(); + + ExecPS2((void *)eh.entry, 0, 0, 0); +} diff --git a/PAYLOAD/payload.elf b/PAYLOAD/payload.elf new file mode 100644 index 0000000000000000000000000000000000000000..b73f9724f4faf84aa99d9df001a0d06054998376 GIT binary patch literal 5374 zcmeHLO>9(E6h8Cbw0(t&uLTW+C~xRU3+0VNX$X>dQVU8*AR336c8WFqnY3d9 zVZj&(vMLQ5SWeu?vVsdYNYhlK#szy#rg5PxON@%a@ch1a-|b8XG`cWh(UZP+&Ueo_ z_nv$1x%b`a`QCxPP$(pt46%f$^oJMf0{`3=2_>#NUE-j#5dm+Iyw_b!# z0~=w#Mr#>Z%fMO&)-te`fwc@g-5F>QGx{Aq_?9f0jMPmOrBUW>cfUx){zM{91GLH6 zko+9&uz!NZ1zZghn`lcP*OpL&w%_~_?grW}S9-Y0t|+D7Z?`S9)QN3<>bd(%rhB<0 z3F|Y@v2J>9sVH7UXQvq9?znXe7Yi#Y)|}^FpO>T79nbB@Jw)oFZag739$t*@mc;XJ zQKZ$*873kj1txsgG`D|L`A^udcl# zUtUQx*GucYk4@&)*EuC~Oct)KL%tZlTP&e2%$blF(Jhj-L$YTF^}Fot2J65Pd&e+p zNHAv877@yflQMJ4v2dg8UOJ*;v9NZ;_L~ZG4AhA~7G6FNOWlku^)rmek}za*W|J5* zt?{IE*jXvVUiBNEX@*V2xgg&oUyO@=7kh$vJ8En@Ss9DDJRyr$Sl<%lf-y`@j>iui zPYn(@zSP@0aHJ=d9PFd+siK3)Gs;NbC{&fZvOY%hX)WNurkjj?o2jK+LztHO0) z-Ay9+lf*L>8(iV#E->%?e}d0~$2V}_p^gJ?JuAY^-vmyg&I9@239lDqo3Gb4TwoqF z8b85BYJE~LV$A==XAJiIJ)(TJ6_+6ZuFxq<9vi2G$uz=3`Iz&yK17uPA5}88iu6O?4nBtV!Mu{YFi1b-4z%-k zS>LRZhuIEU$IuTw$v?=!nKP3Ay9}IjBl&Ss$Y;)uO=gB;L(+RDH+1w^r;O*uhw^9B zFGjdssNW*A$O)AvC)Z9yhp$!HcW%q)TH9m0n1KLON_7dh~JVv zotJd#&SWHVt~@*9LSpB=F?8RX~!+XL4vqLM2|qm?mqYMOtM2dmCXo@eY0~r6 zcokaHW@BfILU|jcEbi w1FYvqd!9o)N7})uPl3~)YeGB#UTx1hs>Ua3@Vme~N4U4?U-jwvAHN@e0S_pdbN~PV literal 0 HcmV?d00001 diff --git a/README.md b/README.md index 0adb171..ae761c4 100644 --- a/README.md +++ b/README.md @@ -36,3 +36,8 @@ Once you've placed all the homebrew files you'd like into the directory, generat ## 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 can be a pain. + +## Replacing loader payload +If you wish to work on the loader payload, see run `build.sh` inside `PAYLOAD` directory, and copy the output `fullpayload.bin` to `VIDEO_TS/VIDEO_TS.IFO` at offset `0x2bb4`. + +The default loader will boot `VIDEO_TS/VTS_02_0.IFO` as an ELF file, but tweaks might be desired to improve compatibility.