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,
unsigned int read_size);
193static int spSetBufSize();
194static int spClose(
void *userdata,
int in_fd);
195static int spAfterOpen();
196static int spBeforeOpen();
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,
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 = (void (*)(
void *))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;
750 switch ( mltargs->command )
753 mi = do_load(mltargs, &res_tmp);
754 ChangeThreadPriority(0, 8);
757 mi = SearchModuleCBByID(mltargs->modid);
762 res_tmp = start_module(mi, mltargs->filename, mltargs->arglen, mltargs->args, mltargs->result);
765 mi = do_load_from_buffer(
766 mltargs->buffer, mltargs->position, (
int *)mltargs->distaddr, mltargs->distoffset, &res_tmp);
769 mi = do_load(mltargs, &res_tmp);
770 ChangeThreadPriority(0, 8);
775 res_tmp = start_module(mi, mltargs->filename, mltargs->arglen, mltargs->args, mltargs->result);
779 mi = SearchModuleCBByID(mltargs->modid);
784 res_tmp = stop_module(mi, mltargs->command, mltargs->modid_2, mltargs->arglen, mltargs->args, mltargs->result);
788 mi = SearchModuleCBByID(mltargs->modid);
793 res_tmp = unload_module(mi);
798 if ( mltargs->command != 7 )
802 modid_2 = mltargs->modid_2;
803 ChangeThreadPriority(0, 1);
804 TerminateThread(modid_2);
805 DeleteThread(modid_2);
806 SignalSema(ModuleLoaderMutex);
813 *mltargs->ret_ptr = res_tmp;
817 *mltargs->ret_ptr = KE_UNKNOWN_MODULE;
821 *mltargs->ret_ptr = mi->id;
823 if ( mltargs->thread_ef )
825 ChangeThreadPriority(0, 1);
826 SetEventFlag(mltargs->thread_ef, 1u);
839 return KE_ILLEGAL_CONTEXT;
841 result = GetThreadId();
848 mltargs->ret_ptr = &ret_tmp;
849 if ( result == modLoadCB )
851 mltargs->thread_ef = 0;
852 ExecModuleLoad(mltargs);
856 mltargs->thread_ef = ModuleLoaderSync;
857 result = WaitSema(ModuleLoaderMutex);
862 StartThread(modLoadCB, mltargs);
863 WaitEventFlag(ModuleLoaderSync, 1u, 17, &efbits);
864 SignalSema(ModuleLoaderMutex);
873 image_info = GetLoadcoreInternalData()->
image_info;
874 while ( image_info != NULL )
876 if ( modid == image_info->id )
880 image_info = image_info->next;
885static ModuleInfo_t *search_for_module_by_name(
const char *name)
889 image_info = GetLoadcoreInternalData()->
image_info;
890 while ( image_info != NULL )
892 if ( strcmp(name, image_info->name) == 0 )
896 image_info = image_info->next;
905 next = load_memory_ll.next;
906 if ( load_memory_ll.next == &load_memory_ll )
911 if ( next == &load_memory_ll )
929 BootMode_4 = QueryBootMode(4);
933 reboot_type = (((u32 *)BootMode_4)[0] >> 8) & 0xff;
935 BootMode_5 = QueryBootMode(5);
939 char *updater_argv[16];
941 memset(updater_argv, 0,
sizeof(updater_argv));
943 get_updater_boot_argument(
944 (
char *)BootMode_5[1], &updater_argc, updater_argv, (
sizeof(updater_argv) /
sizeof(updater_argv[0])) - 1);
945 if ( reboot_type == 0 )
949 mltargs.position = 2;
951 mltargs.distaddr = (
void *)0x100000;
952 mltargs.distoffset = 0;
953 mltargs.functable = &default_filefunc_functable;
955 mltargs.filename = updater_argv[0];
956 module_info = do_load(&mltargs, &module_result);
958 else if ( reboot_type == 1 )
961 void *iop_exec_buffer;
962 void *iop_exec_encrypted_buffer;
970 functable = &default_filefunc_functable;
971 iop_exec_buffer = NULL;
972 iop_exec_encrypted_buffer = NULL;
973 module_fd = open_loadfile(functable, NULL, updater_argv[0], &module_filesize);
974 if ( module_fd >= 0 )
976 iop_exec_encrypted_buffer =
977 read_entire_loadfile(functable, NULL, module_fd, &module_result, module_filesize, 1);
978 if ( iop_exec_encrypted_buffer )
981 CheckKelfPath_func_ptr && CheckKelfPath_func_ptr(updater_argv[0], &card_port, &card_slot)
982 && SecrCardBootFile_func_ptr )
984 iop_exec_buffer = SecrCardBootFile_func_ptr(card_port, card_slot, iop_exec_encrypted_buffer);
986 else if ( SecrDiskBootFile_func_ptr )
988 iop_exec_buffer = SecrDiskBootFile_func_ptr(iop_exec_encrypted_buffer);
990 if ( iop_exec_buffer )
992 module_info = do_load_from_buffer(iop_exec_buffer, 2, (
void *)0x100000, 0, &module_result);
999 FreeSysMemory(iop_exec_encrypted_buffer);
1016 if ( module_result == 0 )
1019 ((int (*)(int,
char **, u32,
ModuleInfo_t *))module_info->
entry)(updater_argc, updater_argv, 0, module_info);
1020 printf(
"return from updater '%s' return value = %d\n", updater_argv[0], module_result);
1023 printf(
"updater '%s' can't load\n", updater_argv[0]);
1026 printf(
"Reboot fail! need file name argument\n");
1030static int start_module(
ModuleInfo_t *module_info,
const char *data,
int arglen,
const char *args,
int *result_out)
1032 const char *args_ptr;
1033 char *in_argv_strs_ptr;
1037 int in_argv_size_strs;
1039 char **in_argv_ptrs;
1042 if ( (module_info->
newflags & 0xF) != 1 )
1044 return KE_ALREADY_STARTED;
1047 data_strlen = strlen(data) + 1;
1048 in_argv_size_strs = data_strlen;
1049 for ( args_ptr = args; args_ptr < &args[arglen]; )
1051 int str_len = strlen(args_ptr) + 1;
1052 in_argv_size_strs += str_len;
1053 args_ptr += str_len;
1056 if ( in_argv_size_strs < data_strlen + arglen )
1058 in_argv_size_strs = data_strlen + arglen;
1060 in_argv_strs = __builtin_alloca(in_argv_size_strs);
1061 memcpy(in_argv_strs, data, data_strlen);
1062 memcpy(in_argv_strs + data_strlen, args, arglen);
1063 in_argv_ptrs = __builtin_alloca((in_argc + 1) *
sizeof(
char *));
1064 for ( i = 0, in_argv_strs_ptr = in_argv_strs; i < in_argc && in_argv_strs_ptr < &in_argv_strs[in_argv_size_strs]; )
1066 int str_len = strlen(in_argv_strs_ptr) + 1;
1067 in_argv_ptrs[i] = in_argv_strs_ptr;
1069 in_argv_strs_ptr += str_len;
1071 in_argv_ptrs[in_argc] = NULL;
1075 ((int (*)(int,
char **, u32,
ModuleInfo_t *))module_info->
entry)(in_argc, in_argv_ptrs, 0, module_info);
1076 ChangeThreadPriority(0, 8);
1079 *result_out = module_result;
1081 switch ( module_result & 3 )
1093 UnLinkLibraryEntries((
void *)module_info->text_start, module_info->text_size);
1094 if ( (module_info->
newflags & 0x40) != 0 )
1096 memset((
void *)module_info->text_start, 77, module_info->text_size);
1098 (
void *)(module_info->text_start + module_info->text_size),
1100 module_info->data_size + module_info->bss_size);
1102 ReleaseModule(module_info);
1103 free_module_block((
modload_ll_t *)module_info, module_info->newflags);
1117stop_module(
ModuleInfo_t *module_info,
int command,
int modid_2,
int arglen,
const char *args,
int *result_out)
1120 const char *args_ptr;
1121 char *in_argv_strs_ptr;
1125 int in_argv_size_strs;
1127 char **in_argv_ptrs;
1130 switch ( module_info->
newflags & 0xF )
1134 return KE_NOT_STARTED;
1137 return KE_ALREADY_STOPPING;
1140 return KE_ALREADY_STOPPED;
1144 if ( (module_info->
newflags & 0x10) == 0 )
1145 return KE_NOT_REMOVABLE;
1146 if ( command == 4 && modid_2 == module_info->id )
1147 return KE_CAN_NOT_STOP;
1152 data_strlen = strlen(data) + 1;
1153 in_argv_size_strs = data_strlen;
1154 for ( args_ptr = args; args_ptr < &args[arglen]; )
1156 int str_len = strlen(args_ptr) + 1;
1157 in_argv_size_strs += str_len;
1158 args_ptr += str_len;
1161 if ( in_argv_size_strs < data_strlen + arglen )
1163 in_argv_size_strs = data_strlen + arglen;
1165 in_argv_strs = __builtin_alloca(in_argv_size_strs);
1166 memcpy(in_argv_strs, data, data_strlen);
1167 memcpy(in_argv_strs + data_strlen, args, arglen);
1168 in_argv_ptrs = __builtin_alloca((in_argc + 1) *
sizeof(
char *));
1169 for ( i = 0, in_argv_strs_ptr = in_argv_strs; i < in_argc && in_argv_strs_ptr < &in_argv_strs[in_argv_size_strs]; )
1171 int str_len = strlen(in_argv_strs_ptr) + 1;
1172 in_argv_ptrs[i] = in_argv_strs_ptr;
1174 in_argv_strs_ptr += str_len;
1176 in_argv_ptrs[in_argc] = NULL;
1184 ((int (*)(int,
char **, u32,
ModuleInfo_t *))module_info->
entry)(-in_argc, in_argv_ptrs, 0, module_info);
1185 ChangeThreadPriority(0, 8);
1187 *result_out = module_result;
1189 switch ( module_result & 3 )
1194 return KE_CAN_NOT_STOP;
1206 return KE_CAN_NOT_STOP;
1219 flags_masked1 = newflags & 0xF;
1220 if ( (newflags & 0x10) == 0 && flags_masked1 != 1 )
1222 return KE_NOT_REMOVABLE;
1224 switch ( flags_masked1 )
1231 return KE_NOT_STOPPED;
1234 UnLinkLibraryEntries((
void *)module_info->text_start, module_info->text_size);
1235 if ( (module_info->
newflags & 0x40) != 0 )
1237 memset((
void *)module_info->text_start, 77, module_info->text_size);
1239 (
void *)(module_info->text_start + module_info->text_size), -1, module_info->data_size + module_info->bss_size);
1241 ReleaseModule(module_info);
1242 free_module_block((
modload_ll_t *)module_info, module_info->newflags);
1247int IsIllegalBootDevice(
const char *arg1)
1258 void *entire_loadfile;
1261 entire_loadfile = read_entire_loadfile(
1262 mltargs->functable, mltargs->funcopt, module_fd, result_out, module_filesize, mltargs->position != 1);
1263 if ( !entire_loadfile )
1268 *module_block = allocate_module_block(
1273 mltargs->distoffset,
1276 if ( !(*module_block) )
1278 FreeSysMemory(entire_loadfile);
1281 LoadExecutableObject(entire_loadfile, fi);
1283 FreeSysMemory(entire_loadfile);
1285 return (
ModuleInfo_t *)((
char *)fi->text_start - 0x30);
1296 char *relocate_offset;
1315 functable = mltargs->functable;
1316 funcopt = mltargs->funcopt;
1320 if ( seek_read(functable, funcopt, module_fd, 0, &lshdr, 144, result_out) != 0 )
1323 module_block = allocate_module_block(
1324 &lshdr, fi, mltargs->position, (
modload_load_memory_t *)mltargs->distaddr, mltargs->distoffset, &res_tmp);
1328 int total_section_size;
1332 if ( !module_block )
1336 if ( fi->ModuleType == 1 )
1338 res_tmp = KE_ILLEGAL_OBJECT;
1341 text_start = (
char *)fi->text_start;
1342 data_size = fi->data_size;
1343 text_end = &text_start[fi->text_size];
1345 dest = (u32 *)&text_end[data_size];
1346 total_section_size = lshdr.elfhdr.shentsize * lshdr.elfhdr.shnum;
1347 if ( CheckThreadStack() < total_section_size + 768 )
1349 res_tmp = KE_NO_MEMORY;
1352 elfshdr = __builtin_alloca(total_section_size);
1354 functable, funcopt, module_fd, lshdr.phdr[1].offset, fi->text_start, lshdr.phdr[1].filesz, &res_tmp) )
1358 if ( seek_read(functable, funcopt, module_fd, lshdr.elfhdr.shoff, elfshdr, total_section_size, &res_tmp) )
1362 if ( fi->ModuleType != 4 )
1366 relocate_offset = (
char *)fi->text_start;
1367 fi->EntryPoint = &relocate_offset[(u32)(u8 *)fi->EntryPoint];
1368 fi->gp = &relocate_offset[(u32)(u8 *)fi->gp];
1369 mod_id = fi->mod_id;
1371 fi->mod_id = (
IopModuleID_t *)&relocate_offset[(u32)(u8 *)mod_id];
1373 for ( i = 1; i < lshdr.elfhdr.shnum; i += 1 )
1375 type = elfshdr[i].type;
1376 if ( (type == 9 || type == 4) && size < elfshdr[i].size )
1377 size = elfshdr[i].size;
1379 switch ( mltargs->access )
1383 if ( fi->bss_size >= size )
1389 modulearea = AllocSysMemory(1, size, 0);
1393 res_tmp = KE_NO_MEMORY;
1397 for ( i = 1; i < lshdr.elfhdr.shnum; i += 1 )
1399 if ( elfshdr[i].type != 9 )
1403 if ( seek_read(functable, funcopt, module_fd, elfshdr[i].offset, modulearea, elfshdr[i].size, &res_tmp) )
1405 entsize = elfshdr[i].entsize;
1408 ApplyElfRelSection(fi->text_start, modulearea, elfshdr[i].size / entsize);
1414 res_tmp = functable->setBufSize(funcopt, module_fd, size);
1419 for ( i = 1; i < lshdr.elfhdr.shnum; i += 1 )
1421 if ( elfshdr[i].type != 9 )
1425 if ( seek_read(functable, funcopt, module_fd, elfshdr[i].offset, 0, 0, &res_tmp) )
1427 res_tmp = functable->beforeRead(funcopt, module_fd, elfshdr[i].size);
1430 shdrcnt = elfshdr[i].size / elfshdr[i].entsize;
1431 for ( j = 0; j < shdrcnt; j += relnumi1 )
1434 if ( (elfrelhdr[0].
info & 0xFF) == 5 || (elfrelhdr[0].
info & 0xFF) == 250 )
1440 for ( k = 0; k < relnumi1; k += 1 )
1442 if ( seek_read(functable, funcopt, module_fd, -1, &elfrelhdr[k], 8, &res_tmp) )
1448 ApplyElfRelSection(fi->text_start, elfrelhdr, relnumi1);
1460 functable->close(funcopt, module_fd);
1463 *result_out = res_tmp;
1464 if ( ptr || (module_block &&
ModInfo) )
1469 if ( module_block &&
ModInfo )
1479 *module_block_ptr = module_block;
1488 memset(dest, 0, fi->bss_size);
1503 int module_filesize;
1507 *result_out = KE_ILLEGAL_OBJECT;
1508 if ( !mltargs->filename )
1513 if ( IsIllegalBootDevice(mltargs->filename) != 0 )
1517 module_fd = open_loadfile(mltargs->functable, mltargs->funcopt, mltargs->filename, &module_filesize);
1518 if ( module_fd < 0 )
1520 *result_out = module_fd;
1523 *result_out = KE_OK;
1525 switch ( mltargs->access )
1529 module_info = do_load_noseek(mltargs, module_fd, module_filesize, &fi, &module_block, result_out);
1535 module_info = do_load_seek(mltargs, module_fd, &fi, &module_block, result_out);
1548 if ( LinkLibraryEntries(fi.text_start, fi.text_size) < 0 )
1550 free_module_block((
modload_ll_t *)module_info, module_block);
1552 *result_out = KE_LINKERR;
1557 module_info->
newflags = module_block;
1558 RegisterModule(module_info);
1564static int open_loadfile(
LDfilefunc *functbl,
void *userdata,
const char *filename,
int *out_filesize)
1569 out_fd = spOpen(functbl, userdata, filename, 1);
1572 filesize = functbl->getfsize(userdata, out_fd);
1573 *out_filesize = filesize;
1574 if ( filesize <= 0 )
1582static void *read_entire_loadfile(
1583 LDfilefunc *functbl,
void *userdata,
int module_fd,
int *result_out,
int module_filesize,
int memory_region)
1588 *result_out = KE_OK;
1590 tmp_mem = AllocSysMemory(memory_region, module_filesize, 0);
1594 *result_out = KE_NO_MEMORY;
1595 functbl->close(userdata, module_fd);
1598 if ( seek_read(functbl, userdata, module_fd, 0, tmp_mem, module_filesize, result_out) == 0 )
1601 FreeSysMemory(tmp_mem);
1605 functbl->close(userdata, module_fd);
1609static int seek_read(
1610 LDfilefunc *functbl,
void *userdata,
int module_fd,
int read_offset,
void *buf,
int read_size,
int *result_out)
1612 if ( !((read_offset < 0 || (functbl->lseek(userdata, module_fd, read_offset, 0) >= 0))
1613 && (read_size <= 0 || (functbl->read(userdata, module_fd, buf, read_size) == read_size))) )
1615 functbl->close(userdata, module_fd);
1616 *result_out = KE_FILEERR;
1623do_load_from_buffer(
void *buffer,
int position,
int *distaddr,
unsigned int distoffset,
int *result_out)
1633 allocate_module_block(buffer, &fi, position, (
modload_load_memory_t *)distaddr, distoffset, result_out);
1636 LoadExecutableObject(buffer, &fi);
1637 if ( LinkLibraryEntries(fi.text_start, fi.text_size) < 0 )
1639 free_module_block((
modload_ll_t *)fi.text_start - 6, module_block & 0xFFFF);
1640 *result_out = KE_LINKERR;
1644 module_info = (
ModuleInfo_t *)((
char *)fi.text_start - 0x30);
1646 module_info->
newflags = module_block & 0xFFFF;
1647 RegisterModule(module_info);
1664 v4 = (
char *)a1 + a2;
1666 if ( v6 < (
char *)a3 )
1668 return v6 < (
char *)a4 + (
int)a3;
1680 memsz_add = fi->MemSize + 64;
1681 if ( distoffset == 1 )
1683 next = &loadmem->ll[2];
1684 prev = loadmem->ll[2].prev;
1685 v8 = (
modload_ll_t *)((
char *)prev + (
unsigned int)prev[1].next);
1691 if ( (distoffset < 0x20) || ((distoffset & 0xF) != 0) )
1693 *result_out = KE_ILLEGAL_OFFSET;
1696 next = loadmem->ll[2].next;
1697 v8 = (
modload_ll_t *)((
char *)loadmem->ll + distoffset);
1698 v10 = &loadmem->ll[2];
1699 for ( i = next; i != v10; i = i->next )
1708 (load_memory_helper_cmpinner(v8, memsz_add, prev, prev[1].next) != 0)
1709 || (load_memory_helper_cmpinner(v8, memsz_add, next, next[1].next) != 0) )
1711 *result_out = KE_MEMINUSE;
1714 linked_list_add_after(next, v8);
1719static int allocate_module_block(
1722 switch ( ProbeExecutableObject(buf, fi) )
1727 char *text_start_tmp;
1730 text_start_tmp = (
char *)fi->text_start;
1731 allocaddr1 = (
char *)(((
unsigned int)(text_start_tmp - 0x30) >> 8 << 8) & 0x1FFFFFFF);
1732 if ( AllocSysMemory(2, &text_start_tmp[fi->MemSize] - allocaddr1, allocaddr1) != 0 )
1734 if ( (
int)QueryBlockTopAddress(allocaddr1) <= 0 )
1735 *result_out = KE_NO_MEMORY;
1737 *result_out = KE_MEMINUSE;
1742 if ( memalloctype == 2 && distoffset )
1745 if ( check_in_linked_list(loadmem->ll) == 0 )
1747 fi->text_start = load_memory_helper(fi, loadmem, distoffset, result_out);
1748 if ( !fi->text_start )
1750 fi->text_start = ((
char *)fi->text_start) + 0x30;
1758 if ( memalloctype == 2 )
1760 allocaddr2 = loadmem;
1766 fi->text_start = AllocSysMemory(memalloctype, fi->MemSize + 0x30, allocaddr2);
1768 if ( !fi->text_start )
1770 *result_out = KE_NO_MEMORY;
1773 fi->text_start = ((
char *)fi->text_start) + 0x30;
1778 *result_out = KE_ILLEGAL_OBJECT;
1784static void free_module_block(
modload_ll_t *buf,
char flags)
1786 if ( (flags & 0x20) != 0 )
1787 linked_list_remove(buf - 2);
1789 FreeSysMemory((
void *)((
unsigned int)buf >> 8 << 8));
1792static int spOpen(
LDfilefunc *functbl,
void *userdata,
const char *filename,
int filemode)
1796 functbl->beforeOpen(userdata, filename, filemode);
1797 ret_fd = open(filename, filemode);
1798 functbl->afterOpen(userdata, ret_fd);
1802static int spBeforeOpen()
1807static int spAfterOpen()
1812static int spClose(
void *userdata,
int in_fd)
1815 return close(in_fd);
1818static int spSetBufSize()
1828static int spRead(
void *userdata,
int in_fd,
void *buffer,
unsigned int read_size)
1831 return read(in_fd, buffer, read_size);
1834static int spLseek(
void *userdata,
int in_fd,
long offset,
int whence)
1837 return lseek(in_fd, offset, whence);
1840static int spGetfsize(
void *userdata,
int in_fd)
1845 ret = lseek(in_fd, 0, 2);
1852static char *get_next_non_whitespace_string(
char *str)
1856 if ( *str !=
' ' && *str !=
'\t' && *str !=
'\n' )
1865static char *get_non_null_string(
char *str)
1867 while ( *str && *str !=
' ' && *str !=
'\t' && *str !=
'\n' )
1874static void get_updater_boot_argument(
char *str,
int *updater_argc,
char **updater_argv,
int updater_argv_count)
1876 char *next_non_whitespace_string;
1877 int updater_argc_cur;
1879 next_non_whitespace_string = get_next_non_whitespace_string(str);
1880 updater_argc_cur = 0;
1881 while ( *next_non_whitespace_string && updater_argc_cur < updater_argv_count )
1883 char *non_null_string;
1885 *updater_argv = next_non_whitespace_string;
1887 non_null_string = get_non_null_string(next_non_whitespace_string);
1888 updater_argc_cur += 1;
1889 if ( !*non_null_string )
1893 *non_null_string = 0;
1894 next_non_whitespace_string = get_next_non_whitespace_string(non_null_string + 1);
1896 *updater_argc = updater_argc_cur;
1899void SetSecrmanCallbacks(
1900 SecrCardBootFile_callback_t SecrCardBootFile_fnc,
1901 SecrDiskBootFile_callback_t SecrDiskBootFile_fnc,
1902 SetLoadfileCallbacks_callback_t SetLoadfileCallbacks_fnc)
1904 SecrCardBootFile_func_ptr = SecrCardBootFile_fnc;
1905 SecrDiskBootFile_func_ptr = SecrDiskBootFile_fnc;
1906 SetLoadfileCallbacks_func_ptr = SetLoadfileCallbacks_fnc;
1909void SetCheckKelfPathCallback(CheckKelfPath_callback_t CheckKelfPath_fnc)
1911 CheckKelfPath_func_ptr = CheckKelfPath_fnc;
1914void GetLoadfileCallbacks(
1915 CheckKelfPath_callback_t *CheckKelfPath_fnc, SetLoadfileCallbacks_callback_t *SetLoadfileCallbacks_fnc)
1917 *CheckKelfPath_fnc = CheckKelfPath_func_ptr;
1918 *SetLoadfileCallbacks_fnc = SetLoadfileCallbacks_func_ptr;
1921static void ml_strcpy(
char *dst,
const char *src)
1930static void TerminateResidentLibraries(
const char *message,
unsigned int options,
int mode)
1935 unsigned int enable_debug;
1937 enable_debug = options & 0x80000000;
1938 if ( enable_debug != 0 )
1941 if ( (LoadcoreData = GetLoadcoreInternalData()) != NULL )
1943 ModuleData = LoadcoreData->let_next;
1944 while ( ModuleData != NULL )
1946 NextModule = ModuleData->prev;
1950 if ( !(ModuleData->flags & 6) )
1952 ModuleData = NextModule;
1956 else if ( (ModuleData->flags & 6) == 2 )
1958 ModuleData = NextModule;
1962 ExportTable = ModuleData->exports;
1963 if ( ExportTable[1] != NULL && ExportTable[2] != NULL )
1965 int (*pexit)(
int arg1);
1967 pexit = ExportTable[2];
1968 if ( enable_debug != 0 )
1969 Kprintf(
" %.8s %x \n", ModuleData->name, pexit);
1973 ModuleData = NextModule;
1981 volatile unsigned int *address, *delay;
1986 {(
volatile unsigned int *)0xbf801000, (
volatile unsigned int *)0xbf801008},
1987 {(
volatile unsigned int *)0xbf801400, (
volatile unsigned int *)0xbf80100C},
1988 {(
volatile unsigned int *)0xbf801404, (
volatile unsigned int *)0xbf801014},
1989 {(
volatile unsigned int *)0xbf801408, (
volatile unsigned int *)0xbf801018},
1990 {(
volatile unsigned int *)0xbf80140C, (
volatile unsigned int *)0xbf801414},
1991 {(
volatile unsigned int *)0xbf801410, (
volatile unsigned int *)0xbf80141C},
1996static volatile unsigned int *func_00000f80(
volatile unsigned int *address)
2001 while ( pSSBUS_regs->address != NULL )
2003 if ( pSSBUS_regs->address == address )
2008 return pSSBUS_regs->delay;
2011static const void *GetFileDataFromImage(
const void *start,
const void *end,
const char *filename);
2013static void TerminateResidentEntriesDI(
const char *command,
unsigned int options)
2016 volatile unsigned int **pReg;
2018 TerminateResidentLibraries(
" ReBootStart:di: Terminate resident Libraries\n", options, 0);
2020 asm volatile(
"mfc0 %0, $15" :
"=r"(prid) :);
2022 if ( !(options & 1) )
2024 pReg = (prid < 0x10 || ((*(
volatile unsigned int *)0xbf801450) & 8)) ? *(
volatile unsigned int ***)0xbfc02008 :
2025 *(volatile unsigned int ***)0xbfc0200C;
2027 while ( pReg[0] != 0 )
2029 if ( func_00000f80(pReg[0]) != 0 )
2030 pReg[0] = (
void *)0xFF;
2035 if ( !(options & 2) )
2038 (prid < 0x10 || ((*(
volatile unsigned int *)0xbf801450) & 8)) ? *(
volatile unsigned int *)0xbfc02010 :
2039 *(volatile unsigned int *)0xbfc02014);
2044 const char *iopboot_entrypoint;
2049 iopboot_entrypoint = GetFileDataFromImage((
const void *)0xBFC00000, (
const void *)0xBFC10000,
"IOPBOOT");
2051 if ( command && command[0] )
2053 ml_strcpy((
char *)0x480, command);
2054 ram_size_in_mb = (QueryMemSize() + 0x100) >> 20;
2055 flagstmp = (options & 0xFF00) | 2;
2056 command_ptr = (
char *)0x480;
2060 ram_size_in_mb = (QueryMemSize() + 0x100) >> 20;
2064 ((int (*)(u32, int,
char *, u32))iopboot_entrypoint)(ram_size_in_mb, flagstmp, command_ptr, 0);
2069extern int CpuExecuteKmode(
void *func, ...);
2073 "\t" ".set push" "\n"
2074 "\t" ".set noat" "\n"
2075 "\t" ".set noreorder" "\n"
2076 "\t" "CpuExecuteKmode:" "\n"
2077 "\t" " addiu $v0, $zero, 0x0C" "\n"
2078 "\t" " syscall 0" "\n"
2081 "\t" ".set pop" "\n"
2085int ReBootStart(
const char *command,
unsigned int flags)
2087 ChangeThreadPriority(0, 7);
2088 TerminateResidentLibraries(
" ReBootStart:ei: Terminate resident Libraries\n", flags, 2);
2089 return CpuExecuteKmode(TerminateResidentEntriesDI, command, flags);
2095 unsigned short int ExtInfoEntrySize;
2100static const void *GetFileDataFromImage(
const void *start,
const void *end,
const char *filename)
2102 const u8 *ImageStart;
2103 const u8 *RomdirStart;
2109 unsigned int offset;
2118 ptr = (u32 *)file->name;
2119 if ( ptr[0] == 0x45534552 && ptr[1] == 0x54 && (*(u16 *)&ptr[2] == 0) && (((file->size + 15) & ~15) == offset) )
2122 RomdirStart = (
const u8 *)ptr;
2128 unsigned int i, offset;
2129 u8 filename_temp[12];
2132 ((u32 *)filename_temp)[0] = 0;
2133 ((u32 *)filename_temp)[1] = 0;
2134 ((u32 *)filename_temp)[2] = 0;
2135 for ( i = 0; *filename >= 0x21 && i <
sizeof(filename_temp); i++ )
2137 filename_temp[i] = *filename;
2141 if ( RomdirStart != NULL )
2145 RomdirEntry = (
const struct RomDirEntry *)RomdirStart;
2150 ((u32 *)filename_temp)[0] == ((u32 *)RomdirEntry->name)[0]
2151 && ((u32 *)filename_temp)[1] == ((u32 *)RomdirEntry->name)[1]
2152 && (*(u16 *)&((u32 *)filename_temp)[2] == *(u16 *)&((u32 *)RomdirEntry->name)[2]) )
2154 return ImageStart + offset;
2157 offset += (RomdirEntry->size + 15) & ~15;
2159 }
while ( ((u32 *)RomdirEntry->name)[0] != 0x00000000 );
2171static int linked_list_next_is_self(
const modload_ll_t *ll)
2173 return ll->next == ll;
2178 ll->next->prev = ll->prev;
2179 ll->prev->next = ll->next;
2183static int linked_list_is_circular(
const modload_ll_t *ll)
2185 return ll->prev == ll->next;
2192 ll2->prev = ll1->prev;
2194 ll2->prev->next = ll2;
int CpuResumeIntr(int state)
int QueryIntrContext(void)
int CpuSuspendIntr(int *state)
ModuleInfo_t * image_info