Added support for LOADCORE's "LoadElf" function which allows loading an executable into EE memory.

Fixed a bug with module parameter passing in the LoadModule function.

git-svn-id: http://svn.purei.org/purei/trunk@1023 b36208d7-6611-0410-8bec-b1987f11c4a2
This commit is contained in:
jpd002 2012-10-24 06:39:29 +00:00
parent b801b3d7f8
commit 91030fbbdd
7 changed files with 114 additions and 23 deletions

View File

@ -506,6 +506,47 @@ void CPS2OS::UnloadExecutable()
DELETEPTR(m_pELF);
}
uint32 CPS2OS::LoadExecutable(const char* path, const char* section)
{
auto ioman = m_iopBios.GetIoman();
uint32 handle = ioman->Open(Iop::Ioman::CDevice::OPEN_FLAG_RDONLY, path);
if(static_cast<int32>(handle) < 0)
{
return -1;
}
uint32 result = 0;
//We don't support loading anything else than all sections
assert(strcmp(section, "all") == 0);
auto fileStream(ioman->GetFileStream(handle));
//Load all program sections
{
CElfFile executable(*fileStream);
const auto& header = executable.GetHeader();
for(unsigned int i = 0; i < header.nProgHeaderCount; i++)
{
auto p = executable.GetProgram(i);
if(p)
{
memcpy(m_ram + p->nVAddress, executable.GetContent() + p->nOffset, p->nFileSize);
}
}
result = executable.GetHeader().nEntryPoint;
}
//Flush all instruction cache
OnRequestInstructionCacheFlush();
ioman->Close(handle);
return result;
}
void CPS2OS::ApplyPatches()
{
auto patchesPath = Framework::PathUtils::GetAppResourcesPath() / PATCHESFILENAME;

View File

@ -37,6 +37,8 @@ public:
BiosDebugModuleInfoArray GetModuleInfos() const;
BiosDebugThreadInfoArray GetThreadInfos() const;
uint32 LoadExecutable(const char*, const char*);
void ExceptionHandler();
void SysCallHandler();
static uint32 TranslateAddress(CMIPS*, uint32);

View File

@ -515,6 +515,8 @@ void CPS2VM::ResetVM()
m_iopOs->GetIoman()->RegisterDevice("mc1", Iop::CIoman::DevicePtr(new Iop::Ioman::CDirectoryDevice(PREF_PS2_MC1_DIRECTORY)));
m_iopOs->GetIoman()->RegisterDevice("cdrom0", Iop::CIoman::DevicePtr(new Iop::Ioman::CIsoDevice(m_pCDROM0)));
m_iopOs->GetLoadcore()->SetLoadExecutableHandler(std::bind(&CPS2OS::LoadExecutable, m_os, std::placeholders::_1, std::placeholders::_2));
m_frameSkip = CAppConfig::GetInstance().GetPreferenceInteger(PREF_PS2_FRAMESKIP);
m_vblankTicks = ONSCREEN_TICKS;

View File

@ -77,6 +77,7 @@ CIopBios::CIopBios(CMIPS& cpu, uint8* ram, uint32 ramSize)
, m_ioman(nullptr)
, m_modload(nullptr)
, m_cdvdman(nullptr)
, m_loadcore(nullptr)
#ifdef _IOP_EMULATE_MODULES
, m_padman(nullptr)
, m_cdvdfsv(nullptr)
@ -159,7 +160,8 @@ void CIopBios::Reset(Iop::CSifMan* sifMan)
RegisterModule(new Iop::CSysclib(m_ram, *m_stdio));
}
{
RegisterModule(new Iop::CLoadcore(*this, m_ram, *m_sifMan));
m_loadcore = new Iop::CLoadcore(*this, m_ram, *m_sifMan);
RegisterModule(m_loadcore);
}
{
RegisterModule(new Iop::CThbase(*this, m_ram));
@ -1425,6 +1427,11 @@ Iop::CCdvdman* CIopBios::GetCdvdman()
return m_cdvdman;
}
Iop::CLoadcore* CIopBios::GetLoadcore()
{
return m_loadcore;
}
#ifdef _IOP_EMULATE_MODULES
Iop::CPadMan* CIopBios::GetPadman()

View File

@ -15,6 +15,7 @@
#include "Iop_Stdio.h"
#include "Iop_Sysmem.h"
#include "Iop_Modload.h"
#include "Iop_Loadcore.h"
#include "Iop_Dynamic.h"
#ifdef _IOP_EMULATE_MODULES
#include "Iop_PadMan.h"
@ -121,6 +122,7 @@ public:
Iop::CIoman* GetIoman();
Iop::CCdvdman* GetCdvdman();
Iop::CLoadcore* GetLoadcore();
#ifdef _IOP_EMULATE_MODULES
Iop::CPadMan* GetPadman();
Iop::CCdvdfsv* GetCdvdfsv();
@ -349,6 +351,7 @@ private:
Iop::CCdvdman* m_cdvdman;
Iop::CSysmem* m_sysmem;
Iop::CModload* m_modload;
Iop::CLoadcore* m_loadcore;
#ifdef _IOP_EMULATE_MODULES
Iop::CPadMan* m_padman;
Iop::CCdvdfsv* m_cdvdfsv;

View File

