-
Notifications
You must be signed in to change notification settings - Fork 18
/
main.c
97 lines (76 loc) · 3.69 KB
/
main.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
#include <psp2kern/kernel/cpu.h>
#include <psp2kern/kernel/modulemgr.h>
#include <psp2kern/kernel/sysmem.h>
#include <psp2kern/kernel/threadmgr.h>
#include <taihen.h>
int module_get_export_func(SceUID pid, const char *modname, uint32_t libnid, uint32_t funcnid, uintptr_t *func);
void (* _ksceKernelCpuDcacheWritebackInvalidateRange)(const void *ptr, SceSize len);
void (* _ksceKernelCpuIcacheInvalidateRange)(const void *ptr, SceSize len);
void (* _ksceKernelCpuIcacheAndL2WritebackInvalidateRange)(const void *ptr, SceSize len);
int (* _kscePowerGetSysClockFrequency)(void);
int (* _kscePowerSetSysClockFrequency)(int freq);
void kuKernelFlushCaches(const void *ptr, SceSize len) {
uintptr_t ptr_aligned;
ptr_aligned = (uintptr_t)ptr & ~0x1F;
len = (((uintptr_t)ptr + len + 0x1F) & ~0x1F) - ptr_aligned;
_ksceKernelCpuDcacheWritebackInvalidateRange((void *)ptr_aligned, len);
// _ksceKernelCpuIcacheAndL2WritebackInvalidateRange((void *)ptr_aligned, len);
_ksceKernelCpuIcacheInvalidateRange((void *)ptr_aligned, len);
}
SceUID kuKernelAllocMemBlock(const char *name, SceKernelMemBlockType type, SceSize size, SceKernelAllocMemBlockKernelOpt *opt) {
char k_name[32];
SceKernelAllocMemBlockKernelOpt k_opt;
uint32_t state;
int res;
ENTER_SYSCALL(state);
res = ksceKernelStrncpyUserToKernel(k_name, (uintptr_t)name, sizeof(k_name));
if (res < 0)
goto error;
res = ksceKernelMemcpyUserToKernel(&k_opt, (uintptr_t)opt, sizeof(k_opt));
if (res < 0)
goto error;
res = ksceKernelAllocMemBlock(k_name, type, size, &k_opt);
if (res < 0)
goto error;
res = ksceKernelCreateUserUid(ksceKernelGetProcessId(), res);
error:
EXIT_SYSCALL(state);
return res;
}
int kuKernelCpuUnrestrictedMemcpy(void *dst, const void *src, SceSize len) {
int prev_dacr;
asm volatile("mrc p15, 0, %0, c3, c0, 0" : "=r" (prev_dacr));
asm volatile("mcr p15, 0, %0, c3, c0, 0" :: "r" (0x15450FC3));
for (int i = 0; i < len; i++) {
uint32_t val;
__asm__ volatile ("ldrbt %0, [%1]" : "=r" (val) : "r" (src + i));
__asm__ volatile ("strbt %0, [%1]" :: "r" (val), "r" (dst + i));
}
asm volatile("mcr p15, 0, %0, c3, c0, 0" :: "r" (prev_dacr));
return 0;
}
int kuPowerGetSysClockFrequency(void) {
return _kscePowerGetSysClockFrequency();
}
int kuPowerSetSysClockFrequency(int freq) {
return _kscePowerSetSysClockFrequency(freq);
}
void _start() __attribute__ ((weak, alias("module_start")));
int module_start(SceSize args, void *argp) {
int res;
res = module_get_export_func(KERNEL_PID, "SceSysmem", TAI_ANY_LIBRARY, 0x6BA2E51C, (uintptr_t *)&_ksceKernelCpuDcacheWritebackInvalidateRange);
if (res < 0)
module_get_export_func(KERNEL_PID, "SceSysmem", TAI_ANY_LIBRARY, 0x4F442396, (uintptr_t *)&_ksceKernelCpuDcacheWritebackInvalidateRange);
res = module_get_export_func(KERNEL_PID, "SceSysmem", TAI_ANY_LIBRARY, 0xF4C7F578, (uintptr_t *)&_ksceKernelCpuIcacheInvalidateRange);
if (res < 0)
module_get_export_func(KERNEL_PID, "SceSysmem", TAI_ANY_LIBRARY, 0x2E637B1D, (uintptr_t *)&_ksceKernelCpuIcacheInvalidateRange);
res = module_get_export_func(KERNEL_PID, "SceSysmem", TAI_ANY_LIBRARY, 0x19F17BD0, (uintptr_t *)&_ksceKernelCpuIcacheAndL2WritebackInvalidateRange);
if (res < 0)
module_get_export_func(KERNEL_PID, "SceSysmem", TAI_ANY_LIBRARY, 0x73E895EA, (uintptr_t *)&_ksceKernelCpuIcacheAndL2WritebackInvalidateRange);
module_get_export_func(KERNEL_PID, "ScePower", TAI_ANY_LIBRARY, 0xC63DACD5, (uintptr_t *)&_kscePowerGetSysClockFrequency);
module_get_export_func(KERNEL_PID, "ScePower", TAI_ANY_LIBRARY, 0x0E333BEC, (uintptr_t *)&_kscePowerSetSysClockFrequency);
return SCE_KERNEL_START_SUCCESS;
}
int module_stop(SceSize args, void *argp) {
return SCE_KERNEL_STOP_SUCCESS;
}