⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 loader.c

📁 索尼公司著名游戏机PS2使用的引导工具文件源代码,这是爱好者自编的工具,可以使用它来引导自己的程序,达到跳过原光驱启动执行自己制作的程序的目的,在windows上可以安装使用ps2的专用开发包,搭建c
💻 C
字号:
/*==================================================================
==											==
==	Copyright(c)2004  Adam Metcalf(gamblore_@hotmail.com)		==
==	Copyright(c)2004  Thomas Hawcroft(t0mb0la@yahoo.com)		==
==	This file is subject to terms and conditions shown in the	==
==	file LICENSE which should be kept in the top folder of	==
==	this distribution.							==
==											==
==	Portions of this code taken from PS2Link:				==
==				pkoLoadElf						==
==				wipeUserMemory					==
==				(C) 2003 Tord Lindstrom (pukko@home.se)	==
==				(C) 2003 adresd (adresd_ps2dev@yahoo.com)	==
==	Portions of this code taken from Independence MC exploit	==
==				tLoadElf						==
==				LoadAndRunHDDElf					==
==				(C) 2003 Marcus Brown <mrbrown@0xd6.org>	==
==											==
==================================================================*/
#include "tamtypes.h"
#include "debug.h"
#include "kernel.h"
#include "sifrpc.h"
#include "loadfile.h"
#include "fileio.h"
#include "iopcontrol.h"
#include "stdarg.h"
#include "string.h"
#include "malloc.h"
#include "libmc.h"
#include "iopheap.h"
#include "sys/fcntl.h"
#include "sys/stat.h"
#include "sys/ioctl.h"
#include "fileXio_rpc.h"
#include "errno.h"
#include "libhdd.h"
#include "sbv_patches.h"

//#define DEBUG
#ifdef DEBUG
#define dbgprintf(args...) scr_printf(args)
#define dbginit_scr() init_scr()
#else
#define dbgprintf(args...) do { } while(0)
#define dbginit_scr() do { } while(0)
#endif

// ELF-header structures and identifiers
#define ELF_MAGIC	0x464c457f
#define ELF_PT_LOAD	1

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;

t_ExecData elfdata;

extern u8 *fakehost_irx;
extern int size_fakehost_irx;
extern u8 *poweroff_irx;
extern int size_poweroff_irx;

int fileMode =  FIO_S_IRUSR | FIO_S_IWUSR | FIO_S_IXUSR | FIO_S_IRGRP | FIO_S_IWGRP | FIO_S_IXGRP | FIO_S_IROTH | FIO_S_IWOTH | FIO_S_IXOTH;
char elfName[256];
char elfPath[256];
char HDDpath[256];
char partition[128];

const char *eeloadimg = "rom0:UDNL rom0:EELOADCNF";
char *imgcmd;

static int pkoLoadElf(char *path);

int userThreadID = 0;
static char userThreadStack[16*1024] __attribute__((aligned(16)));

#define MAX_ARGS 16
#define MAX_ARGLEN 256

struct argData
{
    int flag;                     // Contains thread id atm
    int argc;
    char *argv[MAX_ARGS];
} __attribute__((packed)) userArgs;

