PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
loadcore.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include "loadcore.h"
12#include "irx_imports.h"
13#include "kerr.h"
14#include "xloadcore.h"
15
16extern struct irx_export_table _exp_loadcore;
17
18#ifdef _IOP
19IRX_ID("Module_Manager", 2, 6);
20#endif
21// Based on the module from SCE SDK 3.1.0.
22
23static lc_internals_t loadcore_internals;
24static u32 *reboot_handlers;
25
26typedef struct
27{
28 u8 ident[16]; /* Structure of a ELF header */
29 u16 type;
30 u16 machine;
31 u32 version;
32 u32 entry;
33 u32 phoff;
34 u32 shoff;
35 u32 flags;
36 u16 ehsize;
37 u16 phentsize;
38 u16 phnum;
39 u16 shentsize;
40 u16 shnum;
41 u16 shstrndx;
43
44typedef struct
45{
46 u32 type; /* Structure of a header a sections in an ELF */
47 u32 offset;
48 void *vaddr;
49 u32 paddr;
50 u32 filesz;
51 u32 memsz;
52 u32 flags;
53 u32 align;
55
56typedef struct
57{
58 u32 name;
59 u32 type;
60 u32 flags;
61 u32 addr;
62 u32 offset;
63 u32 size;
64 u32 link;
65 u32 info;
66 u32 addralign;
67 u32 entsize;
69
70typedef struct
71{
72 u32 offset;
73 u32 info;
74} elf_rel;
75
76typedef struct
77{
78 u32 offset;
79 u32 info;
80 u32 addend;
81} elf_rela;
82
83enum ELF_SHT_types
84{
85 SHT_NULL = 0,
86 SHT_PROGBITS,
87 SHT_SYMTAB,
88 SHT_STRTAB,
89 SHT_RELA,
90 SHT_HASH,
91 SHT_DYNAMIC,
92 SHT_NOTE,
93 SHT_NOBITS,
94 SHT_REL,
95 SHT_SHLIB,
96 SHT_DYNSYM
97};
98
99enum ELF_reloc_types
100{
101 R_MIPS_NONE = 0,
102 R_MIPS_16,
103 R_MIPS_32,
104 R_MIPS_REL32,
105 R_MIPS_26,
106 R_MIPS_HI16,
107 R_MIPS_LO16,
108 R_MIPSSCE_MHI16 = 250,
109 R_MIPSSCE_ADDEND = 251,
110};
111
112#define SHT_LOPROC 0x70000000
113#define SHT_LOPROC_EE_IMPORT_TAB 0x90
114#define SHT_LOPROC_IOPMOD 0x80
115#define SHT_HIPROC 0x7fffffff
116#define SHT_LOUSER 0x80000000
117#define SHT_HIUSER 0xffffffff
118
119#define SHF_WRITE 0x1
120#define SHF_ALLOC 0x2
121#define SHF_EXECINSTR 0x4
122#define SHF_MASKPROC 0xf0000000
123
124struct iopmod
125{
126 IopModuleID_t *mod_id;
127 void *EntryPoint;
128 void *gp;
129 unsigned int text_size;
130 unsigned int data_size;
131 unsigned int bss_size;
132 unsigned short int version;
133 // cppcheck-suppress unusedStructMember
134 char modname[];
135};
136
138{
139 u16 f_magic; /* magic number */
140 u16 f_nscns; /* number of sections */
141 u32 f_timdat; /* time & date stamp */
142 u32 f_symptr; /* file pointer to symbolic header */
143 u32 f_nsyms; /* sizeof(symbolic hdr) */
144 u16 f_opthdr; /* sizeof(optional hdr) */
145 u16 f_flags; /* flags */
146};
147
148#define MIPSELMAGIC 0x0162
149
150#define OMAGIC 0407
151#define SOMAGIC 0x0701
152
153typedef struct aouthdr
154{
155 u16 magic; /* see above */
156 u16 vstamp; /* version stamp */
157 u32 tsize; /* text size in bytes, padded to DW bdry */
158 u32 dsize; /* initialized data " " */
159 u32 bsize; /* uninitialized data " " */
160 u32 entry; /* entry pt. */
161 u32 text_start; /* base of text used for this file */
162 u32 data_start; /* base of data used for this file */
163 u32 bss_start; /* base of bss used for this file */
164 // Instead of the GPR and CPR masks, these 5 fields exist.
165 u32 field_20;
166 u32 field_24;
167 u32 field_28;
168 u32 field_2C;
169 IopModuleID_t *mod_id;
170 u32 gp_value; /* the gp value used for this object */
171} AOUTHDR;
172
173struct scnhdr
174{
175 u8 s_name[8]; /* section name */
176 u32 s_paddr; /* physical address, aliased s_nlib */
177 u32 s_vaddr; /* virtual address */
178 u32 s_size; /* section size */
179 u32 s_scnptr; /* file ptr to raw data for section */
180 u32 s_relptr; /* file ptr to relocation */
181 u32 s_lnnoptr; /* file ptr to gp histogram */
182 u16 s_nreloc; /* number of relocation entries */
183 u16 s_nlnno; /* number of gp histogram entries */
184 u32 s_flags; /* flags */
185};
186
187enum IOP_MODULE_TYPES
188{
189 IOP_MOD_TYPE_COFF = 1,
190 IOP_MOD_TYPE_2,
191 IOP_MOD_TYPE_ELF,
192 IOP_MOD_TYPE_IRX
193};
194
195enum E_type_name_enum
196{
197 ET_NONE = 0,
198 ET_REL = 1,
199 ET_EXEC = 2,
200 ET_DYN = 3,
201 ET_CORE = 4,
202 ET_SCE_IOPRELEXEC = 0xFF80,
203 ET_SCE_IOPRELEXEC2 = 0xFF81,
204 ET_SCE_EERELEXEC = 0xFF90,
205 ET_SCE_EERELEXEC2 = 0xFF91,
206};
207
208typedef struct intrman_callbacks_
209{
210 int (*cbCpuSuspendIntr)(int *state);
211 int (*cbCpuResumeIntr)(int state);
212 // cppcheck-suppress unusedStructMember
213 int (*cbQueryIntrContext)(void);
215
216static int IsSameLibrary(const struct irx_export_table *src, const struct irx_export_table *dst);
217static int compLibMinVersion_major(const struct irx_export_table *src, const struct irx_export_table *dst);
218static int compLibMinVersion_minor(const struct irx_export_table *src, const struct irx_export_table *dst);
219static int IsLibraryCompliant(const struct irx_export_table *src, const struct irx_export_table *dst);
220static int compLibMinVersion_major_1(const struct irx_export_table *src, const struct irx_export_table *dst);
221static void cleanStub(const struct irx_import_table *imp);
222static int CheckCallerStub(const struct irx_import_table *imp);
223static int aLinkLibEntries(struct irx_import_table *imp);
224static void aLinkClient(struct irx_import_table *imp, const struct irx_export_table *exp);
225static int aUnLinkLibEntries(struct irx_import_table *a1, const struct irx_import_table *a2);
226static void lc_memset32(int *b, int c, int len);
227static int lc_strlen(const char *s);
228static void lc_memmove(char *dst, const char *src, int len);
229static int cCpuSuspendIntr(int *state);
230static int cCpuResumeIntr(int state);
231static void loadcoff(const void *module);
232static void loadelf(const void *module);
233static void loadrelelf(const void *module, FileInfo_t *ModuleInfo);
234static void CopySection(const void *module, void *buffer, unsigned int FileSize);
235static void ZeroSection(unsigned int *buffer, unsigned int NumWords);
236
237typedef struct ResetData
238{
239 unsigned int MemSize;
240 unsigned int BootMode;
241 const char *command;
242 void *StartAddress;
243 void *IOPRPBuffer;
244 unsigned int IOPRPBufferSize;
245 unsigned int NumModules;
246 const void **ModData;
248
249static u32 bootmodes[17];
250
251static u32 **const bootmodes_start_ptr = (void *)0x3F0;
252static u32 **const bootmodes_end_ptr = (void *)0x3F4;
253
254// The following are defined in the linker script
255extern void *_ftext;
256extern void *_etext;
257extern void *_end;
258
259// clang-format off
260__asm__ (
261 "\t" ".set push" "\n"
262 "\t" ".set noat" "\n"
263 "\t" ".set noreorder" "\n"
264 "\t" ".global _start" "\n"
265 "\t" "_start:" "\n"
266 "\t" " mtc0 $zero, $12" "\n"
267 "\t" " lw $v0, 0x0($a0)" "\n" // boot_params->MemSize
268 "\t" " nop" "\n"
269 "\t" " sll $sp, $v0, 20" "\n" // sp = boot_params->MemSize << 20
270 "\t" " addiu $sp, $sp, -0x40" "\n"
271 "\t" " addu $fp, $sp, $zero" "\n"
272 "\t" " lui $gp, %hi(_gp)" "\n"
273 "\t" " j loadcore_init" "\n"
274 "\t" " addiu $gp, $gp, %lo(_gp)" "\n"
275 "\t" ".set pop" "\n"
276);
277// clang-format on
278
279void loadcore_init(boot_params *in_params)
280{
281 const void **ModData;
282 ModuleInfo_t *sysmemmi;
283 u32 MemSize;
284 unsigned int i;
285 char *blocksize_mask_1;
286 int BlockSize;
287 int blocksize_mask_2;
288 void *curmodaddr_align;
289 elf_header_t **cur_module_addr;
290 int executable_type;
291 int memalloctype;
292 void *memallocaddr;
293 int entrypoint_ret;
294 ModuleInfo_t *mi;
295 int *frame_pointer_curfunc;
296 FileInfo_t fi;
297 boot_params params;
298 u32 *stack_reboot_handlers;
299
300 // cppcheck-suppress unreadVariable
301 params.MemSize = in_params->MemSize;
302 params.BootMode = in_params->BootMode;
303 params.command = in_params->command;
304 params.StartAddress = in_params->StartAddress;
305 params.IOPRPBuffer = in_params->IOPRPBuffer;
306 params.IOPRPBufferSize = in_params->IOPRPBufferSize;
307 params.NumModules = in_params->NumModules;
308 ModData = in_params->ModData;
309 loadcore_internals.let_next = (iop_library_t *)params.StartAddress;
310#pragma GCC diagnostic push
311#pragma GCC diagnostic ignored "-Warray-bounds"
312 *bootmodes_start_ptr = bootmodes;
313 *bootmodes_end_ptr = bootmodes;
314#pragma GCC diagnostic pop
315 loadcore_internals.intr_suspend_tbl = NULL;
316 loadcore_internals.let_prev = (iop_library_t *)params.StartAddress;
317 params.ModData = ModData;
318 loadcore_internals.let_prev->prev = NULL;
319 loadcore_internals.module_count = 2;
320 loadcore_internals.mda_next = 0;
321 loadcore_internals.mda_prev = 0;
322 loadcore_internals.module_index = 3;
323 for ( i = 0; i < 17; i += 1 )
324 {
325 bootmodes[i] = 0;
326 }
327 {
328 u32 bootmode_tmp[1];
329
330 bootmode_tmp[0] = (params.BootMode & 0xFFFF) | 0x40000;
331 RegisterBootMode((iop_bootmode_t *)bootmode_tmp);
332 }
333 sysmemmi = (ModuleInfo_t *)((char *)loadcore_internals.let_prev - 0x30);
334 loadcore_internals.image_info = sysmemmi;
335 sysmemmi->id = 1;
336 sysmemmi->newflags = 3;
337#pragma GCC diagnostic push
338#pragma GCC diagnostic ignored "-Warray-bounds"
339 sysmemmi->next = (ModuleInfo_t *)((u8 *)&_ftext - 0x30);
340 ((ModuleInfo_t *)loadcore_internals.image_info->next)->id = 2;
341 ((ModuleInfo_t *)loadcore_internals.image_info->next)->newflags = 3;
342#pragma GCC diagnostic pop
343 // cppcheck-suppress comparePointers
344 LinkLibraryEntries((u32 *)&_ftext, (u8 *)&_etext - (u8 *)&_ftext);
345 RegisterLibraryEntries(&_exp_loadcore);
346#pragma GCC diagnostic push
347#pragma GCC diagnostic ignored "-Warray-bounds"
348 AllocSysMemory(
349 2,
350 (u32)(((u8 *)&_end) - ((u32)(((u8 *)&_ftext) - 0x30) >> 8 << 8)),
351 (void *)(((u32)(((u8 *)&_ftext) - 0x30) >> 8 << 8) & 0x1FFFFFFF));
352#pragma GCC diagnostic pop
353 if ( params.IOPRPBuffer )
354 params.IOPRPBuffer = AllocSysMemory(2, params.IOPRPBufferSize, params.IOPRPBuffer);
355 frame_pointer_curfunc = __builtin_frame_address(0);
356#if 0
357 // FIXME: wipe current stack contents
358 lc_memset32((int *)((unsigned int)frame_pointer_curfunc & 0x1FFFFF00), stack_pointer_curfunc, 0x11111111);
359#endif
360 if ( ((unsigned int)frame_pointer_curfunc & 0x1FFFFF00) < QueryMemSize() )
361 {
362 MemSize = QueryMemSize();
363 AllocSysMemory(
364 2,
365 MemSize - ((unsigned int)frame_pointer_curfunc & 0x1FFFFF00),
366 (void *)((unsigned int)frame_pointer_curfunc & 0x1FFFFF00));
367 }
368 if ( params.command )
369 {
370 char *stack_command;
371 int stack_command_size;
372 u32 bootmode_tmp[2];
373
374 stack_command_size = lc_strlen(params.command) + 1;
375 stack_command = __builtin_alloca(stack_command_size);
376 lc_memmove(stack_command, params.command, stack_command_size);
377 // cppcheck-suppress unreadVariable
378 params.command = stack_command;
379 bootmode_tmp[0] = 0x1050000;
380 bootmode_tmp[1] = (u32)stack_command;
381 RegisterBootMode((iop_bootmode_t *)bootmode_tmp);
382 }
383 {
384 char *stack_moddata;
385 int stack_moddata_size;
386
387 stack_moddata_size = (params.NumModules + 1) * 4;
388 stack_moddata = __builtin_alloca(stack_moddata_size);
389 lc_memmove(stack_moddata, (const char *)params.ModData, stack_moddata_size);
390 params.ModData = (const void **)stack_moddata;
391 }
392 stack_reboot_handlers = __builtin_alloca(params.NumModules * (sizeof(u32) * 2));
393 reboot_handlers = stack_reboot_handlers;
394
395 for ( i = (unsigned int)QueryBlockTopAddress(0); i != 0xFFFFFFFF;
396 i = (unsigned int)QueryBlockTopAddress(&blocksize_mask_1[blocksize_mask_2]) )
397 {
398 blocksize_mask_1 = (char *)(i & 0x7FFFFFFF);
399 BlockSize = QueryBlockSize(blocksize_mask_1);
400 blocksize_mask_2 = BlockSize & 0x7FFFFFFF;
401 if ( BlockSize < 0 )
402 lc_memset32((int *)blocksize_mask_1, 0x400D, blocksize_mask_2);
403 }
404 curmodaddr_align = 0;
405 stack_reboot_handlers[0] = 0;
406#if 0
407 u8 module_index = 0;
408#endif
409 cur_module_addr = (elf_header_t **)(params.ModData + 2);
410 while ( 1 )
411 {
412 if ( !*cur_module_addr )
413 {
414 if ( params.IOPRPBuffer )
415 {
416 lc_memset32((int *)params.IOPRPBuffer, 0x400D, params.IOPRPBufferSize);
417 FreeSysMemory(params.IOPRPBuffer);
418 }
419 for ( i = 0; i < 4; i += 1 )
420 {
421 u32 *reboot_handler_ptr;
422
423 if ( i == 3 )
424 reboot_handlers = NULL;
425 reboot_handler_ptr = stack_reboot_handlers;
426 while ( *reboot_handler_ptr )
427 {
428 if ( (*reboot_handler_ptr & 3) == i )
429 {
430 iop_init_entry_t next;
431
432 next.callback = (void *)*stack_reboot_handlers;
433 if ( i == 3 )
434 next.callback = (void *)*reboot_handler_ptr;
435 __asm__ __volatile__("\tmove $gp, %0\n" : : "r"(reboot_handler_ptr[1]));
436 ((void (*)(iop_init_entry_t *, int))(*reboot_handler_ptr & (~3)))(&next, 1);
437 }
438 reboot_handler_ptr += 2;
439 }
440 if ( i == 2 )
441 {
442 while ( stack_reboot_handlers < reboot_handler_ptr )
443 {
444 reboot_handler_ptr -= 2;
445 if ( (*reboot_handler_ptr & 3) == 3 )
446 break;
447 *reboot_handler_ptr = 0;
448 }
449 }
450 }
451 break;
452 }
453 if ( ((unsigned int)*cur_module_addr & 1) != 0 )
454 {
455 if ( ((unsigned int)*cur_module_addr & 0xF) == 1 )
456 curmodaddr_align = (void *)((unsigned int)*cur_module_addr >> 2);
457 }
458 else
459 {
460#if 0
461 module_index += 1;
462 module_index &= 0xF;
463#endif
464 executable_type = ProbeExecutableObject(*cur_module_addr, &fi);
465 if ( executable_type == IOP_MOD_TYPE_IRX )
466 {
467 if ( curmodaddr_align )
468 {
469 memalloctype = 2;
470 memallocaddr = curmodaddr_align;
471 }
472 else
473 {
474 memalloctype = 0;
475 memallocaddr = 0;
476 }
477 fi.text_start = AllocSysMemory(memalloctype, fi.MemSize + 0x30, memallocaddr);
478 if ( !fi.text_start )
479 break;
480 fi.text_start = (char *)fi.text_start + 0x30;
481 }
482 mi = (ModuleInfo_t *)((char *)fi.text_start - 48);
483 if ( executable_type == IOP_MOD_TYPE_COFF || executable_type == IOP_MOD_TYPE_ELF )
484 {
485 if ( !AllocSysMemory(
486 2,
487 (int)fi.text_start + fi.MemSize - ((((u32)mi) >> 8 << 8) & 0x1FFFFFFF),
488 (void *)((((u32)mi) >> 8 << 8) & 0x1FFFFFFF)) )
489 break;
490 }
491 LoadExecutableObject(*cur_module_addr, &fi);
492 if ( LinkLibraryEntries(fi.text_start, fi.text_size) == 0 )
493 {
494 FlushIcache();
495 entrypoint_ret = ((int (*)(u32, u32, elf_header_t **, u32))fi.EntryPoint)(0, 0, cur_module_addr, 0);
496 if ( (entrypoint_ret & 3) != 1 )
497 {
498 RegisterModule(mi);
499 mi->newflags = 3;
500 if ( (entrypoint_ret & 3) == 2 )
501 mi->newflags |= 0x10;
502 if ( (entrypoint_ret & (~3)) != 0 )
503 AddRebootNotifyHandler((BootupCallback_t)(entrypoint_ret & (~3)), 2, 0);
504 }
505 else
506 {
507 UnLinkLibraryEntries(fi.text_start, fi.text_size);
508 FreeSysMemory((void *)(((u32)mi) >> 8 << 8));
509 }
510 }
511 else
512 {
513 FreeSysMemory((void *)(((u32)mi) >> 8 << 8));
514 }
515 curmodaddr_align = 0;
516 }
517 cur_module_addr += 1;
518 }
519 while ( 1 )
520 *(vu8 *)0x80000000 = 2;
521}
522
523void RegisterBootMode(iop_bootmode_t *b)
524{
525 u32 *bootmode_dst;
526 int effective_len;
527
528#pragma GCC diagnostic push
529#pragma GCC diagnostic ignored "-Warray-bounds"
530 bootmode_dst = *bootmodes_end_ptr;
531#pragma GCC diagnostic pop
532 effective_len = b->len + 1;
533 if ( sizeof(bootmodes) >= (effective_len * sizeof(bootmodes[0])) )
534 {
535 int i;
536
537 for ( i = 0; i < effective_len; i += 1 )
538 {
539 bootmode_dst[i] = ((u32 *)b)[i];
540 }
541 bootmode_dst[effective_len] = 0;
542#pragma GCC diagnostic push
543#pragma GCC diagnostic ignored "-Warray-bounds"
544 *bootmodes_end_ptr = bootmode_dst;
545#pragma GCC diagnostic pop
546 }
547}
548
549int *QueryBootMode(int mode)
550{
551 iop_bootmode_t *bootmode_cur;
552
553#pragma GCC diagnostic push
554#pragma GCC diagnostic ignored "-Warray-bounds"
555 bootmode_cur = (iop_bootmode_t *)*bootmodes_start_ptr;
556#pragma GCC diagnostic pop
557 while ( *(u32 *)bootmode_cur )
558 {
559 if ( mode == bootmode_cur->id )
560 return (int *)bootmode_cur;
561 bootmode_cur = (iop_bootmode_t *)((u8 *)bootmode_cur + ((bootmode_cur->len + 1)) * 4);
562 }
563 return NULL;
564}
565
566int AddRebootNotifyHandler(BootupCallback_t func, int priority, int *stat)
567{
568 u32 gp_val;
569 iop_init_entry_t next;
570
571 next.callback = (void *)1;
572 gp_val = 0;
573 __asm__ __volatile__("\tmove %0, $gp\n" : "=r"(gp_val) :);
574
575 if ( !reboot_handlers )
576 {
577 int stat_tmp;
578
579 stat_tmp = ((int (*)(iop_init_entry_t *, u32))func)(&next, 0);
580 if ( stat )
581 *stat = stat_tmp;
582 return 0;
583 }
584
585 reboot_handlers[0] = (u32)func + (priority & 3);
586 reboot_handlers[1] = gp_val;
587 reboot_handlers += 2;
588 reboot_handlers[0] = 0;
589 return 1;
590}
591
592void RegisterModule(ModuleInfo_t *mi)
593{
594 ModuleInfo_t *image_info;
595 int module_index;
596
597 image_info = loadcore_internals.image_info;
598 while ( image_info && image_info->next && (image_info->next < mi) )
599 {
600 image_info = image_info->next;
601 }
602 mi->next = image_info;
603 loadcore_internals.image_info = mi;
604 module_index = loadcore_internals.module_index;
605 mi->id = loadcore_internals.module_index & 0xFFFF;
606 loadcore_internals.module_index = module_index + 1;
607 loadcore_internals.module_count += 1;
608}
609
610// cppcheck-suppress constParameterPointer
611void ReleaseModule(ModuleInfo_t *mi)
612{
613 ModuleInfo_t *image_info;
614
615 if ( !mi )
616 {
617 return;
618 }
619 image_info = loadcore_internals.image_info;
620 while ( image_info && (image_info->next != mi) )
621 {
622 image_info = image_info->next;
623 }
624 if ( !image_info )
625 {
626 return;
627 }
628 image_info->next = image_info->next->next;
629 loadcore_internals.module_count -= 1;
630}
631
632ModuleInfo_t *SearchModuleCBByAddr(void *addr)
633{
634 ModuleInfo_t *image_info;
635
636 image_info = loadcore_internals.image_info;
637 while ( image_info )
638 {
639 if ( (unsigned int)addr >= image_info->text_start )
640 {
641 if (
642 (unsigned int)addr
643 < image_info->text_start + image_info->text_size + image_info->data_size + image_info->bss_size )
644 return image_info;
645 }
646 image_info = image_info->next;
647 }
648 return NULL;
649}
650
651int RegisterLibraryEntries(struct irx_export_table *exports)
652{
653 struct irx_export_table *let_next;
654 struct irx_export_table *nexttmp1;
655 struct irx_export_table *next;
656 struct irx_export_table *nexttmp2;
657 iop_library_t **p_mda_next;
658 iop_library_t *nexttmp3;
659 iop_library_t *caller;
660 struct irx_export_table *nexttmp4;
661 struct irx_import_table *nexttmp5;
662 int state;
663
664 if ( !exports || exports->magic != 0x41C00000 )
665 return KE_ILLEGAL_LIBRARY;
666 cCpuSuspendIntr(&state);
667 let_next = (struct irx_export_table *)loadcore_internals.let_next;
668 nexttmp1 = 0;
669 while ( let_next )
670 {
671 if ( IsSameLibrary(exports, let_next) && !compLibMinVersion_major(exports, let_next) )
672 {
673 struct irx_export_table **p_next;
674
675 if ( compLibMinVersion_minor(exports, let_next) <= 0 )
676 {
677 cCpuResumeIntr(state);
678 return KE_LIBRARY_FOUND;
679 }
680 p_next = &let_next->next;
681 next = let_next->next;
682 nexttmp2 = let_next->next;
683 let_next->next = 0;
684 while ( nexttmp2 )
685 {
686 nexttmp2 = next->next;
687 if ( (next->mode & 1) != 0 )
688 {
689 *p_next = next;
690 p_next = &next->next;
691 next->next = 0;
692 }
693 else
694 {
695 next->next = nexttmp1;
696 nexttmp1 = next;
697 }
698 next = nexttmp2;
699 }
700 }
701 let_next = (struct irx_export_table *)let_next->magic;
702 }
703 p_mda_next = &loadcore_internals.mda_next;
704 while ( p_mda_next[1] )
705 {
706 if (
707 !IsLibraryCompliant(exports, (struct irx_export_table *)p_mda_next[1])
708 || compLibMinVersion_major_1(exports, (struct irx_export_table *)p_mda_next[1]) )
709 {
710 p_mda_next = (iop_library_t **)p_mda_next[1];
711 }
712 else
713 {
714 nexttmp3 = p_mda_next[1];
715 caller = (iop_library_t *)nexttmp3->caller;
716 nexttmp3->caller = (struct irx_import_table *)nexttmp1;
717 nexttmp1 = (struct irx_export_table *)p_mda_next[1];
718 p_mda_next[1] = caller;
719 }
720 }
721 exports->next = 0;
722 nexttmp5 = (struct irx_import_table *)nexttmp1;
723 while ( nexttmp1 )
724 {
725 nexttmp4 = nexttmp1->next;
726 aLinkClient(nexttmp5, exports);
727 nexttmp1->next = exports->next;
728 exports->next = nexttmp1;
729 nexttmp1 = nexttmp4;
730 nexttmp5 = (struct irx_import_table *)nexttmp4;
731 }
732 exports->mode &= ~1;
733 exports->magic = (u32)loadcore_internals.let_next;
734 loadcore_internals.let_next = (iop_library_t *)exports;
735 cCpuResumeIntr(state);
736 FlushIcache();
737 return KE_OK;
738}
739
740int RegisterNonAutoLinkEntries(struct irx_export_table *exports)
741{
742 if ( !exports || exports->magic != 0x41C00000 )
743 return KE_ILLEGAL_LIBRARY;
744 exports->mode |= 1;
745 exports->magic = (u32)loadcore_internals.let_next;
746 loadcore_internals.let_next = (iop_library_t *)exports;
747 FlushIcache();
748 return KE_OK;
749}
750
751int ReleaseLibraryEntries(struct irx_export_table *exports)
752{
753 lc_internals_t *lcitmp;
754 struct irx_export_table *let_next;
755 u32 magic;
756 int state;
757
758 cCpuSuspendIntr(&state);
759 lcitmp = &loadcore_internals;
760 let_next = (struct irx_export_table *)loadcore_internals.let_next;
761 while ( let_next && let_next != exports )
762 {
763 lcitmp = (lc_internals_t *)let_next;
764 let_next = (struct irx_export_table *)let_next->magic;
765 }
766 if ( let_next != exports )
767 {
768 cCpuResumeIntr(state);
769 return KE_LIBRARY_NOTFOUND;
770 }
771 if ( exports->next )
772 {
773 cCpuResumeIntr(state);
774 return KE_LIBRARY_INUSE;
775 }
776 magic = exports->magic;
777 exports->next = 0;
778 lcitmp->let_next = (iop_library_t *)magic;
779 exports->magic = 0x41C00000;
780 cCpuResumeIntr(state);
781 return KE_OK;
782}
783
784void *QueryLibraryEntryTable(iop_library_t *library)
785{
786 struct irx_export_table *let_next;
787
788 let_next = (struct irx_export_table *)loadcore_internals.let_next;
789 while ( let_next )
790 {
791 if ( IsLibraryCompliant(let_next, (struct irx_export_table *)library) )
792 {
793 if ( compLibMinVersion_major_1(let_next, (struct irx_export_table *)library) == 0 )
794 return let_next->fptrs;
795 }
796 let_next = (struct irx_export_table *)let_next->magic;
797 }
798 return NULL;
799}
800
801int LinkLibraryEntries(void *addr, int size)
802{
803 unsigned int i;
804
805 for ( i = 0; i < (unsigned int)size >> 2; i += 1 )
806 {
807 struct irx_import_table *importtmp1;
808
809 importtmp1 = (struct irx_import_table *)((u32 *)addr)[i];
810 if ( importtmp1->magic == 0x41E00000 && CheckCallerStub(importtmp1) && (importtmp1->mode & 7) == 0 )
811 {
812 if ( aLinkLibEntries(importtmp1) )
813 {
814 UnLinkLibraryEntries(addr, size);
815 return KE_ERROR;
816 }
817 }
818 }
819 return KE_OK;
820}
821
822int UnLinkLibraryEntries(void *addr, int size)
823{
824 struct irx_import_table *let_next;
825 const struct irx_import_table *nexttmp1;
826 struct irx_import_table *next;
827 struct irx_import_table *magic;
828 struct irx_import_table *p_mda_next;
829 struct irx_import_table *nexttmp2;
830 struct irx_import_table *nexttmp3;
831
832 let_next = (struct irx_import_table *)loadcore_internals.let_next;
833 nexttmp1 = (struct irx_import_table *)((char *)addr + 4 * ((unsigned int)size >> 2));
834 while ( let_next )
835 {
836 next = let_next->next;
837 magic = (struct irx_import_table *)let_next->magic;
838 while ( next )
839 {
840 if ( (u8 *)next >= (u8 *)addr && next < nexttmp1 )
841 {
842 if ( aUnLinkLibEntries(let_next, next) != 0 )
843 return KE_ERROR;
844 next->mode &= ~7;
845 cleanStub(next);
846 }
847 next = next->next;
848 }
849#pragma GCC diagnostic push
850#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
851 if ( (u8 *)let_next >= (u8 *)addr && let_next < nexttmp1 )
852 ReleaseLibraryEntries((void *)let_next);
853#pragma GCC diagnostic pop
854 let_next = magic;
855 }
856 p_mda_next = (struct irx_import_table *)&loadcore_internals.mda_next;
857 while ( p_mda_next->next )
858 {
859 next = p_mda_next->next;
860 if ( next < (struct irx_import_table *)addr || next >= nexttmp1 )
861 {
862 p_mda_next = p_mda_next->next;
863 }
864 else
865 {
866 next->mode &= ~7;
867 cleanStub(p_mda_next->next);
868 nexttmp2 = p_mda_next->next;
869 nexttmp3 = nexttmp2->next;
870 nexttmp2->next = 0;
871 p_mda_next->next = nexttmp3;
872 }
873 }
874 return KE_OK;
875}
876
877lc_internals_t *GetLoadcoreInternalData(void)
878{
879 return &loadcore_internals;
880}
881
882void LockLibraryClient(struct irx_export_table *export)
883{
884 export->mode |= 1;
885}
886
887void UnLockLibraryClient(struct irx_export_table *export)
888{
889 export->mode &= ~1;
890}
891
892int SetRebootTimeLibraryHandlingMode(struct irx_export_table *exports, int mode)
893{
894 struct irx_export_table *let_next;
895 int state;
896
897 if ( !exports )
898 return KE_ILLEGAL_LIBRARY;
899 cCpuSuspendIntr(&state);
900 let_next = (struct irx_export_table *)loadcore_internals.let_next;
901 while ( let_next && let_next->magic )
902 {
903 let_next = (struct irx_export_table *)let_next->magic;
904 }
905 if ( let_next != exports && exports->magic != 0x41C00000 )
906 {
907 cCpuResumeIntr(state);
908 return KE_LIBRARY_NOTFOUND;
909 }
910 exports->mode &= ~6;
911 exports->mode |= (mode & 6);
912 cCpuResumeIntr(state);
913 return KE_OK;
914}
915
916static int IsSameLibrary(const struct irx_export_table *src, const struct irx_export_table *dst)
917{
918 return (*(u32 *)src->name == *(u32 *)dst->name) && (*(u32 *)&src->name[4] == *(u32 *)&dst->name[4]);
919}
920
921static int compLibMinVersion_major(const struct irx_export_table *src, const struct irx_export_table *dst)
922{
923 return ((src->version & 0xFF00) >> 8) - ((dst->version & 0xFF00) >> 8);
924}
925
926static int compLibMinVersion_minor(const struct irx_export_table *src, const struct irx_export_table *dst)
927{
928 return (src->version & 0xFF) - (dst->version & 0xFF);
929}
930
931static int IsLibraryCompliant(const struct irx_export_table *src, const struct irx_export_table *dst)
932{
933 return (*(u32 *)dst->name == *(u32 *)src->name) && (*(u32 *)&dst->name[4] == *(u32 *)&src->name[4]);
934}
935
936static int compLibMinVersion_major_1(const struct irx_export_table *src, const struct irx_export_table *dst)
937{
938 return ((src->version & 0xFF00) >> 8) - ((dst->version & 0xFF00) >> 8);
939}
940
941static void cleanStub(const struct irx_import_table *imp)
942{
943 const void **stubs;
944
945#pragma GCC diagnostic push
946#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
947 stubs = (const void **)(imp->stubs);
948#pragma GCC diagnostic pop
949 while ( stubs[0] && (unsigned int)stubs[1] >> 26 != 9 )
950 {
951 stubs[0] = (void *)0x3E00008;
952 stubs += 2;
953 }
954}
955
956static int CheckCallerStub(const struct irx_import_table *imp)
957{
958 const void **stubs;
959
960 if ( imp->magic != 0x41E00000 )
961 return 0;
962#pragma GCC diagnostic push
963#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
964 stubs = (const void **)(imp->stubs);
965#pragma GCC diagnostic pop
966 while ( stubs[0] && (unsigned int)stubs[1] >> 26 == 9
967 && (stubs[0] == (void *)0x3E00008 || (unsigned int)(stubs[0]) >> 26 == 2) )
968 {
969 stubs += 2;
970 }
971 if ( stubs[0] || stubs[1] )
972 return 0;
973 return (const void **)(imp->stubs) < stubs;
974}
975
976static int aLinkLibEntries(struct irx_import_table *imp)
977{
978 iop_library_t *let_next;
979
980 let_next = loadcore_internals.let_next;
981#pragma GCC diagnostic push
982#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
983 while (
984 let_next
985 && ((let_next->flags & 1) != 0 || !IsLibraryCompliant((struct irx_export_table *)let_next, (struct irx_export_table *)imp) || compLibMinVersion_major_1((struct irx_export_table *)let_next, (struct irx_export_table *)imp)) )
986 {
987 let_next = let_next->prev;
988 }
989#pragma GCC diagnostic pop
990 if ( !let_next )
991 return KE_ERROR;
992 aLinkClient(imp, (const struct irx_export_table *)let_next);
993 imp->next = let_next->caller;
994 let_next->caller = imp;
995 FlushIcache();
996 return KE_OK;
997}
998
999static void aLinkClient(struct irx_import_table *imp, const struct irx_export_table *exp)
1000{
1001 void **stubs;
1002 unsigned int fptrs_count;
1003 const void **fptrs;
1004
1005#pragma GCC diagnostic push
1006#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
1007 stubs = imp->stubs;
1008#pragma GCC diagnostic pop
1009 fptrs_count = 0;
1010 fptrs = (const void **)exp->fptrs;
1011 while ( fptrs[fptrs_count] )
1012 {
1013 fptrs_count += 1;
1014 }
1015 for ( ; *stubs; stubs += 2 )
1016 {
1017 unsigned int stubtmp;
1018
1019 stubtmp = (u16)(uiptr)stubs[1];
1020 if ( (unsigned int)stubs[1] >> 26 != 9 )
1021 break;
1022 *stubs =
1023 (void *)(stubtmp >= fptrs_count ? 0x3E00008 : (((unsigned int)fptrs[stubtmp] >> 2) & 0x3FFFFFF) | 0x8000000);
1024 }
1025 imp->mode &= ~6;
1026 imp->mode |= 2;
1027}
1028
1029static int aUnLinkLibEntries(struct irx_import_table *a1, const struct irx_import_table *a2)
1030{
1031 struct irx_import_table *next;
1032 struct irx_import_table *nexttmp1;
1033
1034 next = a1->next;
1035 if ( next == a2 )
1036 {
1037 a1->next = a2->next;
1038 return KE_OK;
1039 }
1040 while ( next->next )
1041 {
1042 nexttmp1 = next->next;
1043 if ( nexttmp1 == a2 )
1044 {
1045 next->next = nexttmp1->next;
1046 nexttmp1->next = 0;
1047 return KE_OK;
1048 }
1049 if ( !nexttmp1->next )
1050 break;
1051 next = nexttmp1;
1052 }
1053 return KE_ERROR;
1054}
1055
1056static void lc_memset32(int *b, int c, int len)
1057{
1058 int i;
1059 for ( i = 0; i < len; i += 1 )
1060 {
1061 b[i] = c;
1062 }
1063}
1064
1065static int lc_strlen(const char *s)
1066{
1067 int len;
1068
1069 len = 0;
1070 if ( !s )
1071 return 0;
1072 while ( s[len] )
1073 len += 1;
1074 return len;
1075}
1076
1077static void lc_memmove(char *dst, const char *src, int len)
1078{
1079 if ( dst )
1080 {
1081 if ( dst < src )
1082 {
1083 char *v3;
1084
1085 v3 = dst;
1086
1087 for ( ; len > 0; v3 += 1 )
1088 {
1089 *v3 = *src;
1090 src += 1;
1091 len -= 1;
1092 }
1093 }
1094 else
1095 {
1096 int i;
1097 char *v5;
1098 char v6;
1099
1100 for ( i = len - 1; i >= 0; *v5 = v6 )
1101 {
1102 v5 = &dst[i];
1103 v6 = src[i];
1104 i -= 1;
1105 }
1106 }
1107 }
1108}
1109
1110static int cCpuSuspendIntr(int *state)
1111{
1112 intrman_callbacks_t *intrman_callbacks = (intrman_callbacks_t *)(loadcore_internals.intr_suspend_tbl);
1113 if ( intrman_callbacks && intrman_callbacks->cbCpuSuspendIntr )
1114 return intrman_callbacks->cbCpuSuspendIntr(state);
1115 else
1116 return 0;
1117}
1118
1119static int cCpuResumeIntr(int state)
1120{
1121 intrman_callbacks_t *intrman_callbacks = (intrman_callbacks_t *)(loadcore_internals.intr_suspend_tbl);
1122 if ( intrman_callbacks && intrman_callbacks->cbCpuResumeIntr )
1123 return intrman_callbacks->cbCpuResumeIntr(state);
1124 else
1125 return 0;
1126}
1127
1128#if 0
1129static int cQueryIntrContext(void)
1130{
1131 intrman_callbacks_t *intrman_callbacks = (intrman_callbacks_t *)(loadcore_internals.intr_suspend_tbl);
1132 if ( intrman_callbacks && intrman_callbacks->cbQueryIntrContext )
1133 return intrman_callbacks->cbQueryIntrContext();
1134 else
1135 return 0;
1136}
1137#endif
1138
1139int ProbeExecutableObject(void *image, FileInfo_t *result)
1140{
1141 const struct scnhdr *COFF_ScnHdr;
1142 const AOUTHDR *COFF_AoutHdr;
1143 const struct iopmod *iopmod;
1144
1145 COFF_AoutHdr = (AOUTHDR *)((unsigned int)image + sizeof(struct coff_filehdr));
1146 COFF_ScnHdr = (struct scnhdr *)((unsigned int)image + sizeof(struct coff_filehdr) + sizeof(AOUTHDR));
1147 if (
1148 ((struct coff_filehdr *)image)->f_magic == MIPSELMAGIC && COFF_AoutHdr->magic == OMAGIC
1149 && ((struct coff_filehdr *)image)->f_nscns < 0x20 && (((struct coff_filehdr *)image)->f_opthdr == 0x38)
1150 && ((((struct coff_filehdr *)image)->f_flags & 0x2) != 0) && COFF_ScnHdr->s_paddr == COFF_AoutHdr->text_start )
1151 {
1152 if ( COFF_AoutHdr->vstamp != 0x7001 )
1153 {
1154 result->ModuleType = IOP_MOD_TYPE_COFF;
1155 result->EntryPoint = (void *)COFF_AoutHdr->entry;
1156 result->gp = (void *)COFF_AoutHdr->gp_value;
1157 result->text_start = (void *)COFF_AoutHdr->text_start;
1158 result->text_size = COFF_AoutHdr->tsize;
1159 result->data_size = COFF_AoutHdr->dsize;
1160 result->bss_size = COFF_AoutHdr->bsize;
1161 result->MemSize = COFF_AoutHdr->bss_start + COFF_AoutHdr->bsize - COFF_AoutHdr->text_start;
1162 result->mod_id = COFF_AoutHdr->mod_id;
1163
1164 return result->ModuleType;
1165 }
1166 }
1167 else
1168 {
1169 const elf_header_t *ELF_Hdr;
1170 const elf_pheader_t *ELF_phdr;
1171
1172 ELF_Hdr = image;
1173 ELF_phdr = (elf_pheader_t *)((unsigned int)image + ELF_Hdr->phoff);
1174
1175 if (
1176 ((unsigned short int *)ELF_Hdr->ident)[2] == 0x101 && ELF_Hdr->machine == 8
1177 && ELF_Hdr->phentsize == sizeof(elf_pheader_t) && ELF_Hdr->phnum == 2
1178 && (ELF_phdr->type == (SHT_LOPROC | SHT_LOPROC_IOPMOD))
1179 && (ELF_Hdr->type == ET_SCE_IOPRELEXEC || ELF_Hdr->type == ET_SCE_IOPRELEXEC2 || ELF_Hdr->type == ET_EXEC) )
1180 {
1181 result->ModuleType = (ELF_Hdr->type == ET_SCE_IOPRELEXEC || ELF_Hdr->type == ET_SCE_IOPRELEXEC2) ?
1182 IOP_MOD_TYPE_IRX :
1183 IOP_MOD_TYPE_ELF;
1184
1185 iopmod = (struct iopmod *)((unsigned int)image + ELF_phdr->offset);
1186 result->EntryPoint = (void *)iopmod->EntryPoint;
1187 result->gp = (void *)iopmod->gp;
1188 result->text_start = (void *)ELF_phdr[1].vaddr;
1189 result->text_size = iopmod->text_size;
1190 result->data_size = iopmod->data_size;
1191 result->bss_size = iopmod->bss_size;
1192 result->MemSize = ELF_phdr[1].memsz;
1193 result->mod_id = iopmod->mod_id;
1194
1195 return result->ModuleType;
1196 }
1197 }
1198 return KE_ERROR;
1199}
1200
1201// cppcheck-suppress constParameterPointer
1202int LoadExecutableObject(void *image, FileInfo_t *fi)
1203{
1204 switch ( fi->ModuleType )
1205 {
1206 case IOP_MOD_TYPE_ELF:
1207 loadelf(image);
1208 break;
1209 case IOP_MOD_TYPE_COFF:
1210 loadcoff(image);
1211 break;
1212 case IOP_MOD_TYPE_IRX:
1213 loadrelelf(image, fi);
1214 break;
1215 default:
1216 return KE_ERROR;
1217 }
1218
1219 CopyModInfo(fi, (void *)((u8 *)(fi->text_start) - 0x30));
1220
1221 return KE_OK;
1222}
1223
1224void CopyModInfo(FileInfo_t *fi, ModuleInfo_t *mi)
1225{
1226 mi->next = 0;
1227 mi->name = 0;
1228 mi->version = 0;
1229 mi->newflags = 0;
1230 mi->id = 0;
1231 mi->flags = 0;
1232 if ( fi->mod_id != (IopModuleID_t *)0xFFFFFFFF )
1233 {
1234 mi->name = (char *)(fi->mod_id->name);
1235 mi->version = fi->mod_id->version;
1236 }
1237 mi->entry = (u32)fi->EntryPoint;
1238 mi->gp = (u32)fi->gp;
1239 mi->text_start = (u32)fi->text_start;
1240 mi->text_size = fi->text_size;
1241 mi->data_size = fi->data_size;
1242 mi->bss_size = fi->bss_size;
1243}
1244
1245static void loadcoff(const void *module)
1246{
1247 const AOUTHDR *COFF_AoutHdr;
1248 const struct scnhdr *ScnHdr;
1249
1250 COFF_AoutHdr = (AOUTHDR *)((u8 *)module + sizeof(struct coff_filehdr));
1251 ScnHdr = (struct scnhdr *)((u8 *)module + sizeof(struct coff_filehdr) + sizeof(AOUTHDR));
1252
1253 CopySection((void *)((u8 *)module + ScnHdr[0].s_size), (void *)COFF_AoutHdr->text_start, COFF_AoutHdr->tsize);
1254 CopySection((void *)((u8 *)module + COFF_AoutHdr->tsize), (void *)COFF_AoutHdr->data_start, COFF_AoutHdr->dsize);
1255
1256 if ( COFF_AoutHdr->bss_start != 0 && COFF_AoutHdr->bsize != 0 )
1257 {
1258 ZeroSection((unsigned int *)COFF_AoutHdr->bss_start, COFF_AoutHdr->bsize >> 2);
1259 }
1260}
1261
1262static void loadelf(const void *module)
1263{
1264 const elf_header_t *ELF_Hdr;
1265 const elf_pheader_t *ELF_phdr;
1266
1267 ELF_Hdr = module;
1268 ELF_phdr = (elf_pheader_t *)((u8 *)ELF_Hdr + ELF_Hdr->phoff);
1269
1270 CopySection((void *)((u8 *)module + ELF_phdr[1].offset), (void *)ELF_phdr[1].vaddr, ELF_phdr[1].filesz);
1271
1272 if ( ELF_phdr[1].filesz < ELF_phdr[1].memsz )
1273 {
1274 ZeroSection(
1275 (unsigned int *)((u8 *)(ELF_phdr[1].vaddr) + ELF_phdr[1].filesz), (ELF_phdr[1].memsz - ELF_phdr[1].filesz) >> 2);
1276 }
1277}
1278
1279static void loadrelelf(const void *module, FileInfo_t *ModuleInfo)
1280{
1281 const elf_header_t *ELF_hdr;
1282 const elf_pheader_t *ELF_phdr;
1283 const elf_shdr_t *ELF_shdr, *CurrentELF_shdr;
1284 unsigned int NumRelocs, SectionNum;
1285
1286 ELF_hdr = (elf_header_t *)module;
1287 ELF_phdr = (elf_pheader_t *)((u8 *)module + ELF_hdr->phoff);
1288
1289 ModuleInfo->gp = (void *)((u8 *)ModuleInfo->gp + (unsigned int)ModuleInfo->text_start);
1290 ModuleInfo->EntryPoint = (void *)((u8 *)ModuleInfo->EntryPoint + (unsigned int)ModuleInfo->text_start);
1291
1292 if ( ModuleInfo->mod_id != (void *)0xFFFFFFFF )
1293 {
1294 ModuleInfo->mod_id = (IopModuleID_t *)((u8 *)ModuleInfo->mod_id + (unsigned int)ModuleInfo->text_start);
1295 }
1296
1297 ELF_shdr = (elf_shdr_t *)((u8 *)module + ELF_hdr->shoff);
1298
1299 CopySection((void *)((u8 *)module + ELF_phdr[1].offset), ModuleInfo->text_start, ELF_phdr[1].filesz);
1300
1301 if ( ELF_phdr[1].filesz < ELF_phdr[1].memsz )
1302 {
1303 ZeroSection(
1304 (unsigned int *)((u8 *)(ModuleInfo->text_start) + ELF_phdr[1].filesz),
1305 (ELF_phdr[1].memsz - ELF_phdr[1].filesz) >> 2);
1306 }
1307
1308 for ( SectionNum = 0, CurrentELF_shdr = ELF_shdr + 1; SectionNum < ELF_hdr->shnum;
1309 SectionNum += 1, CurrentELF_shdr += 1 )
1310 {
1311 if ( CurrentELF_shdr->type == SHT_REL )
1312 {
1313 u32 entsize;
1314 entsize = CurrentELF_shdr->entsize;
1315 if ( !entsize )
1316 __builtin_trap();
1317 NumRelocs = CurrentELF_shdr->size / entsize;
1318 ApplyElfRelSection(ModuleInfo->text_start, (const elf_rel *)((u8 *)module + CurrentELF_shdr->offset), NumRelocs);
1319 }
1320 }
1321}
1322
1323void ApplyElfRelSection(void *buffer, const void *module, int element_count)
1324{
1325 u32 startaddr;
1326 int i;
1327 const elf_rel *ELF_relocation;
1328
1329 startaddr = (u32)buffer;
1330 ELF_relocation = module;
1331 for ( i = 0; i < element_count; i += 1 )
1332 {
1333 u32 *datal;
1334 u32 datai;
1335 int daddr;
1336
1337 datal = (u32 *)((u8 *)buffer + ELF_relocation[i].offset);
1338 switch ( ELF_relocation[i].info & 0xFF )
1339 {
1340 case R_MIPS_16:
1341 datai = startaddr + (s16) * (u32 *)datal;
1342 *(u32 *)datal &= 0xFFFF0000;
1343 *(u32 *)datal |= (u16)datai;
1344 break;
1345 case R_MIPS_32:
1346 *(u32 *)datal += startaddr;
1347 break;
1348 case R_MIPS_26:
1349 datai = startaddr + ((ELF_relocation[i].offset & 0xF0000000) | (4 * (*(u32 *)datal & 0x3FFFFFF)));
1350 *(u32 *)datal &= 0xFC000000;
1351 *(u32 *)datal |= datai << 4 >> 6;
1352 break;
1353 case R_MIPS_HI16:
1354 datai = startaddr + (s16) * (u32 *)((u8 *)buffer + ELF_relocation[i + 1].offset) + (*(u32 *)datal << 16);
1355 *(u32 *)datal &= 0xFFFF0000;
1356 *(u32 *)datal |= (u16)(((datai >> 15) + 1) >> 1);
1357 break;
1358 case R_MIPS_LO16:
1359 datai = (startaddr + *(u32 *)datal) & 0xFFFF;
1360 *(u32 *)datal &= 0xFFFF0000;
1361 *(u32 *)datal |= datai;
1362 break;
1363 case R_MIPSSCE_MHI16:
1364 datai = ((((startaddr + ELF_relocation[i + 1].offset) >> 15) + 1) >> 1) & 0xFFFF;
1365 for ( daddr = 1; daddr != 0; datal += daddr )
1366 {
1367 daddr = *(u16 *)datal << 16 >> 14;
1368 *(u32 *)datal &= 0xFFFF0000;
1369 *(u32 *)datal |= datai;
1370 }
1371 i += 1;
1372 break;
1373 default:
1374 break;
1375 }
1376 }
1377}
1378
1379static void CopySection(const void *module, void *buffer, unsigned int FileSize)
1380{
1381 unsigned int *dst;
1382 const unsigned int *src;
1383 const void *src_end;
1384
1385 dst = buffer;
1386 src = module;
1387 src_end = (const void *)((unsigned int)module + (FileSize >> 2 << 2));
1388 while ( (unsigned int)src < (unsigned int)src_end )
1389 {
1390 *dst = *src;
1391 src += 1;
1392 dst += 1;
1393 }
1394}
1395
1396static void ZeroSection(unsigned int *buffer, unsigned int NumWords)
1397{
1398 while ( NumWords > 0 )
1399 {
1400 *buffer = 0;
1401 NumWords -= 1;
1402 buffer += 1;
1403 }
1404}
1405
1406// clang-format off
1407__asm__ (
1408 "\t" ".set push" "\n"
1409 "\t" ".set noat" "\n"
1410 "\t" ".set noreorder" "\n"
1411 "\t" ".global FlushIcache" "\n"
1412 "\t" "FlushIcache:" "\n"
1413 "\t" " mfc0 $t0, $12" "\n"
1414 "\t" " nop" "\n"
1415 "\t" " lui $t4, %hi(FlushIcache_inner)" "\n"
1416 "\t" " addiu $t4, $t4, %lo(FlushIcache_inner)" "\n"
1417 "\t" " lui $at, (0xA0000000 >> 16)" "\n"
1418 "\t" " or $t4, $t4, $at" "\n"
1419 "\t" " jr $t4" "\n"
1420 "\t" "FlushIcache_inner:" "\n"
1421 "\t" " mtc0 $zero, $12" "\n"
1422 "\t" " nop" "\n"
1423 "\t" " nop" "\n"
1424 "\t" " lui $t6, 0xBF80" "\n"
1425 "\t" " lw $t6, (0xBF801450 & 0xFFFF)($t6)" "\n"
1426 "\t" " nop" "\n"
1427 "\t" " addiu $t7, $zero, -0x2" "\n"
1428 "\t" " and $t1, $t6, $t7" "\n"
1429 "\t" " lui $at, 0xBF80" "\n"
1430 "\t" " sw $t1, (0xBF801450 & 0xFFFF)($at)" "\n"
1431 "\t" " lui $at, 0xBF80" "\n"
1432 "\t" " lw $zero, (0xBF801450 & 0xFFFF)($at)" "\n"
1433 "\t" " lui $t7, 0xBF80" "\n"
1434 "\t" " lw $t7, (0xBF801578 & 0xFFFF)($t7)" "\n"
1435 "\t" " lui $at, 0xBF80" "\n"
1436 "\t" " sw $zero, (0xBF801578 & 0xFFFF)($at)" "\n"
1437 "\t" " lui $at, 0xBF80" "\n"
1438 "\t" " lw $zero, (0xBF801578 & 0xFFFF)($at)" "\n"
1439 "\t" " lui $t5, (0xFFFE0130 >> 16)" "\n"
1440 "\t" " lw $t5, (0xFFFE0130 & 0xFFFF)($t5)" "\n"
1441 "\t" " addiu $t1, $zero, 0xC04" "\n"
1442 "\t" " lui $at, (0xFFFE0130 >> 16)" "\n"
1443 "\t" " sw $t1, (0xFFFE0130 & 0xFFFF)($at)" "\n"
1444 "\t" " lui $t4, (0x10000 >> 16)" "\n"
1445 "\t" " mtc0 $t4, $12" "\n"
1446 "\t" " nop" "\n"
1447 "\t" " nop" "\n"
1448 "\t" " addiu $t2, $zero, 0x0" "\n"
1449 "\t" " addiu $t3, $zero, 0xF80" "\n"
1450 "\t" ".LFlushIcache_1:" "\n"
1451 "\t" " sw $zero, 0x0($t2)" "\n"
1452 "\t" " sw $zero, 0x10($t2)" "\n"
1453 "\t" " sw $zero, 0x20($t2)" "\n"
1454 "\t" " sw $zero, 0x30($t2)" "\n"
1455 "\t" " sw $zero, 0x40($t2)" "\n"
1456 "\t" " sw $zero, 0x50($t2)" "\n"
1457 "\t" " sw $zero, 0x60($t2)" "\n"
1458 "\t" " sw $zero, 0x70($t2)" "\n"
1459 "\t" " bne $t2, $t3, .LFlushIcache_1" "\n"
1460 "\t" " addi $t2, $t2, 0x80" "\n"
1461 "\t" " mtc0 $zero, $12" "\n"
1462 "\t" " nop" "\n"
1463 "\t" " lui $at, (0xFFFE0130 >> 16)" "\n"
1464 "\t" " sw $t5, (0xFFFE0130 & 0xFFFF)($at)" "\n"
1465 "\t" " lui $at, (0xFFFE0130 >> 16)" "\n"
1466 "\t" " lw $zero, (0xFFFE0130 & 0xFFFF)($at)" "\n"
1467 "\t" " nop" "\n"
1468 "\t" " lui $at, 0xBF80" "\n"
1469 "\t" " sw $t7, (0xBF801578 & 0xFFFF)($at)" "\n"
1470 "\t" " lui $at, 0xBF80" "\n"
1471 "\t" " lw $zero, (0xBF801578 & 0xFFFF)($at)" "\n"
1472 "\t" " lui $at, 0xBF80" "\n"
1473 "\t" " sw $t6, (0xBF801450 & 0xFFFF)($at)" "\n"
1474 "\t" " lui $at, 0xBF80" "\n"
1475 "\t" " lw $zero, (0xBF801450 & 0xFFFF)($at)" "\n"
1476 "\t" " mtc0 $t0, $12" "\n"
1477 "\t" " nop" "\n"
1478 "\t" " jr $ra" "\n"
1479 "\t" " nop" "\n"
1480 "\t" ".set pop" "\n"
1481);
1482
1483__asm__ (
1484 "\t" ".set push" "\n"
1485 "\t" ".set noat" "\n"
1486 "\t" ".set noreorder" "\n"
1487 "\t" ".global FlushDcache" "\n"
1488 "\t" "FlushDcache:" "\n"
1489 "\t" " mfc0 $t0, $12" "\n"
1490 "\t" " nop" "\n"
1491 "\t" " lui $t4, %hi(FlushDcache_inner)" "\n"
1492 "\t" " addiu $t4, $t4, %lo(FlushDcache_inner)" "\n"
1493 "\t" " lui $at, (0xA0000000 >> 16)" "\n"
1494 "\t" " or $t4, $t4, $at" "\n"
1495 "\t" " jr $t4" "\n"
1496 "\t" "FlushDcache_inner:" "\n"
1497 "\t" " mtc0 $zero, $12" "\n"
1498 "\t" " nop" "\n"
1499 "\t" " nop" "\n"
1500 "\t" " lui $t6, 0xBF80" "\n"
1501 "\t" " lw $t6, (0xBF801450 & 0xFFFF)($t6)" "\n"
1502 "\t" " nop" "\n"
1503 "\t" " addiu $t7, $zero, -0x2" "\n"
1504 "\t" " and $t1, $t6, $t7" "\n"
1505 "\t" " lui $at, 0xBF80" "\n"
1506 "\t" " sw $t1, (0xBF801450 & 0xFFFF)($at)" "\n"
1507 "\t" " lui $at, 0xBF80" "\n"
1508 "\t" " lw $zero, (0xBF801450 & 0xFFFF)($at)" "\n"
1509 "\t" " lui $t7, 0xBF80" "\n"
1510 "\t" " lw $t7, (0xBF801578 & 0xFFFF)($t7)" "\n"
1511 "\t" " lui $at, 0xBF80" "\n"
1512 "\t" " sw $zero, (0xBF801578 & 0xFFFF)($at)" "\n"
1513 "\t" " lui $at, 0xBF80" "\n"
1514 "\t" " lw $zero, (0xBF801578 & 0xFFFF)($at)" "\n"
1515 "\t" " lui $t5, (0xFFFE0130 >> 16)" "\n"
1516 "\t" " lw $t5, (0xFFFE0130 & 0xFFFF)($t5)" "\n"
1517 "\t" " addiu $t1, $zero, 0xC4" "\n"
1518 "\t" " lui $at, (0xFFFE0130 >> 16)" "\n"
1519 "\t" " sw $t1, (0xFFFE0130 & 0xFFFF)($at)" "\n"
1520 "\t" " lui $t4, (0x10000 >> 16)" "\n"
1521 "\t" " mtc0 $t4, $12" "\n"
1522 "\t" " nop" "\n"
1523 "\t" " nop" "\n"
1524 "\t" " addiu $t2, $zero, 0x0" "\n"
1525 "\t" " addiu $t3, $zero, 0x380" "\n"
1526 "\t" ".LFlushDcache_1:" "\n"
1527 "\t" " sw $zero, 0x0($t2)" "\n"
1528 "\t" " sw $zero, 0x10($t2)" "\n"
1529 "\t" " sw $zero, 0x20($t2)" "\n"
1530 "\t" " sw $zero, 0x30($t2)" "\n"
1531 "\t" " sw $zero, 0x40($t2)" "\n"
1532 "\t" " sw $zero, 0x50($t2)" "\n"
1533 "\t" " sw $zero, 0x60($t2)" "\n"
1534 "\t" " sw $zero, 0x70($t2)" "\n"
1535 "\t" " bne $t2, $t3, .LFlushDcache_1" "\n"
1536 "\t" " addi $t2, $t2, 0x80" "\n"
1537 "\t" " mtc0 $zero, $12" "\n"
1538 "\t" " nop" "\n"
1539 "\t" " lui $at, (0xFFFE0130 >> 16)" "\n"
1540 "\t" " sw $t5, (0xFFFE0130 & 0xFFFF)($at)" "\n"
1541 "\t" " lui $at, (0xFFFE0130 >> 16)" "\n"
1542 "\t" " lw $zero, (0xFFFE0130 & 0xFFFF)($at)" "\n"
1543 "\t" " nop" "\n"
1544 "\t" " lui $at, 0xBF80" "\n"
1545 "\t" " sw $t7, (0xBF801578 & 0xFFFF)($at)" "\n"
1546 "\t" " lui $at, 0xBF80" "\n"
1547 "\t" " lw $zero, (0xBF801578 & 0xFFFF)($at)" "\n"
1548 "\t" " lui $at, 0xBF80" "\n"
1549 "\t" " sw $t6, (0xBF801450 & 0xFFFF)($at)" "\n"
1550 "\t" " lui $at, 0xBF80" "\n"
1551 "\t" " lw $zero, (0xBF801450 & 0xFFFF)($at)" "\n"
1552 "\t" " mtc0 $t0, $12" "\n"
1553 "\t" " nop" "\n"
1554 "\t" " jr $ra" "\n"
1555 "\t" " nop" "\n"
1556 "\t" ".set pop" "\n"
1557);
1558
1559__asm__ (
1560 "\t" ".set push" "\n"
1561 "\t" ".set noat" "\n"
1562 "\t" ".set noreorder" "\n"
1563 "\t" ".global SetCacheCtrl" "\n"
1564 "\t" "SetCacheCtrl:" "\n"
1565 "\t" " mfc0 $t0, $12" "\n"
1566 "\t" " nop" "\n"
1567 "\t" " lui $t4, %hi(SetCacheCtrl_inner)" "\n"
1568 "\t" " addiu $t4, $t4, %lo(SetCacheCtrl_inner)" "\n"
1569 "\t" " lui $at, (0xA0000000 >> 16)" "\n"
1570 "\t" " or $t4, $t4, $at" "\n"
1571 "\t" " jr $t4" "\n"
1572 "\t" "SetCacheCtrl_inner:" "\n"
1573 "\t" " mtc0 $zero, $12" "\n"
1574 "\t" " nop" "\n"
1575 "\t" " lui $at, (0xFFFE0130 >> 16)" "\n"
1576 "\t" " sw $a0, (0xFFFE0130 & 0xFFFF)($at)" "\n"
1577 "\t" " lui $at, (0xFFFE0130 >> 16)" "\n"
1578 "\t" " lw $zero, (0xFFFE0130 & 0xFFFF)($at)" "\n"
1579 "\t" " nop" "\n"
1580 "\t" " mtc0 $t0, $12" "\n"
1581 "\t" " nop" "\n"
1582 "\t" " jr $ra" "\n"
1583 "\t" " nop" "\n"
1584 "\t" ".set pop" "\n"
1585);
1586// clang-format on
unsigned int version
Definition fileXio.h:3
ModuleInfo_t * image_info
Definition loadcore.h:82
u16 newflags
Definition loadcore.h:36
Definition loadcore.h:100