mirror of https://github.com/PCSX2/pcsx2.git
253 lines
7.6 KiB
C
253 lines
7.6 KiB
C
//
|
|
// iopboot.c
|
|
//
|
|
// this is the c code for the iopboot file in the ps2 rom.
|
|
// this file is located at 0xBFC4A000 in the ps2 bios rom0.
|
|
// modload.irx also from the ps2 bios executes this direct from the rom
|
|
// (no loading to ram first)
|
|
//
|
|
// this is based on florin's disasm and converted to c code by xorloser and zerofrog
|
|
//
|
|
|
|
#include <tamtypes.h>
|
|
#include <stdio.h>
|
|
|
|
#include "iopload.h"
|
|
#include "iopdebug.h"
|
|
#include "iopelf.h"
|
|
#include "romdir.h"
|
|
#include "kloadcore.h"
|
|
|
|
static void kstrcpy(char* dst, const char* src);
|
|
static int kstrlen(const char* src);
|
|
|
|
//BOOT_PARAMS boot_params;
|
|
//u32* next_free_address[0x40]; // up to 64 modules
|
|
|
|
|
|
// this is the start point of execution at 0xBFC4A000
|
|
//
|
|
// it loads the IOPBTCONF module list from rom0 and compiles a
|
|
// list of modules and their addresses.
|
|
//
|
|
// this list is then passed to loadcore as it is executed in order
|
|
// to then load the rest of the modules
|
|
//
|
|
// args: total size of IOP ram in MegaBytes
|
|
// bootinfo flags
|
|
// string containing the reboot image filepath
|
|
// ? doesnt seem to be used
|
|
void _start(int ramMBSize, int bootInfo, char* udnlString, int unk)
|
|
{
|
|
ROMFS ri;
|
|
void *(*sysmem_entry)(u32 iopmemsize);
|
|
void (*loadcore_entry)(BOOT_PARAMS *init);
|
|
int i;
|
|
ROMDIR_INFO romdir_info;
|
|
ROMFILE_INFO romfile_info;
|
|
char conf_filename[10];
|
|
int ram_byte_size, num_lines;
|
|
u32 module_load_addr;
|
|
u32** modules_ptr;
|
|
char* file_data_ptr, *file_data_end;
|
|
void* psysmemstart;
|
|
BOOT_PARAMS* boot_params;
|
|
|
|
if( ramMBSize <= 2 )
|
|
ram_byte_size = 2;
|
|
else
|
|
ram_byte_size = ramMBSize;
|
|
ram_byte_size <<= 20;
|
|
|
|
// compile module list to send to loadcore
|
|
boot_params = (BOOT_PARAMS*)0x30000; // random address, has to be clear before loadcore call
|
|
boot_params->ramMBSize = ramMBSize;
|
|
boot_params->bootInfo = bootInfo;
|
|
boot_params->udnlString = NULL;
|
|
boot_params->moduleAddrs = (u32**)((u32)boot_params + sizeof(BOOT_PARAMS)); // right after
|
|
|
|
// if a undl string is specified, get a copy of it and store a pointer to it
|
|
if(udnlString)
|
|
{
|
|
boot_params->udnlString = (char*)boot_params->moduleAddrs;
|
|
kstrcpy(boot_params->udnlString, udnlString);
|
|
boot_params->moduleAddrs = (u32**)((u32)boot_params->udnlString + ROUND_UP(kstrlen(udnlString) + 8, 4));
|
|
}
|
|
|
|
// find the romdir table in the rom
|
|
if( searchRomDir((u32*)0xBFC00000, (u32*)0xBFC10000, &romdir_info) == NULL )
|
|
{
|
|
__printf("IOPBOOT: failed to find start of rom!\n");
|
|
// error - cant find romdir!
|
|
while(1) *(u8*)0x80000000 = 0;
|
|
}
|
|
|
|
// find the bootconf file in the romdir table
|
|
kstrcpy(conf_filename, "IOPBTCONF");
|
|
conf_filename[8] = '0' + bootInfo;
|
|
if( !searchFileInRom(&romdir_info, conf_filename, &romfile_info) )
|
|
{
|
|
kstrcpy(conf_filename, "IOPBTCONF");
|
|
if( !searchFileInRom(&romdir_info, conf_filename, &romfile_info) )
|
|
{
|
|
__printf("IOPBTCONF file not found!\n");
|
|
// error - cant find conf file!
|
|
while(1) *(u8*)0x80000000 = 1;
|
|
}
|
|
}
|
|
|
|
// count the number of lines in conf file
|
|
file_data_ptr = (char*)romfile_info.fileData;
|
|
file_data_end = (char*)romfile_info.fileData + romfile_info.entry->fileSize;
|
|
{
|
|
num_lines = 0;
|
|
while( file_data_ptr < file_data_end ) {
|
|
// loop until a "newline" charcter is found
|
|
while(file_data_ptr < file_data_end) {
|
|
if(*file_data_ptr++ < ' ')
|
|
break;
|
|
}
|
|
|
|
// loop until a "non-newline" charcter is found
|
|
while(file_data_ptr < file_data_end) {
|
|
if(*file_data_ptr++ >= ' ')
|
|
break;
|
|
}
|
|
|
|
num_lines++;
|
|
}
|
|
num_lines++;
|
|
}
|
|
|
|
// get the addresses of each module
|
|
{
|
|
module_load_addr = 0;
|
|
boot_params->numConfLines = num_lines-1;
|
|
modules_ptr = boot_params->moduleAddrs;
|
|
char* file_data_ptr = (char*)romfile_info.fileData;
|
|
while( file_data_ptr < file_data_end ) {
|
|
if(*file_data_ptr == '@') {
|
|
file_data_ptr++;
|
|
module_load_addr = getHexNumber(&file_data_ptr);
|
|
}
|
|
else if(*file_data_ptr == '!') {
|
|
if( file_data_ptr[1] == 'a' &&
|
|
file_data_ptr[2] == 'd' &&
|
|
file_data_ptr[3] == 'd' &&
|
|
file_data_ptr[4] == 'r' &&
|
|
file_data_ptr[5] == ' ' ) {
|
|
file_data_ptr += 6;
|
|
*modules_ptr++ = (u32*)(getHexNumber(&file_data_ptr) * 4 + 1);
|
|
*modules_ptr++ = 0;
|
|
}
|
|
}
|
|
else if(*file_data_ptr != '#') {
|
|
// 'file_data_ptr' should be pointing to a filename
|
|
// this finds the address of that file in the rom
|
|
ROMFILE_INFO module_fileinfo;
|
|
char strmodule[16];
|
|
for(i = 0; i < 16; ++i) {
|
|
if( file_data_ptr[i] < ' ' )
|
|
break;
|
|
strmodule[i] = file_data_ptr[i];
|
|
}
|
|
strmodule[i] = 0;
|
|
|
|
if( searchFileInRom(&romdir_info, strmodule, &module_fileinfo) == NULL ) {
|
|
__printf("IOPBOOT: failed to find %s module\n", strmodule);
|
|
return;
|
|
}
|
|
|
|
//__printf("mod: %s:%x\n", strmodule, module_fileinfo.fileData);
|
|
|
|
*modules_ptr++ = (u32*)module_fileinfo.fileData;
|
|
*modules_ptr = 0; // don't increment
|
|
}
|
|
|
|
// loop until a "newline" charcter is found
|
|
while(file_data_ptr < file_data_end) {
|
|
if(*file_data_ptr++ < ' ')
|
|
break;
|
|
}
|
|
|
|
// loop until a "non-newline" charcter is found
|
|
while(file_data_ptr < file_data_end) {
|
|
if(*file_data_ptr >= ' ')
|
|
break;
|
|
file_data_ptr++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( searchFileInRom(&romdir_info, "IOPBOOT", &romfile_info) == NULL ) {
|
|
__printf("loadElfFile: failed to find IOPBOOT module\n");
|
|
return;
|
|
}
|
|
|
|
// load sysmem module to memory and execute it
|
|
if( searchFileInRom(&romdir_info, "SYSMEM", &romfile_info) == NULL ) {
|
|
__printf("loadElfFile: failed to find SYSMEM module\n");
|
|
return;
|
|
}
|
|
sysmem_entry = (void *(*)(u32))loadElfFile(&romfile_info, module_load_addr);
|
|
if( sysmem_entry == 0 )
|
|
return;
|
|
|
|
psysmemstart = sysmem_entry(ram_byte_size);
|
|
//FlushIcache();
|
|
if( psysmemstart == 0 ) {
|
|
__printf("IOPBOOT: sysmem failed\n");
|
|
return;
|
|
}
|
|
|
|
__printf("SYSMEM success, start addr: %x, alloc start: %x\n", module_load_addr, psysmemstart);
|
|
|
|
if( searchFileInRom(&romdir_info, "LOADCORE", &romfile_info) == NULL ) {
|
|
__printf("loadElfFile: failed to find SYSMEM module\n");
|
|
return;
|
|
}
|
|
loadcore_entry = (void (*)())loadElfFile(&romfile_info, (u32)psysmemstart);
|
|
if( loadcore_entry == 0 )
|
|
return;
|
|
|
|
boot_params->firstModuleAddr = (u32)module_load_addr + 0x30; // skip elf?
|
|
if(0x1FC10000 < ram_byte_size) {
|
|
boot_params->pos = 0x1FC00000;
|
|
boot_params->size = 0x10100;
|
|
}
|
|
else {
|
|
boot_params->pos = 0;
|
|
boot_params->size = 0;
|
|
}
|
|
|
|
__printf("executing LOADCORE entry at %p\n", loadcore_entry);
|
|
loadcore_entry(boot_params);
|
|
|
|
__printf("iopboot error\n");
|
|
|
|
// error - loadcore shouldnt ever return
|
|
while(1) *(u8*)0x80000000 = 2;
|
|
}
|
|
|
|
void Kmemcpy(void *dest, const void *src, int n) {
|
|
const u8 *s = (u8*)src;
|
|
u8 *d = (u8*)dest;
|
|
|
|
while (n) {
|
|
*d++ = *s++; n--;
|
|
}
|
|
}
|
|
|
|
static void kstrcpy(char* dst, const char* src)
|
|
{
|
|
while(*src) *dst++ = *src++;
|
|
*dst = 0;
|
|
}
|
|
|
|
static int kstrlen(const char* src)
|
|
{
|
|
int len = 0;
|
|
while(*src++) len++;
|
|
return len;
|
|
}
|