////////////////////////////////////////////////////////////////////////
// Read ELF from hard drive to required location(s) in memory.
// Modified version of loader from Independence
//	(C) 2003 Marcus R. Brown <mrbrown@0xd6.org>
//
static int tLoadElf(char *filename)
{
	u8 *boot_elf = (u8 *)0x1800000;
	elf_header_t *eh = (elf_header_t *)boot_elf;
	elf_pheader_t *eph;

	int fd, size, i, ret;

	ret = fileXioMount("pfs0:", partition, FIO_MT_RDONLY);
	if ((fd = fileXioOpen(filename, O_RDONLY, fileMode)) < 0)
	{
		dbgprintf("Failed in fileXioOpen %s\n",filename);
		goto error;
		}
	dbgprintf("Opened file %s\n",filename);
	size = fileXioLseek(fd, 0, SEEK_END);
	dbgprintf("File size = %i\n",size);
	if (!size)
	{
		dbgprintf("Failed in fileXioLseek\n");
		fileXioClose(fd);
		goto error;
		}
	fileXioLseek(fd, 0, SEEK_SET);
	fileXioRead(fd, boot_elf, 52);
	dbgprintf("Read elf header from file\n");
	fileXioLseek(fd, eh->phoff, SEEK_SET);
	eph = (elf_pheader_t *)(boot_elf + eh->phoff);
	size=eh->phnum*eh->phentsize;
	size=fileXioRead(fd, (void *)eph, size);
	dbgprintf("Read %i bytes of program header(s) from file\n",size);
	for (i = 0; i < eh->phnum; i++)
	{
		if (eph[i].type != ELF_PT_LOAD)
		continue;

		fileXioLseek(fd, eph[i].offset, SEEK_SET);
		size=eph[i].filesz;
		size=fileXioRead(fd, eph[i].vaddr, size);
		dbgprintf("Read %i bytes to %x\n", size, eph[i].vaddr);
		if (eph[i].memsz > eph[i].filesz)
			memset(eph[i].vaddr + eph[i].filesz, 0,
					eph[i].memsz - eph[i].filesz);
		}		

	fileXioClose(fd);
//	fileXioUmount("pfs0:");		We leave the filesystem mounted now for fakehost

	if (_lw((u32)&eh->ident) != ELF_MAGIC)		// this should have already been
	{								// done by menu, but a double-check
		dbgprintf("Not a recognised ELF.\n");	// doesn't do any harm
		goto error;
		}
	
	dbgprintf("entry=%x\n",eh->entry);
	elfdata.epc=eh->entry;
	return 0;
error:
	elfdata.epc=0;
	return -1;
	}

////////////////////////////////////////////////////////////////////////
// Load the actual elf, and create a thread for it
// Return the thread id
// PS2Link (C) 2003 Tord Lindstrom (pukko@home.se)
//         (C) 2003 adresd (adresd_ps2dev@yahoo.com)
static int
pkoLoadElf(char *path)
{
    ee_thread_t th_attr;
    int ret=0;
    int pid;

// Some lines added here to check for loading from HDD, at the moment it should only
// call tLoadElf, but support for loading ELF from mc0, host or any other device may
// well be added in future
    if(!strncmp(path, "host", 4)) ret = SifLoadElf(path, &elfdata);
    else if(!strncmp(path, "mc", 2)) ret = SifLoadElf(path, &elfdata);
    else if(!strncmp(path, "cdrom", 5)) ret = SifLoadElf(path, &elfdata);
    else if(!strncmp(path, "cdfs", 4)) ret = SifLoadElf(path, &elfdata);
    else if(!strncmp(path, "pfs0", 4)) ret = tLoadElf(path);
    else ret = SifLoadElf(path, &elfdata);

    FlushCache(0);
    FlushCache(2);

    dbgprintf("EE: LoadElf returned %d\n", ret);

    dbgprintf("EE: Creating user thread (ent: %x, gp: %x, st: %x)\n", 
              elfdata.epc, elfdata.gp, elfdata.sp);

    if (elfdata.epc == 0) {
        dbgprintf("EE: Could not load file\n");
        return -1;
    }

    th_attr.func = (void *)elfdata.epc;
    th_attr.stack = userThreadStack;
    th_attr.stack_size = sizeof(userThreadStack);
    th_attr.gp_reg = (void *)elfdata.gp;
    th_attr.initial_priority = 64;

    pid = CreateThread(&th_attr);
    if (pid < 0) {
        dbgprintf("EE: Create user thread failed %d\n", pid);
        return -1;
    }
    dbgprintf("EE: Created user thread: %d\n", pid);

    return pid;
}

