195 lines
3.7 KiB
C++
195 lines
3.7 KiB
C++
#include "Common.h"
|
|
#include "KernelLoader.h"
|
|
#include "kELF.h"
|
|
#include "Utilities.h"
|
|
#include "../../../Misc/DriverDefinitions.h"
|
|
#include "OrbisDriver.h"
|
|
|
|
_OffsetTable* OffsetTable;
|
|
|
|
typedef int vm_prot_t;
|
|
typedef uint64_t vm_offset_t;
|
|
typedef uint64_t vm_map_t;
|
|
typedef uint64_t vm_size_t;
|
|
|
|
uint64_t getkernbase() {
|
|
return __readmsr(0xC0000082) - OffsetTable->Xfast_syscall;
|
|
}
|
|
|
|
struct InstallArgs {
|
|
uint64_t sycall;
|
|
void* payload;
|
|
size_t psize;
|
|
};
|
|
|
|
//Crashes because its using userland function calls for memcpy memcmp and memset etc...
|
|
int install_orbis(struct thread* td, struct InstallArgs* args)
|
|
{
|
|
uint64_t kernbase = getkernbase();
|
|
auto Log = (void(*)(vm_map_t, vm_size_t))(kernbase + OffsetTable->kmem_alloc);
|
|
auto kmem_alloc = (vm_offset_t(*)(vm_map_t, vm_size_t))(kernbase + OffsetTable->kmem_alloc);
|
|
auto kernel_map = *(vm_map_t*)(kernbase + OffsetTable->kernel_map);
|
|
|
|
size_t msize = 0;
|
|
if (elf_mapped_size(args->payload, &msize)) {
|
|
return 1;
|
|
}
|
|
|
|
int s = (msize + 0x3FFFull) & ~0x3FFFull;
|
|
void* payloadbase = (void*)kmem_alloc(kernel_map, s);
|
|
if (!payloadbase) {
|
|
return 1;
|
|
}
|
|
|
|
KDriver_Info DriverInfo;
|
|
DriverInfo.ELFBase = payloadbase;
|
|
DriverInfo.Size = s;
|
|
|
|
int r = 0;
|
|
if ((r = load_elf(args->payload, args->psize, payloadbase, msize, (void**)&DriverInfo.Entry))) {
|
|
return r;
|
|
}
|
|
|
|
if (DriverInfo.Entry(&DriverInfo)) {
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct RemoveArgs {
|
|
uint64_t sycall;
|
|
KDriver_Info* Info;
|
|
};
|
|
|
|
int Remove_Orbis(thread* td, RemoveArgs* Args)
|
|
{
|
|
uint64_t kernbase = getkernbase();
|
|
auto kmem_free = (void(*)(void* map, void* addr, size_t size))(kernbase + OffsetTable->kmem_free);
|
|
auto kernel_map = *(vm_map_t*)(kernbase + OffsetTable->kernel_map);
|
|
|
|
int res = Args->Info->Shutdown();
|
|
if (res != 0)
|
|
return 1;
|
|
|
|
kmem_free((void*)kernel_map, Args->Info->ELFBase, Args->Info->Size);
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool SetKernelVersion(int Firmware)
|
|
{
|
|
OffsetTable = new _OffsetTable();
|
|
switch (Firmware >> 16)
|
|
{
|
|
default:
|
|
klog("Unknown Firmware %01X.%02X.\n", (Firmware >> 24) & 0xFF, (Firmware >> 16) & 0xFF);
|
|
return false;
|
|
break;
|
|
|
|
case 0x505:
|
|
klog("Loading Offsets for 5.05\n");
|
|
OffsetTable->Init505();
|
|
break;
|
|
|
|
case 0x672:
|
|
OffsetTable->Init672();
|
|
break;
|
|
|
|
case 0x702:
|
|
OffsetTable->Init702();
|
|
break;
|
|
|
|
case 0x755:
|
|
OffsetTable->Init755();
|
|
break;
|
|
|
|
case 0x900:
|
|
OffsetTable->Init900();
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool LoadKernel(char* Path, int Firmware)
|
|
{
|
|
klog("Loading Kernel \"%s\"\n", Path);
|
|
|
|
int FileHandle = sceKernelOpen(Path, ORBIS_KERNEL_O_RDONLY, 0);
|
|
|
|
if (FileHandle < 0)
|
|
{
|
|
if (FileHandle == 0x80020002)
|
|
Notify("Firmware Version %01X.%02X is not supported.", (Firmware >> 24) & 0xFF, (Firmware >> 16) & 0xFF);
|
|
else
|
|
Notify("Error 0x%08X", FileHandle);
|
|
|
|
return false;
|
|
}
|
|
|
|
//Get File size
|
|
OrbisKernelStat Stats;
|
|
sceKernelFstat(FileHandle, &Stats);
|
|
|
|
if (Stats.st_size == 0)
|
|
{
|
|
klog("[OrbisLib] Failed to get file size.");
|
|
|
|
//Cleanup
|
|
sceKernelClose(FileHandle);
|
|
|
|
return false;
|
|
}
|
|
|
|
//Allocate space to read data.
|
|
char* File_Data = (char*)malloc(Stats.st_size);
|
|
|
|
//ReadFile.
|
|
size_t Bytes_Read = sceKernelRead(FileHandle, File_Data, Stats.st_size);
|
|
|
|
if (Bytes_Read != Stats.st_size)
|
|
{
|
|
//Cleanup
|
|
sceKernelClose(FileHandle);
|
|
free(File_Data);
|
|
|
|
return false;
|
|
}
|
|
|
|
int res = syscall(11, install_orbis, File_Data, Stats.st_size);
|
|
if (res != 0)
|
|
{
|
|
klog("LoadKernel syscall failed with %i\n", res);
|
|
|
|
//Cleanup
|
|
sceKernelClose(FileHandle);
|
|
free(File_Data);
|
|
|
|
return false;
|
|
}
|
|
|
|
//Cleanup
|
|
sceKernelClose(FileHandle);
|
|
free(File_Data);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool UnloadKernel()
|
|
{
|
|
KDriver_Info Info;
|
|
if (OrbisDriver::GetDriverInfo(&Info))
|
|
{
|
|
int res = syscall(11, Remove_Orbis, &Info);
|
|
if (res != 0)
|
|
{
|
|
klog("LoadKernel syscall failed with %i\n", res);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
} |