11#include "irx_imports.h"
17IRX_ID(
"Moldule_File_loader", 2, 9);
23static SecrCardBootFile_callback_t SecrCardBootFile_func_ptr;
24static SecrDiskBootFile_callback_t SecrDiskBootFile_func_ptr;
25static SetLoadfileCallbacks_callback_t SetLoadfileCallbacks_func_ptr;
26static CheckKelfPath_callback_t CheckKelfPath_func_ptr;
29static int ModuleLoaderMutex;
30static int ModuleLoaderSync;
150 R_MIPSSCE_MHI16 = 250,
151 R_MIPSSCE_ADDEND = 251,
161#define SHT_LOPROC 0x70000000
162#define SHT_LOPROC_EE_IMPORT_TAB 0x90
163#define SHT_LOPROC_IOPMOD 0x80
164#define SHT_HIPROC 0x7fffffff
165#define SHT_LOUSER 0x80000000
166#define SHT_HIUSER 0xffffffff
170#define SHF_EXECINSTR 0x4
171#define SHF_MASKPROC 0xf0000000
176 int (*cbCpuSuspendIntr)(
int *state);
178 int (*cbCpuResumeIntr)(
int state);
180 int (*cbQueryIntrContext)(void);
183static ModuleInfo_t *search_for_module_by_name(
const char *name);
186static int linked_list_next_is_self(
const modload_ll_t *ll);
188static void get_updater_boot_argument(
char *str,
int *updater_argc,
char **updater_argv,
int updater_argv_count);
189static int spGetfsize(
void *userdata,
int in_fd);
190static int spLseek(
void *userdata,
int in_fd,
long offset,
int whence);
191static int spRead(
void *userdata,
int in_fd,
void *buffer,
size_t read_size);
192static int spBread(
void *opt,
int fd,
size_t nbyte);
193static int spSetBufSize(
void *opt,
int fd,
size_t size);
194static int spClose(
void *userdata,
int in_fd);
195static int spAfterOpen(
void *opt,
int fd);
196static int spBeforeOpen(
void *opt,
const char *filename,
int flag);
197static int spOpen(
LDfilefunc *functbl,
void *userdata,
const char *filename,
int filemode);
198static void free_module_block(
modload_ll_t *buf,
char flags);
201do_load_from_buffer(
void *buffer,
int position,
int *distaddr,
unsigned int distoffset,
int *result_out);
203 LDfilefunc *functbl,
void *userdata,
int module_fd,
int read_offset,
void *buf,
int read_size,
int *result_out);
204static void *read_entire_loadfile(
205 LDfilefunc *functbl,
void *userdata,
int module_fd,
int *result_out,
int module_filesize,
int memory_region);
206static int open_loadfile(
LDfilefunc *functbl,
void *userdata,
const char *filename,
int *out_filesize);
210stop_module(
ModuleInfo_t *module_info,
int command,
int modid_2,
int arglen,
const char *args,
int *result_out);
211static int start_module(
ModuleInfo_t *module_info,
const char *data,
int arglen,
const char *args,
int *result_out);
215static int allocate_module_block(
220 unsigned int distoffset,
223static void ExecModuleLoad(
void *userdata);
227static LDfilefunc default_filefunc_functable = {
228 &spBeforeOpen, &spAfterOpen, &spClose, &spSetBufSize, &spBread, &spRead, &spLseek, &spGetfsize};
230int _start(
int argc,
char *argv[])
239 if ( RegisterLibraryEntries(&_exp_modload) < 0 )
246 BootMode_4 = QueryBootMode(4);
249 if ( (((u32 *)BootMode_4)[0] & 0xff) == 2 )
251 AddRebootNotifyHandler((BootupCallback_t)modload_post_boot_callback, 1, 0);
258 sysmem_module = search_for_module_by_name(
"System_Memory_Manager");
259 if ( sysmem_module && sysmem_module->version >= 0x201u )
261 GetSysmemInternalData()->intr_suspend_tbl = (
void *)&intrman_callbacks;
263 loadcore_module = search_for_module_by_name(
"Module_Manager");
264 if ( loadcore_module )
266 if ( loadcore_module->version >= 0x205u )
268 GetLoadcoreInternalData()->intr_suspend_tbl = (
void *)&intrman_callbacks;
272 thparam.attr = 0x2000000;
273 thparam.thread = ExecModuleLoad;
274 thparam.priority = 8;
275 thparam.stacksize = 4096;
277 modLoadCB = CreateThread(&thparam);
279 semaparam.initial = 1;
281 semaparam.option = 0;
282 ModuleLoaderMutex = CreateSema(&semaparam);
283 memset(&efparam, 0,
sizeof(efparam));
284 ModuleLoaderSync = CreateEventFlag(&efparam);
285 linked_list_set_self(&load_memory_ll);
289void *AllocLoadMemory(
int type,
unsigned int size,
void *addr)
296 memset(newbuf, -1, 32);
297 linked_list_set_self(&newbuf->ll[2]);
299 linked_list_add_after(&load_memory_ll, newbuf->ll);
303int FreeLoadMemory(
void *in_area)
311 if ( check_in_linked_list(area->ll) )
315 else if ( !linked_list_next_is_self(&area->ll[2]) )
321 linked_list_remove(area->ll);
322 ret = FreeSysMemory(area);
328int SetModuleFlags(
int modid,
int flag)
335 return KE_ILLEGAL_CONTEXT;
337 if ( (flag & 0xFFFFFFBF) != 0 )
339 return KE_ILLEGAL_FLAG;
342 image_info = GetLoadcoreInternalData()->
image_info;
343 while ( image_info && modid != image_info->id )
345 image_info = image_info->next;
350 return KE_UNKNOWN_MODULE;
357int LoadModuleWithOption(
const char *filename,
const LMWOoption *option)
362 if ( (
unsigned int)option->position >= 3 )
363 return KE_ILLEGAL_POSITION;
364 switch ( option->access )
371 return KE_ILLEGAL_ACCESS;
374 mltargs.position = option->position;
375 mltargs.filename = filename;
377 mltargs.access = option->access & 0xFF;
378 mltargs.distaddr = option->distaddr;
379 mltargs.distoffset = option->distoffset;
380 functable = option->functable;
382 functable = &default_filefunc_functable;
383 mltargs.functable = functable;
384 mltargs.funcopt = option->funcopt;
385 return ModuleLoaderThread(&mltargs);
388int LoadModuleAddress(
const char *name,
void *addr,
int offset)
394 mltargs.position = 2;
396 mltargs.position = 0;
398 mltargs.filename = name;
400 mltargs.distaddr = addr;
401 mltargs.distoffset = offset;
402 mltargs.functable = &default_filefunc_functable;
404 return ModuleLoaderThread(&mltargs);
407int LoadModule(
const char *name)
409 return LoadModuleAddress(name, 0, 0);
412int LoadModuleBufferAddress(
void *buffer,
void *addr,
int offset)
418 mltargs.position = 2;
420 mltargs.position = 0;
421 mltargs.buffer = buffer;
423 mltargs.filename = 0;
424 mltargs.distaddr = addr;
425 mltargs.distoffset = offset;
426 return ModuleLoaderThread(&mltargs);
429int LoadModuleBuffer(
void *buffer)
431 return LoadModuleBufferAddress(buffer, 0, 0);
434int LoadStartModule(
const char *name,
int arglen,
const char *args,
int *result)
440 mltargs.filename = name;
441 mltargs.position = 0;
443 mltargs.distaddr = 0;
444 mltargs.distoffset = 0;
445 mltargs.arglen = arglen;
447 mltargs.result = result;
448 mltargs.functable = &default_filefunc_functable;
450 return ModuleLoaderThread(&mltargs);
453int StartModule(
int modid,
const char *name,
int arglen,
const char *args,
int *result)
457 mltargs.modid = modid;
459 mltargs.filename = name;
460 mltargs.arglen = arglen;
462 mltargs.result = result;
463 return ModuleLoaderThread(&mltargs);
466int StopModule(
int modid,
int arglen,
const char *args,
int *result)
473 return KE_ILLEGAL_CONTEXT;
475 modid_2 = SearchModuleByAddress(__builtin_return_address(0));
478 Kprintf(
"StopModule(): panic !!! call from unknown Module !!!\n");
479 return KE_CAN_NOT_STOP;
482 mltargs.modid = modid;
483 mltargs.modid_2 = modid_2;
484 mltargs.filename = 0;
485 mltargs.arglen = arglen;
487 mltargs.result = result;
488 return ModuleLoaderThread(&mltargs);
491int UnloadModule(
int modid)
495 mltargs.modid = modid;
497 mltargs.filename = 0;
501 return ModuleLoaderThread(&mltargs);
504int SelfStopModule(
int arglen,
const char *args,
int *result)
511 return KE_ILLEGAL_CONTEXT;
513 modid = SearchModuleByAddress(__builtin_return_address(0));
516 Kprintf(
"SelfStopModule(): panic !!! call from unknown Module !!!\n");
517 return KE_ILLEGAL_CONTEXT;
520 mltargs.modid = modid;
521 mltargs.modid_2 = modid;
522 mltargs.filename = 0;
523 mltargs.arglen = arglen;
525 mltargs.result = result;
526 return ModuleLoaderThread(&mltargs);
529void SelfUnloadModule(
void)
540 Kprintf(
"SelfUnloadModule(): panic !!! illegal context !!!\n");
542 ThreadId = GetThreadId();
545 Kprintf(
"SelfUnloadModule(): panic !!! can't get ThreadID !!!\n");
547 modid = SearchModuleByAddress(__builtin_return_address(0));
550 Kprintf(
"SelfUnloadModule(): panic !!! call from unknown Module !!!\n");
553 mltargs.modid = modid;
554 mltargs.modid_2 = ThreadId;
555 mltargs.filename = 0;
559 mltargs.ret_ptr = &ret_tmp;
560 if ( ThreadId == modLoadCB )
562 Kprintf(
"SelfUnloadModule(): panic !!! Unexpected case !!!\n");
564 mltargs.thread_ef = ModuleLoaderSync;
565 sema_res = WaitSema(ModuleLoaderMutex);
568 Kprintf(
"SelfUnloadModule(): panic !!! Unload fail semerror=%d !!!\n", sema_res);
570 StartThread(modLoadCB, &mltargs);
571 ChangeThreadPriority(0, 123);
572 WaitEventFlag(ModuleLoaderSync, 1u, 17, &efbits);
573 SignalSema(ModuleLoaderMutex);
574 Kprintf(
"SelfUnloadModule(): panic !!! Unload fail error=%d !!!\n", ret_tmp);
578 Kprintf(
"Thread 0x%x. Unload Fail\n", GetThreadId());
582int SearchModuleByName(
const char *name)
590 for ( i = GetLoadcoreInternalData()->image_info; i; i = i->next )
592 if ( !strcmp(name, i->name) && modid < i->
id )
597 return KE_UNKNOWN_MODULE;
601int SearchModuleByAddress(
const void *addr)
607 image_info = SearchModuleCBByAddr((
void *)addr);
610 return KE_UNKNOWN_MODULE;
611 return image_info->id;
614int LoadStartKelfModule(
const char *name,
int arglen,
const char *args,
int *result)
617 void *iop_exec_buffer;
618 void *iop_exec_encrypted_buffer;
627 functable = &default_filefunc_functable;
628 iop_exec_buffer = NULL;
633 module_fd = open_loadfile(functable, NULL, name, &module_filesize);
638 iop_exec_encrypted_buffer = read_entire_loadfile(functable, NULL, module_fd, &ret_tmp, module_filesize, 1);
639 if ( iop_exec_encrypted_buffer == NULL )
643 if ( CheckKelfPath_func_ptr && CheckKelfPath_func_ptr(name, &card_port, &card_slot) && SecrCardBootFile_func_ptr )
645 iop_exec_buffer = SecrCardBootFile_func_ptr(card_port, card_slot, iop_exec_encrypted_buffer);
647 else if ( SecrDiskBootFile_func_ptr )
649 iop_exec_buffer = SecrDiskBootFile_func_ptr(iop_exec_encrypted_buffer);
651 ret_tmp = KE_ILLEGAL_OBJECT;
652 if ( iop_exec_buffer )
654 ret_tmp = LoadModuleBuffer(iop_exec_buffer);
658 ret_tmp = StartModule(ret_tmp, name, arglen, args, result);
661 FreeSysMemory(iop_exec_encrypted_buffer);
666int GetModuleIdListByName(
const char *name,
int *readbuf,
int readbufsize,
int *modulecount)
676 for ( image_info = GetLoadcoreInternalData()->image_info; image_info; image_info = image_info->next )
680 if ( strcmp(name, image_info->name) != 0 )
683 if ( readbufoffset < readbufsize )
686 readbuf[readbufoffset] = image_info->id;
692 *modulecount = modcount;
693 return readbufoffset;
696int GetModuleIdList(
int *readbuf,
int readbufsize,
int *modulecount)
698 return GetModuleIdListByName(0, readbuf, readbufsize, modulecount);
708 image_info = GetLoadcoreInternalData()->
image_info;
709 while ( image_info && modid != image_info->id )
711 image_info = image_info->next;
716 return KE_UNKNOWN_MODULE;
719 name = image_info->name;
721 strncpy(status->name, name, 56);
722 status->name[55] = 0;
723 status->version = image_info->version;
724 status->id = image_info->id;
725 status->flags = image_info->
newflags;
726 status->entry_addr = image_info->
entry;
727 status->gp_value = image_info->gp;
728 status->text_addr = image_info->text_start;
729 status->text_size = image_info->text_size;
730 status->data_size = image_info->data_size;
731 status->bss_size = image_info->bss_size;
736void GetModloadInternalData(
void **pInternalData)
739 *pInternalData = NULL;
742static void ExecModuleLoad(
void *userdata)
752 switch ( mltargs->command )
755 mi = do_load(mltargs, &res_tmp);
756 ChangeThreadPriority(0, 8);
759 mi = SearchModuleCBByID(mltargs->modid);
764 res_tmp = start_module(mi, mltargs->filename, mltargs->arglen, mltargs->args, mltargs->result);
767 mi = do_load_from_buffer(
768 mltargs->buffer, mltargs->position, (
int *)mltargs->distaddr, mltargs->distoffset, &res_tmp);
771 mi = do_load(mltargs, &res_tmp);
772 ChangeThreadPriority(0, 8);
777 res_tmp = start_module(mi, mltargs->filename, mltargs->arglen, mltargs->args, mltargs->result);
781 mi = SearchModuleCBByID(mltargs->modid);
786 res_tmp = stop_module(mi, mltargs->command, mltargs->modid_2, mltargs->arglen, mltargs->args, mltargs->result);
790 mi = SearchModuleCBByID(mltargs->modid);
795 res_tmp = unload_module(mi);
800 if ( mltargs->command != 7 )
804 modid_2 = mltargs->modid_2;
805 ChangeThreadPriority(0, 1);
806 TerminateThread(modid_2);
807 DeleteThread(modid_2);
808 SignalSema(ModuleLoaderMutex);
815 *mltargs->ret_ptr = res_tmp;
819 *mltargs->ret_ptr = KE_UNKNOWN_MODULE;
823 *mltargs->ret_ptr = mi->id;
825 if ( mltargs->thread_ef )
827 ChangeThreadPriority(0, 1);
828 SetEventFlag(mltargs->thread_ef, 1u);
841 return KE_ILLEGAL_CONTEXT;
843 result = GetThreadId();
850 mltargs->ret_ptr = &ret_tmp;
851 if ( result == modLoadCB )
853 mltargs->thread_ef = 0;
854 ExecModuleLoad((
void *)mltargs);
858 mltargs->thread_ef = ModuleLoaderSync;
859 result = WaitSema(ModuleLoaderMutex);
864 StartThread(modLoadCB, mltargs);
865 WaitEventFlag(ModuleLoaderSync, 1u, 17, &efbits);
866 SignalSema(ModuleLoaderMutex);
875 image_info = GetLoadcoreInternalData()->
image_info;
876 while ( image_info != NULL )
878 if ( modid == image_info->id )
882 image_info = image_info->next;
887static ModuleInfo_t *search_for_module_by_name(
const char *name)
891 image_info = GetLoadcoreInternalData()->
image_info;
892 while ( image_info != NULL )
894 if ( strcmp(name, image_info->name) == 0 )
898 image_info = image_info->next;
907 next = load_memory_ll.next;
908 if ( load_memory_ll.next == &load_memory_ll )
913 if ( next == &load_memory_ll )
931 BootMode_4 = QueryBootMode(4);
935 reboot_type = (((u32 *)BootMode_4)[0] >> 8) & 0xff;
937 BootMode_5 = QueryBootMode(5);
941 char *updater_argv[16];
943 memset(updater_argv, 0,
sizeof(updater_argv));
945 get_updater_boot_argument(
946 (
char *)BootMode_5[1], &updater_argc, updater_argv, (
sizeof(updater_argv) /
sizeof(updater_argv[0])) - 1);
947 if ( reboot_type == 0 )
951 mltargs.position = 2;
953 mltargs.distaddr = (
void *)0x100000;
954 mltargs.distoffset = 0;
955 mltargs.functable = &default_filefunc_functable;
957 mltargs.filename = updater_argv[0];
958 module_info = do_load(&mltargs, &module_result);
960 else if ( reboot_type == 1 )
963 void *iop_exec_buffer;
964 void *iop_exec_encrypted_buffer;
972 functable = &default_filefunc_functable;
973 iop_exec_buffer = NULL;
974 iop_exec_encrypted_buffer = NULL;
975 module_fd = open_loadfile(functable, NULL, updater_argv[0], &module_filesize);
976 if ( module_fd >= 0 )
978 iop_exec_encrypted_buffer =
979 read_entire_loadfile(functable, NULL, module_fd, &module_result, module_filesize, 1);
980 if ( iop_exec_encrypted_buffer )
983 CheckKelfPath_func_ptr && CheckKelfPath_func_ptr(updater_argv[0], &card_port, &card_slot)
984 && SecrCardBootFile_func_ptr )
986 iop_exec_buffer = SecrCardBootFile_func_ptr(card_port, card_slot, iop_exec_encrypted_buffer);
988 else if ( SecrDiskBootFile_func_ptr )
990 iop_exec_buffer = SecrDiskBootFile_func_ptr(iop_exec_encrypted_buffer);
992 if ( iop_exec_buffer )
994 module_info = do_load_from_buffer(iop_exec_buffer, 2, (
void *)0x100000, 0, &module_result);
1001 FreeSysMemory(iop_exec_encrypted_buffer);
1018 if ( module_result == 0 )
1022 printf(
"return from updater '%s' return value = %d\n", updater_argv[0], module_result);
1025 printf(
"updater '%s' can't load\n", updater_argv[0]);
1028 printf(
"Reboot fail! need file name argument\n");
1032static int start_module(
ModuleInfo_t *module_info,
const char *data,
int arglen,
const char *args,
int *result_out)
1034 const char *args_ptr;
1035 char *in_argv_strs_ptr;
1039 int in_argv_size_strs;
1041 char **in_argv_ptrs;
1044 if ( (module_info->
newflags & 0xF) != 1 )
1046 return KE_ALREADY_STARTED;
1049 data_strlen = strlen(data) + 1;
1050 in_argv_size_strs = data_strlen;
1051 for ( args_ptr = args; args_ptr < &args[arglen]; )
1053 int str_len = strlen(args_ptr) + 1;
1054 in_argv_size_strs += str_len;
1055 args_ptr += str_len;
1058 if ( in_argv_size_strs < data_strlen + arglen )
1060 in_argv_size_strs = data_strlen + arglen;
1062 in_argv_strs = __builtin_alloca(in_argv_size_strs);
1063 memcpy(in_argv_strs, data, data_strlen);
1064 memcpy(in_argv_strs + data_strlen, args, arglen);
1065 in_argv_ptrs = __builtin_alloca((in_argc + 1) *
sizeof(
char *));
1066 for ( i = 0, in_argv_strs_ptr = in_argv_strs; i < in_argc && in_argv_strs_ptr < &in_argv_strs[in_argv_size_strs]; )
1068 int str_len = strlen(in_argv_strs_ptr) + 1;
1069 in_argv_ptrs[i] = in_argv_strs_ptr;
1071 in_argv_strs_ptr += str_len;
1073 in_argv_ptrs[in_argc] = NULL;
1078 ChangeThreadPriority(0, 8);
1081 *result_out = module_result;
1083 switch ( module_result & 3 )
1095 UnLinkLibraryEntries((
void *)module_info->text_start, module_info->text_size);
1096 if ( (module_info->
newflags & 0x40) != 0 )
1098 memset((
void *)module_info->text_start, 77, module_info->text_size);
1100 (
void *)(module_info->text_start + module_info->text_size),
1102 module_info->data_size + module_info->bss_size);
1104 ReleaseModule(module_info);
1105 free_module_block((
modload_ll_t *)module_info, module_info->newflags);
1119stop_module(
ModuleInfo_t *module_info,
int command,
int modid_2,
int arglen,
const char *args,
int *result_out)
1122 const char *args_ptr;
1123 char *in_argv_strs_ptr;
1127 int in_argv_size_strs;
1129 char **in_argv_ptrs;
1132 switch ( module_info->
newflags & 0xF )
1136 return KE_NOT_STARTED;
1139 return KE_ALREADY_STOPPING;
1142 return KE_ALREADY_STOPPED;
1146 if ( (module_info->
newflags & 0x10) == 0 )
1147 return KE_NOT_REMOVABLE;
1148 if ( command == 4 && modid_2 == module_info->id )
1149 return KE_CAN_NOT_STOP;
1154 data_strlen = strlen(data) + 1;
1155 in_argv_size_strs = data_strlen;
1156 for ( args_ptr = args; args_ptr < &args[arglen]; )
1158 int str_len = strlen(args_ptr) + 1;
1159 in_argv_size_strs += str_len;
1160 args_ptr += str_len;
1163 if ( in_argv_size_strs < data_strlen + arglen )
1165 in_argv_size_strs = data_strlen + arglen;
1167 in_argv_strs = __builtin_alloca(in_argv_size_strs);
1168 memcpy(in_argv_strs, data, data_strlen);
1169 memcpy(in_argv_strs + data_strlen, args, arglen);
1170 in_argv_ptrs = __builtin_alloca((in_argc + 1) *
sizeof(
char *));
1171 for ( i = 0, in_argv_strs_ptr = in_argv_strs; i < in_argc && in_argv_strs_ptr < &in_argv_strs[in_argv_size_strs]; )
1173 int str_len = strlen(in_argv_strs_ptr) + 1;
1174 in_argv_ptrs[i] = in_argv_strs_ptr;
1176 in_argv_strs_ptr += str_len;
1178 in_argv_ptrs[in_argc] = NULL;
1187 ChangeThreadPriority(0, 8);
1189 *result_out = module_result;
1191 switch ( module_result & 3 )
1196 return KE_CAN_NOT_STOP;
1208 return KE_CAN_NOT_STOP;
1221 flags_masked1 = newflags & 0xF;
1222 if ( (newflags & 0x10) == 0 && flags_masked1 != 1 )
1224 return KE_NOT_REMOVABLE;
1226 switch ( flags_masked1 )
1233 return KE_NOT_STOPPED;
1236 UnLinkLibraryEntries((
void *)module_info->text_start, module_info->text_size);
1237 if ( (module_info->
newflags & 0x40) != 0 )
1239 memset((
void *)module_info->text_start, 77, module_info->text_size);
1241 (
void *)(module_info->text_start + module_info->text_size), -1, module_info->data_size + module_info->bss_size);
1243 ReleaseModule(module_info);
1244 free_module_block((
modload_ll_t *)module_info, module_info->newflags);
1249int IsIllegalBootDevice(
const char *arg1)
1260 void *entire_loadfile;
1263 entire_loadfile = read_entire_loadfile(
1264 mltargs->functable, mltargs->funcopt, module_fd, result_out, module_filesize, mltargs->position != 1);
1265 if ( !entire_loadfile )
1270 *module_block = allocate_module_block(
1275 mltargs->distoffset,
1278 if ( !(*module_block) )
1280 FreeSysMemory(entire_loadfile);
1283 LoadExecutableObject(entire_loadfile, fi);
1285 FreeSysMemory(entire_loadfile);
1287 return (
ModuleInfo_t *)((
char *)fi->text_start - 0x30);
1298 char *relocate_offset;
1317 functable = mltargs->functable;
1318 funcopt = mltargs->funcopt;
1322 if ( seek_read(functable, funcopt, module_fd, 0, &lshdr, 144, result_out) != 0 )
1325 module_block = allocate_module_block(
1326 &lshdr, fi, mltargs->position, (
modload_load_memory_t *)mltargs->distaddr, mltargs->distoffset, &res_tmp);
1330 int total_section_size;
1334 if ( !module_block )
1338 if ( fi->ModuleType == 1 )
1340 res_tmp = KE_ILLEGAL_OBJECT;
1343 text_start = (
char *)fi->text_start;
1344 data_size = fi->data_size;
1345 text_end = &text_start[fi->text_size];
1347 dest = (u32 *)&text_end[data_size];
1348 total_section_size = lshdr.elfhdr.shentsize * lshdr.elfhdr.shnum;
1349 if ( CheckThreadStack() < total_section_size + 768 )
1351 res_tmp = KE_NO_MEMORY;
1354 elfshdr = __builtin_alloca(total_section_size);
1356 functable, funcopt, module_fd, lshdr.phdr[1].offset, fi->text_start, lshdr.phdr[1].filesz, &res_tmp) )
1360 if ( seek_read(functable, funcopt, module_fd, lshdr.elfhdr.shoff, elfshdr, total_section_size, &res_tmp) )
1364 if ( fi->ModuleType != 4 )
1368 relocate_offset = (
char *)fi->text_start;
1369 fi->EntryPoint = &relocate_offset[(u32)(u8 *)fi->EntryPoint];
1370 fi->gp = &relocate_offset[(u32)(u8 *)fi->gp];
1371 mod_id = fi->mod_id;
1373 fi->mod_id = (
IopModuleID_t *)&relocate_offset[(u32)(u8 *)mod_id];
1375 for ( i = 1; i < lshdr.elfhdr.shnum; i += 1 )
1377 type = elfshdr[i].type;
1378 if ( (type == 9 || type == 4) && size < elfshdr[i].size )
1379 size = elfshdr[i].size;
1381 switch ( mltargs->access )
1385 if ( fi->bss_size >= size )
1391 modulearea = AllocSysMemory(1, size, 0);
1395 res_tmp = KE_NO_MEMORY;
1399 for ( i = 1; i < lshdr.elfhdr.shnum; i += 1 )
1401 if ( elfshdr[i].type != 9 )
1405 if ( seek_read(functable, funcopt, module_fd, elfshdr[i].offset, modulearea, elfshdr[i].size, &res_tmp) )
1407 entsize = elfshdr[i].entsize;
1410 ApplyElfRelSection(fi->text_start, modulearea, elfshdr[i].size / entsize);
1416 res_tmp = functable->setBufSize(funcopt, module_fd, size);
1421 for ( i = 1; i < lshdr.elfhdr.shnum; i += 1 )
1423 if ( elfshdr[i].type != 9 )
1427 if ( seek_read(functable, funcopt, module_fd, elfshdr[i].offset, 0, 0, &res_tmp) )
1429 res_tmp = functable->beforeRead(funcopt, module_fd, elfshdr[i].size);
1432 shdrcnt = elfshdr[i].size / elfshdr[i].entsize;
1433 for ( j = 0; j < shdrcnt; j += relnumi1 )
1436 if ( (elfrelhdr[0].
info & 0xFF) == 5 || (elfrelhdr[0].
info & 0xFF) == 250 )
1442 for ( k = 0; k < relnumi1; k += 1 )
1444 if ( seek_read(functable, funcopt, module_fd, -1, &elfrelhdr[k], 8, &res_tmp) )
1450 ApplyElfRelSection(fi->text_start, elfrelhdr, relnumi1);
1462 functable->close(funcopt, module_fd);
1465 *result_out = res_tmp;
1466 if ( ptr || (module_block &&
ModInfo) )
1471 if ( module_block &&
ModInfo )
1481 *module_block_ptr = module_block;
1490 memset(dest, 0, fi->bss_size);
1505 int module_filesize;
1509 *result_out = KE_ILLEGAL_OBJECT;
1510 if ( !mltargs->filename )
1515 if ( IsIllegalBootDevice(mltargs->filename) != 0 )
1519 module_fd = open_loadfile(mltargs->functable, mltargs->funcopt, mltargs->filename, &module_filesize);
1520 if ( module_fd < 0 )
1522 *result_out = module_fd;
1525 *result_out = KE_OK;
1527 switch ( mltargs->access )
1531 module_info = do_load_noseek(mltargs, module_fd, module_filesize, &fi, &module_block, result_out);
1537 module_info = do_load_seek(mltargs, module_fd, &fi, &module_block, result_out);
1550 if ( LinkLibraryEntries(fi.text_start, fi.text_size) < 0 )
1552 free_module_block((
modload_ll_t *)module_info, module_block);
1554 *result_out = KE_LINKERR;
1559 module_info->
newflags = module_block;
1560 RegisterModule(module_info);
1566static int open_loadfile(
LDfilefunc *functbl,
void *userdata,
const char *filename,
int *out_filesize)
1571 out_fd = spOpen(functbl, userdata, filename, 1);
1574 filesize = functbl->getfsize(userdata, out_fd);
1575 *out_filesize = filesize;
1576 if ( filesize <= 0 )
1584static void *read_entire_loadfile(
1585 LDfilefunc *functbl,
void *userdata,
int module_fd,
int *result_out,
int module_filesize,
int memory_region)
1590 *result_out = KE_OK;
1592 tmp_mem = AllocSysMemory(memory_region, module_filesize, 0);
1596 *result_out = KE_NO_MEMORY;
1597 functbl->close(userdata, module_fd);
1600 if ( seek_read(functbl, userdata, module_fd, 0, tmp_mem, module_filesize, result_out) == 0 )
1603 FreeSysMemory(tmp_mem);
1607 functbl->close(userdata, module_fd);
1611static int seek_read(
1612 LDfilefunc *functbl,
void *userdata,
int module_fd,
int read_offset,
void *buf,
int read_size,
int *result_out)
1614 if ( !((read_offset < 0 || (functbl->lseek(userdata, module_fd, read_offset, 0) >= 0))
1615 && (read_size <= 0 || (functbl->read(userdata, module_fd, buf, read_size) == read_size))) )
1617 functbl->close(userdata, module_fd);
1618 *result_out = KE_FILEERR;
1625do_load_from_buffer(
void *buffer,
int position,
int *distaddr,
unsigned int distoffset,
int *result_out)
1635 allocate_module_block(buffer, &fi, position, (
modload_load_memory_t *)distaddr, distoffset, result_out);
1638 LoadExecutableObject(buffer, &fi);
1639 if ( LinkLibraryEntries(fi.text_start, fi.text_size) < 0 )
1641 free_module_block((
modload_ll_t *)fi.text_start - 6, module_block & 0xFFFF);
1642 *result_out = KE_LINKERR;
1646 module_info = (
ModuleInfo_t *)((
char *)fi.text_start - 0x30);
1648 module_info->
newflags = module_block & 0xFFFF;
1649 RegisterModule(module_info);
1666 v4 = (
char *)a1 + a2;
1668 if ( v6 < (
char *)a3 )
1670 return v6 < (
char *)a4 + (
int)a3;
1682 memsz_add = fi->MemSize + 64;
1683 if ( distoffset == 1 )
1685 next = &loadmem->ll[2];
1686 prev = loadmem->ll[2].prev;
1687 v8 = (
modload_ll_t *)((
char *)prev + (
unsigned int)prev[1].next);
1693 if ( (distoffset < 0x20) || ((distoffset & 0xF) != 0) )
1695 *result_out = KE_ILLEGAL_OFFSET;
1698 next = loadmem->ll[2].next;
1699 v8 = (
modload_ll_t *)((
char *)loadmem->ll + distoffset);
1700 v10 = &loadmem->ll[2];
1701 for ( i = next; i != v10; i = i->next )
1710 (load_memory_helper_cmpinner(v8, memsz_add, prev, prev[1].next) != 0)
1711 || (load_memory_helper_cmpinner(v8, memsz_add, next, next[1].next) != 0) )
1713 *result_out = KE_MEMINUSE;
1716 linked_list_add_after(next, v8);
1721static int allocate_module_block(
1724 switch ( ProbeExecutableObject(buf, fi) )
1729 char *text_start_tmp;
1732 text_start_tmp = (
char *)fi->text_start;
1733 allocaddr1 = (
char *)(((
unsigned int)(text_start_tmp - 0x30) >> 8 << 8) & 0x1FFFFFFF);
1734 if ( AllocSysMemory(2, &text_start_tmp[fi->MemSize] - allocaddr1, allocaddr1) != 0 )
1736 if ( (
int)QueryBlockTopAddress(allocaddr1) <= 0 )
1737 *result_out = KE_NO_MEMORY;
1739 *result_out = KE_MEMINUSE;
1744 if ( memalloctype == 2 && distoffset )
1747 if ( check_in_linked_list(loadmem->ll) == 0 )
1749 fi->text_start = load_memory_helper(fi, loadmem, distoffset, result_out);
1750 if ( !fi->text_start )
1752 fi->text_start = ((
char *)fi->text_start) + 0x30;
1760 if ( memalloctype == 2 )
1762 allocaddr2 = loadmem;
1768 fi->text_start = AllocSysMemory(memalloctype, fi->MemSize + 0x30, allocaddr2);
1770 if ( !fi->text_start )
1772 *result_out = KE_NO_MEMORY;
1775 fi->text_start = ((
char *)fi->text_start) + 0x30;
1780 *result_out = KE_ILLEGAL_OBJECT;
1786static void free_module_block(
modload_ll_t *buf,
char flags)
1788 if ( (flags & 0x20) != 0 )
1789 linked_list_remove(buf - 2);
1791 FreeSysMemory((
void *)((
unsigned int)buf >> 8 << 8));
1794static int spOpen(
LDfilefunc *functbl,
void *userdata,
const char *filename,
int filemode)
1798 functbl->beforeOpen(userdata, filename, filemode);
1799 ret_fd = open(filename, filemode);
1800 functbl->afterOpen(userdata, ret_fd);
1804static int spBeforeOpen(
void *opt,
const char *filename,
int flag)
1812static int spAfterOpen(
void *opt,
int fd)
1819static int spClose(
void *userdata,
int in_fd)
1823 return close(in_fd);
1826static int spSetBufSize(
void *opt,
int fd,
size_t size)
1834static int spBread(
void *opt,
int fd,
size_t nbyte)
1842static int spRead(
void *userdata,
int in_fd,
void *buffer,
size_t read_size)
1847 return read(in_fd, buffer, read_size);
1850static int spLseek(
void *userdata,
int in_fd,
long offset,
int whence)
1855 return lseek(in_fd, offset, whence);
1858static int spGetfsize(
void *userdata,
int in_fd)
1863 ret = lseek(in_fd, 0, 2);
1870static char *get_next_non_whitespace_string(
char *str)
1874 if ( *str !=
' ' && *str !=
'\t' && *str !=
'\n' )
1883static char *get_non_null_string(
char *str)
1885 while ( *str && *str !=
' ' && *str !=
'\t' && *str !=
'\n' )
1892static void get_updater_boot_argument(
char *str,
int *updater_argc,
char **updater_argv,
int updater_argv_count)
1894 char *next_non_whitespace_string;
1895 int updater_argc_cur;
1897 next_non_whitespace_string = get_next_non_whitespace_string(str);
1898 updater_argc_cur = 0;
1899 while ( *next_non_whitespace_string && updater_argc_cur < updater_argv_count )
1901 char *non_null_string;
1903 *updater_argv = next_non_whitespace_string;
1905 non_null_string = get_non_null_string(next_non_whitespace_string);
1906 updater_argc_cur += 1;
1907 if ( !*non_null_string )
1911 *non_null_string = 0;
1912 next_non_whitespace_string = get_next_non_whitespace_string(non_null_string + 1);
1914 *updater_argc = updater_argc_cur;
1917void SetSecrmanCallbacks(
1918 SecrCardBootFile_callback_t SecrCardBootFile_fnc,
1919 SecrDiskBootFile_callback_t SecrDiskBootFile_fnc,
1920 SetLoadfileCallbacks_callback_t SetLoadfileCallbacks_fnc)
1922 SecrCardBootFile_func_ptr = SecrCardBootFile_fnc;
1923 SecrDiskBootFile_func_ptr = SecrDiskBootFile_fnc;
1924 SetLoadfileCallbacks_func_ptr = SetLoadfileCallbacks_fnc;
1927void SetCheckKelfPathCallback(CheckKelfPath_callback_t CheckKelfPath_fnc)
1929 CheckKelfPath_func_ptr = CheckKelfPath_fnc;
1932void GetLoadfileCallbacks(
1933 CheckKelfPath_callback_t *CheckKelfPath_fnc, SetLoadfileCallbacks_callback_t *SetLoadfileCallbacks_fnc)
1935 *CheckKelfPath_fnc = CheckKelfPath_func_ptr;
1936 *SetLoadfileCallbacks_fnc = SetLoadfileCallbacks_func_ptr;
1939static void ml_strcpy(
char *dst,
const char *src)
1948static void TerminateResidentLibraries(
const char *message,
unsigned int options,
int mode)
1953 unsigned int enable_debug;
1955 enable_debug = options & 0x80000000;
1956 if ( enable_debug != 0 )
1959 if ( (LoadcoreData = GetLoadcoreInternalData()) != NULL )
1961 ModuleData = LoadcoreData->let_next;
1962 while ( ModuleData != NULL )
1964 NextModule = ModuleData->prev;
1968 if ( !(ModuleData->flags & 6) )
1970 ModuleData = NextModule;
1974 else if ( (ModuleData->flags & 6) == 2 )
1976 ModuleData = NextModule;
1980 ExportTable = ModuleData->exports;
1981 if ( ExportTable[1] != NULL && ExportTable[2] != NULL )
1983 int (*pexit)(
int arg1);
1985 pexit = ExportTable[2];
1986 if ( enable_debug != 0 )
1987 Kprintf(
" %.8s %x \n", ModuleData->name, pexit);
1991 ModuleData = NextModule;
1999 volatile unsigned int *address, *delay;
2004 {(
volatile unsigned int *)0xbf801000, (
volatile unsigned int *)0xbf801008},
2005 {(
volatile unsigned int *)0xbf801400, (
volatile unsigned int *)0xbf80100C},
2006 {(
volatile unsigned int *)0xbf801404, (
volatile unsigned int *)0xbf801014},
2007 {(
volatile unsigned int *)0xbf801408, (
volatile unsigned int *)0xbf801018},
2008 {(
volatile unsigned int *)0xbf80140C, (
volatile unsigned int *)0xbf801414},
2009 {(
volatile unsigned int *)0xbf801410, (
volatile unsigned int *)0xbf80141C},
2014static volatile unsigned int *func_00000f80(
volatile unsigned int *address)
2019 while ( pSSBUS_regs->address != NULL )
2021 if ( pSSBUS_regs->address == address )
2026 return pSSBUS_regs->delay;
2029static const void *GetFileDataFromImage(
const void *start,
const void *end,
const char *filename);
2031static void TerminateResidentEntriesDI(
const char *command,
unsigned int options)
2034 volatile unsigned int **pReg;
2036 TerminateResidentLibraries(
" ReBootStart:di: Terminate resident Libraries\n", options, 0);
2038 asm volatile(
"mfc0 %0, $15" :
"=r"(prid) :);
2040 if ( !(options & 1) )
2042 pReg = (prid < 0x10 || ((*(
volatile unsigned int *)0xbf801450) & 8)) ? *(
volatile unsigned int ***)0xbfc02008 :
2043 *(volatile unsigned int ***)0xbfc0200C;
2045 while ( pReg[0] != 0 )
2047 if ( func_00000f80(pReg[0]) != 0 )
2048 pReg[0] = (
void *)0xFF;
2053 if ( !(options & 2) )
2056 (prid < 0x10 || ((*(
volatile unsigned int *)0xbf801450) & 8)) ? *(
volatile unsigned int *)0xbfc02010 :
2057 *(
volatile unsigned int *)0xbfc02014);
2062 const char *iopboot_entrypoint;
2067 iopboot_entrypoint = GetFileDataFromImage((
const void *)0xBFC00000, (
const void *)0xBFC10000,
"IOPBOOT");
2069 if ( command && command[0] )
2071 ml_strcpy((
char *)0x480, command);
2072 ram_size_in_mb = (QueryMemSize() + 0x100) >> 20;
2073 flagstmp = (options & 0xFF00) | 2;
2074 command_ptr = (
char *)0x480;
2078 ram_size_in_mb = (QueryMemSize() + 0x100) >> 20;
2082 ((int (*)(u32 ram_mb,
int flags,
char *cmdptr, u32 xunk))iopboot_entrypoint)(ram_size_in_mb, flagstmp, command_ptr, 0);
2087extern int CpuExecuteKmode(
void *func, ...);
2091 "\t" ".set push" "\n"
2092 "\t" ".set noat" "\n"
2093 "\t" ".set noreorder" "\n"
2094 "\t" "CpuExecuteKmode:" "\n"
2095 "\t" " addiu $v0, $zero, 0x0C" "\n"
2096 "\t" " syscall 0" "\n"
2099 "\t" ".set pop" "\n"
2103int ReBootStart(
const char *command,
unsigned int flags)
2105 ChangeThreadPriority(0, 7);
2106 TerminateResidentLibraries(
" ReBootStart:ei: Terminate resident Libraries\n", flags, 2);
2107 return CpuExecuteKmode(TerminateResidentEntriesDI, command, flags);
2113 unsigned short int ExtInfoEntrySize;
2118static const void *GetFileDataFromImage(
const void *start,
const void *end,
const char *filename)
2120 const u8 *ImageStart;
2121 const u8 *RomdirStart;
2127 unsigned int offset;
2136 ptr = (u32 *)file->name;
2137 if ( ptr[0] == 0x45534552 && ptr[1] == 0x54 && (*(u16 *)&ptr[2] == 0) && (((file->size + 15) & ~15) == offset) )
2140 RomdirStart = (const u8 *)ptr;
2146 unsigned int i, offset;
2147 u8 filename_temp[12];
2150 ((u32 *)filename_temp)[0] = 0;
2151 ((u32 *)filename_temp)[1] = 0;
2152 ((u32 *)filename_temp)[2] = 0;
2153 for ( i = 0; *filename >= 0x21 && i <
sizeof(filename_temp); i++ )
2155 filename_temp[i] = *filename;
2159 if ( RomdirStart != NULL )
2163 RomdirEntry = (
const struct RomDirEntry *)RomdirStart;
2168 ((u32 *)filename_temp)[0] == ((u32 *)RomdirEntry->name)[0]
2169 && ((u32 *)filename_temp)[1] == ((u32 *)RomdirEntry->name)[1]
2170 && (*(u16 *)&((u32 *)filename_temp)[2] == *(u16 *)&((u32 *)RomdirEntry->name)[2]) )
2172 return ImageStart + offset;
2175 offset += (RomdirEntry->size + 15) & ~15;
2177 }
while ( ((u32 *)RomdirEntry->name)[0] != 0x00000000 );
2189static int linked_list_next_is_self(
const modload_ll_t *ll)
2191 return ll->next == ll;
2196 ll->next->prev = ll->prev;
2197 ll->prev->next = ll->next;
2201static int linked_list_is_circular(
const modload_ll_t *ll)
2203 return ll->prev == ll->next;
2210 ll2->prev = ll1->prev;
2212 ll2->prev->next = ll2;
int CpuResumeIntr(int state)
int QueryIntrContext(void)
int CpuSuspendIntr(int *state)
ModuleInfo_t * image_info