////////////////////////////////////////////////////////////////////////
// Clear user memory
// PS2Link (C) 2003 Tord Lindstrom (pukko@home.se)
//         (C) 2003 adresd (adresd_ps2dev@yahoo.com)
void
wipeUserMem(void)
{
    int i;
    for (i = 0x100000; i < 0x2000000 ; i += 64) {
        asm (
            "\tsq $0, 0(%0) \n"
            "\tsq $0, 16(%0) \n"
            "\tsq $0, 32(%0) \n"
            "\tsq $0, 48(%0) \n"
            :: "r" (i) );
    }
}

////////////////////////////////////////////////////////////////////////
// C standard strrchr func.. returns pointer to the last occurance of a
// character in a string, or NULL if not found
// PS2Link (C) 2003 Tord Lindstrom (pukko@home.se)
//         (C) 2003 adresd (adresd_ps2dev@yahoo.com)
char *strrchr(const char *sp, int i)
{
	const char *last = NULL;
	char c = i;

	while (*sp)
	{
		if (*sp == c)
		{
			last = sp;
			}
		sp++;
		}

	if (*sp == c)
	{
		last = sp;
		}

	return (char *) last;
}

void poweroffHandler(int i)
{
	hddPowerOff();
}

// *************************************************************************
// *** MAIN
// *************************************************************************
int main(int argc, char *argv[])
{
	char s[256],fakepart[128], *ptr;
	int pid=-1,ret;

// Initialise
	SifInitRpc(0);
	hddPreparePoweroff();
	hddSetUserPoweroffCallback((void *)poweroffHandler,(void *)pid);
	init_scr();
	wipeUserMem();
	dbgprintf("Welcome to PS2Menu Loader v2.1\nPlease wait...loading.\n");
	dbgprintf("Init MrBrown sbv_patches\n");
	sbv_patch_enable_lmb();			// not sure we really need to do this again
	sbv_patch_disable_prefix_check();	// here, but will it do any harm?
	dbgprintf("Loading poweroff.irx %i bytes\n", size_poweroff_irx);
	SifExecModuleBuffer(&poweroff_irx, size_poweroff_irx, 0, NULL, &ret);

	strcpy(s,argv[0]);
	dbgprintf("argv[0] = %s\n",s);
	if (argc==1)
	{						// should be two params passed by menu
		while(1);				// leave this here for adding mc0, host or other
							// to be added in future
		}
	if (argc==2)				// if call came from hddmenu.elf
	{						// arg1=path to ELF, arg2=partition to mount
		strcpy(partition,argv[1]);
		dbgprintf("argv[1] = %s\n", partition);
		strcpy(HDDpath,s);
		}
	scr_printf("Loading %s\n",HDDpath);
	pid = pkoLoadElf(HDDpath);
	dbgprintf("pkoLoadElf returned %i\n",pid);
	if (pid < 0)
	{
		scr_printf("failed\n");
		dbgprintf("Could not execute file %s\n", HDDpath);
		return -1;
		}
	if(!strncmp(HDDpath, "pfs0", 4))
	{
		strcpy(fakepart,HDDpath);
		ptr=strrchr(fakepart,'/');
		if(ptr==NULL) strcpy(fakepart,"pfs0:");
		else
		{
			ptr++;
			*ptr='\0';
			}
		ptr=strrchr(s,'/');
		if(ptr==NULL) ptr=strrchr(s,':');
		if(ptr!=NULL)
		{
			ptr++;
			strcpy(HDDpath,"host:");
			strcat(HDDpath,ptr);
			}
		dbgprintf("Loading fakehost.irx %i bytes\n", size_fakehost_irx);
		dbgprintf("%s\n", fakepart);
		SifExecModuleBuffer(&fakehost_irx, size_fakehost_irx, strlen(fakepart), fakepart, &ret);
		}
	
	FlushCache(0);
	FlushCache(2);
	
	userThreadID = pid;

	userArgs.argc=1;
	userArgs.argv[0]=HDDpath;
	userArgs.flag = (int)&userThreadID;

	ret = StartThread(userThreadID, &userArgs);
	if (ret < 0)
	{
		scr_printf("failed\n");
		dbgprintf("EE: Start user thread failed %d\n", ret);
		DeleteThread(userThreadID);
		return -1;
		}
	SleepThread();
	
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -