Code:
/*
Filename: rom0:EELOAD
Description: EE executable Loader
BIOS version: v1.01
Host console: SCPH-10000
Date: 2012/04/13
Arguments:
argv[0]=<filename of ELF to load> or <"moduleload">
(Or if "moduleload" was specified as the first argument):
argv[1...n]= commands, where:
"-m <module to load>" -> Loads a regular IOP module.
"-k <Encrypted module to load>" -> Loads an encrypted IOP module.
"-x <Encrypted program to load>" -> Loads and executes an encrypted EE program.
(Strings remaining in the argv[] array are arguments that are to be passed to the loaded program)
Other notes: If no arguments are specified, it loads rom0:OSDSYS.
*/
#include <sifrpc.h>
#include <loadfile.h>
#include <iopcontrol.h>
#include <kernel.h>
#include <dma_registers.h>
static int var_000869a8;
static t_ExecData ElfData;
/* 0x000825a0 */
static void func_000825a0(void){
/* TODO! Seems to be the same function that some Sony programs will call before doing anything. Probably not program-specific stuff. */
}
/* 0x000869a8 */
static void func_00082640(void){
if(var_000869a8==0){
var_000869a8=1;
func_000825a0
}
}
/* 0x000820e8 */
static void func_000820e8(void){
int i;
if(*DMA_REG_STAT&0x20){
SifSetDChain();
*DMA_REG_STAT=0x20;
while(*(volatile unsigned int *)0x1000f240&0x3000){
__asm("nop\nnop\nnop\n");
}
for(i=0x1000; i>0; i--) __asm("nop\nnop\nnop\nnop\nnop\n");
}
}
static const char IOPRP_path[8]="";
/* 0x00082170 */
static void func_00082170(void){
while((*EE_SBUS_SMFLAG&0x00040000)==0) __asm("nop\nnop\nnop\n");
*EE_SBUS_SMFLAG=0x00040000;
}
/* 0x000821b0 */
static void ResetIOP(void){
SifIopReset(IOPRP_path, 0);
while(!SifIopSync()){};
func_00082170();
}
/* 0x000821e0 */
static void func_000821e0(void){ /* Seems to have been written in asm. */
FNC_000821e0: #
lui v0, $1000 # 000821e0:3c021000 v0=$10000000
ori v0, v0, $f240 # 000821e4:3442f240 v0=reg_1000f240
lw v1, $0000(v0) # 000821e8:8c430000 v1=reg_1000f240
andi v1, v1, $0020 # 000821ec:30630020
beq v1, zero, $00082254 # 000821f0:10600018 v __00082254
lui v1, $0001 # 000821f4:3c030001 v1=$00010000
__000821f8: #
di # 000821f8:42000039
sync.p # 000821fc:0000040f
mfc0 v0, Status # 00082200:40026000
and v0, v0, v1 # 00082204:00431024
nop # 00082208:00000000
bne v0, zero, $000821f8 # 0008220c:1440fffa ^ __000821f8
nop # 00082210:00000000
mfc0 v1, Status # 00082214:40036000
lui v0, $ffff # 00082218:3c02ffff v0=$ffff0000
ori v0, v0, $ffe7 # 0008221c:3442ffe7 v0=$ffffffe7
and v1, v1, v0 # 00082220:00621824
mtc0 v1, Status # 00082224:40836000
sync.p # 00082228:0000040f
lui v0, $bd00 # 0008222c:3c02bd00 v0=$bd000000
addiu v1, zero, $0020 # 00082230:24030020 v1=$00000020
ori v0, v0, $0040 # 00082234:34420040 v0=$bd000040
sw v1, $0000(v0) # 00082238:ac430000 [bd000040]
sync # 0008223c:0000000f
mfc0 v1, Status # 00082240:40036000
ori v1, v1, $0010 # 00082244:34630010
mtc0 v1, Status # 00082248:40836000
sync.p # 0008224c:0000040f
ei # 00082250:42000038
__00082254: #
lui v0, $1000 # 00082254:3c021000 v0=$10000000
ori v0, v0, $e010 # 00082258:3442e010 v0=DMA_REG_STAT
lw v1, $0000(v0) # 0008225c:8c430000 v1=DMA_REG_STAT
andi v1, v1, $0020 # 00082260:30630020
beq v1, zero, $00082274 # 00082264:10600003 v __00082274
addiu v0, zero, $0020 # 00082268:24020020 v0=$00000020
lui at, $1001 # 0008226c:3c011001 at=$10010000
sw v0, $e010(at) # 00082270:ac22e010 DMA_REG_STAT
__00082274: #
jr ra # 00082274:03e00008
}
/* 0x00082318 */
static void BootError(const char *path){
char *argv[2];
SifExitRpc();
argv[0]="BootError";
argv[1]=path;
ExecOSD(2, argv);
}
/* 0x000822c0 */
static void ExecExecutable(int argc, char **argv){
FlushCache(0);
SifExitRpc();
ExecPS2((void *)ElfData.epc, (void *)ElfData.gp, argc, argv);
}
static const char OSDSYS_path[]="rom0:OSDSYS";
static const char *DefaultBootData[]={OSDSYS_path, 0x00000000};
/* 0x00082280
Returns NULL if the argument doesn't contain the specified switch, otherwise, returns the first character after the switch.
*/
static const char *IsSwitchCheck(const char *SwitchString, const char *cmd){
while(*SwitchString!='\0'){
if(*SwitchString!=*cmd) return NULL;
SwitchString++;
cmd++;
}
return cmd;
}
int main(int argc, char **argv){
const char *CommandString;
int value;
if(argc>=2){
argv++;
argc--;
func_000820e8();
ResetIOP();
func_000821e0();
SifInitRpc(0);
/* 0x000823cc */
if(IsSwitchCheck("moduleload", argv[0])!=NULL){
argc--;
argv++;
while(argc>0){
if((CommandString=IsSwitchCheck("-m ", argv[0]))!=NULL){
SifLoadModule(CommandString, 0, NULL);
}
else if((CommandString=IsSwitchCheck("-k ", argv[0]))!=NULL){
SifLoadModuleEncrypted(CommandString, 0, NULL);
}
else if((CommandString=IsSwitchCheck("-x ", argv[0]))!=NULL){
FlushCache(0);
if(SifLoadElfEncrypted(CommandString, &ElfData)<0){
BootError(CommandString);
}
ExecExecutable(argc, argv);
}
else break;
argc--;
argv++;
}
}
FlushCache(0);
if(SifLoadElf(argv[0], &ElfData)<0){
BootError(argv[0]);
}
ExecExecutable(argc, argv);
}
value=0;
func_00082170();
SifInitRpc(0);
FlushCache(0);
while(value==0){
if(SifLoadElf(DefaultBootData[0], &ElfData)<0){
value=1;
}
}
ExecExecutable(1, DefaultBootData[value]);
return 0;
}
So you can all see here that rom0:EELOAD basically calls SifLoadElf() again to load rom0:OSDSYS when it fails to load the ELF/KELF you tell it to. However, so far I've found that it usually results in a BSOD for some reason...