-
Notifications
You must be signed in to change notification settings - Fork 0
/
loadutil.c
126 lines (111 loc) · 3.36 KB
/
loadutil.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include <psptypes.h>
#include <pspkernel.h>
#include <pspctrl.h>
#include <pspdisplay.h>
#include <pspiofilemgr.h>
#include <pspiofilemgr_fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "loadutil.h"
////////////////////////////////////////////////////////////////////
// SLIME NOTE: Module library linkage trickery
// we need to be in special kernel mode to load flash0: libraries
// (created kernel thread + kernel memory module flag set)
// for everything else program runs in user mode
// the system does not patch the stubs properly, so we do it ourselves
// slightly cleaned up version
# ifndef PSPFW30X
static u32 FindProcEntry(u32 oid, u32 nid)
{
SceModule* modP = sceKernelFindModuleByUID(oid);
if (modP == NULL)
{
// dprintf("ERROR: Failed to find mod $%x\n", oid);
return 0;
}
SceLibraryEntryTable* entP = (SceLibraryEntryTable*)modP->ent_top;
while ((u32)entP < ((u32)modP->ent_top + modP->ent_size))
{
int count = entP->stubcount + entP->vstubcount;
u32* nidtable = (u32*)entP->entrytable;
int i;
for (i = 0; i < count; i++)
{
if (nidtable[i] == nid)
{
u32 procAddr = nidtable[count+i];
return procAddr;
}
}
entP++;
}
return 0;
}
static int PatchMyLibraryEntries(SceModuleInfo* modInfoPtr, SceUID oidLib)
{
//dumb version
int nPatched = 0;
int* stubPtr; // 20 byte structure
for (stubPtr = modInfoPtr->stub_top;
stubPtr + 5 <= (int*)modInfoPtr->stub_end;
stubPtr += 5)
{
int count = (stubPtr[2] >> 16) & 0xFFFF;
int* idPtr = (int*)stubPtr[3];
int* procPtr = (int*)stubPtr[4];
if (stubPtr[1] != 0x90000)
continue; // skip non-lazy loaded modules
while (count--)
{
if (procPtr[0] == 0x54C && procPtr[1] == 0)
{
// SWI - scan for NID
u32 proc = FindProcEntry(oidLib, *idPtr);
if (proc != 0)
{
if (((u32)procPtr & 0xF0000000) != (proc & 0xF0000000))
{
// if not in user space we can't use it
//dprintf("!! NOT PATCH\n");
}
else
{
u32 val = (proc & 0x03FFFFFF) >> 2;
procPtr[0] = 0x0A000000 | val;
procPtr[1] = 0;
nPatched++;
}
}
}
idPtr++;
procPtr += 2; // 2 opcodes
}
}
return nPatched;
}
# endif
SceUID LoadAndStartAndPatch(SceModuleInfo* modInfoPtr, const char* szFile)
// return oid or error code
{
SceUID oid;
int err;
int startStatus; // ignored
oid = sceKernelLoadModule(szFile, 0, NULL);
if (oid & 0x80000000)
return oid; // error code
err = sceKernelStartModule(oid, 0, 0, &startStatus, 0);
if (err != oid)
return err;
# ifndef PSPFW30X
PatchMyLibraryEntries(modInfoPtr, oid);
# endif
return oid;
}
extern void sceKernelIcacheInvalidateAll();
void FlushCaches()
{
// not sure if these are necessary, but to be extra safe
sceKernelDcacheWritebackAll();
sceKernelIcacheInvalidateAll();
}