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, &param);
1756 	else
1757 		memset(&param, 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