1 // Copyright (c) 2012- PPSSPP Project.
2
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0 or later versions.
6
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // GNU General Public License 2.0 for more details.
11
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
14
15 // Official git repository and contact information can be found at
16 // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17
18 #include <algorithm>
19 #include <set>
20
21 #include "zlib.h"
22
23 #include "Common/Data/Convert/SmallDataConvert.h"
24 #include "Common/Serialize/Serializer.h"
25 #include "Common/Serialize/SerializeFuncs.h"
26 #include "Common/Serialize/SerializeSet.h"
27 #include "Common/File/FileUtil.h"
28 #include "Common/StringUtils.h"
29 #include "Core/Config.h"
30 #include "Core/Core.h"
31 #include "Core/HLE/HLE.h"
32 #include "Core/HLE/FunctionWrappers.h"
33 #include "Core/HLE/HLETables.h"
34 #include "Core/HLE/Plugins.h"
35 #include "Core/HLE/ReplaceTables.h"
36 #include "Core/HLE/sceDisplay.h"
37 #include "Core/Reporting.h"
38 #include "Core/Host.h"
39 #include "Core/Loaders.h"
40 #include "Core/MIPS/MIPS.h"
41 #include "Core/MIPS/MIPSAnalyst.h"
42 #include "Core/MIPS/MIPSCodeUtils.h"
43 #include "Core/ELF/ElfReader.h"
44 #include "Core/ELF/PBPReader.h"
45 #include "Core/ELF/PrxDecrypter.h"
46 #include "Core/FileSystems/FileSystem.h"
47 #include "Core/FileSystems/MetaFileSystem.h"
48 #include "Core/Util/BlockAllocator.h"
49 #include "Core/CoreTiming.h"
50 #include "Core/PSPLoaders.h"
51 #include "Core/System.h"
52 #include "Core/MemMapHelpers.h"
53 #include "Core/Debugger/SymbolMap.h"
54 #include "Core/MIPS/MIPS.h"
55
56 #include "Core/HLE/sceKernel.h"
57 #include "Core/HLE/sceKernelModule.h"
58 #include "Core/HLE/sceKernelThread.h"
59 #include "Core/HLE/sceKernelMemory.h"
60 #include "Core/HLE/sceMpeg.h"
61 #include "Core/HLE/scePsmf.h"
62 #include "Core/HLE/sceIo.h"
63 #include "Core/HLE/KernelWaitHelpers.h"
64 #include "Core/ELF/ParamSFO.h"
65
66 #include "GPU/Debugger/Playback.h"
67 #include "GPU/GPU.h"
68 #include "GPU/GPUInterface.h"
69 #include "GPU/GPUState.h"
70
71 enum {
72 PSP_THREAD_ATTR_KERNEL = 0x00001000,
73 PSP_THREAD_ATTR_USER = 0x80000000,
74 };
75
76 enum : u32 {
77 // Function exports.
78 NID_MODULE_START = 0xD632ACDB,
79 NID_MODULE_STOP = 0xCEE8593C,
80 NID_MODULE_REBOOT_BEFORE = 0x2F064FA6,
81 NID_MODULE_REBOOT_PHASE = 0xADF12745,
82 NID_MODULE_BOOTSTART = 0xD3744BE0,
83
84 // Variable exports.
85 NID_MODULE_INFO = 0xF01D73A7,
86 NID_MODULE_START_THREAD_PARAMETER = 0x0F7C276C,
87 NID_MODULE_STOP_THREAD_PARAMETER = 0xCF0CC697,
88 NID_MODULE_REBOOT_BEFORE_THREAD_PARAMETER = 0xF4F4299D,
89 NID_MODULE_SDK_VERSION = 0x11B97506,
90 };
91
92 // This is a workaround for misbehaving homebrew (like TBL's Suicide Barbie (Final)).
93 static const char * const lieAboutSuccessModules[] = {
94 "flash0:/kd/audiocodec.prx",
95 "flash0:/kd/audiocodec_260.prx",
96 "flash0:/kd/libatrac3plus.prx",
97 "disc0:/PSP_GAME/SYSDIR/UPDATE/EBOOT.BIN",
98 "flash0:/kd/ifhandle.prx",
99 "flash0:/kd/pspnet.prx",
100 "flash0:/kd/pspnet_inet.prx",
101 "flash0:/kd/pspnet_apctl.prx",
102 "flash0:/kd/pspnet_resolver.prx",
103 };
104
105 // Modules to not load. TODO: Look into loosening this a little (say sceFont).
106 static const char * const blacklistedModules[] = {
107 "sceATRAC3plus_Library",
108 "sceFont_Library",
109 "SceFont_Library",
110 "SceHttp_Library",
111 "sceMpeg_library",
112 "sceNetAdhocctl_Library",
113 "sceNetAdhocDownload_Library",
114 "sceNetAdhocMatching_Library",
115 "sceNetApDialogDummy_Library",
116 "sceNetAdhoc_Library",
117 "sceNetApctl_Library",
118 "sceNetInet_Library",
119 "sceNetResolver_Library",
120 "sceNet_Library",
121 "sceNetAdhoc_Library",
122 "sceNetAdhocAuth_Service",
123 "sceNetAdhocctl_Library",
124 "sceNetIfhandle_Service",
125 "sceSsl_Module",
126 "sceDEFLATE_Library",
127 "sceMD5_Library",
128 "sceMemab",
129 };
130
131 struct WriteVarSymbolState;
132
133 struct VarSymbolImport {
134 char moduleName[KERNELOBJECT_MAX_NAME_LENGTH + 1];
135 u32 nid;
136 u32 stubAddr;
137 u8 type;
138 };
139
140 struct VarSymbolExport {
MatchesVarSymbolExport141 bool Matches(const VarSymbolImport &other) const {
142 return nid == other.nid && !strncmp(moduleName, other.moduleName, KERNELOBJECT_MAX_NAME_LENGTH);
143 }
144
145 char moduleName[KERNELOBJECT_MAX_NAME_LENGTH + 1];
146 u32 nid;
147 u32 symAddr;
148 };
149
150 struct FuncSymbolImport {
151 char moduleName[KERNELOBJECT_MAX_NAME_LENGTH + 1];
152 u32 stubAddr;
153 u32 nid;
154 };
155
156 struct FuncSymbolExport {
MatchesFuncSymbolExport157 bool Matches(const FuncSymbolImport &other) const {
158 return nid == other.nid && !strncmp(moduleName, other.moduleName, KERNELOBJECT_MAX_NAME_LENGTH);
159 }
160
161 char moduleName[KERNELOBJECT_MAX_NAME_LENGTH + 1];
162 u32 symAddr;
163 u32 nid;
164 };
165
166 void ImportVarSymbol(WriteVarSymbolState &state, const VarSymbolImport &var);
167 void ExportVarSymbol(const VarSymbolExport &var);
168 void UnexportVarSymbol(const VarSymbolExport &var);
169
170 void ImportFuncSymbol(const FuncSymbolImport &func, bool reimporting, const char *importingModule);
171 void ExportFuncSymbol(const FuncSymbolExport &func);
172 void UnexportFuncSymbol(const FuncSymbolExport &func);
173
174 class PSPModule;
175 static bool KernelImportModuleFuncs(PSPModule *module, u32 *firstImportStubAddr, bool reimporting = false);
176
177 struct NativeModule {
178 u32_le next;
179 u16_le attribute;
180 u8 version[2];
181 char name[28];
182 u32_le status;
183 u32_le unk1;
184 u32_le modid; // 0x2C
185 u32_le usermod_thid;
186 u32_le memid;
187 u32_le mpidtext;
188 u32_le mpiddata;
189 u32_le ent_top;
190 u32_le ent_size;
191 u32_le stub_top;
192 u32_le stub_size;
193 u32_le module_start_func;
194 u32_le module_stop_func;
195 u32_le module_bootstart_func;
196 u32_le module_reboot_before_func;
197 u32_le module_reboot_phase_func;
198 u32_le entry_addr;
199 u32_le gp_value;
200 u32_le text_addr;
201 u32_le text_size;
202 u32_le data_size;
203 u32_le bss_size;
204 u32_le nsegment;
205 u32_le segmentaddr[4];
206 u32_le segmentsize[4];
207 u32_le module_start_thread_priority;
208 u32_le module_start_thread_stacksize;
209 u32_le module_start_thread_attr;
210 u32_le module_stop_thread_priority;
211 u32_le module_stop_thread_stacksize;
212 u32_le module_stop_thread_attr;
213 u32_le module_reboot_before_thread_priority;
214 u32_le module_reboot_before_thread_stacksize;
215 u32_le module_reboot_before_thread_attr;
216 };
217
218 // by QueryModuleInfo
219 struct ModuleInfo {
220 SceSize_le size;
221 u32_le nsegment;
222 u32_le segmentaddr[4];
223 u32_le segmentsize[4];
224 u32_le entry_addr;
225 u32_le gp_value;
226 u32_le text_addr;
227 u32_le text_size;
228 u32_le data_size;
229 u32_le bss_size;
230 u16_le attribute;
231 u8 version[2];
232 char name[28];
233 };
234
235 struct ModuleWaitingThread {
236 SceUID threadID;
237 u32 statusPtr;
238 };
239
240 enum NativeModuleStatus {
241 MODULE_STATUS_STARTING = 4,
242 MODULE_STATUS_STARTED = 5,
243 MODULE_STATUS_STOPPING = 6,
244 MODULE_STATUS_STOPPED = 7,
245 MODULE_STATUS_UNLOADING = 8,
246 };
247
248 class PSPModule : public KernelObject {
249 public:
~PSPModule()250 ~PSPModule() {
251 if (memoryBlockAddr) {
252 // If it's either below user memory, or using a high kernel bit, it's in kernel.
253 if (memoryBlockAddr < PSP_GetUserMemoryBase() || memoryBlockAddr > PSP_GetUserMemoryEnd()) {
254 kernelMemory.Free(memoryBlockAddr);
255 } else {
256 userMemory.Free(memoryBlockAddr);
257 }
258 g_symbolMap->UnloadModule(memoryBlockAddr, memoryBlockSize);
259 }
260
261 if (modulePtr) {
262 //Only alloc at kernel memory.
263 kernelMemory.Free(modulePtr);
264 }
265 }
GetName()266 const char *GetName() override { return nm.name; }
GetTypeName()267 const char *GetTypeName() override { return GetStaticTypeName(); }
GetStaticTypeName()268 static const char *GetStaticTypeName() { return "Module"; }
GetQuickInfo(char * ptr,int size)269 void GetQuickInfo(char *ptr, int size) override
270 {
271 // ignore size
272 sprintf(ptr, "%sname=%s gp=%08x entry=%08x",
273 isFake ? "faked " : "",
274 nm.name,
275 nm.gp_value,
276 nm.entry_addr);
277 }
GetMissingErrorCode()278 static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_MODULE; }
GetStaticIDType()279 static int GetStaticIDType() { return PPSSPP_KERNEL_TMID_Module; }
GetIDType() const280 int GetIDType() const override { return PPSSPP_KERNEL_TMID_Module; }
281
DoState(PointerWrap & p)282 void DoState(PointerWrap &p) override
283 {
284 auto s = p.Section("Module", 1, 5);
285 if (!s)
286 return;
287
288 if (s >= 5) {
289 Do(p, nm);
290 } else {
291 char temp[192];
292 NativeModule *pnm = &nm;
293 char *ptemp = temp;
294 DoArray(p, ptemp, 0xC0);
295 memcpy(pnm, ptemp, 0x2C);
296 pnm->modid = GetUID();
297 memcpy(((uint8_t *)pnm) + 0x30, ((uint8_t *)ptemp) + 0x2C, 0xC0 - 0x2C);
298 }
299
300 Do(p, memoryBlockAddr);
301 Do(p, memoryBlockSize);
302 Do(p, isFake);
303
304 if (s < 2) {
305 bool isStarted = false;
306 Do(p, isStarted);
307 if (isStarted)
308 nm.status = MODULE_STATUS_STARTED;
309 else
310 nm.status = MODULE_STATUS_STOPPED;
311 }
312
313 if (s >= 3) {
314 Do(p, textStart);
315 Do(p, textEnd);
316 }
317 if (s >= 4) {
318 Do(p, libstub);
319 Do(p, libstubend);
320 }
321
322 if (s >= 5) {
323 Do(p, modulePtr);
324 }
325
326 ModuleWaitingThread mwt = {0};
327 Do(p, waitingThreads, mwt);
328 FuncSymbolExport fsx = {{0}};
329 Do(p, exportedFuncs, fsx);
330 FuncSymbolImport fsi = {{0}};
331 Do(p, importedFuncs, fsi);
332 VarSymbolExport vsx = {{0}};
333 Do(p, exportedVars, vsx);
334 VarSymbolImport vsi = {{0}};
335 Do(p, importedVars, vsi);
336
337 if (p.mode == p.MODE_READ) {
338 // On load state, we re-examine in case our syscall ids changed.
339 if (libstub != 0) {
340 importedFuncs.clear();
341 // Imports reloaded in KernelModuleDoState.
342 } else {
343 // Older save state. Let's still reload, but this may not pick up new flags, etc.
344 bool foundBroken = false;
345 auto importedFuncsState = importedFuncs;
346 importedFuncs.clear();
347 for (auto func : importedFuncsState) {
348 if (func.moduleName[KERNELOBJECT_MAX_NAME_LENGTH] != '\0' || !Memory::IsValidAddress(func.stubAddr)) {
349 foundBroken = true;
350 } else {
351 ImportFunc(func, true);
352 }
353 }
354
355 if (foundBroken) {
356 ERROR_LOG(LOADER, "Broken stub import data while loading state");
357 }
358 }
359
360 char moduleName[29] = {0};
361 truncate_cpy(moduleName, nm.name);
362 if (memoryBlockAddr != 0) {
363 g_symbolMap->AddModule(moduleName, memoryBlockAddr, memoryBlockSize);
364 }
365 }
366
367 HLEPlugins::DoState(p);
368
369 RebuildImpExpModuleNames();
370 }
371
372 // We don't do this in the destructor to avoid annoying messages on game shutdown.
373 void Cleanup();
374
ImportFunc(const FuncSymbolImport & func,bool reimporting)375 void ImportFunc(const FuncSymbolImport &func, bool reimporting) {
376 if (!Memory::IsValidAddress(func.stubAddr)) {
377 WARN_LOG_REPORT(LOADER, "Invalid address for syscall stub %s %08x", func.moduleName, func.nid);
378 return;
379 }
380
381 DEBUG_LOG(LOADER, "Importing %s : %08x", GetFuncName(func.moduleName, func.nid), func.stubAddr);
382
383 // Add the symbol to the symbol map for debugging.
384 char temp[256];
385 sprintf(temp,"zz_%s", GetFuncName(func.moduleName, func.nid));
386 g_symbolMap->AddFunction(temp,func.stubAddr,8);
387
388 // Keep track and actually hook it up if possible.
389 importedFuncs.push_back(func);
390 impExpModuleNames.insert(func.moduleName);
391 ImportFuncSymbol(func, reimporting, GetName());
392 }
393
ImportVar(WriteVarSymbolState & state,const VarSymbolImport & var)394 void ImportVar(WriteVarSymbolState &state, const VarSymbolImport &var) {
395 // Keep track and actually hook it up if possible.
396 importedVars.push_back(var);
397 impExpModuleNames.insert(var.moduleName);
398 ImportVarSymbol(state, var);
399 }
400
ExportFunc(const FuncSymbolExport & func)401 void ExportFunc(const FuncSymbolExport &func) {
402 if (isFake) {
403 return;
404 }
405 exportedFuncs.push_back(func);
406 impExpModuleNames.insert(func.moduleName);
407 ExportFuncSymbol(func);
408 }
409
ExportVar(const VarSymbolExport & var)410 void ExportVar(const VarSymbolExport &var) {
411 if (isFake) {
412 return;
413 }
414 exportedVars.push_back(var);
415 impExpModuleNames.insert(var.moduleName);
416 ExportVarSymbol(var);
417 }
418
419 template <typename T>
RebuildImpExpList(const std::vector<T> & list)420 void RebuildImpExpList(const std::vector<T> &list) {
421 for (size_t i = 0; i < list.size(); ++i) {
422 impExpModuleNames.insert(list[i].moduleName);
423 }
424 }
425
RebuildImpExpModuleNames()426 void RebuildImpExpModuleNames() {
427 impExpModuleNames.clear();
428 RebuildImpExpList(exportedFuncs);
429 RebuildImpExpList(importedFuncs);
430 RebuildImpExpList(exportedVars);
431 RebuildImpExpList(importedVars);
432 }
433
ImportsOrExportsModuleName(const std::string & moduleName)434 bool ImportsOrExportsModuleName(const std::string &moduleName) {
435 return impExpModuleNames.find(moduleName) != impExpModuleNames.end();
436 }
437
438 NativeModule nm{};
439 std::vector<ModuleWaitingThread> waitingThreads;
440
441 std::vector<FuncSymbolExport> exportedFuncs;
442 std::vector<FuncSymbolImport> importedFuncs;
443 std::vector<VarSymbolExport> exportedVars;
444 std::vector<VarSymbolImport> importedVars;
445 std::set<std::string> impExpModuleNames;
446 // Keep track of the code region so we can throw out analysis results
447 // when unloaded.
448 u32 textStart = 0;
449 u32 textEnd = 0;
450
451 // Keep track of the libstub pointers so we can recheck on load state.
452 u32 libstub = 0;
453 u32 libstubend = 0;
454
455 u32 memoryBlockAddr = 0;
456 u32 memoryBlockSize = 0;
457 u32 modulePtr = 0;
458 bool isFake = false;
459 };
460
__KernelModuleObject()461 KernelObject *__KernelModuleObject()
462 {
463 return new PSPModule;
464 }
465
466 class AfterModuleEntryCall : public PSPAction {
467 public:
AfterModuleEntryCall()468 AfterModuleEntryCall() {}
469 SceUID moduleID_;
470 u32 retValAddr;
471 void run(MipsCall &call) override;
DoState(PointerWrap & p)472 void DoState(PointerWrap &p) override {
473 auto s = p.Section("AfterModuleEntryCall", 1);
474 if (!s)
475 return;
476
477 Do(p, moduleID_);
478 Do(p, retValAddr);
479 }
Create()480 static PSPAction *Create() {
481 return new AfterModuleEntryCall;
482 }
483 };
484
run(MipsCall & call)485 void AfterModuleEntryCall::run(MipsCall &call) {
486 Memory::Write_U32(retValAddr, currentMIPS->r[MIPS_REG_V0]);
487 }
488
489 //////////////////////////////////////////////////////////////////////////
490 // MODULES
491 //////////////////////////////////////////////////////////////////////////
492 struct StartModuleInfo
493 {
494 u32_le size;
495 u32_le mpidtext;
496 u32_le mpiddata;
497 u32_le threadpriority;
498 u32_le threadattributes;
499 };
500
501 struct SceKernelLMOption {
502 SceSize_le size;
503 SceUID_le mpidtext;
504 SceUID_le mpiddata;
505 u32_le flags;
506 char position;
507 char access;
508 char creserved[2];
509 };
510
511 struct SceKernelSMOption {
512 SceSize_le size;
513 SceUID_le mpidstack;
514 SceSize_le stacksize;
515 s32_le priority;
516 u32_le attribute;
517 };
518
519 //////////////////////////////////////////////////////////////////////////
520 // STATE BEGIN
521 static int actionAfterModule;
522
523 static std::set<SceUID> loadedModules;
524 // STATE END
525 //////////////////////////////////////////////////////////////////////////
526
__KernelModuleInit()527 static void __KernelModuleInit()
528 {
529 actionAfterModule = __KernelRegisterActionType(AfterModuleEntryCall::Create);
530 }
531
__KernelModuleDoState(PointerWrap & p)532 void __KernelModuleDoState(PointerWrap &p)
533 {
534 auto s = p.Section("sceKernelModule", 1, 2);
535 if (!s)
536 return;
537
538 Do(p, actionAfterModule);
539 __KernelRestoreActionType(actionAfterModule, AfterModuleEntryCall::Create);
540
541 if (s >= 2) {
542 Do(p, loadedModules);
543 }
544
545 if (p.mode == p.MODE_READ) {
546 u32 error;
547 // We process these late, since they depend on loadedModules for interlinking.
548 for (SceUID moduleId : loadedModules) {
549 PSPModule *module = kernelObjects.Get<PSPModule>(moduleId, error);
550 if (module && module->libstub != 0) {
551 if (!KernelImportModuleFuncs(module, nullptr, true)) {
552 ERROR_LOG(LOADER, "Something went wrong loading imports on load state");
553 }
554 }
555 }
556 }
557
558 if (g_Config.bFuncReplacements) {
559 MIPSAnalyst::ReplaceFunctions();
560 }
561 }
562
__KernelModuleShutdown()563 void __KernelModuleShutdown()
564 {
565 loadedModules.clear();
566 MIPSAnalyst::Reset();
567 HLEPlugins::Unload();
568 }
569
570 // Sometimes there are multiple LO16's or HI16's per pair, even though the ABI says nothing of this.
571 // For multiple LO16's, we need the original (unrelocated) instruction data of the HI16.
572 // For multiple HI16's, we just need to set each one.
573 struct HI16RelocInfo {
574 u32 addr;
575 u32 data;
576 };
577 // We have to post-process the HI16 part, since it might be +1 or not depending on the LO16 value.
578 // For that purpose, we use this state to track HI16s to adjust.
579 struct WriteVarSymbolState {
580 u32 lastHI16ExportAddress = 0;
581 std::vector<HI16RelocInfo> lastHI16Relocs;
582 bool lastHI16Processed = true;
583 };
584
WriteVarSymbol(WriteVarSymbolState & state,u32 exportAddress,u32 relocAddress,u8 type,bool reverse=false)585 static void WriteVarSymbol(WriteVarSymbolState &state, u32 exportAddress, u32 relocAddress, u8 type, bool reverse = false) {
586 u32 relocData = Memory::Read_Instruction(relocAddress, true).encoding;
587
588 switch (type) {
589 case R_MIPS_NONE:
590 WARN_LOG_REPORT(LOADER, "Var relocation type NONE - %08x => %08x", exportAddress, relocAddress);
591 break;
592
593 case R_MIPS_32:
594 if (!reverse) {
595 relocData += exportAddress;
596 } else {
597 relocData -= exportAddress;
598 }
599 break;
600
601 // Not really tested, but should work...
602 /*
603 case R_MIPS_26:
604 if (exportAddress % 4 || (exportAddress >> 28) != ((relocAddress + 4) >> 28)) {
605 WARN_LOG_REPORT(LOADER, "Bad var relocation addresses for type 26 - %08x => %08x", exportAddress, relocAddress)
606 } else {
607 if (!reverse) {
608 relocData = (relocData & ~0x03ffffff) | ((relocData + (exportAddress >> 2)) & 0x03ffffff);
609 } else {
610 relocData = (relocData & ~0x03ffffff) | ((relocData - (exportAddress >> 2)) & 0x03ffffff);
611 }
612 }
613 break;
614 */
615
616 case R_MIPS_HI16:
617 if (state.lastHI16ExportAddress != exportAddress) {
618 if (!state.lastHI16Processed && !state.lastHI16Relocs.empty()) {
619 WARN_LOG_REPORT(LOADER, "Unsafe unpaired HI16 variable relocation @ %08x / %08x", state.lastHI16Relocs[state.lastHI16Relocs.size() - 1].addr, relocAddress);
620 }
621
622 state.lastHI16ExportAddress = exportAddress;
623 state.lastHI16Relocs.clear();
624 }
625
626 // After this will be an R_MIPS_LO16. If that addition overflows, we need to account for it in HI16.
627 // The R_MIPS_LO16 and R_MIPS_HI16 will often be *different* relocAddress values.
628 HI16RelocInfo reloc;
629 reloc.addr = relocAddress;
630 reloc.data = Memory::Read_Instruction(relocAddress, true).encoding;
631 state.lastHI16Relocs.push_back(reloc);
632 state.lastHI16Processed = false;
633 break;
634
635 case R_MIPS_LO16:
636 {
637 // Sign extend the existing low value (e.g. from addiu.)
638 const u32 offsetLo = SignExtend16ToU32(relocData);
639 u32 full = exportAddress;
640 // This is only used in the error case (no hi/wrong hi.)
641 if (!reverse) {
642 full = offsetLo + exportAddress;
643 } else {
644 full = offsetLo - exportAddress;
645 }
646
647 // The ABI requires that these come in pairs, at least.
648 if (state.lastHI16Relocs.empty()) {
649 ERROR_LOG_REPORT(LOADER, "LO16 without any HI16 variable import at %08x for %08x", relocAddress, exportAddress);
650 // Try to process at least the low relocation...
651 } else if (state.lastHI16ExportAddress != exportAddress) {
652 ERROR_LOG_REPORT(LOADER, "HI16 and LO16 imports do not match at %08x for %08x (should be %08x)", relocAddress, state.lastHI16ExportAddress, exportAddress);
653 } else {
654 // Process each of the HI16. Usually there's only one.
655 for (auto &reloc : state.lastHI16Relocs) {
656 if (!reverse) {
657 full = (reloc.data << 16) + offsetLo + exportAddress;
658 } else {
659 full = (reloc.data << 16) + offsetLo - exportAddress;
660 }
661 // The low instruction will be a signed add, which means (full & 0x8000) will subtract.
662 // We add 1 in that case so that it ends up the right value.
663 u16 high = (full >> 16) + ((full & 0x8000) ? 1 : 0);
664 Memory::Write_U32((reloc.data & ~0xFFFF) | high, reloc.addr);
665 currentMIPS->InvalidateICache(reloc.addr, 4);
666 }
667 state.lastHI16Processed = true;
668 }
669
670 // With full set above (hopefully), now we just need to correct the low instruction.
671 relocData = (relocData & ~0xFFFF) | (full & 0xFFFF);
672 }
673 break;
674
675 default:
676 WARN_LOG_REPORT(LOADER, "Unsupported var relocation type %d - %08x => %08x", type, exportAddress, relocAddress);
677 }
678
679 Memory::Write_U32(relocData, relocAddress);
680 currentMIPS->InvalidateICache(relocAddress, 4);
681 }
682
ImportVarSymbol(WriteVarSymbolState & state,const VarSymbolImport & var)683 void ImportVarSymbol(WriteVarSymbolState &state, const VarSymbolImport &var) {
684 if (var.nid == 0) {
685 // TODO: What's the right thing for this?
686 ERROR_LOG_REPORT(LOADER, "Var import with nid = 0, type = %d", var.type);
687 return;
688 }
689
690 if (!Memory::IsValidAddress(var.stubAddr)) {
691 ERROR_LOG_REPORT(LOADER, "Invalid address for var import nid = %08x, type = %d, addr = %08x", var.nid, var.type, var.stubAddr);
692 return;
693 }
694
695 u32 error;
696 for (SceUID moduleId : loadedModules) {
697 PSPModule *module = kernelObjects.Get<PSPModule>(moduleId, error);
698 if (!module || !module->ImportsOrExportsModuleName(var.moduleName)) {
699 continue;
700 }
701
702 // Look for exports currently loaded modules already have. Maybe it's available?
703 for (const auto &exported : module->exportedVars) {
704 if (exported.Matches(var)) {
705 WriteVarSymbol(state, exported.symAddr, var.stubAddr, var.type);
706 return;
707 }
708 }
709 }
710
711 // It hasn't been exported yet, but hopefully it will later.
712 INFO_LOG(LOADER, "Variable (%s,%08x) unresolved, storing for later resolving", var.moduleName, var.nid);
713 }
714
ExportVarSymbol(const VarSymbolExport & var)715 void ExportVarSymbol(const VarSymbolExport &var) {
716 u32 error;
717 for (SceUID moduleId : loadedModules) {
718 PSPModule *module = kernelObjects.Get<PSPModule>(moduleId, error);
719 if (!module || !module->ImportsOrExportsModuleName(var.moduleName)) {
720 continue;
721 }
722
723 // Look for imports currently loaded modules already have, hook it up right away.
724 WriteVarSymbolState state;
725 for (auto &imported : module->importedVars) {
726 if (var.Matches(imported)) {
727 INFO_LOG(LOADER, "Resolving var %s/%08x", var.moduleName, var.nid);
728 WriteVarSymbol(state, var.symAddr, imported.stubAddr, imported.type);
729 }
730 }
731 }
732 }
733
UnexportVarSymbol(const VarSymbolExport & var)734 void UnexportVarSymbol(const VarSymbolExport &var) {
735 u32 error;
736 for (SceUID moduleId : loadedModules) {
737 PSPModule *module = kernelObjects.Get<PSPModule>(moduleId, error);
738 if (!module || !module->ImportsOrExportsModuleName(var.moduleName)) {
739 continue;
740 }
741
742 // Look for imports modules that are *still* loaded have, and reverse them.
743 WriteVarSymbolState state;
744 for (auto &imported : module->importedVars) {
745 if (var.Matches(imported)) {
746 INFO_LOG(LOADER, "Unresolving var %s/%08x", var.moduleName, var.nid);
747 WriteVarSymbol(state, var.symAddr, imported.stubAddr, imported.type, true);
748 }
749 }
750 }
751 }
752
ImportFuncSymbol(const FuncSymbolImport & func,bool reimporting,const char * importingModule)753 void ImportFuncSymbol(const FuncSymbolImport &func, bool reimporting, const char *importingModule) {
754 // Prioritize HLE implementations.
755 // TODO: Or not?
756 if (FuncImportIsSyscall(func.moduleName, func.nid)) {
757 if (reimporting && Memory::Read_Instruction(func.stubAddr + 4) != GetSyscallOp(func.moduleName, func.nid)) {
758 WARN_LOG(LOADER, "Reimporting updated syscall %s", GetFuncName(func.moduleName, func.nid));
759 }
760 WriteSyscall(func.moduleName, func.nid, func.stubAddr);
761 currentMIPS->InvalidateICache(func.stubAddr, 8);
762 MIPSAnalyst::PrecompileFunction(func.stubAddr, 8);
763 return;
764 }
765
766 u32 error;
767 for (SceUID moduleId : loadedModules) {
768 PSPModule *module = kernelObjects.Get<PSPModule>(moduleId, error);
769 if (!module || !module->ImportsOrExportsModuleName(func.moduleName)) {
770 continue;
771 }
772
773 // Look for exports currently loaded modules already have. Maybe it's available?
774 for (auto it = module->exportedFuncs.begin(), end = module->exportedFuncs.end(); it != end; ++it) {
775 if (it->Matches(func)) {
776 if (reimporting && Memory::Read_Instruction(func.stubAddr) != MIPS_MAKE_J(it->symAddr)) {
777 WARN_LOG_REPORT(LOADER, "Reimporting: func import %s/%08x changed", func.moduleName, func.nid);
778 }
779 WriteFuncStub(func.stubAddr, it->symAddr);
780 currentMIPS->InvalidateICache(func.stubAddr, 8);
781 MIPSAnalyst::PrecompileFunction(func.stubAddr, 8);
782 return;
783 }
784 }
785 }
786
787 // It hasn't been exported yet, but hopefully it will later.
788 bool isKnownModule = GetModuleIndex(func.moduleName) != -1;
789 if (isKnownModule) {
790 // We used to report this, but I don't think it's very interesting anymore.
791 WARN_LOG(LOADER, "Unknown syscall from known module '%s': 0x%08x (import for '%s')", func.moduleName, func.nid, importingModule);
792 } else {
793 INFO_LOG(LOADER, "Function (%s,%08x) unresolved in '%s', storing for later resolving", func.moduleName, func.nid, importingModule);
794 }
795 if (isKnownModule || !reimporting) {
796 WriteFuncMissingStub(func.stubAddr, func.nid);
797 currentMIPS->InvalidateICache(func.stubAddr, 8);
798 }
799 }
800
ExportFuncSymbol(const FuncSymbolExport & func)801 void ExportFuncSymbol(const FuncSymbolExport &func) {
802 if (FuncImportIsSyscall(func.moduleName, func.nid)) {
803 // HLE covers this already - let's ignore the function.
804 WARN_LOG(LOADER, "Ignoring func export %s/%08x, already implemented in HLE.", func.moduleName, func.nid);
805 return;
806 }
807
808 u32 error;
809 for (SceUID moduleId : loadedModules) {
810 PSPModule *module = kernelObjects.Get<PSPModule>(moduleId, error);
811 if (!module || !module->ImportsOrExportsModuleName(func.moduleName)) {
812 continue;
813 }
814
815 // Look for imports currently loaded modules already have, hook it up right away.
816 for (auto it = module->importedFuncs.begin(), end = module->importedFuncs.end(); it != end; ++it) {
817 if (func.Matches(*it)) {
818 INFO_LOG(LOADER, "Resolving function %s/%08x", func.moduleName, func.nid);
819 WriteFuncStub(it->stubAddr, func.symAddr);
820 currentMIPS->InvalidateICache(it->stubAddr, 8);
821 MIPSAnalyst::PrecompileFunction(it->stubAddr, 8);
822 }
823 }
824 }
825 }
826
UnexportFuncSymbol(const FuncSymbolExport & func)827 void UnexportFuncSymbol(const FuncSymbolExport &func) {
828 if (FuncImportIsSyscall(func.moduleName, func.nid)) {
829 // Oops, HLE covers this.
830 return;
831 }
832
833 u32 error;
834 for (SceUID moduleId : loadedModules) {
835 PSPModule *module = kernelObjects.Get<PSPModule>(moduleId, error);
836 if (!module || !module->ImportsOrExportsModuleName(func.moduleName)) {
837 continue;
838 }
839
840 // Look for imports modules that are *still* loaded have, and write back stubs.
841 for (auto it = module->importedFuncs.begin(), end = module->importedFuncs.end(); it != end; ++it) {
842 if (func.Matches(*it)) {
843 INFO_LOG(LOADER, "Unresolving function %s/%08x", func.moduleName, func.nid);
844 WriteFuncMissingStub(it->stubAddr, it->nid);
845 currentMIPS->InvalidateICache(it->stubAddr, 8);
846 }
847 }
848 }
849 }
850
Cleanup()851 void PSPModule::Cleanup() {
852 MIPSAnalyst::ForgetFunctions(textStart, textEnd);
853
854 loadedModules.erase(GetUID());
855
856 for (auto it = exportedVars.begin(), end = exportedVars.end(); it != end; ++it) {
857 UnexportVarSymbol(*it);
858 }
859 for (auto it = exportedFuncs.begin(), end = exportedFuncs.end(); it != end; ++it) {
860 UnexportFuncSymbol(*it);
861 }
862
863 if (memoryBlockAddr != 0 && nm.text_addr != 0 && memoryBlockSize >= nm.data_size + nm.bss_size + nm.text_size) {
864 DEBUG_LOG(LOADER, "Zeroing out module %s memory: %08x - %08x", nm.name, memoryBlockAddr, memoryBlockAddr + memoryBlockSize);
865 u32 clearSize = Memory::ValidSize(nm.text_addr, (u32)nm.text_size + 3);
866 for (u32 i = 0; i < clearSize; i += 4) {
867 Memory::WriteUnchecked_U32(MIPS_MAKE_BREAK(1), nm.text_addr + i);
868 }
869 NotifyMemInfo(MemBlockFlags::WRITE, nm.text_addr, clearSize, "ModuleClear");
870 Memory::Memset(nm.text_addr + nm.text_size, -1, nm.data_size + nm.bss_size, "ModuleClear");
871
872 // Let's also invalidate, just to make sure it's cleared out for any future data.
873 currentMIPS->InvalidateICache(memoryBlockAddr, memoryBlockSize);
874 }
875 }
876
__SaveDecryptedEbootToStorageMedia(const u8 * decryptedEbootDataPtr,const u32 length)877 static void __SaveDecryptedEbootToStorageMedia(const u8 *decryptedEbootDataPtr, const u32 length) {
878 if (!decryptedEbootDataPtr) {
879 ERROR_LOG(SCEMODULE, "Error saving decrypted EBOOT.BIN: invalid pointer");
880 return;
881 }
882
883 if (length == 0) {
884 ERROR_LOG(SCEMODULE, "Error saving decrypted EBOOT.BIN: invalid length");
885 return;
886 }
887
888 const std::string filenameToDumpTo = g_paramSFO.GetDiscID() + ".BIN";
889 const Path dumpDirectory = GetSysDirectory(DIRECTORY_DUMP);
890 const Path fullPath = dumpDirectory / filenameToDumpTo;
891
892 // If the file already exists, don't dump it again.
893 if (File::Exists(fullPath)) {
894 INFO_LOG(SCEMODULE, "Decrypted EBOOT.BIN already exists for this game, skipping dump.");
895 return;
896 }
897
898 // Make sure the dump directory exists before continuing.
899 if (!File::Exists(dumpDirectory)) {
900 if (!File::CreateDir(dumpDirectory)) {
901 ERROR_LOG(SCEMODULE, "Unable to create directory for EBOOT dumping, aborting.");
902 return;
903 }
904 }
905
906 FILE *decryptedEbootFile = File::OpenCFile(fullPath, "wb");
907 if (!decryptedEbootFile) {
908 ERROR_LOG(SCEMODULE, "Unable to write decrypted EBOOT.");
909 return;
910 }
911
912 const size_t lengthToWrite = length;
913
914 fwrite(decryptedEbootDataPtr, sizeof(u8), lengthToWrite, decryptedEbootFile);
915 fclose(decryptedEbootFile);
916 INFO_LOG(SCEMODULE, "Successfully wrote decrypted EBOOT to %s", fullPath.c_str());
917 }
918
IsHLEVersionedModule(const char * name)919 static bool IsHLEVersionedModule(const char *name) {
920 // TODO: Only some of these are currently known to be versioned.
921 // Potentially only sceMpeg_library matters.
922 // For now, we're just reporting version numbers.
923 for (size_t i = 0; i < ARRAY_SIZE(blacklistedModules); i++) {
924 if (!strncmp(name, blacklistedModules[i], 28)) {
925 return true;
926 }
927 }
928 static const char *otherModules[] = {
929 "sceAvcodec_driver",
930 "sceAudiocodec_Driver",
931 "sceAudiocodec",
932 "sceVideocodec_Driver",
933 "sceVideocodec",
934 "sceMpegbase_Driver",
935 "sceMpegbase",
936 "scePsmf_library",
937 "scePsmfP_library",
938 "scePsmfPlayer",
939 "sceSAScore",
940 "sceCcc_Library",
941 "SceParseHTTPheader_Library",
942 "SceParseURI_Library",
943 // Guessing.
944 "sceJpeg",
945 "sceJpeg_library",
946 "sceJpeg_Library",
947 };
948 for (size_t i = 0; i < ARRAY_SIZE(otherModules); i++) {
949 if (!strncmp(name, otherModules[i], 28)) {
950 return true;
951 }
952 }
953 return false;
954 }
955
KernelImportModuleFuncs(PSPModule * module,u32 * firstImportStubAddr,bool reimporting)956 static bool KernelImportModuleFuncs(PSPModule *module, u32 *firstImportStubAddr, bool reimporting) {
957 struct PspLibStubEntry {
958 u32_le name;
959 u16_le version;
960 u16_le flags;
961 u8 size;
962 u8 numVars;
963 u16_le numFuncs;
964 // each symbol has an associated nid; nidData is a pointer
965 // (in .rodata.sceNid section) to an array of longs, one
966 // for each function, which identifies the function whose
967 // address is to be inserted.
968 //
969 // The hash is the first 4 bytes of a SHA-1 hash of the function
970 // name. (Represented as a little-endian long, so the order
971 // of the bytes is reversed.)
972 u32_le nidData;
973 // the address of the function stubs where the function address jumps
974 // should be filled in
975 u32_le firstSymAddr;
976 // Optional, this is where var relocations are.
977 // They use the format: u32 addr, u32 nid, ...
978 // WARNING: May have garbage if size < 6.
979 u32_le varData;
980 // Not sure what this is yet, assume garbage for now.
981 // TODO: Tales of the World: Radiant Mythology 2 has something here?
982 u32_le extra;
983 };
984
985 // Can't run - we didn't keep track of the libstub entry.
986 if (module->libstub == 0) {
987 return false;
988 }
989 if (!Memory::IsValidRange(module->libstub, module->libstubend - module->libstub)) {
990 ERROR_LOG_REPORT(LOADER, "Garbage libstub address %08x or end %08x", module->libstub, module->libstubend);
991 return false;
992 }
993
994 u32_le *entryPos = (u32_le *)Memory::GetPointerUnchecked(module->libstub);
995 u32_le *entryEnd = (u32_le *)Memory::GetPointerUnchecked(module->libstubend);
996
997 bool needReport = false;
998 while (entryPos < entryEnd) {
999 PspLibStubEntry *entry = (PspLibStubEntry *)entryPos;
1000 entryPos += entry->size;
1001
1002 const char *modulename;
1003 if (Memory::IsValidAddress(entry->name)) {
1004 modulename = Memory::GetCharPointer(entry->name);
1005 } else {
1006 modulename = "(invalidname)";
1007 needReport = true;
1008 }
1009
1010 DEBUG_LOG(LOADER, "Importing Module %s, stubs at %08x", modulename, entry->firstSymAddr);
1011 if (entry->size != 5 && entry->size != 6) {
1012 if (entry->size != 7) {
1013 WARN_LOG_REPORT(LOADER, "Unexpected module entry size %d", entry->size);
1014 needReport = true;
1015 } else if (entry->extra != 0) {
1016 WARN_LOG_REPORT(LOADER, "Unexpected module entry with non-zero 7th value %08x", entry->extra);
1017 needReport = true;
1018 }
1019 }
1020
1021 // Prevent infinite spin on bad data.
1022 if (entry->size == 0)
1023 break;
1024
1025 // If nidData is 0, only variables are being imported.
1026 if (entry->numFuncs > 0 && entry->nidData != 0) {
1027 if (!Memory::IsValidAddress(entry->nidData)) {
1028 ERROR_LOG_REPORT(LOADER, "Crazy nidData address %08x, skipping entire module", entry->nidData);
1029 needReport = true;
1030 continue;
1031 }
1032
1033 FuncSymbolImport func;
1034 strncpy(func.moduleName, modulename, KERNELOBJECT_MAX_NAME_LENGTH);
1035 func.moduleName[KERNELOBJECT_MAX_NAME_LENGTH] = '\0';
1036
1037 u32_le *nidDataPtr = (u32_le *)Memory::GetPointer(entry->nidData);
1038 for (int i = 0; i < entry->numFuncs; ++i) {
1039 // This is the id of the import.
1040 func.nid = nidDataPtr[i];
1041 // This is the address to write the j and delay slot to.
1042 func.stubAddr = entry->firstSymAddr + i * 8;
1043 module->ImportFunc(func, reimporting);
1044 }
1045
1046 if (firstImportStubAddr && (!*firstImportStubAddr || *firstImportStubAddr > (u32)entry->firstSymAddr))
1047 *firstImportStubAddr = entry->firstSymAddr;
1048 } else if (entry->numFuncs > 0) {
1049 WARN_LOG_REPORT(LOADER, "Module entry with %d imports but no valid address", entry->numFuncs);
1050 needReport = true;
1051 }
1052
1053 // We skip vars when reimporting, since we might double-offset.
1054 // We only reimport funcs, which can't be double-offset.
1055 if (entry->numVars > 0 && entry->varData != 0 && !reimporting) {
1056 if (!Memory::IsValidAddress(entry->varData)) {
1057 ERROR_LOG_REPORT(LOADER, "Crazy varData address %08x, skipping rest of module", entry->varData);
1058 needReport = true;
1059 continue;
1060 }
1061
1062 VarSymbolImport var;
1063 strncpy(var.moduleName, modulename, KERNELOBJECT_MAX_NAME_LENGTH);
1064 var.moduleName[KERNELOBJECT_MAX_NAME_LENGTH] = '\0';
1065
1066 for (int i = 0; i < entry->numVars; ++i) {
1067 u32 varRefsPtr = Memory::Read_U32(entry->varData + i * 8);
1068 u32 nid = Memory::Read_U32(entry->varData + i * 8 + 4);
1069 if (!Memory::IsValidAddress(varRefsPtr)) {
1070 WARN_LOG_REPORT(LOADER, "Bad relocation list address for nid %08x in %s", nid, modulename);
1071 continue;
1072 }
1073
1074 WriteVarSymbolState state;
1075 u32_le *varRef = (u32_le *)Memory::GetPointer(varRefsPtr);
1076 for (; *varRef != 0; ++varRef) {
1077 var.nid = nid;
1078 var.stubAddr = (*varRef & 0x03FFFFFF) << 2;
1079 var.type = *varRef >> 26;
1080 module->ImportVar(state, var);
1081 }
1082 }
1083 } else if (entry->numVars > 0 && !reimporting) {
1084 WARN_LOG_REPORT(LOADER, "Module entry with %d var imports but no valid address", entry->numVars);
1085 needReport = true;
1086 }
1087
1088 DEBUG_LOG(LOADER, "-------------------------------------------------------------");
1089 }
1090
1091 if (needReport) {
1092 std::string debugInfo;
1093 entryPos = (u32_le *)Memory::GetPointer(module->libstub);
1094 while (entryPos < entryEnd) {
1095 PspLibStubEntry *entry = (PspLibStubEntry *)entryPos;
1096 entryPos += entry->size;
1097
1098 char temp[512];
1099 const char *modulename;
1100 if (Memory::IsValidAddress(entry->name)) {
1101 modulename = Memory::GetCharPointer(entry->name);
1102 } else {
1103 modulename = "(invalidname)";
1104 }
1105
1106 snprintf(temp, sizeof(temp), "%s ver=%04x, flags=%04x, size=%d, numVars=%d, numFuncs=%d, nidData=%08x, firstSym=%08x, varData=%08x, extra=%08x\n",
1107 modulename, entry->version, entry->flags, entry->size, entry->numVars, entry->numFuncs, entry->nidData, entry->firstSymAddr, entry->size >= 6 ? (u32)entry->varData : 0, entry->size >= 7 ? (u32)entry->extra : 0);
1108 debugInfo += temp;
1109 }
1110
1111 Reporting::ReportMessage("Module linking debug info:\n%s", debugInfo.c_str());
1112 }
1113
1114 return true;
1115 }
1116
gzipDecompress(u8 * OutBuffer,int OutBufferLength,u8 * InBuffer)1117 static int gzipDecompress(u8 *OutBuffer, int OutBufferLength, u8 *InBuffer) {
1118 int err;
1119 z_stream stream;
1120 u8 *outBufferPtr;
1121
1122 outBufferPtr = OutBuffer;
1123 stream.next_in = InBuffer;
1124 stream.avail_in = (uInt)OutBufferLength;
1125 stream.next_out = outBufferPtr;
1126 stream.avail_out = (uInt)OutBufferLength;
1127 stream.zalloc = (alloc_func)0;
1128 stream.zfree = (free_func)0;
1129 err = inflateInit2(&stream, 16+MAX_WBITS);
1130 if (err != Z_OK) {
1131 return -1;
1132 }
1133 err = inflate(&stream, Z_FINISH);
1134 if (err != Z_STREAM_END) {
1135 inflateEnd(&stream);
1136 return -2;
1137 }
1138 inflateEnd(&stream);
1139 return stream.total_out;
1140 }
1141
__KernelLoadELFFromPtr(const u8 * ptr,size_t elfSize,u32 loadAddress,bool fromTop,std::string * error_string,u32 * magic,u32 & error)1142 static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAddress, bool fromTop, std::string *error_string, u32 *magic, u32 &error) {
1143 PSPModule *module = new PSPModule();
1144 kernelObjects.Create(module);
1145 loadedModules.insert(module->GetUID());
1146 memset(&module->nm, 0, sizeof(module->nm));
1147
1148 module->nm.modid = module->GetUID();
1149
1150 bool reportedModule = false;
1151 u32 devkitVersion = 0;
1152 u8 *newptr = 0;
1153 u32_le *magicPtr = (u32_le *) ptr;
1154 if (*magicPtr == 0x4543537e) { // "~SCE"
1155 INFO_LOG(SCEMODULE, "~SCE module, skipping header");
1156 u32 headerSize = *(u32_le*)(ptr + 4);
1157 ptr += headerSize;
1158 elfSize -= headerSize;
1159 magicPtr = (u32_le *)ptr;
1160 }
1161 *magic = *magicPtr;
1162 if (*magic == 0x5053507e) { // "~PSP"
1163 DEBUG_LOG(SCEMODULE, "Decrypting ~PSP file");
1164 PSP_Header *head = (PSP_Header*)ptr;
1165 devkitVersion = head->devkitversion;
1166
1167 if (IsHLEVersionedModule(head->modname)) {
1168 int ver = (head->module_ver_hi << 8) | head->module_ver_lo;
1169 INFO_LOG(SCEMODULE, "Loading module %s with version %04x, devkit %08x", head->modname, ver, head->devkitversion);
1170 reportedModule = true;
1171
1172 if (!strcmp(head->modname, "sceMpeg_library")) {
1173 __MpegLoadModule(ver);
1174 }
1175 if (!strcmp(head->modname, "scePsmfP_library") || !strcmp(head->modname, "scePsmfPlayer")) {
1176 __PsmfPlayerLoadModule(head->devkitversion);
1177 }
1178 }
1179
1180 const u8 *in = ptr;
1181 const auto isGzip = head->comp_attribute & 1;
1182 // Kind of odd.
1183 u32 size = head->psp_size;
1184 if (size > elfSize) {
1185 *error_string = StringFromFormat("ELF/PRX truncated: %d > %d", (int)size, (int)elfSize);
1186 module->Cleanup();
1187 kernelObjects.Destroy<PSPModule>(module->GetUID());
1188 // TODO: Might be the wrong error code.
1189 error = SCE_KERNEL_ERROR_FILEERR;
1190 return nullptr;
1191 }
1192 const auto maxElfSize = std::max(head->elf_size, head->psp_size);
1193 newptr = new u8[maxElfSize];
1194 ptr = newptr;
1195 magicPtr = (u32_le *)ptr;
1196 int ret = pspDecryptPRX(in, (u8*)ptr, head->psp_size);
1197 if (reportedModule) {
1198 // This should happen for all "kernel" modules.
1199 *error_string = "Missing key";
1200 delete [] newptr;
1201 module->isFake = true;
1202 strncpy(module->nm.name, head->modname, ARRAY_SIZE(module->nm.name));
1203 module->nm.entry_addr = -1;
1204 module->nm.gp_value = -1;
1205
1206 // Let's still try to allocate it. It may use user memory.
1207 u32 totalSize = 0;
1208 for (int i = 0; i < 4; ++i) {
1209 if (head->seg_size[i]) {
1210 const u32 align = head->seg_align[i] - 1;
1211 totalSize = ((totalSize + align) & ~align) + head->seg_size[i];
1212 }
1213 }
1214 bool kernelModule = (head->attribute & 0x1000) != 0;
1215 BlockAllocator &memblock = kernelModule ? kernelMemory : userMemory;
1216 size_t n = strnlen(head->modname, 28);
1217 const std::string modName = "ELF/" + std::string(head->modname, n);
1218 u32 addr = memblock.Alloc(totalSize, fromTop, modName.c_str());
1219 if (addr == (u32)-1) {
1220 error = SCE_KERNEL_ERROR_MEMBLOCK_ALLOC_FAILED;
1221 module->Cleanup();
1222 kernelObjects.Destroy<PSPModule>(module->GetUID());
1223 } else {
1224 error = 0;
1225 module->memoryBlockAddr = addr;
1226 module->memoryBlockSize = totalSize;
1227 }
1228
1229 return module;
1230 } else if (ret <= 0) {
1231 ERROR_LOG(SCEMODULE, "Failed decrypting PRX! That's not normal! ret = %i\n", ret);
1232 Reporting::ReportMessage("Failed decrypting the PRX (ret = %i, size = %i, psp_size = %i)!", ret, head->elf_size, head->psp_size);
1233 // Fall through to safe exit in the next check.
1234 } else {
1235 // TODO: Is this right?
1236 module->nm.bss_size = head->bss_size;
1237
1238 // decompress if required
1239 if (isGzip)
1240 {
1241 auto temp = new u8[ret];
1242 memcpy(temp, ptr, ret);
1243 gzipDecompress((u8 *)ptr, maxElfSize, temp);
1244 delete[] temp;
1245 }
1246
1247 // If we've made it this far, it should be safe to dump.
1248 if (g_Config.bDumpDecryptedEboot) {
1249 INFO_LOG(SCEMODULE, "Dumping decrypted EBOOT.BIN to file.");
1250 const u32 dumpLength = ret;
1251 __SaveDecryptedEbootToStorageMedia(ptr, dumpLength);
1252 }
1253 }
1254 }
1255
1256 // DO NOT change to else if, see above.
1257 if (*magicPtr != 0x464c457f) {
1258 ERROR_LOG(SCEMODULE, "Wrong magic number %08x", *magicPtr);
1259 *error_string = "File corrupt";
1260 if (newptr)
1261 delete [] newptr;
1262 module->Cleanup();
1263 kernelObjects.Destroy<PSPModule>(module->GetUID());
1264 error = SCE_KERNEL_ERROR_UNSUPPORTED_PRX_TYPE;
1265 return nullptr;
1266 }
1267
1268 // Open ELF reader
1269 ElfReader reader((void*)ptr, elfSize);
1270
1271 int result = reader.LoadInto(loadAddress, fromTop);
1272 if (result != SCE_KERNEL_ERROR_OK) {
1273 ERROR_LOG(SCEMODULE, "LoadInto failed with error %08x",result);
1274 if (newptr)
1275 delete [] newptr;
1276 module->Cleanup();
1277 kernelObjects.Destroy<PSPModule>(module->GetUID());
1278 error = result;
1279 return nullptr;
1280 }
1281 module->memoryBlockAddr = reader.GetVaddr();
1282 module->memoryBlockSize = reader.GetTotalSize();
1283
1284 currentMIPS->InvalidateICache(module->memoryBlockAddr, module->memoryBlockSize);
1285
1286 SectionID sceModuleInfoSection = reader.GetSectionByName(".rodata.sceModuleInfo");
1287 PspModuleInfo *modinfo;
1288 if (sceModuleInfoSection != -1)
1289 modinfo = (PspModuleInfo *)Memory::GetPointer(reader.GetSectionAddr(sceModuleInfoSection));
1290 else
1291 modinfo = (PspModuleInfo *)Memory::GetPointer(reader.GetSegmentVaddr(0) + (reader.GetSegmentPaddr(0) & 0x7FFFFFFF) - reader.GetSegmentOffset(0));
1292
1293 module->nm.nsegment = reader.GetNumSegments();
1294 module->nm.attribute = modinfo->moduleAttrs;
1295 module->nm.version[0] = modinfo->moduleVersion & 0xFF;
1296 module->nm.version[1] = modinfo->moduleVersion >> 8;
1297 module->nm.data_size = 0;
1298 // TODO: Is summing them up correct? Must not be since the numbers aren't exactly right.
1299 for (int i = 0; i < reader.GetNumSegments(); ++i) {
1300 if (i < (int)ARRAY_SIZE(module->nm.segmentaddr)) {
1301 module->nm.segmentsize[i] = reader.GetSegmentMemSize(i);
1302 if (module->nm.segmentsize[i] != 0) {
1303 module->nm.segmentaddr[i] = reader.GetSegmentVaddr(i);
1304 } else {
1305 module->nm.segmentaddr[i] = 0;
1306 }
1307 }
1308 module->nm.data_size += reader.GetSegmentDataSize(i);
1309 }
1310 module->nm.gp_value = modinfo->gp;
1311 strncpy(module->nm.name, modinfo->name, ARRAY_SIZE(module->nm.name));
1312
1313 // Let's also get a truncated version.
1314 char moduleName[29] = {0};
1315 strncpy(moduleName, modinfo->name, ARRAY_SIZE(module->nm.name));
1316
1317 // Check for module blacklist - we don't allow games to load these modules from disc
1318 // as we have HLE implementations and the originals won't run in the emu because they
1319 // directly access hardware or for other reasons.
1320 for (u32 i = 0; i < ARRAY_SIZE(blacklistedModules); i++) {
1321 if (strncmp(modinfo->name, blacklistedModules[i], ARRAY_SIZE(modinfo->name)) == 0) {
1322 module->isFake = true;
1323 }
1324 }
1325
1326 if (!module->isFake && module->memoryBlockAddr != 0) {
1327 g_symbolMap->AddModule(moduleName, module->memoryBlockAddr, module->memoryBlockSize);
1328 }
1329
1330 SectionID textSection = reader.GetSectionByName(".text");
1331
1332 if (textSection != -1) {
1333 module->textStart = reader.GetSectionAddr(textSection);
1334 u32 textSize = reader.GetSectionSize(textSection);
1335 module->textEnd = module->textStart + textSize - 4;
1336
1337 module->nm.text_addr = module->textStart;
1338 module->nm.text_size = reader.GetTotalTextSize();
1339 } else {
1340 module->nm.text_addr = 0;
1341 module->nm.text_size = 0;
1342 }
1343
1344 module->nm.bss_size = reader.GetTotalSectionSizeByPrefix(".bss");
1345 module->nm.data_size = reader.GetTotalDataSize() - module->nm.bss_size;
1346 module->libstub = modinfo->libstub;
1347 module->libstubend = modinfo->libstubend;
1348
1349 INFO_LOG(LOADER, "Module %s: %08x %08x %08x", modinfo->name, modinfo->gp, modinfo->libent, modinfo->libstub);
1350 DEBUG_LOG(LOADER,"===================================================");
1351
1352 u32 firstImportStubAddr = 0;
1353 KernelImportModuleFuncs(module, &firstImportStubAddr);
1354
1355 if (textSection == -1) {
1356 module->textStart = reader.GetVaddr();
1357 module->textEnd = firstImportStubAddr == 0 ? reader.GetVaddr() : firstImportStubAddr - 4;
1358 // Reference Jpcsp.
1359 if (reader.GetFirstSegmentAlign() > 0)
1360 module->textStart &= ~(reader.GetFirstSegmentAlign() - 1);
1361 // PSP set these values even if no section.
1362 module->nm.text_addr = module->textStart;
1363 module->nm.text_size = reader.GetTotalTextSizeFromSeg();
1364 }
1365
1366 if (!module->isFake) {
1367 bool scan = true;
1368 #if defined(MOBILE_DEVICE)
1369 scan = g_Config.bFuncReplacements;
1370 #endif
1371
1372 // If the ELF has debug symbols, don't add entries to the symbol table.
1373 bool insertSymbols = scan && !reader.LoadSymbols();
1374 std::vector<SectionID> codeSections = reader.GetCodeSections();
1375 for (SectionID id : codeSections) {
1376 u32 start = reader.GetSectionAddr(id);
1377 // Note: scan end is inclusive.
1378 u32 end = start + reader.GetSectionSize(id) - 4;
1379 u32 len = end + 4 - start;
1380 if (!Memory::IsValidRange(start, len)) {
1381 ERROR_LOG(LOADER, "Bad section %08x (len %08x) of section %d", start, len, id);
1382 continue;
1383 }
1384
1385 if (start < module->textStart)
1386 module->textStart = start;
1387 if (end > module->textEnd)
1388 module->textEnd = end;
1389
1390 if (scan) {
1391 insertSymbols = MIPSAnalyst::ScanForFunctions(start, end, insertSymbols);
1392 }
1393 }
1394
1395 // Some games don't have any sections at all.
1396 if (scan && codeSections.empty()) {
1397 u32 scanStart = module->textStart;
1398 u32 scanEnd = module->textEnd;
1399
1400 if (Memory::IsValidRange(scanStart, scanEnd - scanStart)) {
1401 // Skip the exports and imports sections, they're not code.
1402 if (scanEnd >= std::min(modinfo->libent, modinfo->libstub)) {
1403 insertSymbols = MIPSAnalyst::ScanForFunctions(scanStart, std::min(modinfo->libent, modinfo->libstub) - 4, insertSymbols);
1404 scanStart = std::min(modinfo->libentend, modinfo->libstubend);
1405 }
1406 if (scanEnd >= std::max(modinfo->libent, modinfo->libstub)) {
1407 insertSymbols = MIPSAnalyst::ScanForFunctions(scanStart, std::max(modinfo->libent, modinfo->libstub) - 4, insertSymbols);
1408 scanStart = std::max(modinfo->libentend, modinfo->libstubend);
1409 }
1410 insertSymbols = MIPSAnalyst::ScanForFunctions(scanStart, scanEnd, insertSymbols);
1411 } else {
1412 ERROR_LOG(LOADER, "Bad text scan range %08x-%08x", scanStart, scanEnd);
1413 }
1414 }
1415
1416 if (scan) {
1417 MIPSAnalyst::FinalizeScan(insertSymbols);
1418 }
1419 }
1420
1421 // Look at the exports, too.
1422
1423 struct PspLibEntEntry
1424 {
1425 u32_le name; /* ent's name (module name) address */
1426 u16_le version;
1427 u16_le flags;
1428 u8 size;
1429 u8 vcount;
1430 u16_le fcount;
1431 u32_le resident;
1432 u16_le vcountNew;
1433 u8 unknown1;
1434 u8 unknown2;
1435 };
1436
1437 module->nm.ent_top = modinfo->libent;
1438 module->nm.ent_size = modinfo->libentend - modinfo->libent;
1439 module->nm.stub_top = modinfo->libstub;
1440 module->nm.stub_size = modinfo->libstubend - modinfo->libstub;
1441
1442 const u32_le *entPos = (u32_le *)Memory::GetPointer(modinfo->libent);
1443 const u32_le *entEnd = (u32_le *)Memory::GetPointer(modinfo->libentend);
1444
1445 for (int m = 0; entPos < entEnd; ++m) {
1446 const PspLibEntEntry *ent = (const PspLibEntEntry *)entPos;
1447 entPos += ent->size;
1448 if (ent->size == 0) {
1449 WARN_LOG_REPORT(LOADER, "Invalid export entry size %d", ent->size);
1450 entPos += 4;
1451 continue;
1452 }
1453
1454 u32 variableCount = ent->size <= 4 ? ent->vcount : std::max((u32)ent->vcount , (u32)ent->vcountNew);
1455 const char *name;
1456 if (Memory::IsValidAddress(ent->name)) {
1457 name = Memory::GetCharPointer(ent->name);
1458 } else if (ent->name == 0) {
1459 name = module->nm.name;
1460 } else {
1461 name = "invalid?";
1462 }
1463
1464 INFO_LOG(LOADER, "Exporting ent %d named %s, %d funcs, %d vars, resident %08x", m, name, ent->fcount, ent->vcount, ent->resident);
1465
1466 if (!Memory::IsValidAddress(ent->resident)) {
1467 if (ent->fcount + variableCount > 0) {
1468 WARN_LOG_REPORT(LOADER, "Invalid export resident address %08x", ent->resident);
1469 }
1470 continue;
1471 }
1472
1473 u32_le *residentPtr = (u32_le *)Memory::GetPointer(ent->resident);
1474 u32_le *exportPtr = residentPtr + ent->fcount + variableCount;
1475
1476 if (ent->size != 4 && ent->unknown1 != 0 && ent->unknown2 != 0) {
1477 WARN_LOG_REPORT(LOADER, "Unexpected export module entry size %d, vcountNew=%08x, unknown1=%08x, unknown2=%08x", ent->size, ent->vcountNew, ent->unknown1, ent->unknown2);
1478 }
1479
1480 FuncSymbolExport func;
1481 strncpy(func.moduleName, name, KERNELOBJECT_MAX_NAME_LENGTH);
1482 func.moduleName[KERNELOBJECT_MAX_NAME_LENGTH] = '\0';
1483
1484 for (u32 j = 0; j < ent->fcount; j++) {
1485 u32 nid = residentPtr[j];
1486 u32 exportAddr = exportPtr[j];
1487
1488 switch (nid) {
1489 case NID_MODULE_START:
1490 module->nm.module_start_func = exportAddr;
1491 break;
1492 case NID_MODULE_STOP:
1493 module->nm.module_stop_func = exportAddr;
1494 break;
1495 case NID_MODULE_REBOOT_BEFORE:
1496 module->nm.module_reboot_before_func = exportAddr;
1497 break;
1498 case NID_MODULE_REBOOT_PHASE:
1499 module->nm.module_reboot_phase_func = exportAddr;
1500 break;
1501 case NID_MODULE_BOOTSTART:
1502 module->nm.module_bootstart_func = exportAddr;
1503 break;
1504 default:
1505 func.nid = nid;
1506 func.symAddr = exportAddr;
1507 if (ent->name == 0) {
1508 WARN_LOG_REPORT(HLE, "Exporting func from syslib export: %08x", nid);
1509 }
1510 module->ExportFunc(func);
1511 }
1512 }
1513
1514 VarSymbolExport var;
1515 strncpy(var.moduleName, name, KERNELOBJECT_MAX_NAME_LENGTH);
1516 var.moduleName[KERNELOBJECT_MAX_NAME_LENGTH] = '\0';
1517
1518 for (u32 j = 0; j < variableCount; j++) {
1519 u32 nid = residentPtr[ent->fcount + j];
1520 u32 exportAddr = exportPtr[ent->fcount + j];
1521
1522 int size;
1523 switch (nid) {
1524 case NID_MODULE_INFO:
1525 // Points to a PspModuleInfo, often the exact one .rodata.sceModuleInfo points to.
1526 break;
1527 case NID_MODULE_START_THREAD_PARAMETER:
1528 size = Memory::Read_U32(exportAddr);
1529 if (size == 0)
1530 break;
1531 else if (size != 3)
1532 WARN_LOG_REPORT(LOADER, "Strange value at module_start_thread_parameter export: %08x", Memory::Read_U32(exportAddr));
1533 module->nm.module_start_thread_priority = Memory::Read_U32(exportAddr + 4);
1534 module->nm.module_start_thread_stacksize = Memory::Read_U32(exportAddr + 8);
1535 module->nm.module_start_thread_attr = Memory::Read_U32(exportAddr + 12);
1536 break;
1537 case NID_MODULE_STOP_THREAD_PARAMETER:
1538 size = Memory::Read_U32(exportAddr);
1539 if (size == 0)
1540 break;
1541 else if (size != 3)
1542 WARN_LOG_REPORT(LOADER, "Strange value at module_stop_thread_parameter export: %08x", Memory::Read_U32(exportAddr));
1543 module->nm.module_stop_thread_priority = Memory::Read_U32(exportAddr + 4);
1544 module->nm.module_stop_thread_stacksize = Memory::Read_U32(exportAddr + 8);
1545 module->nm.module_stop_thread_attr = Memory::Read_U32(exportAddr + 12);
1546 break;
1547 case NID_MODULE_REBOOT_BEFORE_THREAD_PARAMETER:
1548 size = Memory::Read_U32(exportAddr);
1549 if (size == 0)
1550 break;
1551 else if (size != 3)
1552 WARN_LOG_REPORT(LOADER, "Strange value at module_reboot_before_thread_parameter export: %08x", Memory::Read_U32(exportAddr));
1553 module->nm.module_reboot_before_thread_priority = Memory::Read_U32(exportAddr + 4);
1554 module->nm.module_reboot_before_thread_stacksize = Memory::Read_U32(exportAddr + 8);
1555 module->nm.module_reboot_before_thread_attr = Memory::Read_U32(exportAddr + 12);
1556 break;
1557 case NID_MODULE_SDK_VERSION:
1558 DEBUG_LOG(LOADER, "Module SDK: %08x", Memory::Read_U32(exportAddr));
1559 devkitVersion = Memory::Read_U32(exportAddr);
1560 break;
1561 default:
1562 var.nid = nid;
1563 var.symAddr = exportAddr;
1564 if (ent->name == 0) {
1565 WARN_LOG_REPORT(HLE, "Exporting var from syslib export: %08x", nid);
1566 }
1567 module->ExportVar(var);
1568 break;
1569 }
1570 }
1571 }
1572
1573 if (!module->isFake) {
1574 module->nm.entry_addr = reader.GetEntryPoint();
1575
1576 // use module_start_func instead of entry_addr if entry_addr is 0
1577 if (module->nm.entry_addr == 0)
1578 module->nm.entry_addr = module->nm.module_start_func;
1579
1580 MIPSAnalyst::PrecompileFunctions();
1581
1582 } else {
1583 module->nm.entry_addr = -1;
1584 }
1585
1586 if (newptr)
1587 delete [] newptr;
1588
1589 if (!reportedModule && IsHLEVersionedModule(modinfo->name)) {
1590 INFO_LOG(SCEMODULE, "Loading module %s with version %04x, devkit %08x", modinfo->name, modinfo->moduleVersion, devkitVersion);
1591
1592 if (!strcmp(modinfo->name, "sceMpeg_library")) {
1593 __MpegLoadModule(modinfo->moduleVersion);
1594 }
1595 if (!strcmp(modinfo->name, "scePsmfP_library") || !strcmp(modinfo->name, "scePsmfPlayer")) {
1596 __PsmfPlayerLoadModule(devkitVersion);
1597 }
1598 }
1599
1600 u32 moduleSize = sizeof(module->nm);
1601 char tag[32];
1602 snprintf(tag, sizeof(tag), "SceModule-%d", module->nm.modid);
1603 module->modulePtr = kernelMemory.Alloc(moduleSize, true, tag);
1604
1605 // Fill the struct.
1606 if (Memory::IsValidAddress(module->modulePtr))
1607 Memory::WriteStruct(module->modulePtr, &module->nm);
1608
1609 error = 0;
1610 return module;
1611 }
1612
KernelLoadModule(const std::string & filename,std::string * error_string)1613 SceUID KernelLoadModule(const std::string &filename, std::string *error_string) {
1614 PSPFileInfo info = pspFileSystem.GetFileInfo(filename);
1615 if (!info.exists)
1616 return SCE_KERNEL_ERROR_NOFILE;
1617
1618 std::vector<uint8_t> buffer;
1619 buffer.resize((size_t)info.size);
1620
1621 u32 handle = pspFileSystem.OpenFile(filename, FILEACCESS_READ);
1622 pspFileSystem.ReadFile(handle, &buffer[0], info.size);
1623 pspFileSystem.CloseFile(handle);
1624
1625 u32 error = SCE_KERNEL_ERROR_ILLEGAL_OBJECT;
1626 u32 magic;
1627 PSPModule *module = __KernelLoadELFFromPtr(&buffer[0], buffer.size(), 0, false, error_string, &magic, error);
1628
1629 if (module == nullptr)
1630 return error;
1631 return module->GetUID();
1632 }
1633
__KernelLoadModule(u8 * fileptr,size_t fileSize,SceKernelLMOption * options,std::string * error_string)1634 static PSPModule *__KernelLoadModule(u8 *fileptr, size_t fileSize, SceKernelLMOption *options, std::string *error_string) {
1635 PSPModule *module = nullptr;
1636 // Check for PBP
1637 if (memcmp(fileptr, "\0PBP", 4) == 0) {
1638 // PBP!
1639 u32_le version;
1640 memcpy(&version, fileptr + 4, 4);
1641 u32_le offset0, offsets[16];
1642
1643 memcpy(&offset0, fileptr + 8, 4);
1644 int numfiles = (offset0 - 8)/4;
1645 offsets[0] = offset0;
1646 for (int i = 1; i < numfiles; i++)
1647 memcpy(&offsets[i], fileptr + 12 + 4*i, 4);
1648
1649 if (offsets[6] > fileSize) {
1650 // File is too small to fully contain the ELF! Must have been truncated.
1651 *error_string = "ELF file truncated - can't load";
1652 return nullptr;
1653 }
1654
1655 u32 magic = 0;
1656 u8 *temp = nullptr;
1657 size_t elfSize = offsets[6] - offsets[5];
1658 if (offsets[5] & 3) {
1659 // Our loader does NOT like to load from an unaligned address on ARM! Copy to a new block.
1660 temp = new u8[elfSize];
1661
1662 memcpy(temp, fileptr + offsets[5], elfSize);
1663 INFO_LOG(LOADER, "PBP: ELF unaligned (%d: %d), aligning!", offsets[5], offsets[5] & 3);
1664 }
1665
1666 u32 error;
1667 module = __KernelLoadELFFromPtr(temp ? temp : fileptr + offsets[5], elfSize, PSP_GetDefaultLoadAddress(), false, error_string, &magic, error);
1668
1669 if (temp) {
1670 delete [] temp;
1671 }
1672 } else {
1673 u32 error;
1674 u32 magic = 0;
1675 module = __KernelLoadELFFromPtr(fileptr, fileSize, PSP_GetDefaultLoadAddress(), false, error_string, &magic, error);
1676 }
1677
1678 return module;
1679 }
1680
__KernelStartModule(PSPModule * m,int args,const char * argp,SceKernelSMOption * options)1681 static void __KernelStartModule(PSPModule *m, int args, const char *argp, SceKernelSMOption *options) {
1682 m->nm.status = MODULE_STATUS_STARTED;
1683 if (m->nm.module_start_func != 0 && m->nm.module_start_func != (u32)-1)
1684 {
1685 if (m->nm.module_start_func != m->nm.entry_addr)
1686 WARN_LOG_REPORT(LOADER, "Main module has start func (%08x) different from entry (%08x)?", m->nm.module_start_func, m->nm.entry_addr);
1687 // TODO: Should we try to run both?
1688 currentMIPS->pc = m->nm.module_start_func;
1689 }
1690
1691 SceUID threadID = __KernelSetupRootThread(m->GetUID(), args, argp, options->priority, options->stacksize, options->attribute);
1692 __KernelSetThreadRA(threadID, NID_MODULERETURN);
1693
1694 if (HLEPlugins::Load()) {
1695 KernelRotateThreadReadyQueue(0);
1696 __KernelReSchedule("Started plugins");
1697 }
1698 }
1699
1700
__KernelGetModuleGP(SceUID uid)1701 u32 __KernelGetModuleGP(SceUID uid) {
1702 u32 error;
1703 PSPModule *module = kernelObjects.Get<PSPModule>(uid, error);
1704 if (module) {
1705 return module->nm.gp_value;
1706 } else {
1707 return 0;
1708 }
1709 }
1710
KernelModuleIsKernelMode(SceUID uid)1711 bool KernelModuleIsKernelMode(SceUID uid) {
1712 u32 error;
1713 PSPModule *module = kernelObjects.Get<PSPModule>(uid, error);
1714 if (module) {
1715 return (module->nm.attribute & 0x1000) != 0;
1716 } else {
1717 return false;
1718 }
1719 }
1720
__KernelLoadReset()1721 void __KernelLoadReset() {
1722 // Wipe kernel here, loadexec should reset the entire system
1723 if (__KernelIsRunning()) {
1724 u32 error;
1725 while (!loadedModules.empty()) {
1726 SceUID moduleID = *loadedModules.begin();
1727 PSPModule *module = kernelObjects.Get<PSPModule>(moduleID, error);
1728 if (module) {
1729 module->Cleanup();
1730 } else {
1731 // An invalid module. We need to remove it or we'll loop forever.
1732 WARN_LOG(LOADER, "Invalid module still marked as loaded on loadexec");
1733 loadedModules.erase(moduleID);
1734 }
1735 }
1736
1737 Replacement_Shutdown();
1738 __KernelShutdown();
1739 // HLE needs to be reset here
1740 HLEShutdown();
1741 Replacement_Init();
1742 HLEInit();
1743 }
1744
1745 __KernelModuleInit();
1746 __KernelInit();
1747 }
1748
__KernelLoadExec(const char * filename,u32 paramPtr,std::string * error_string)1749 bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_string) {
1750 SceKernelLoadExecParam param;
1751
1752 PSP_SetLoading("Loading exec...");
1753
1754 if (paramPtr)
1755 Memory::ReadStruct(paramPtr, ¶m);
1756 else
1757 memset(¶m, 0, sizeof(SceKernelLoadExecParam));
1758
1759 u8 *param_argp = 0;
1760 u8 *param_key = 0;
1761 if (param.args > 0) {
1762 u32 argpAddr = param.argp;
1763 param_argp = new u8[param.args];
1764 Memory::Memcpy(param_argp, argpAddr, param.args, "KernelLoadParam");
1765 }
1766 if (param.keyp != 0) {
1767 u32 keyAddr = param.keyp;
1768 size_t keylen = strlen(Memory::GetCharPointer(keyAddr))+1;
1769 param_key = new u8[keylen];
1770 Memory::Memcpy(param_key, keyAddr, (u32)keylen, "KernelLoadParam");
1771 }
1772
1773 __KernelLoadReset();
1774
1775 PSPFileInfo info = pspFileSystem.GetFileInfo(filename);
1776 if (!info.exists) {
1777 ERROR_LOG(LOADER, "Failed to load executable %s - file doesn't exist", filename);
1778 *error_string = StringFromFormat("Could not find executable %s", filename);
1779 if (paramPtr) {
1780 if (param_argp) delete[] param_argp;
1781 if (param_key) delete[] param_key;
1782 }
1783 __KernelShutdown();
1784 return false;
1785 }
1786
1787 u32 handle = pspFileSystem.OpenFile(filename, FILEACCESS_READ);
1788
1789 u8 *temp = new u8[(int)info.size + 0x01000000];
1790
1791 pspFileSystem.ReadFile(handle, temp, (size_t)info.size);
1792
1793 PSP_SetLoading("Loading modules...");
1794 PSPModule *module = __KernelLoadModule(temp, (size_t)info.size, 0, error_string);
1795
1796 if (!module || module->isFake) {
1797 if (module) {
1798 module->Cleanup();
1799 kernelObjects.Destroy<PSPModule>(module->GetUID());
1800 }
1801 ERROR_LOG(LOADER, "Failed to load module %s", filename);
1802 *error_string = "Failed to load executable: " + *error_string;
1803 delete [] temp;
1804 if (paramPtr) {
1805 if (param_argp) delete[] param_argp;
1806 if (param_key) delete[] param_key;
1807 }
1808 return false;
1809 }
1810
1811 host->NotifySymbolMapUpdated();
1812
1813 mipsr4k.pc = module->nm.entry_addr;
1814
1815 INFO_LOG(LOADER, "Module entry: %08x", mipsr4k.pc);
1816
1817 delete [] temp;
1818
1819 pspFileSystem.CloseFile(handle);
1820
1821 SceKernelSMOption option;
1822 option.size = sizeof(SceKernelSMOption);
1823 option.attribute = PSP_THREAD_ATTR_USER;
1824 option.mpidstack = 2;
1825 option.priority = 0x20;
1826 option.stacksize = 0x40000; // crazy? but seems to be the truth
1827
1828 // Replace start options with module-specified values if they exist.
1829 if (module->nm.module_start_thread_attr != 0)
1830 option.attribute = module->nm.module_start_thread_attr;
1831 if (module->nm.module_start_thread_priority != 0)
1832 option.priority = module->nm.module_start_thread_priority;
1833 if (module->nm.module_start_thread_stacksize != 0)
1834 option.stacksize = module->nm.module_start_thread_stacksize;
1835
1836 PSP_SetLoading("Starting modules...");
1837 if (paramPtr)
1838 __KernelStartModule(module, param.args, (const char*)param_argp, &option);
1839 else
1840 __KernelStartModule(module, (u32)strlen(filename) + 1, filename, &option);
1841
1842 __KernelStartIdleThreads(module->GetUID());
1843
1844 if (param_argp) delete[] param_argp;
1845 if (param_key) delete[] param_key;
1846
1847 hleSkipDeadbeef();
1848 return true;
1849 }
1850
__KernelLoadGEDump(const std::string & base_filename,std::string * error_string)1851 bool __KernelLoadGEDump(const std::string &base_filename, std::string *error_string) {
1852 __KernelLoadReset();
1853 PSP_SetLoading("Generating code...");
1854
1855 mipsr4k.pc = PSP_GetUserMemoryBase();
1856
1857 const static u32_le runDumpCode[] = {
1858 // Save the filename.
1859 MIPS_MAKE_ORI(MIPS_REG_S0, MIPS_REG_A0, 0),
1860 MIPS_MAKE_ORI(MIPS_REG_S1, MIPS_REG_A1, 0),
1861 // Call the actual render.
1862 MIPS_MAKE_SYSCALL("FakeSysCalls", "__KernelGPUReplay"),
1863 // Make sure we don't get out of sync.
1864 MIPS_MAKE_LUI(MIPS_REG_A0, 0),
1865 MIPS_MAKE_SYSCALL("sceGe_user", "sceGeDrawSync"),
1866 // Set the return address after the entry which saved the filename.
1867 MIPS_MAKE_LUI(MIPS_REG_RA, mipsr4k.pc >> 16),
1868 MIPS_MAKE_ADDIU(MIPS_REG_RA, MIPS_REG_RA, 8),
1869 // Wait for the next vblank to render again.
1870 MIPS_MAKE_JR_RA(),
1871 MIPS_MAKE_SYSCALL("sceDisplay", "sceDisplayWaitVblankStart"),
1872 // This never gets reached, just here to be safe.
1873 MIPS_MAKE_BREAK(0),
1874 };
1875
1876 for (size_t i = 0; i < ARRAY_SIZE(runDumpCode); ++i) {
1877 Memory::WriteUnchecked_U32(runDumpCode[i], mipsr4k.pc + (int)i * sizeof(u32_le));
1878 }
1879
1880 PSPModule *module = new PSPModule();
1881 kernelObjects.Create(module);
1882 loadedModules.insert(module->GetUID());
1883 memset(&module->nm, 0, sizeof(module->nm));
1884 module->isFake = true;
1885 module->nm.entry_addr = mipsr4k.pc;
1886 module->nm.gp_value = -1;
1887
1888 SceUID threadID = __KernelSetupRootThread(module->GetUID(), (int)base_filename.size(), base_filename.data(), 0x20, 0x1000, 0);
1889 __KernelSetThreadRA(threadID, NID_MODULERETURN);
1890
1891 __KernelStartIdleThreads(module->GetUID());
1892 return true;
1893 }
1894
__KernelGPUReplay()1895 void __KernelGPUReplay() {
1896 // Special ABI: s0 and s1 are the "args". Not null terminated.
1897 const char *filenamep = Memory::GetCharPointer(currentMIPS->r[MIPS_REG_S1]);
1898 if (!filenamep) {
1899 ERROR_LOG(G3D, "Failed to load dump filename");
1900 Core_Stop();
1901 return;
1902 }
1903
1904 std::string filename(filenamep, currentMIPS->r[MIPS_REG_S0]);
1905 if (!GPURecord::RunMountedReplay(filename)) {
1906 Core_Stop();
1907 }
1908
1909 if (PSP_CoreParameter().headLess && !PSP_CoreParameter().startBreak) {
1910 PSPPointer<u8> topaddr;
1911 u32 linesize = 512;
1912 __DisplayGetFramebuf(&topaddr, &linesize, nullptr, 0);
1913 host->SendDebugScreenshot(topaddr, linesize, 272);
1914 Core_Stop();
1915 }
1916 }
1917
sceKernelLoadExec(const char * filename,u32 paramPtr)1918 int sceKernelLoadExec(const char *filename, u32 paramPtr)
1919 {
1920 std::string exec_filename = filename;
1921 PSPFileInfo info = pspFileSystem.GetFileInfo(exec_filename);
1922
1923 // If there's an EBOOT.BIN, redirect to that instead.
1924 if (info.exists && endsWith(exec_filename, "/BOOT.BIN")) {
1925 std::string eboot_filename = exec_filename.substr(0, exec_filename.length() - strlen("BOOT.BIN")) + "EBOOT.BIN";
1926
1927 PSPFileInfo eboot_info = pspFileSystem.GetFileInfo(eboot_filename);
1928 if (eboot_info.exists) {
1929 exec_filename = eboot_filename;
1930 info = eboot_info;
1931 }
1932 }
1933
1934 if (!info.exists) {
1935 ERROR_LOG(LOADER, "sceKernelLoadExec(%s, ...): File does not exist", filename);
1936 return SCE_KERNEL_ERROR_NOFILE;
1937 }
1938
1939 s64 size = (s64)info.size;
1940 if (!size) {
1941 ERROR_LOG(LOADER, "sceKernelLoadExec(%s, ...): File is size 0", filename);
1942 return SCE_KERNEL_ERROR_ILLEGAL_OBJECT;
1943 }
1944
1945 DEBUG_LOG(SCEMODULE, "sceKernelLoadExec(name=%s,...): loading %s", filename, exec_filename.c_str());
1946 std::string error_string;
1947 if (!__KernelLoadExec(exec_filename.c_str(), paramPtr, &error_string)) {
1948 ERROR_LOG(SCEMODULE, "sceKernelLoadExec failed: %s", error_string.c_str());
1949 Core_UpdateState(CORE_RUNTIME_ERROR);
1950 return -1;
1951 }
1952 if (gpu) {
1953 gpu->Reinitialize();
1954 }
1955 return 0;
1956 }
1957
sceKernelLoadModule(const char * name,u32 flags,u32 optionAddr)1958 u32 sceKernelLoadModule(const char *name, u32 flags, u32 optionAddr) {
1959 if (!name) {
1960 return hleLogError(LOADER, SCE_KERNEL_ERROR_ILLEGAL_ADDR, "bad filename");
1961 }
1962
1963 for (size_t i = 0; i < ARRAY_SIZE(lieAboutSuccessModules); i++) {
1964 if (!strcmp(name, lieAboutSuccessModules[i])) {
1965 PSPModule *module = new PSPModule();
1966 kernelObjects.Create(module);
1967 loadedModules.insert(module->GetUID());
1968 memset(&module->nm, 0, sizeof(module->nm));
1969 module->isFake = true;
1970 module->nm.entry_addr = -1;
1971 module->nm.gp_value = -1;
1972
1973 u32 moduleSize = sizeof(module->nm);
1974 char tag[32];
1975 snprintf(tag, sizeof(tag), "SceModule-%d", module->nm.modid);
1976 module->modulePtr = kernelMemory.Alloc(moduleSize, true, tag);
1977
1978 // Fill the struct.
1979 if(Memory::IsValidAddress(module->modulePtr))
1980 Memory::WriteStruct(module->modulePtr, &module->nm);
1981
1982 // TODO: It would be more ideal to allocate memory for this module.
1983
1984 return hleLogSuccessInfoI(LOADER, module->GetUID(), "created fake module");
1985 }
1986 }
1987
1988 PSPFileInfo info = pspFileSystem.GetFileInfo(name);
1989 s64 size = (s64)info.size;
1990
1991 if (!info.exists) {
1992 const u32 error = hleLogError(LOADER, SCE_KERNEL_ERROR_ERRNO_FILE_NOT_FOUND, "file does not exist");
1993 return hleDelayResult(error, "module loaded", 500);
1994 }
1995
1996 if (!size) {
1997 const u32 error = hleLogError(LOADER, SCE_KERNEL_ERROR_FILEERR, "module file size is 0");
1998 return hleDelayResult(error, "module loaded", 500);
1999 }
2000
2001 // We log before hand because ELF loading logs a bunch.
2002 DEBUG_LOG(LOADER, "sceKernelLoadModule(%s, %08x)", name, flags);
2003
2004 if (flags != 0) {
2005 WARN_LOG_REPORT(LOADER, "sceKernelLoadModule: unsupported flags: %08x", flags);
2006 }
2007 SceKernelLMOption *lmoption = 0;
2008 if (optionAddr) {
2009 lmoption = (SceKernelLMOption *)Memory::GetPointer(optionAddr);
2010 if (lmoption->position < PSP_SMEM_Low || lmoption->position > PSP_SMEM_HighAligned) {
2011 ERROR_LOG_REPORT(LOADER, "sceKernelLoadModule(%s): invalid position (%i)", name, (int)lmoption->position);
2012 return hleDelayResult(SCE_KERNEL_ERROR_ILLEGAL_MEMBLOCKTYPE, "module loaded", 500);
2013 }
2014 if (lmoption->position == PSP_SMEM_LowAligned || lmoption->position == PSP_SMEM_HighAligned) {
2015 ERROR_LOG_REPORT(LOADER, "sceKernelLoadModule(%s): invalid position (aligned)", name);
2016 return hleDelayResult(SCE_KERNEL_ERROR_ILLEGAL_ALIGNMENT_SIZE, "module loaded", 500);
2017 }
2018 if (lmoption->position == PSP_SMEM_Addr) {
2019 ERROR_LOG_REPORT(LOADER, "sceKernelLoadModule(%s): invalid position (fixed)", name);
2020 return hleDelayResult(SCE_KERNEL_ERROR_MEMBLOCK_ALLOC_FAILED, "module loaded", 500);
2021 }
2022 WARN_LOG_REPORT(LOADER, "sceKernelLoadModule: unsupported options size=%08x, flags=%08x, pos=%d, access=%d, data=%d, text=%d", lmoption->size, lmoption->flags, lmoption->position, lmoption->access, lmoption->mpiddata, lmoption->mpidtext);
2023 }
2024
2025 PSPModule *module = nullptr;
2026 u8 *temp = new u8[(int)size];
2027 u32 handle = pspFileSystem.OpenFile(name, FILEACCESS_READ);
2028 pspFileSystem.ReadFile(handle, temp, (size_t)size);
2029 u32 magic;
2030 u32 error;
2031 std::string error_string;
2032 module = __KernelLoadELFFromPtr(temp, (size_t)size, 0, lmoption ? lmoption->position == PSP_SMEM_High : false, &error_string, &magic, error);
2033 delete [] temp;
2034 pspFileSystem.CloseFile(handle);
2035
2036 if (!module) {
2037 if (magic == 0x46535000) {
2038 ERROR_LOG(LOADER, "Game tried to load an SFO as a module. Go figure? Magic = %08x", magic);
2039 // TODO: What's actually going on here?
2040 error = -1;
2041 return hleDelayResult(error, "module loaded", 500);
2042 }
2043
2044 if (info.name == "BOOT.BIN") {
2045 NOTICE_LOG_REPORT(LOADER, "Module %s is blacklisted or undecryptable - we try __KernelLoadExec", name);
2046 // Name might get deleted.
2047 const std::string safeName = name;
2048 if (gpu) {
2049 gpu->Reinitialize();
2050 }
2051 return __KernelLoadExec(safeName.c_str(), 0, &error_string);
2052 } else {
2053 hleLogError(LOADER, error, "failed to load");
2054 return hleDelayResult(error, "module loaded", 500);
2055 }
2056 }
2057
2058 if (lmoption) {
2059 INFO_LOG(SCEMODULE,"%i=sceKernelLoadModule(name=%s,flag=%08x,%08x,%08x,%08x,position = %08x)",
2060 module->GetUID(),name,flags,
2061 lmoption->size,lmoption->mpidtext,lmoption->mpiddata,lmoption->position);
2062 } else {
2063 INFO_LOG(SCEMODULE,"%i=sceKernelLoadModule(name=%s,flag=%08x,(...))", module->GetUID(), name, flags);
2064 }
2065
2066 // TODO: This is not the right timing and probably not the right wait type, just an approximation.
2067 return hleDelayResult(module->GetUID(), "module loaded", 500);
2068 }
2069
sceKernelLoadModuleNpDrm(const char * name,u32 flags,u32 optionAddr)2070 static u32 sceKernelLoadModuleNpDrm(const char *name, u32 flags, u32 optionAddr)
2071 {
2072 DEBUG_LOG(LOADER, "sceKernelLoadModuleNpDrm(%s, %08x)", name, flags);
2073
2074 return sceKernelLoadModule(name, flags, optionAddr);
2075 }
2076
KernelStartModule(SceUID moduleId,u32 argsize,u32 argAddr,u32 returnValueAddr,SceKernelSMOption * smoption,bool * needsWait)2077 int KernelStartModule(SceUID moduleId, u32 argsize, u32 argAddr, u32 returnValueAddr, SceKernelSMOption *smoption, bool *needsWait) {
2078 if (needsWait) {
2079 *needsWait = false;
2080 }
2081
2082 u32 error;
2083 PSPModule *module = kernelObjects.Get<PSPModule>(moduleId, error);
2084 if (!module) {
2085 return error;
2086 }
2087
2088 u32 priority = 0x20;
2089 u32 stacksize = 0x40000;
2090 int attribute = module->nm.attribute;
2091 u32 entryAddr = module->nm.entry_addr;
2092
2093 if (module->nm.module_start_func != 0 && module->nm.module_start_func != (u32)-1) {
2094 entryAddr = module->nm.module_start_func;
2095 if (module->nm.module_start_thread_attr != 0)
2096 attribute = module->nm.module_start_thread_attr;
2097 }
2098
2099 if (Memory::IsValidAddress(entryAddr)) {
2100 if (smoption && smoption->priority > 0) {
2101 priority = smoption->priority;
2102 } else if (module->nm.module_start_thread_priority > 0) {
2103 priority = module->nm.module_start_thread_priority;
2104 }
2105
2106 if (smoption && smoption->stacksize > 0) {
2107 stacksize = smoption->stacksize;
2108 } else if (module->nm.module_start_thread_stacksize > 0) {
2109 stacksize = module->nm.module_start_thread_stacksize;
2110 }
2111
2112 // TODO: Why do we skip smoption->attribute here?
2113
2114 SceUID threadID = __KernelCreateThread(module->nm.name, moduleId, entryAddr, priority, stacksize, attribute, 0, (module->nm.attribute & 0x1000) != 0);
2115 __KernelStartThreadValidate(threadID, argsize, argAddr);
2116 __KernelSetThreadRA(threadID, NID_MODULERETURN);
2117
2118 if (needsWait) {
2119 *needsWait = true;
2120 }
2121 } else if (entryAddr == 0 || entryAddr == (u32)-1) {
2122 INFO_LOG(SCEMODULE, "sceKernelStartModule(%d,asize=%08x,aptr=%08x,retptr=%08x): no entry address", moduleId, argsize, argAddr, returnValueAddr);
2123 module->nm.status = MODULE_STATUS_STARTED;
2124 } else {
2125 ERROR_LOG(SCEMODULE, "sceKernelStartModule(%d,asize=%08x,aptr=%08x,retptr=%08x): invalid entry address", moduleId, argsize, argAddr, returnValueAddr);
2126 return -1;
2127 }
2128
2129 return moduleId;
2130 }
2131
sceKernelStartModule(u32 moduleId,u32 argsize,u32 argAddr,u32 returnValueAddr,u32 optionAddr)2132 static void sceKernelStartModule(u32 moduleId, u32 argsize, u32 argAddr, u32 returnValueAddr, u32 optionAddr)
2133 {
2134 SceKernelSMOption smoption = {0};
2135 if (optionAddr) {
2136 Memory::ReadStruct(optionAddr, &smoption);
2137 }
2138 u32 error;
2139 PSPModule *module = kernelObjects.Get<PSPModule>(moduleId, error);
2140 if (!module) {
2141 INFO_LOG(SCEMODULE, "sceKernelStartModule(%d,asize=%08x,aptr=%08x,retptr=%08x,%08x): error %08x", moduleId, argsize, argAddr, returnValueAddr, optionAddr, error);
2142 RETURN(error);
2143 return;
2144 } else if (module->isFake) {
2145 INFO_LOG(SCEMODULE, "sceKernelStartModule(%d,asize=%08x,aptr=%08x,retptr=%08x,%08x): faked (undecryptable module)",
2146 moduleId,argsize,argAddr,returnValueAddr,optionAddr);
2147 if (returnValueAddr)
2148 Memory::Write_U32(0, returnValueAddr);
2149 RETURN(moduleId);
2150 return;
2151 } else if (module->nm.status == MODULE_STATUS_STARTED) {
2152 ERROR_LOG(SCEMODULE, "sceKernelStartModule(%d,asize=%08x,aptr=%08x,retptr=%08x,%08x) : already started",
2153 moduleId,argsize,argAddr,returnValueAddr,optionAddr);
2154 // TODO: Maybe should be SCE_KERNEL_ERROR_ALREADY_STARTED, but I get SCE_KERNEL_ERROR_ERROR.
2155 // But I also get crashes...
2156 RETURN(SCE_KERNEL_ERROR_ERROR);
2157 return;
2158 } else {
2159 INFO_LOG(SCEMODULE, "sceKernelStartModule(%d,asize=%08x,aptr=%08x,retptr=%08x,%08x)",
2160 moduleId,argsize,argAddr,returnValueAddr,optionAddr);
2161
2162 bool needsWait;
2163 int ret = KernelStartModule(moduleId, argsize, argAddr, returnValueAddr, optionAddr ? &smoption : nullptr, &needsWait);
2164
2165 if (needsWait) {
2166 __KernelWaitCurThread(WAITTYPE_MODULE, moduleId, 1, 0, false, "started module");
2167
2168 const ModuleWaitingThread mwt = {__KernelGetCurThread(), returnValueAddr};
2169 module->nm.status = MODULE_STATUS_STARTING;
2170 module->waitingThreads.push_back(mwt);
2171 }
2172
2173 RETURN(ret);
2174 }
2175 }
2176
sceKernelStopModule(u32 moduleId,u32 argSize,u32 argAddr,u32 returnValueAddr,u32 optionAddr)2177 static u32 sceKernelStopModule(u32 moduleId, u32 argSize, u32 argAddr, u32 returnValueAddr, u32 optionAddr)
2178 {
2179 u32 priority = 0x20;
2180 u32 stacksize = 0x40000;
2181 u32 attr = 0;
2182
2183 // TODO: In a lot of cases (even for errors), this should resched. Needs testing.
2184
2185 u32 error;
2186 PSPModule *module = kernelObjects.Get<PSPModule>(moduleId, error);
2187 if (!module)
2188 {
2189 ERROR_LOG(SCEMODULE, "sceKernelStopModule(%08x, %08x, %08x, %08x, %08x): invalid module id", moduleId, argSize, argAddr, returnValueAddr, optionAddr);
2190 return error;
2191 }
2192
2193 if (module->isFake)
2194 {
2195 INFO_LOG(SCEMODULE, "sceKernelStopModule(%08x, %08x, %08x, %08x, %08x) - faking", moduleId, argSize, argAddr, returnValueAddr, optionAddr);
2196 if (returnValueAddr)
2197 Memory::Write_U32(0, returnValueAddr);
2198 return 0;
2199 }
2200 if (module->nm.status != MODULE_STATUS_STARTED)
2201 {
2202 ERROR_LOG(SCEMODULE, "sceKernelStopModule(%08x, %08x, %08x, %08x, %08x): already stopped", moduleId, argSize, argAddr, returnValueAddr, optionAddr);
2203 return SCE_KERNEL_ERROR_ALREADY_STOPPED;
2204 }
2205
2206 u32 stopFunc = module->nm.module_stop_func;
2207 if (module->nm.module_stop_thread_priority != 0)
2208 priority = module->nm.module_stop_thread_priority;
2209 if (module->nm.module_stop_thread_stacksize != 0)
2210 stacksize = module->nm.module_stop_thread_stacksize;
2211 if (module->nm.module_stop_thread_attr != 0)
2212 attr = module->nm.module_stop_thread_attr;
2213
2214 // TODO: Need to test how this really works. Let's assume it's an override.
2215 if (Memory::IsValidAddress(optionAddr))
2216 {
2217 auto options = PSPPointer<SceKernelSMOption>::Create(optionAddr);
2218 // TODO: Check how size handling actually works.
2219 if (options->size != 0 && options->priority != 0)
2220 priority = options->priority;
2221 if (options->size != 0 && options->stacksize != 0)
2222 stacksize = options->stacksize;
2223 if (options->size != 0 && options->attribute != 0)
2224 attr = options->attribute;
2225 // TODO: Maybe based on size?
2226 else if (attr != 0)
2227 WARN_LOG_REPORT(SCEMODULE, "Stopping module with attr=%x, but options specify 0", attr);
2228 }
2229
2230 if (Memory::IsValidAddress(stopFunc))
2231 {
2232 SceUID threadID = __KernelCreateThread(module->nm.name, moduleId, stopFunc, priority, stacksize, attr, 0, (module->nm.attribute & 0x1000) != 0);
2233 __KernelStartThreadValidate(threadID, argSize, argAddr);
2234 __KernelSetThreadRA(threadID, NID_MODULERETURN);
2235 __KernelWaitCurThread(WAITTYPE_MODULE, moduleId, 1, 0, false, "stopped module");
2236
2237 const ModuleWaitingThread mwt = {__KernelGetCurThread(), returnValueAddr};
2238 module->nm.status = MODULE_STATUS_STOPPING;
2239 module->waitingThreads.push_back(mwt);
2240 }
2241 else if (stopFunc == 0)
2242 {
2243 INFO_LOG(SCEMODULE, "sceKernelStopModule(%08x, %08x, %08x, %08x, %08x): no stop func, skipping", moduleId, argSize, argAddr, returnValueAddr, optionAddr);
2244 module->nm.status = MODULE_STATUS_STOPPED;
2245 }
2246 else
2247 {
2248 ERROR_LOG_REPORT(SCEMODULE, "sceKernelStopModule(%08x, %08x, %08x, %08x, %08x): bad stop func address", moduleId, argSize, argAddr, returnValueAddr, optionAddr);
2249 module->nm.status = MODULE_STATUS_STOPPED;
2250 }
2251
2252 return 0;
2253 }
2254
sceKernelUnloadModule(u32 moduleId)2255 static u32 sceKernelUnloadModule(u32 moduleId)
2256 {
2257 INFO_LOG(SCEMODULE,"sceKernelUnloadModule(%i)", moduleId);
2258 u32 error;
2259 PSPModule *module = kernelObjects.Get<PSPModule>(moduleId, error);
2260 if (!module)
2261 return hleDelayResult(error, "module unloaded", 150);
2262
2263 module->Cleanup();
2264 kernelObjects.Destroy<PSPModule>(moduleId);
2265 return hleDelayResult(moduleId, "module unloaded", 500);
2266 }
2267
hleKernelStopUnloadSelfModuleWithOrWithoutStatus(u32 exitCode,u32 argSize,u32 argp,u32 statusAddr,u32 optionAddr,bool WithStatus)2268 u32 hleKernelStopUnloadSelfModuleWithOrWithoutStatus(u32 exitCode, u32 argSize, u32 argp, u32 statusAddr, u32 optionAddr, bool WithStatus) {
2269 if (loadedModules.size() > 1) {
2270 if (WithStatus)
2271 ERROR_LOG_REPORT(SCEMODULE, "UNIMPL sceKernelStopUnloadSelfModuleWithStatus(%08x, %08x, %08x, %08x, %08x): game may have crashed", exitCode, argSize, argp, statusAddr, optionAddr);
2272 else
2273 ERROR_LOG_REPORT(SCEMODULE, "UNIMPL sceKernelSelfStopUnloadModule(%08x, %08x, %08x): game may have crashed", exitCode, argSize, argp);
2274 SceUID moduleID = __KernelGetCurThreadModuleId();
2275 u32 priority = 0x20;
2276 u32 stacksize = 0x40000;
2277 u32 attr = 0;
2278 // TODO: In a lot of cases (even for errors), this should resched. Needs testing.
2279
2280 u32 error;
2281 PSPModule *module = kernelObjects.Get<PSPModule>(moduleID, error);
2282 if (!module) {
2283 if (WithStatus)
2284 ERROR_LOG(SCEMODULE, "sceKernelStopUnloadSelfModuleWithStatus(%08x, %08x, %08x, %08x, %08x): invalid module id", exitCode, argSize, argp, statusAddr, optionAddr);
2285 else
2286 ERROR_LOG(SCEMODULE, "sceKernelSelfStopUnloadModule(%08x, %08x, %08x): invalid module id", exitCode, argSize, argp);
2287
2288 return error;
2289 }
2290
2291 u32 stopFunc = module->nm.module_stop_func;
2292 if (module->nm.module_stop_thread_priority != 0)
2293 priority = module->nm.module_stop_thread_priority;
2294 if (module->nm.module_stop_thread_stacksize != 0)
2295 stacksize = module->nm.module_stop_thread_stacksize;
2296 if (module->nm.module_stop_thread_attr != 0)
2297 attr = module->nm.module_stop_thread_attr;
2298
2299 // TODO: Need to test how this really works. Let's assume it's an override.
2300 if (Memory::IsValidAddress(optionAddr)) {
2301 auto options = PSPPointer<SceKernelSMOption>::Create(optionAddr);
2302 // TODO: Check how size handling actually works.
2303 if (options->size != 0 && options->priority != 0)
2304 priority = options->priority;
2305 if (options->size != 0 && options->stacksize != 0)
2306 stacksize = options->stacksize;
2307 if (options->size != 0 && options->attribute != 0)
2308 attr = options->attribute;
2309 // TODO: Maybe based on size?
2310 else if (attr != 0)
2311 WARN_LOG_REPORT(SCEMODULE, "Stopping module with attr=%x, but options specify 0", attr);
2312 }
2313
2314 if (Memory::IsValidAddress(stopFunc)) {
2315 SceUID threadID = __KernelCreateThread(module->nm.name, moduleID, stopFunc, priority, stacksize, attr, 0, (module->nm.attribute & 0x1000) != 0);
2316 __KernelStartThreadValidate(threadID, argSize, argp);
2317 __KernelSetThreadRA(threadID, NID_MODULERETURN);
2318 __KernelWaitCurThread(WAITTYPE_MODULE, moduleID, 1, 0, false, "unloadstopped module");
2319
2320 const ModuleWaitingThread mwt = {__KernelGetCurThread(), statusAddr};
2321 module->nm.status = MODULE_STATUS_UNLOADING;
2322 module->waitingThreads.push_back(mwt);
2323 } else if (stopFunc == 0) {
2324 if (WithStatus)
2325 INFO_LOG(SCEMODULE, "sceKernelStopUnloadSelfModuleWithStatus(%08x, %08x, %08x, %08x, %08x): no stop func", exitCode, argSize, argp, statusAddr, optionAddr);
2326 else
2327 INFO_LOG(SCEMODULE, "sceKernelSelfStopUnloadModule(%08x, %08x, %08x): no stop func", exitCode, argSize, argp);
2328 sceKernelExitDeleteThread(exitCode);
2329 module->Cleanup();
2330 kernelObjects.Destroy<PSPModule>(moduleID);
2331 } else {
2332 if (WithStatus)
2333 ERROR_LOG_REPORT(SCEMODULE, "sceKernelStopUnloadSelfModuleWithStatus(%08x, %08x, %08x, %08x, %08x): bad stop func address", exitCode, argSize, argp, statusAddr, optionAddr);
2334 else
2335 ERROR_LOG_REPORT(SCEMODULE, "sceKernelSelfStopUnloadModule(%08x, %08x, %08x): bad stop func address", exitCode, argSize, argp);
2336 sceKernelExitDeleteThread(exitCode);
2337 module->Cleanup();
2338 kernelObjects.Destroy<PSPModule>(moduleID);
2339 }
2340 } else {
2341 if (WithStatus)
2342 ERROR_LOG_REPORT(SCEMODULE, "UNIMPL sceKernelStopUnloadSelfModuleWithStatus(%08x, %08x, %08x, %08x, %08x): game has likely crashed", exitCode, argSize, argp, statusAddr, optionAddr);
2343 else
2344 ERROR_LOG_REPORT(SCEMODULE, "UNIMPL sceKernelSelfStopUnloadModule(%08x, %08x, %08x): game has likely crashed", exitCode, argSize, argp);
2345 }
2346
2347 return 0;
2348 }
2349
sceKernelSelfStopUnloadModule(u32 exitCode,u32 argSize,u32 argp)2350 static u32 sceKernelSelfStopUnloadModule(u32 exitCode, u32 argSize, u32 argp) {
2351 // Used in Tom Clancy's Splinter Cell Essentials,Ghost in the Shell Stand Alone Complex
2352 return hleKernelStopUnloadSelfModuleWithOrWithoutStatus(exitCode, argSize, argp, 0, 0, false);
2353 }
2354
sceKernelStopUnloadSelfModuleWithStatus(u32 exitCode,u32 argSize,u32 argp,u32 statusAddr,u32 optionAddr)2355 static u32 sceKernelStopUnloadSelfModuleWithStatus(u32 exitCode, u32 argSize, u32 argp, u32 statusAddr, u32 optionAddr) {
2356 return hleKernelStopUnloadSelfModuleWithOrWithoutStatus(exitCode, argSize, argp, statusAddr, optionAddr, true);
2357 }
2358
__KernelReturnFromModuleFunc()2359 void __KernelReturnFromModuleFunc()
2360 {
2361 // Return from the thread as normal.
2362 hleSkipDeadbeef();
2363 __KernelReturnFromThread();
2364
2365 SceUID leftModuleID = __KernelGetCurThreadModuleId();
2366 SceUID leftThreadID = __KernelGetCurThread();
2367 int exitStatus = __KernelGetThreadExitStatus(leftThreadID);
2368
2369 // Reschedule immediately (to leave the thread) and delete it and its stack.
2370 __KernelReSchedule("returned from module");
2371 sceKernelDeleteThread(leftThreadID);
2372
2373 u32 error;
2374 PSPModule *module = kernelObjects.Get<PSPModule>(leftModuleID, error);
2375 if (!module) {
2376 ERROR_LOG_REPORT(SCEMODULE, "Returned from deleted module start/stop func");
2377 return;
2378 }
2379
2380 // We can't be starting and stopping at the same time, so no need to differentiate.
2381 if (module->nm.status == MODULE_STATUS_STARTING)
2382 module->nm.status = MODULE_STATUS_STARTED;
2383 if (module->nm.status == MODULE_STATUS_STOPPING)
2384 module->nm.status = MODULE_STATUS_STOPPED;
2385 for (auto it = module->waitingThreads.begin(), end = module->waitingThreads.end(); it < end; ++it) {
2386 // Still waiting?
2387 if (HLEKernel::VerifyWait(it->threadID, WAITTYPE_MODULE, leftModuleID))
2388 {
2389 if (module->nm.status == MODULE_STATUS_UNLOADING) {
2390 // TODO: Maybe should maintain the exitCode?
2391 sceKernelTerminateDeleteThread(it->threadID);
2392 } else {
2393 if (it->statusPtr != 0)
2394 Memory::Write_U32(exitStatus, it->statusPtr);
2395 __KernelResumeThreadFromWait(it->threadID, module->nm.status == MODULE_STATUS_STARTED ? leftModuleID : 0);
2396 }
2397 }
2398 }
2399 module->waitingThreads.clear();
2400
2401 if (module->nm.status == MODULE_STATUS_UNLOADING) {
2402 // TODO: Delete the waiting thread?
2403 module->Cleanup();
2404 kernelObjects.Destroy<PSPModule>(leftModuleID);
2405 }
2406 }
2407
2408 struct GetModuleIdByAddressArg
2409 {
2410 u32 addr;
2411 SceUID result;
2412 };
2413
__GetModuleIdByAddressIterator(PSPModule * module,GetModuleIdByAddressArg * state)2414 static bool __GetModuleIdByAddressIterator(PSPModule *module, GetModuleIdByAddressArg *state) {
2415 const u32 start = module->memoryBlockAddr, size = module->memoryBlockSize;
2416 if (start != 0 && start <= state->addr && start + size > state->addr) {
2417 state->result = module->GetUID();
2418 return false;
2419 }
2420 return true;
2421 }
2422
sceKernelGetModuleIdByAddress(u32 moduleAddr)2423 static u32 sceKernelGetModuleIdByAddress(u32 moduleAddr)
2424 {
2425 GetModuleIdByAddressArg state;
2426 state.addr = moduleAddr;
2427 state.result = SCE_KERNEL_ERROR_UNKNOWN_MODULE;
2428
2429 kernelObjects.Iterate(&__GetModuleIdByAddressIterator, &state);
2430 if (state.result == (SceUID)SCE_KERNEL_ERROR_UNKNOWN_MODULE)
2431 ERROR_LOG(SCEMODULE, "sceKernelGetModuleIdByAddress(%08x): module not found", moduleAddr);
2432 else
2433 DEBUG_LOG(SCEMODULE, "%x=sceKernelGetModuleIdByAddress(%08x)", state.result, moduleAddr);
2434 return state.result;
2435 }
2436
sceKernelGetModuleId()2437 static u32 sceKernelGetModuleId()
2438 {
2439 INFO_LOG(SCEMODULE,"sceKernelGetModuleId()");
2440 return __KernelGetCurThreadModuleId();
2441 }
2442
sceKernelFindModuleByUID(u32 uid)2443 u32 sceKernelFindModuleByUID(u32 uid)
2444 {
2445 u32 error;
2446 PSPModule *module = kernelObjects.Get<PSPModule>(uid, error);
2447 if (!module || module->isFake) {
2448 ERROR_LOG(SCEMODULE, "0 = sceKernelFindModuleByUID(%d): Module Not Found or Fake", uid);
2449 return 0;
2450 }
2451 INFO_LOG(SCEMODULE, "%d = sceKernelFindModuleByUID(%d)", module->modulePtr, uid);
2452 return module->modulePtr;
2453 }
2454
sceKernelFindModuleByName(const char * name)2455 u32 sceKernelFindModuleByName(const char *name)
2456 {
2457 u32 error;
2458 for (SceUID moduleId : loadedModules) {
2459 PSPModule *module = kernelObjects.Get<PSPModule>(moduleId, error);
2460 if (!module)
2461 continue;
2462 if (strcmp(name, module->nm.name) == 0) {
2463 if (!module->isFake) {
2464 INFO_LOG(SCEMODULE, "%d = sceKernelFindModuleByName(%s)", module->modulePtr, name);
2465 return module->modulePtr;
2466 }
2467 else {
2468 WARN_LOG(SCEMODULE, "0 = sceKernelFindModuleByName(%s): Module Fake", name);
2469 return hleDelayResult(0, "Module Fake", 1000 * 1000);
2470 }
2471 }
2472 }
2473 WARN_LOG(SCEMODULE, "0 = sceKernelFindModuleByName(%s): Module Not Found", name);
2474 return 0;
2475 }
2476
sceKernelLoadModuleByID(u32 id,u32 flags,u32 lmoptionPtr)2477 static u32 sceKernelLoadModuleByID(u32 id, u32 flags, u32 lmoptionPtr)
2478 {
2479 u32 error;
2480 u32 handle = __IoGetFileHandleFromId(id, error);
2481 if (handle == (u32)-1) {
2482 ERROR_LOG(SCEMODULE,"sceKernelLoadModuleByID(%08x, %08x, %08x): could not open file id",id,flags,lmoptionPtr);
2483 return error;
2484 }
2485 if (flags != 0) {
2486 WARN_LOG_REPORT(LOADER, "sceKernelLoadModuleByID: unsupported flags: %08x", flags);
2487 }
2488 SceKernelLMOption *lmoption = 0;
2489 if (lmoptionPtr) {
2490 lmoption = (SceKernelLMOption *)Memory::GetPointer(lmoptionPtr);
2491 WARN_LOG_REPORT(LOADER, "sceKernelLoadModuleByID: unsupported options size=%08x, flags=%08x, pos=%d, access=%d, data=%d, text=%d", lmoption->size, lmoption->flags, lmoption->position, lmoption->access, lmoption->mpiddata, lmoption->mpidtext);
2492 }
2493 u32 pos = (u32) pspFileSystem.SeekFile(handle, 0, FILEMOVE_CURRENT);
2494 size_t size = pspFileSystem.SeekFile(handle, 0, FILEMOVE_END);
2495 std::string error_string;
2496 pspFileSystem.SeekFile(handle, pos, FILEMOVE_BEGIN);
2497 PSPModule *module = nullptr;
2498 u8 *temp = new u8[size - pos];
2499 pspFileSystem.ReadFile(handle, temp, size - pos);
2500 u32 magic;
2501 module = __KernelLoadELFFromPtr(temp, size - pos, 0, lmoption ? lmoption->position == PSP_SMEM_High : false, &error_string, &magic, error);
2502 delete [] temp;
2503
2504 if (!module) {
2505 // Some games try to load strange stuff as PARAM.SFO as modules and expect it to fail.
2506 // This checks for the SFO magic number.
2507 if (magic == 0x46535000) {
2508 ERROR_LOG(LOADER, "Game tried to load an SFO as a module. Go figure? Magic = %08x", magic);
2509 return error;
2510 }
2511
2512 if ((int)error >= 0)
2513 {
2514 // Module was blacklisted or couldn't be decrypted, which means it's a kernel module we don't want to run..
2515 // Let's just act as if it worked.
2516 NOTICE_LOG(LOADER, "Module %d is blacklisted or undecryptable - we lie about success", id);
2517 return 1;
2518 }
2519 else
2520 {
2521 NOTICE_LOG(LOADER, "Module %d failed to load: %08x", id, error);
2522 return error;
2523 }
2524 }
2525
2526 if (lmoption) {
2527 INFO_LOG(SCEMODULE,"%i=sceKernelLoadModuleByID(%d,flag=%08x,%08x,%08x,%08x,position = %08x)",
2528 module->GetUID(),id,flags,
2529 lmoption->size,lmoption->mpidtext,lmoption->mpiddata,lmoption->position);
2530 } else {
2531 INFO_LOG(SCEMODULE,"%i=sceKernelLoadModuleByID(%d,flag=%08x,(...))", module->GetUID(), id, flags);
2532 }
2533
2534 return module->GetUID();
2535 }
2536
sceKernelLoadModuleDNAS(const char * name,u32 flags)2537 static u32 sceKernelLoadModuleDNAS(const char *name, u32 flags)
2538 {
2539 ERROR_LOG_REPORT(SCEMODULE, "UNIMPL 0=sceKernelLoadModuleDNAS()");
2540 return 0;
2541 }
2542
2543 // Pretty sure this is a badly brute-forced function name...
sceKernelLoadModuleBufferUsbWlan(u32 size,u32 bufPtr,u32 flags,u32 lmoptionPtr)2544 static SceUID sceKernelLoadModuleBufferUsbWlan(u32 size, u32 bufPtr, u32 flags, u32 lmoptionPtr)
2545 {
2546 if (flags != 0) {
2547 WARN_LOG_REPORT(LOADER, "sceKernelLoadModuleBufferUsbWlan: unsupported flags: %08x", flags);
2548 }
2549 SceKernelLMOption *lmoption = 0;
2550 if (lmoptionPtr) {
2551 lmoption = (SceKernelLMOption *)Memory::GetPointer(lmoptionPtr);
2552 WARN_LOG_REPORT(LOADER, "sceKernelLoadModuleBufferUsbWlan: unsupported options size=%08x, flags=%08x, pos=%d, access=%d, data=%d, text=%d", lmoption->size, lmoption->flags, lmoption->position, lmoption->access, lmoption->mpiddata, lmoption->mpidtext);
2553 }
2554 std::string error_string;
2555 PSPModule *module = nullptr;
2556 u32 magic;
2557 u32 error;
2558 module = __KernelLoadELFFromPtr(Memory::GetPointer(bufPtr), size, 0, lmoption ? lmoption->position == PSP_SMEM_High : false, &error_string, &magic, error);
2559
2560 if (!module) {
2561 // Some games try to load strange stuff as PARAM.SFO as modules and expect it to fail.
2562 // This checks for the SFO magic number.
2563 if (magic == 0x46535000) {
2564 ERROR_LOG(LOADER, "Game tried to load an SFO as a module. Go figure? Magic = %08x", magic);
2565 return error;
2566 }
2567
2568 if ((int)error >= 0)
2569 {
2570 // Module was blacklisted or couldn't be decrypted, which means it's a kernel module we don't want to run..
2571 // Let's just act as if it worked.
2572 NOTICE_LOG(LOADER, "Module is blacklisted or undecryptable - we lie about success");
2573 return 1;
2574 }
2575 else
2576 {
2577 NOTICE_LOG(LOADER, "Module failed to load: %08x", error);
2578 return error;
2579 }
2580 }
2581
2582 if (lmoption) {
2583 INFO_LOG(SCEMODULE,"%i=sceKernelLoadModuleBufferUsbWlan(%x,%08x,flag=%08x,%08x,%08x,%08x,position = %08x)",
2584 module->GetUID(),size,bufPtr,flags,
2585 lmoption->size,lmoption->mpidtext,lmoption->mpiddata,lmoption->position);
2586 } else {
2587 INFO_LOG(SCEMODULE,"%i=sceKernelLoadModuleBufferUsbWlan(%x,%08x,flag=%08x,(...))", module->GetUID(), size,bufPtr, flags);
2588 }
2589
2590 return module->GetUID();
2591 }
2592
sceKernelQueryModuleInfo(u32 uid,u32 infoAddr)2593 static u32 sceKernelQueryModuleInfo(u32 uid, u32 infoAddr)
2594 {
2595 INFO_LOG(SCEMODULE, "sceKernelQueryModuleInfo(%i, %08x)", uid, infoAddr);
2596 u32 error;
2597 PSPModule *module = kernelObjects.Get<PSPModule>(uid, error);
2598 if (!module)
2599 return error;
2600 if (!Memory::IsValidAddress(infoAddr)) {
2601 ERROR_LOG(SCEMODULE, "sceKernelQueryModuleInfo(%i, %08x) - bad infoAddr", uid, infoAddr);
2602 return -1;
2603 }
2604
2605 auto info = PSPPointer<ModuleInfo>::Create(infoAddr);
2606
2607 memcpy(info->segmentaddr, module->nm.segmentaddr, sizeof(info->segmentaddr));
2608 memcpy(info->segmentsize, module->nm.segmentsize, sizeof(info->segmentsize));
2609 info->nsegment = module->nm.nsegment;
2610 info->entry_addr = module->nm.entry_addr;
2611 info->gp_value = module->nm.gp_value;
2612 info->text_addr = module->nm.text_addr;
2613 info->text_size = module->nm.text_size;
2614 info->data_size = module->nm.data_size;
2615 info->bss_size = module->nm.bss_size;
2616
2617 // Even if it's bigger, if it's not exactly 96, skip this extra data.
2618 // Even if it's 0, the above are all written though.
2619 if (info->size == 96) {
2620 info->attribute = module->nm.attribute;
2621 info->version[0] = module->nm.version[0];
2622 info->version[1] = module->nm.version[1];
2623 memcpy(info->name, module->nm.name, 28);
2624 }
2625
2626 return 0;
2627 }
2628
sceKernelGetModuleIdList(u32 resultBuffer,u32 resultBufferSize,u32 idCountAddr)2629 static u32 sceKernelGetModuleIdList(u32 resultBuffer, u32 resultBufferSize, u32 idCountAddr)
2630 {
2631 ERROR_LOG(SCEMODULE, "UNTESTED sceKernelGetModuleIdList(%08x, %i, %08x)", resultBuffer, resultBufferSize, idCountAddr);
2632
2633 int idCount = 0;
2634 u32 resultBufferOffset = 0;
2635
2636 u32 error;
2637 for (SceUID moduleId : loadedModules) {
2638 PSPModule *module = kernelObjects.Get<PSPModule>(moduleId, error);
2639 if (!module->isFake) {
2640 if (resultBufferOffset < resultBufferSize) {
2641 Memory::Write_U32(module->GetUID(), resultBuffer + resultBufferOffset);
2642 resultBufferOffset += 4;
2643 }
2644 idCount++;
2645 }
2646 }
2647
2648 Memory::Write_U32(idCount, idCountAddr);
2649
2650 return 0;
2651 }
2652
2653 //fix for tiger x dragon
sceKernelLoadModuleForLoadExecVSHDisc(const char * name,u32 flags,u32 optionAddr)2654 static u32 sceKernelLoadModuleForLoadExecVSHDisc(const char *name, u32 flags, u32 optionAddr) {
2655 return sceKernelLoadModule(name, flags, optionAddr);
2656 }
2657
2658 const HLEFunction ModuleMgrForUser[] =
2659 {
2660 {0X977DE386, &WrapU_CUU<sceKernelLoadModule>, "sceKernelLoadModule", 'x', "sxx" },
2661 {0XB7F46618, &WrapU_UUU<sceKernelLoadModuleByID>, "sceKernelLoadModuleByID", 'x', "xxx" },
2662 {0X50F0C1EC, &WrapV_UUUUU<sceKernelStartModule>, "sceKernelStartModule", 'v', "xxxxx", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
2663 {0XD675EBB8, &WrapU_UUU<sceKernelSelfStopUnloadModule>, "sceKernelSelfStopUnloadModule", 'x', "xxx" },
2664 {0XD1FF982A, &WrapU_UUUUU<sceKernelStopModule>, "sceKernelStopModule", 'x', "xxxxx", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
2665 {0X2E0911AA, &WrapU_U<sceKernelUnloadModule>, "sceKernelUnloadModule", 'x', "x" },
2666 {0X710F61B5, nullptr, "sceKernelLoadModuleMs", '?', "" },
2667 {0XF9275D98, &WrapI_UUUU<sceKernelLoadModuleBufferUsbWlan>, "sceKernelLoadModuleBufferUsbWlan", 'i', "xxxx" }, /// ??
2668 {0XCC1D3699, nullptr, "sceKernelStopUnloadSelfModule", '?', "" },
2669 {0X748CBED9, &WrapU_UU<sceKernelQueryModuleInfo>, "sceKernelQueryModuleInfo", 'x', "xx" },
2670 {0XD8B73127, &WrapU_U<sceKernelGetModuleIdByAddress>, "sceKernelGetModuleIdByAddress", 'x', "x" },
2671 {0XF0A26395, &WrapU_V<sceKernelGetModuleId>, "sceKernelGetModuleId", 'x', "" },
2672 {0X8F2DF740, &WrapU_UUUUU<sceKernelStopUnloadSelfModuleWithStatus>, "sceKernelStopUnloadSelfModuleWithStatus", 'x', "xxxxx" },
2673 {0XFEF27DC1, &WrapU_CU<sceKernelLoadModuleDNAS>, "sceKernelLoadModuleDNAS", 'x', "sx" },
2674 {0X644395E2, &WrapU_UUU<sceKernelGetModuleIdList>, "sceKernelGetModuleIdList", 'x', "xxx" },
2675 {0XF2D8D1B4, &WrapU_CUU<sceKernelLoadModuleNpDrm>, "sceKernelLoadModuleNpDrm", 'x', "sxx" },
2676 {0XE4C4211C, nullptr, "ModuleMgrForUser_E4C4211C", '?', "" },
2677 {0XFBE27467, nullptr, "ModuleMgrForUser_FBE27467", '?', "" },
2678 };
2679
2680
2681 const HLEFunction ModuleMgrForKernel[] =
2682 {
2683 {0x50F0C1EC, &WrapV_UUUUU<sceKernelStartModule>, "sceKernelStartModule", 'v', "xxxxx", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED | HLE_KERNEL_SYSCALL },
2684 {0x977DE386, &WrapU_CUU<sceKernelLoadModule>, "sceKernelLoadModule", 'x', "sxx", HLE_KERNEL_SYSCALL },
2685 {0xA1A78C58, &WrapU_CUU<sceKernelLoadModuleForLoadExecVSHDisc>, "sceKernelLoadModuleForLoadExecVSHDisc", 'x', "sxx", HLE_KERNEL_SYSCALL }, //fix for tiger x dragon
2686 {0xCC1D3699, &WrapU_UUU<sceKernelSelfStopUnloadModule>, "sceKernelSelfStopUnloadModule", 'x', "xxx", HLE_KERNEL_SYSCALL }, // used in Dissidia final fantasy chinese patch
2687 {0XD1FF982A, &WrapU_UUUUU<sceKernelStopModule>, "sceKernelStopModule", 'x', "xxxxx", HLE_KERNEL_SYSCALL | HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED }, // used in Dissidia final fantasy chinese patch
2688 {0x748CBED9, &WrapU_UU<sceKernelQueryModuleInfo>, "sceKernelQueryModuleInfo", 'x', "xx", HLE_KERNEL_SYSCALL },
2689 {0x644395E2, &WrapU_UUU<sceKernelGetModuleIdList>, "sceKernelGetModuleIdList", 'x', "xxx", HLE_KERNEL_SYSCALL },
2690 {0X2E0911AA, &WrapU_U<sceKernelUnloadModule>, "sceKernelUnloadModule", 'x', "x" , HLE_KERNEL_SYSCALL },
2691 };
2692
Register_ModuleMgrForUser()2693 void Register_ModuleMgrForUser()
2694 {
2695 RegisterModule("ModuleMgrForUser", ARRAY_SIZE(ModuleMgrForUser), ModuleMgrForUser);
2696 }
2697
Register_ModuleMgrForKernel()2698 void Register_ModuleMgrForKernel()
2699 {
2700 RegisterModule("ModuleMgrForKernel", ARRAY_SIZE(ModuleMgrForKernel), ModuleMgrForKernel);
2701
2702 };
2703