@ -72,6 +72,9 @@ bool CLoadcore::Invoke(uint32 method, uint32* args, uint32 argsSize, uint32* ret
case 0x00:
LoadModule(args, argsSize, ret, retSize);
break;
case 0x01:
LoadExecutable(args, argsSize, ret, retSize);
break;
case 0x06:
LoadModuleFromMemory(args, argsSize, ret, retSize);
break;
@ -86,6 +89,11 @@ bool CLoadcore::Invoke(uint32 method, uint32* args, uint32 argsSize, uint32* ret
return true;
}
void CLoadcore::SetLoadExecutableHandler(const LoadExecutableHandler& loadExecutableHandler)
{
m_loadExecutableHandler = loadExecutableHandler;
}
uint32 CLoadcore::RegisterLibraryEntries(uint32* exportTable)
{
#ifdef _DEBUG
@ -97,8 +105,8 @@ uint32 CLoadcore::RegisterLibraryEntries(uint32* exportTable)
void CLoadcore::LoadModule(uint32* args, uint32 argsSize, uint32* ret, uint32 retSize)
{
char moduleName[PATH_MAX_SIZE + 1];
char moduleArgs[ARGS_MAX_SIZE + 1];
char moduleName[PATH_MAX_SIZE];
char moduleArgs[ARGS_MAX_SIZE];
assert(argsSize == 512);
@ -107,14 +115,8 @@ void CLoadcore::LoadModule(uint32* args, uint32 argsSize, uint32* ret, uint32 re
uint32 moduleArgsSize = args[0];
memset(moduleName, 0, PATH_MAX_SIZE + 1);
memset(moduleArgs, 0, ARGS_MAX_SIZE + 1);
strncpy(moduleName, reinterpret_cast<const char*>(args) + 8, PATH_MAX_SIZE);
if(moduleArgsSize != 0)
{
strncpy(moduleArgs, reinterpret_cast<const char*>(args) + 8 + PATH_MAX_SIZE, ARGS_MAX_SIZE);
}
memcpy(moduleName, reinterpret_cast<const char*>(args) + 8, PATH_MAX_SIZE);
memcpy(moduleArgs, reinterpret_cast<const char*>(args) + 8 + PATH_MAX_SIZE, ARGS_MAX_SIZE);
//Load the module
CLog::GetInstance().Print(LOG_NAME, "Request to load module '%s' received with %d bytes arguments payload.\r\n", moduleName, moduleArgsSize);
@ -125,6 +127,32 @@ void CLoadcore::LoadModule(uint32* args, uint32 argsSize, uint32* ret, uint32 re
ret[0] = 0x00000000;
}
void CLoadcore::LoadExecutable(uint32* args, uint32 argsSize, uint32* ret, uint32 retSize)
{
char moduleName[PATH_MAX_SIZE];
char sectionName[ARGS_MAX_SIZE];
assert(argsSize == 512);
assert(retSize >= 8);
memcpy(moduleName, reinterpret_cast<const char*>(args) + 8, PATH_MAX_SIZE);
memcpy(sectionName, reinterpret_cast<const char*>(args) + 8 + PATH_MAX_SIZE, ARGS_MAX_SIZE);
CLog::GetInstance().Print(LOG_NAME, "Request to load section '%s' from executable '%s' received.\r\n", sectionName, moduleName);
uint32 result = 0;
//Load executable in EE memory
if(m_loadExecutableHandler)
{
result = m_loadExecutableHandler(moduleName, sectionName);
}
//This function returns something negative upon failure
ret[0] = result; //epc or result (if negative)
ret[1] = 0x00000000; //gp
}
void CLoadcore::LoadModuleFromMemory(uint32* args, uint32 argsSize, uint32* ret, uint32 retSize)
{
CLog::GetInstance().Print(LOG_NAME, "Request to load module at 0x%0.8X received with %d bytes arguments payload.\r\n", args[0], 0);

View File

@ -3,6 +3,7 @@
#include "Iop_Module.h"
#include "Iop_SifMan.h"
#include <functional>
class CIopBios;
@ -11,13 +12,17 @@ namespace Iop
class CLoadcore : public CModule, public CSifModule
{
public:
CLoadcore(CIopBios&, uint8*, CSifMan&);
virtual ~CLoadcore();
typedef std::function<uint32 (const char*, const char*)> LoadExecutableHandler;
std::string GetId() const;
std::string GetFunctionName(unsigned int) const;
void Invoke(CMIPS&, unsigned int);
bool Invoke(uint32, uint32*, uint32, uint32*, uint32, uint8*);
CLoadcore(CIopBios&, uint8*, CSifMan&);
virtual ~CLoadcore();
std::string GetId() const;
std::string GetFunctionName(unsigned int) const;
void Invoke(CMIPS&, unsigned int);
bool Invoke(uint32, uint32*, uint32, uint32*, uint32, uint8*);
void SetLoadExecutableHandler(const LoadExecutableHandler&);
private:
enum MODULE_ID
@ -25,13 +30,16 @@ namespace Iop
MODULE_ID = 0x80000006
};
uint32 RegisterLibraryEntries(uint32*);
void LoadModule(uint32*, uint32, uint32*, uint32);
void LoadModuleFromMemory(uint32*, uint32, uint32*, uint32);
void Initialize(uint32*, uint32, uint32*, uint32);
uint32 RegisterLibraryEntries(uint32*);
void LoadModule(uint32*, uint32, uint32*, uint32);
void LoadExecutable(uint32*, uint32, uint32*, uint32);
void LoadModuleFromMemory(uint32*, uint32, uint32*, uint32);
void Initialize(uint32*, uint32, uint32*, uint32);
CIopBios& m_bios;
uint8* m_ram;
CIopBios& m_bios;
uint8* m_ram;
LoadExecutableHandler m_loadExecutableHandler;
};
}