11 #include "irx_imports.h"
18 IRX_ID(
"Moldule_File_loader", 2, 9);
24 static SecrCardBootFile_callback_t SecrCardBootFile_func_ptr;
25 static SecrDiskBootFile_callback_t SecrDiskBootFile_func_ptr;
26 static SetLoadfileCallbacks_callback_t SetLoadfileCallbacks_func_ptr;
27 static CheckKelfPath_callback_t CheckKelfPath_func_ptr;
30 static int ModuleLoaderMutex;
31 static int ModuleLoaderSync;
151 R_MIPSSCE_MHI16 = 250,
152 R_MIPSSCE_ADDEND = 251,
162 #define SHT_LOPROC 0x70000000
163 #define SHT_LOPROC_EE_IMPORT_TAB 0x90
164 #define SHT_LOPROC_IOPMOD 0x80
165 #define SHT_HIPROC 0x7fffffff
166 #define SHT_LOUSER 0x80000000
167 #define SHT_HIUSER 0xffffffff
169 #define SHF_WRITE 0x1
170 #define SHF_ALLOC 0x2
171 #define SHF_EXECINSTR 0x4
172 #define SHF_MASKPROC 0xf0000000
177 int (*cbCpuSuspendIntr)(
int *state);
179 int (*cbCpuResumeIntr)(
int state);
181 int (*cbQueryIntrContext)(void);
184 static ModuleInfo_t *search_for_module_by_name(
const char *name);
187 static int linked_list_next_is_self(
const modload_ll_t *ll);
189 static void get_updater_boot_argument(
char *str,
int *updater_argc,
char **updater_argv,
int updater_argv_count);
190 static int spGetfsize(
void *userdata,
int in_fd);
191 static int spLseek(
void *userdata,
int in_fd,
long offset,
int whence);
192 static int spRead(
void *userdata,
int in_fd,
void *buffer,
size_t read_size);
193 static int spBread(
void *opt,
int fd,
size_t nbyte);
194 static int spSetBufSize(
void *opt,
int fd,
size_t size);
195 static int spClose(
void *userdata,
int in_fd);
196 static int spAfterOpen(
void *opt,
int fd);
197 static int spBeforeOpen(
void *opt,
const char *filename,
int flag);
198 static int spOpen(
LDfilefunc *functbl,
void *userdata,
const char *filename,
int filemode);
199 static void free_module_block(
modload_ll_t *buf,
char flags);
202 do_load_from_buffer(
void *buffer,
int position,
int *distaddr,
unsigned int distoffset,
int *result_out);
203 static int seek_read(
204 LDfilefunc *functbl,
void *userdata,
int module_fd,
int read_offset,
void *buf,
int read_size,
int *result_out);
205 static void *read_entire_loadfile(
206 LDfilefunc *functbl,
void *userdata,
int module_fd,
int *result_out,
int module_filesize,
int memory_region);
207 static int open_loadfile(
LDfilefunc *functbl,
void *userdata,
const char *filename,
int *out_filesize);
211 stop_module(
ModuleInfo_t *module_info,
int command,
int modid_2,
int arglen,
const char *args,
int *result_out);
212 static int start_module(
ModuleInfo_t *module_info,
const char *data,
int arglen,
const char *args,
int *result_out);
214 static int check_in_linked_list(
const modload_ll_t *ll);
216 static int allocate_module_block(
221 unsigned int distoffset,
224 static void ExecModuleLoad(
void *userdata);
228 static LDfilefunc default_filefunc_functable = {
229 &spBeforeOpen, &spAfterOpen, &spClose, &spSetBufSize, &spBread, &spRead, &spLseek, &spGetfsize};
231 int _start(
int argc,
char *argv[])
240 if ( RegisterLibraryEntries(&_exp_modload) < 0 )
247 BootMode_4 = QueryBootMode(4);
250 if ( (((u32 *)BootMode_4)[0] & 0xff) == 2 )
252 AddRebootNotifyHandler((BootupCallback_t)modload_post_boot_callback, 1, 0);
259 sysmem_module = search_for_module_by_name(
"System_Memory_Manager");
260 if ( sysmem_module && sysmem_module->version >= 0x201u )
262 GetSysmemInternalData()->intr_suspend_tbl = (
void *)&intrman_callbacks;
264 loadcore_module = search_for_module_by_name(
"Module_Manager");
265 if ( loadcore_module )
267 if ( loadcore_module->version >= 0x205u )
269 GetLoadcoreInternalData()->intr_suspend_tbl = (
void *)&intrman_callbacks;
273 thparam.attr = 0x2000000;
274 thparam.thread = ExecModuleLoad;
275 thparam.priority = 8;
276 thparam.stacksize = 4096;
278 modLoadCB = CreateThread(&thparam);
280 semaparam.initial = 1;
282 semaparam.option = 0;
283 ModuleLoaderMutex = CreateSema(&semaparam);
284 memset(&efparam, 0,
sizeof(efparam));
285 ModuleLoaderSync = CreateEventFlag(&efparam);
286 linked_list_set_self(&load_memory_ll);
290 void *AllocLoadMemory(
int type,
unsigned int size,
void *addr)
297 memset(newbuf, -1, 32);
298 linked_list_set_self(&newbuf->ll[2]);
300 linked_list_add_after(&load_memory_ll, newbuf->ll);
304 int FreeLoadMemory(
void *in_area)
312 if ( check_in_linked_list(area->ll) )
316 else if ( !linked_list_next_is_self(&area->ll[2]) )
322 linked_list_remove(area->ll);
323 ret = FreeSysMemory(area);
329 int SetModuleFlags(
int modid,
int flag)
336 return KE_ILLEGAL_CONTEXT;
338 if ( (flag & 0xFFFFFFBF) != 0 )
340 return KE_ILLEGAL_FLAG;
343 image_info = GetLoadcoreInternalData()->
image_info;
344 while ( image_info && modid != image_info->id )
346 image_info = image_info->next;
351 return KE_UNKNOWN_MODULE;
358 int LoadModuleWithOption(
const char *filename,
const LMWOoption *option)
363 if ( (
unsigned int)option->position >= 3 )
364 return KE_ILLEGAL_POSITION;
365 switch ( option->access )
372 return KE_ILLEGAL_ACCESS;
375 mltargs.position = option->position;
376 mltargs.filename = filename;
378 mltargs.access = option->access & 0xFF;
379 mltargs.distaddr = option->distaddr;
380 mltargs.distoffset = option->distoffset;
381 functable = option->functable;
383 functable = &default_filefunc_functable;
384 mltargs.functable = functable;
385 mltargs.funcopt = option->funcopt;
386 return ModuleLoaderThread(&mltargs);
389 int LoadModuleAddress(
const char *name,
void *addr,
int offset)
395 mltargs.position = 2;
397 mltargs.position = 0;
399 mltargs.filename = name;
401 mltargs.distaddr = addr;
402 mltargs.distoffset = offset;
403 mltargs.functable = &default_filefunc_functable;
405 return ModuleLoaderThread(&mltargs);
408 int LoadModule(
const char *name)
410 return LoadModuleAddress(name, 0, 0);
413 int LoadModuleBufferAddress(
void *buffer,
void *addr,
int offset)
419 mltargs.position = 2;
421 mltargs.position = 0;
422 mltargs.buffer = buffer;
424 mltargs.filename = 0;
425 mltargs.distaddr = addr;
426 mltargs.distoffset = offset;
427 return ModuleLoaderThread(&mltargs);
430 int LoadModuleBuffer(
void *buffer)
432 return LoadModuleBufferAddress(buffer, 0, 0);
435 int LoadStartModule(
const char *name,
int arglen,
const char *args,
int *result)
441 mltargs.filename = name;
442 mltargs.position = 0;
444 mltargs.distaddr = 0;
445 mltargs.distoffset = 0;
446 mltargs.arglen = arglen;
448 mltargs.result = result;
449 mltargs.functable = &default_filefunc_functable;
451 return ModuleLoaderThread(&mltargs);
454 int StartModule(
int modid,
const char *name,
int arglen,
const char *args,
int *result)
458 mltargs.modid = modid;
460 mltargs.filename = name;
461 mltargs.arglen = arglen;
463 mltargs.result = result;
464 return ModuleLoaderThread(&mltargs);
467 int StopModule(
int modid,
int arglen,
const char *args,
int *result)
474 return KE_ILLEGAL_CONTEXT;
476 modid_2 = SearchModuleByAddress(__builtin_return_address(0));
479 Kprintf(
"StopModule(): panic !!! call from unknown Module !!!\n");
480 return KE_CAN_NOT_STOP;
483 mltargs.modid = modid;
484 mltargs.modid_2 = modid_2;
485 mltargs.filename = 0;
486 mltargs.arglen = arglen;
488 mltargs.result = result;
489 return ModuleLoaderThread(&mltargs);
492 int UnloadModule(
int modid)
496 mltargs.modid = modid;
498 mltargs.filename = 0;
502 return ModuleLoaderThread(&mltargs);
505 int SelfStopModule(
int arglen,
const char *args,
int *result)
512 return KE_ILLEGAL_CONTEXT;
514 modid = SearchModuleByAddress(__builtin_return_address(0));
517 Kprintf(
"SelfStopModule(): panic !!! call from unknown Module !!!\n");
518 return KE_ILLEGAL_CONTEXT;
521 mltargs.modid = modid;
522 mltargs.modid_2 = modid;
523 mltargs.filename = 0;
524 mltargs.arglen = arglen;
526 mltargs.result = result;
527 return ModuleLoaderThread(&mltargs);
530 void SelfUnloadModule(
void)
541 Kprintf(
"SelfUnloadModule(): panic !!! illegal context !!!\n");
543 ThreadId = GetThreadId();
546 Kprintf(
"SelfUnloadModule(): panic !!! can't get ThreadID !!!\n");
548 modid = SearchModuleByAddress(__builtin_return_address(0));
551 Kprintf(
"SelfUnloadModule(): panic !!! call from unknown Module !!!\n");
554 mltargs.modid = modid;
555 mltargs.modid_2 = ThreadId;
556 mltargs.filename = 0;
560 mltargs.ret_ptr = &ret_tmp;
561 if ( ThreadId == modLoadCB )
563 Kprintf(
"SelfUnloadModule(): panic !!! Unexpected case !!!\n");
565 mltargs.thread_ef = ModuleLoaderSync;
566 sema_res = WaitSema(ModuleLoaderMutex);
569 Kprintf(
"SelfUnloadModule(): panic !!! Unload fail semerror=%d !!!\n", sema_res);
571 StartThread(modLoadCB, &mltargs);
572 ChangeThreadPriority(0, 123);
573 WaitEventFlag(ModuleLoaderSync, 1u, 17, &efbits);
574 SignalSema(ModuleLoaderMutex);
575 Kprintf(
"SelfUnloadModule(): panic !!! Unload fail error=%d !!!\n", ret_tmp);
579 Kprintf(
"Thread 0x%x. Unload Fail\n", GetThreadId());
583 int SearchModuleByName(
const char *name)
591 for ( i = GetLoadcoreInternalData()->image_info; i; i = i->next )
593 if ( !strcmp(name, i->name) && modid < i->
id )
598 return KE_UNKNOWN_MODULE;
602 int SearchModuleByAddress(
const void *addr)
608 image_info = SearchModuleCBByAddr((
void *)addr);
611 return KE_UNKNOWN_MODULE;
612 return image_info->id;
615 int LoadStartKelfModule(
const char *name,
int arglen,
const char *args,
int *result)
618 void *iop_exec_buffer;
619 void *iop_exec_encrypted_buffer;
628 functable = &default_filefunc_functable;
629 iop_exec_buffer = NULL;
634 module_fd = open_loadfile(functable, NULL, name, &module_filesize);
639 iop_exec_encrypted_buffer = read_entire_loadfile(functable, NULL, module_fd, &ret_tmp, module_filesize, 1);
640 if ( iop_exec_encrypted_buffer == NULL )
644 if ( CheckKelfPath_func_ptr && CheckKelfPath_func_ptr(name, &card_port, &card_slot) && SecrCardBootFile_func_ptr )
646 iop_exec_buffer = SecrCardBootFile_func_ptr(card_port, card_slot, iop_exec_encrypted_buffer);
648 else if ( SecrDiskBootFile_func_ptr )
650 iop_exec_buffer = SecrDiskBootFile_func_ptr(iop_exec_encrypted_buffer);
652 ret_tmp = KE_ILLEGAL_OBJECT;
653 if ( iop_exec_buffer )
655 ret_tmp = LoadModuleBuffer(iop_exec_buffer);
659 ret_tmp = StartModule(ret_tmp, name, arglen, args, result);
662 FreeSysMemory(iop_exec_encrypted_buffer);
667 int GetModuleIdListByName(
const char *name,
int *readbuf,
int readbufsize,
int *modulecount)
677 for ( image_info = GetLoadcoreInternalData()->image_info; image_info; image_info = image_info->next )
681 if ( strcmp(name, image_info->name) != 0 )
684 if ( readbufoffset < readbufsize )
687 readbuf[readbufoffset] = image_info->id;
693 *modulecount = modcount;
694 return readbufoffset;
697 int GetModuleIdList(
int *readbuf,
int readbufsize,
int *modulecount)
699 return GetModuleIdListByName(0, readbuf, readbufsize, modulecount);
709 image_info = GetLoadcoreInternalData()->
image_info;
710 while ( image_info && modid != image_info->id )
712 image_info = image_info->next;
717 return KE_UNKNOWN_MODULE;
720 name = image_info->name;
722 strncpy(status->name, name, 56);
723 status->name[55] = 0;
724 status->version = image_info->version;
725 status->id = image_info->id;
726 status->flags = image_info->
newflags;
727 status->entry_addr = image_info->
entry;
728 status->gp_value = image_info->gp;
729 status->text_addr = image_info->text_start;
730 status->text_size = image_info->text_size;
731 status->data_size = image_info->data_size;
732 status->bss_size = image_info->bss_size;
737 void GetModloadInternalData(
void **pInternalData)
740 *pInternalData = NULL;
743 static void ExecModuleLoad(
void *userdata)
753 switch ( mltargs->command )
756 mi = do_load(mltargs, &res_tmp);
757 ChangeThreadPriority(0, 8);
760 mi = SearchModuleCBByID(mltargs->modid);
765 res_tmp = start_module(mi, mltargs->filename, mltargs->arglen, mltargs->args, mltargs->result);
768 mi = do_load_from_buffer(
769 mltargs->buffer, mltargs->position, (
int *)mltargs->distaddr, mltargs->distoffset, &res_tmp);
772 mi = do_load(mltargs, &res_tmp);
773 ChangeThreadPriority(0, 8);
778 res_tmp = start_module(mi, mltargs->filename, mltargs->arglen, mltargs->args, mltargs->result);
782 mi = SearchModuleCBByID(mltargs->modid);
787 res_tmp = stop_module(mi, mltargs->command, mltargs->modid_2, mltargs->arglen, mltargs->args, mltargs->result);
791 mi = SearchModuleCBByID(mltargs->modid);
796 res_tmp = unload_module(mi);
801 if ( mltargs->command != 7 )
805 modid_2 = mltargs->modid_2;
806 ChangeThreadPriority(0, 1);
807 TerminateThread(modid_2);
808 DeleteThread(modid_2);
809 SignalSema(ModuleLoaderMutex);
816 *mltargs->ret_ptr = res_tmp;
820 *mltargs->ret_ptr = KE_UNKNOWN_MODULE;
824 *mltargs->ret_ptr = mi->id;
826 if ( mltargs->thread_ef )
828 ChangeThreadPriority(0, 1);
829 SetEventFlag(mltargs->thread_ef, 1u);
842 return KE_ILLEGAL_CONTEXT;
844 result = GetThreadId();
851 mltargs->ret_ptr = &ret_tmp;
852 if ( result == modLoadCB )
854 mltargs->thread_ef = 0;
855 ExecModuleLoad((
void *)mltargs);
859 mltargs->thread_ef = ModuleLoaderSync;
860 result = WaitSema(ModuleLoaderMutex);
865 StartThread(modLoadCB, mltargs);
866 WaitEventFlag(ModuleLoaderSync, 1u, 17, &efbits);
867 SignalSema(ModuleLoaderMutex);
876 image_info = GetLoadcoreInternalData()->
image_info;
877 while ( image_info != NULL )
879 if ( modid == image_info->id )
883 image_info = image_info->next;
888 static ModuleInfo_t *search_for_module_by_name(
const char *name)
892 image_info = GetLoadcoreInternalData()->
image_info;
893 while ( image_info != NULL )
895 if ( strcmp(name, image_info->name) == 0 )
899 image_info = image_info->next;
908 next = load_memory_ll.next;
909 if ( load_memory_ll.next == &load_memory_ll )
914 if ( next == &load_memory_ll )
932 BootMode_4 = QueryBootMode(4);
936 reboot_type = (((u32 *)BootMode_4)[0] >> 8) & 0xff;
938 BootMode_5 = QueryBootMode(5);
942 char *updater_argv[16];
944 memset(updater_argv, 0,
sizeof(updater_argv));
946 get_updater_boot_argument(
947 (
char *)BootMode_5[1], &updater_argc, updater_argv, (
sizeof(updater_argv) /
sizeof(updater_argv[0])) - 1);
948 if ( reboot_type == 0 )
952 mltargs.position = 2;
954 mltargs.distaddr = (
void *)0x100000;
955 mltargs.distoffset = 0;
956 mltargs.functable = &default_filefunc_functable;
958 mltargs.filename = updater_argv[0];
959 module_info = do_load(&mltargs, &module_result);
961 else if ( reboot_type == 1 )
964 void *iop_exec_buffer;
965 void *iop_exec_encrypted_buffer;
973 functable = &default_filefunc_functable;
974 iop_exec_buffer = NULL;
975 iop_exec_encrypted_buffer = NULL;
976 module_fd = open_loadfile(functable, NULL, updater_argv[0], &module_filesize);
977 if ( module_fd >= 0 )
979 iop_exec_encrypted_buffer =
980 read_entire_loadfile(functable, NULL, module_fd, &module_result, module_filesize, 1);
981 if ( iop_exec_encrypted_buffer )
984 CheckKelfPath_func_ptr && CheckKelfPath_func_ptr(updater_argv[0], &card_port, &card_slot)
985 && SecrCardBootFile_func_ptr )
987 iop_exec_buffer = SecrCardBootFile_func_ptr(card_port, card_slot, iop_exec_encrypted_buffer);
989 else if ( SecrDiskBootFile_func_ptr )
991 iop_exec_buffer = SecrDiskBootFile_func_ptr(iop_exec_encrypted_buffer);
993 if ( iop_exec_buffer )
995 module_info = do_load_from_buffer(iop_exec_buffer, 2, (
void *)0x100000, 0, &module_result);
1002 FreeSysMemory(iop_exec_encrypted_buffer);
1019 if ( module_result == 0 )
1023 printf(
"return from updater '%s' return value = %d\n", updater_argv[0], module_result);
1026 printf(
"updater '%s' can't load\n", updater_argv[0]);
1029 printf(
"Reboot fail! need file name argument\n");
1033 static int start_module(
ModuleInfo_t *module_info,
const char *data,
int arglen,
const char *args,
int *result_out)
1035 const char *args_ptr;
1036 char *in_argv_strs_ptr;
1040 int in_argv_size_strs;
1042 char **in_argv_ptrs;
1045 if ( (module_info->
newflags & 0xF) != 1 )
1047 return KE_ALREADY_STARTED;
1050 data_strlen = strlen(data) + 1;
1051 in_argv_size_strs = data_strlen;
1052 for ( args_ptr = args; args_ptr < &args[arglen]; )
1054 int str_len = strlen(args_ptr) + 1;
1055 in_argv_size_strs += str_len;
1056 args_ptr += str_len;
1059 if ( in_argv_size_strs < data_strlen + arglen )
1061 in_argv_size_strs = data_strlen + arglen;
1063 in_argv_strs = __builtin_alloca(in_argv_size_strs);
1064 memcpy(in_argv_strs, data, data_strlen);
1065 memcpy(in_argv_strs + data_strlen, args, arglen);
1066 in_argv_ptrs = __builtin_alloca((in_argc + 1) *
sizeof(
char *));
1067 for ( i = 0, in_argv_strs_ptr = in_argv_strs; i < in_argc && in_argv_strs_ptr < &in_argv_strs[in_argv_size_strs]; )
1069 int str_len = strlen(in_argv_strs_ptr) + 1;
1070 in_argv_ptrs[i] = in_argv_strs_ptr;
1072 in_argv_strs_ptr += str_len;
1074 in_argv_ptrs[in_argc] = NULL;
1079 ChangeThreadPriority(0, 8);
1082 *result_out = module_result;
1084 switch ( module_result & 3 )
1096 UnLinkLibraryEntries((
void *)module_info->text_start, module_info->text_size);
1097 if ( (module_info->
newflags & 0x40) != 0 )
1099 memset((
void *)module_info->text_start, 77, module_info->text_size);
1101 (
void *)(module_info->text_start + module_info->text_size),
1103 module_info->data_size + module_info->bss_size);
1105 ReleaseModule(module_info);
1106 free_module_block((
modload_ll_t *)module_info, module_info->newflags);
1120 stop_module(
ModuleInfo_t *module_info,
int command,
int modid_2,
int arglen,
const char *args,
int *result_out)
1123 const char *args_ptr;
1124 char *in_argv_strs_ptr;
1128 int in_argv_size_strs;
1130 char **in_argv_ptrs;
1133 switch ( module_info->
newflags & 0xF )
1137 return KE_NOT_STARTED;
1140 return KE_ALREADY_STOPPING;
1143 return KE_ALREADY_STOPPED;
1147 if ( (module_info->
newflags & 0x10) == 0 )
1148 return KE_NOT_REMOVABLE;
1149 if ( command == 4 && modid_2 == module_info->id )
1150 return KE_CAN_NOT_STOP;
1155 data_strlen = strlen(data) + 1;
1156 in_argv_size_strs = data_strlen;
1157 for ( args_ptr = args; args_ptr < &args[arglen]; )
1159 int str_len = strlen(args_ptr) + 1;
1160 in_argv_size_strs += str_len;
1161 args_ptr += str_len;
1164 if ( in_argv_size_strs < data_strlen + arglen )
1166 in_argv_size_strs = data_strlen + arglen;
1168 in_argv_strs = __builtin_alloca(in_argv_size_strs);
1169 memcpy(in_argv_strs, data, data_strlen);
1170 memcpy(in_argv_strs + data_strlen, args, arglen);
1171 in_argv_ptrs = __builtin_alloca((in_argc + 1) *
sizeof(
char *));
1172 for ( i = 0, in_argv_strs_ptr = in_argv_strs; i < in_argc && in_argv_strs_ptr < &in_argv_strs[in_argv_size_strs]; )
1174 int str_len = strlen(in_argv_strs_ptr) + 1;
1175 in_argv_ptrs[i] = in_argv_strs_ptr;
1177 in_argv_strs_ptr += str_len;
1179 in_argv_ptrs[in_argc] = NULL;
1188 ChangeThreadPriority(0, 8);
1190 *result_out = module_result;
1192 switch ( module_result & 3 )
1197 return KE_CAN_NOT_STOP;
1209 return KE_CAN_NOT_STOP;
1222 flags_masked1 = newflags & 0xF;
1223 if ( (newflags & 0x10) == 0 && flags_masked1 != 1 )
1225 return KE_NOT_REMOVABLE;
1227 switch ( flags_masked1 )
1234 return KE_NOT_STOPPED;
1237 UnLinkLibraryEntries((
void *)module_info->text_start, module_info->text_size);
1238 if ( (module_info->
newflags & 0x40) != 0 )
1240 memset((
void *)module_info->text_start, 77, module_info->text_size);
1242 (
void *)(module_info->text_start + module_info->text_size), -1, module_info->data_size + module_info->bss_size);
1244 ReleaseModule(module_info);
1245 free_module_block((
modload_ll_t *)module_info, module_info->newflags);
1250 int IsIllegalBootDevice(
const char *arg1)
1261 void *entire_loadfile;
1264 entire_loadfile = read_entire_loadfile(
1265 mltargs->functable, mltargs->funcopt, module_fd, result_out, module_filesize, mltargs->position != 1);
1266 if ( !entire_loadfile )
1271 *module_block = allocate_module_block(
1276 mltargs->distoffset,
1279 if ( !(*module_block) )
1281 FreeSysMemory(entire_loadfile);
1284 LoadExecutableObject(entire_loadfile, fi);
1286 FreeSysMemory(entire_loadfile);
1288 return (
ModuleInfo_t *)((
char *)fi->text_start - 0x30);
1299 char *relocate_offset;
1318 functable = mltargs->functable;
1319 funcopt = mltargs->funcopt;
1323 if ( seek_read(functable, funcopt, module_fd, 0, &lshdr, 144, result_out) != 0 )
1326 module_block = allocate_module_block(
1327 &lshdr, fi, mltargs->position, (
modload_load_memory_t *)mltargs->distaddr, mltargs->distoffset, &res_tmp);
1331 int total_section_size;
1335 if ( !module_block )
1339 if ( fi->ModuleType == 1 )
1341 res_tmp = KE_ILLEGAL_OBJECT;
1344 text_start = (
char *)fi->text_start;
1345 data_size = fi->data_size;
1346 text_end = &text_start[fi->text_size];
1348 dest = (u32 *)&text_end[data_size];
1349 total_section_size = lshdr.elfhdr.shentsize * lshdr.elfhdr.shnum;
1350 if ( CheckThreadStack() < total_section_size + 768 )
1352 res_tmp = KE_NO_MEMORY;
1355 elfshdr = __builtin_alloca(total_section_size);
1357 functable, funcopt, module_fd, lshdr.phdr[1].offset, fi->text_start, lshdr.phdr[1].filesz, &res_tmp) )
1361 if ( seek_read(functable, funcopt, module_fd, lshdr.elfhdr.shoff, elfshdr, total_section_size, &res_tmp) )
1365 if ( fi->ModuleType != 4 )
1369 relocate_offset = (
char *)fi->text_start;
1370 fi->EntryPoint = &relocate_offset[(u32)(u8 *)fi->EntryPoint];
1371 fi->gp = &relocate_offset[(u32)(u8 *)fi->gp];
1372 mod_id = fi->mod_id;
1374 fi->mod_id = (
IopModuleID_t *)&relocate_offset[(u32)(u8 *)mod_id];
1376 for ( i = 1; i < lshdr.elfhdr.shnum; i += 1 )
1378 type = elfshdr[i].type;
1379 if ( (type == 9 || type == 4) && size < elfshdr[i].size )
1380 size = elfshdr[i].size;
1382 switch ( mltargs->access )
1386 if ( fi->bss_size >= size )
1392 modulearea = AllocSysMemory(1, size, 0);
1396 res_tmp = KE_NO_MEMORY;
1400 for ( i = 1; i < lshdr.elfhdr.shnum; i += 1 )
1402 if ( elfshdr[i].type != 9 )
1406 if ( seek_read(functable, funcopt, module_fd, elfshdr[i].offset, modulearea, elfshdr[i].size, &res_tmp) )
1408 entsize = elfshdr[i].entsize;
1411 ApplyElfRelSection(fi->text_start, modulearea, elfshdr[i].size / entsize);
1417 res_tmp = functable->setBufSize(funcopt, module_fd, size);
1422 for ( i = 1; i < lshdr.elfhdr.shnum; i += 1 )
1424 if ( elfshdr[i].type != 9 )
1428 if ( seek_read(functable, funcopt, module_fd, elfshdr[i].offset, 0, 0, &res_tmp) )
1430 res_tmp = functable->beforeRead(funcopt, module_fd, elfshdr[i].size);
1433 shdrcnt = elfshdr[i].size / elfshdr[i].entsize;
1434 for ( j = 0; j < shdrcnt; j += relnumi1 )
1437 if ( (elfrelhdr[0].
info & 0xFF) == 5 || (elfrelhdr[0].
info & 0xFF) == 250 )
1443 for ( k = 0; k < relnumi1; k += 1 )
1445 if ( seek_read(functable, funcopt, module_fd, -1, &elfrelhdr[k], 8, &res_tmp) )
1451 ApplyElfRelSection(fi->text_start, elfrelhdr, relnumi1);
1463 functable->close(funcopt, module_fd);
1466 *result_out = res_tmp;
1467 if ( ptr || (module_block &&
ModInfo) )
1472 if ( module_block &&
ModInfo )
1482 *module_block_ptr = module_block;
1491 memset(dest, 0, fi->bss_size);
1506 int module_filesize;
1510 *result_out = KE_ILLEGAL_OBJECT;
1511 if ( !mltargs->filename )
1516 if ( IsIllegalBootDevice(mltargs->filename) != 0 )
1520 module_fd = open_loadfile(mltargs->functable, mltargs->funcopt, mltargs->filename, &module_filesize);
1521 if ( module_fd < 0 )
1523 *result_out = module_fd;
1526 *result_out = KE_OK;
1528 switch ( mltargs->access )
1532 module_info = do_load_noseek(mltargs, module_fd, module_filesize, &fi, &module_block, result_out);
1538 module_info = do_load_seek(mltargs, module_fd, &fi, &module_block, result_out);
1551 if ( LinkLibraryEntries(fi.text_start, fi.text_size) < 0 )
1553 free_module_block((
modload_ll_t *)module_info, module_block);
1555 *result_out = KE_LINKERR;
1560 module_info->
newflags = module_block;
1561 RegisterModule(module_info);
1567 static int open_loadfile(
LDfilefunc *functbl,
void *userdata,
const char *filename,
int *out_filesize)
1572 out_fd = spOpen(functbl, userdata, filename, 1);
1575 filesize = functbl->getfsize(userdata, out_fd);
1576 *out_filesize = filesize;
1577 if ( filesize <= 0 )
1585 static void *read_entire_loadfile(
1586 LDfilefunc *functbl,
void *userdata,
int module_fd,
int *result_out,
int module_filesize,
int memory_region)
1591 *result_out = KE_OK;
1593 tmp_mem = AllocSysMemory(memory_region, module_filesize, 0);
1597 *result_out = KE_NO_MEMORY;
1598 functbl->close(userdata, module_fd);
1601 if ( seek_read(functbl, userdata, module_fd, 0, tmp_mem, module_filesize, result_out) == 0 )
1604 FreeSysMemory(tmp_mem);
1608 functbl->close(userdata, module_fd);
1612 static int seek_read(
1613 LDfilefunc *functbl,
void *userdata,
int module_fd,
int read_offset,
void *buf,
int read_size,
int *result_out)
1615 if ( !((read_offset < 0 || (functbl->lseek(userdata, module_fd, read_offset, 0) >= 0))
1616 && (read_size <= 0 || (functbl->read(userdata, module_fd, buf, read_size) == read_size))) )
1618 functbl->close(userdata, module_fd);
1619 *result_out = KE_FILEERR;
1626 do_load_from_buffer(
void *buffer,
int position,
int *distaddr,
unsigned int distoffset,
int *result_out)
1636 allocate_module_block(buffer, &fi, position, (
modload_load_memory_t *)distaddr, distoffset, result_out);
1639 LoadExecutableObject(buffer, &fi);
1640 if ( LinkLibraryEntries(fi.text_start, fi.text_size) < 0 )
1642 free_module_block((
modload_ll_t *)fi.text_start - 6, module_block & 0xFFFF);
1643 *result_out = KE_LINKERR;
1647 module_info = (
ModuleInfo_t *)((
char *)fi.text_start - 0x30);
1649 module_info->
newflags = module_block & 0xFFFF;
1650 RegisterModule(module_info);
1667 v4 = (
char *)a1 + a2;
1669 if ( v6 < (
char *)a3 )
1671 return v6 < (
char *)a4 + (
int)a3;
1683 memsz_add = fi->MemSize + 64;
1684 if ( distoffset == 1 )
1686 next = &loadmem->ll[2];
1687 prev = loadmem->ll[2].prev;
1688 v8 = (
modload_ll_t *)((
char *)prev + (
unsigned int)prev[1].next);
1694 if ( (distoffset < 0x20) || ((distoffset & 0xF) != 0) )
1696 *result_out = KE_ILLEGAL_OFFSET;
1699 next = loadmem->ll[2].next;
1700 v8 = (
modload_ll_t *)((
char *)loadmem->ll + distoffset);
1701 v10 = &loadmem->ll[2];
1702 for ( i = next; i != v10; i = i->next )
1711 (load_memory_helper_cmpinner(v8, memsz_add, prev, prev[1].next) != 0)
1712 || (load_memory_helper_cmpinner(v8, memsz_add, next, next[1].next) != 0) )
1714 *result_out = KE_MEMINUSE;
1717 linked_list_add_after(next, v8);
1722 static int allocate_module_block(
1725 switch ( ProbeExecutableObject(buf, fi) )
1730 char *text_start_tmp;
1733 text_start_tmp = (
char *)fi->text_start;
1734 allocaddr1 = (
char *)(((
unsigned int)(text_start_tmp - 0x30) >> 8 << 8) & 0x1FFFFFFF);
1735 if ( AllocSysMemory(2, &text_start_tmp[fi->MemSize] - allocaddr1, allocaddr1) != 0 )
1737 if ( (
int)QueryBlockTopAddress(allocaddr1) <= 0 )
1738 *result_out = KE_NO_MEMORY;
1740 *result_out = KE_MEMINUSE;
1745 if ( memalloctype == 2 && distoffset )
1748 if ( check_in_linked_list(loadmem->ll) == 0 )
1750 fi->text_start = load_memory_helper(fi, loadmem, distoffset, result_out);
1751 if ( !fi->text_start )
1753 fi->text_start = ((
char *)fi->text_start) + 0x30;
1761 if ( memalloctype == 2 )
1763 allocaddr2 = loadmem;
1769 fi->text_start = AllocSysMemory(memalloctype, fi->MemSize + 0x30, allocaddr2);
1771 if ( !fi->text_start )
1773 *result_out = KE_NO_MEMORY;
1776 fi->text_start = ((
char *)fi->text_start) + 0x30;
1781 *result_out = KE_ILLEGAL_OBJECT;
1787 static void free_module_block(
modload_ll_t *buf,
char flags)
1789 if ( (flags & 0x20) != 0 )
1790 linked_list_remove(buf - 2);
1792 FreeSysMemory((
void *)((
unsigned int)buf >> 8 << 8));
1795 static int spOpen(
LDfilefunc *functbl,
void *userdata,
const char *filename,
int filemode)
1799 functbl->beforeOpen(userdata, filename, filemode);
1800 ret_fd = open(filename, filemode);
1801 functbl->afterOpen(userdata, ret_fd);
1805 static int spBeforeOpen(
void *opt,
const char *filename,
int flag)
1813 static int spAfterOpen(
void *opt,
int fd)
1820 static int spClose(
void *userdata,
int in_fd)
1824 return close(in_fd);
1827 static int spSetBufSize(
void *opt,
int fd,
size_t size)
1835 static int spBread(
void *opt,
int fd,
size_t nbyte)
1843 static int spRead(
void *userdata,
int in_fd,
void *buffer,
size_t read_size)
1848 return read(in_fd, buffer, read_size);
1851 static int spLseek(
void *userdata,
int in_fd,
long offset,
int whence)
1856 return lseek(in_fd, offset, whence);
1859 static int spGetfsize(
void *userdata,
int in_fd)
1864 ret = lseek(in_fd, 0, 2);
1871 static char *get_next_non_whitespace_string(
char *str)
1875 if ( *str !=
' ' && *str !=
'\t' && *str !=
'\n' )
1884 static char *get_non_null_string(
char *str)
1886 while ( *str && *str !=
' ' && *str !=
'\t' && *str !=
'\n' )
1893 static void get_updater_boot_argument(
char *str,
int *updater_argc,
char **updater_argv,
int updater_argv_count)
1895 char *next_non_whitespace_string;
1896 int updater_argc_cur;
1898 next_non_whitespace_string = get_next_non_whitespace_string(str);
1899 updater_argc_cur = 0;
1900 while ( *next_non_whitespace_string && updater_argc_cur < updater_argv_count )
1902 char *non_null_string;
1904 *updater_argv = next_non_whitespace_string;
1906 non_null_string = get_non_null_string(next_non_whitespace_string);
1907 updater_argc_cur += 1;
1908 if ( !*non_null_string )
1912 *non_null_string = 0;
1913 next_non_whitespace_string = get_next_non_whitespace_string(non_null_string + 1);
1915 *updater_argc = updater_argc_cur;
1918 void SetSecrmanCallbacks(
1919 SecrCardBootFile_callback_t SecrCardBootFile_fnc,
1920 SecrDiskBootFile_callback_t SecrDiskBootFile_fnc,
1921 SetLoadfileCallbacks_callback_t SetLoadfileCallbacks_fnc)
1923 SecrCardBootFile_func_ptr = SecrCardBootFile_fnc;
1924 SecrDiskBootFile_func_ptr = SecrDiskBootFile_fnc;
1925 SetLoadfileCallbacks_func_ptr = SetLoadfileCallbacks_fnc;
1928 void SetCheckKelfPathCallback(CheckKelfPath_callback_t CheckKelfPath_fnc)
1930 CheckKelfPath_func_ptr = CheckKelfPath_fnc;
1933 void GetLoadfileCallbacks(
1934 CheckKelfPath_callback_t *CheckKelfPath_fnc, SetLoadfileCallbacks_callback_t *SetLoadfileCallbacks_fnc)
1936 *CheckKelfPath_fnc = CheckKelfPath_func_ptr;
1937 *SetLoadfileCallbacks_fnc = SetLoadfileCallbacks_func_ptr;
1940 static void ml_strcpy(
char *dst,
const char *src)
1949 static void TerminateResidentLibraries(
const char *message,
unsigned int options,
int mode)
1954 unsigned int enable_debug;
1956 enable_debug = options & 0x80000000;
1957 if ( enable_debug != 0 )
1960 if ( (LoadcoreData = GetLoadcoreInternalData()) != NULL )
1962 ModuleData = LoadcoreData->let_next;
1963 while ( ModuleData != NULL )
1965 NextModule = ModuleData->prev;
1969 if ( !(ModuleData->flags & 6) )
1971 ModuleData = NextModule;
1975 else if ( (ModuleData->flags & 6) == 2 )
1977 ModuleData = NextModule;
1981 ExportTable = ModuleData->exports;
1982 if ( ExportTable[1] != NULL && ExportTable[2] != NULL )
1984 int (*pexit)(
int arg1);
1986 pexit = ExportTable[2];
1987 if ( enable_debug != 0 )
1988 Kprintf(
" %.8s %x \n", ModuleData->name, pexit);
1992 ModuleData = NextModule;
2000 volatile unsigned int *address, *delay;
2005 {(
volatile unsigned int *)0xbf801000, (
volatile unsigned int *)0xbf801008},
2006 {(
volatile unsigned int *)0xbf801400, (
volatile unsigned int *)0xbf80100C},
2007 {(
volatile unsigned int *)0xbf801404, (
volatile unsigned int *)0xbf801014},
2008 {(
volatile unsigned int *)0xbf801408, (
volatile unsigned int *)0xbf801018},
2009 {(
volatile unsigned int *)0xbf80140C, (
volatile unsigned int *)0xbf801414},
2010 {(
volatile unsigned int *)0xbf801410, (
volatile unsigned int *)0xbf80141C},
2015 static volatile unsigned int *func_00000f80(
volatile unsigned int *address)
2020 while ( pSSBUS_regs->address != NULL )
2022 if ( pSSBUS_regs->address == address )
2027 return pSSBUS_regs->delay;
2030 static const void *GetFileDataFromImage(
const void *start,
const void *end,
const char *filename);
2032 static void TerminateResidentEntriesDI(
const char *command,
unsigned int options)
2035 volatile unsigned int **pReg;
2037 TerminateResidentLibraries(
" ReBootStart:di: Terminate resident Libraries\n", options, 0);
2041 if ( !(options & 1) )
2043 pReg = (prid < 0x10 || ((*(
volatile unsigned int *)0xbf801450) & 8)) ? *(
volatile unsigned int ***)0xbfc02008 :
2044 *(
volatile unsigned int ***)0xbfc0200C;
2046 while ( pReg[0] != 0 )
2048 if ( func_00000f80(pReg[0]) != 0 )
2049 pReg[0] = (
void *)0xFF;
2054 if ( !(options & 2) )
2057 (prid < 0x10 || ((*(
volatile unsigned int *)0xbf801450) & 8)) ? *(
volatile unsigned int *)0xbfc02010 :
2058 *(
volatile unsigned int *)0xbfc02014);
2063 const char *iopboot_entrypoint;
2068 iopboot_entrypoint = GetFileDataFromImage((
const void *)0xBFC00000, (
const void *)0xBFC10000,
"IOPBOOT");
2070 if ( command && command[0] )
2072 ml_strcpy((
char *)0x480, command);
2073 ram_size_in_mb = (QueryMemSize() + 0x100) >> 20;
2074 flagstmp = (options & 0xFF00) | 2;
2075 command_ptr = (
char *)0x480;
2079 ram_size_in_mb = (QueryMemSize() + 0x100) >> 20;
2083 ((int (*)(u32 ram_mb,
int flags,
char *cmdptr, u32 xunk))iopboot_entrypoint)(ram_size_in_mb, flagstmp, command_ptr, 0);
2088 extern int CpuExecuteKmode(
void *func, ...);
2092 "\t" ".set push" "\n"
2093 "\t" ".set noat" "\n"
2094 "\t" ".set noreorder" "\n"
2095 "\t" "CpuExecuteKmode:" "\n"
2096 "\t" " addiu $v0, $zero, 0x0C" "\n"
2097 "\t" " syscall 0" "\n"
2100 "\t" ".set pop" "\n"
2104 int ReBootStart(
const char *command,
unsigned int flags)
2106 ChangeThreadPriority(0, 7);
2107 TerminateResidentLibraries(
" ReBootStart:ei: Terminate resident Libraries\n", flags, 2);
2108 return CpuExecuteKmode(TerminateResidentEntriesDI, command, flags);
2114 unsigned short int ExtInfoEntrySize;
2119 static const void *GetFileDataFromImage(
const void *start,
const void *end,
const char *filename)
2121 const u8 *ImageStart;
2122 const u8 *RomdirStart;
2128 unsigned int offset;
2137 ptr = (u32 *)file->name;
2138 if ( ptr[0] == 0x45534552 && ptr[1] == 0x54 && (*(u16 *)&ptr[2] == 0) && (((file->size + 15) & ~15) == offset) )
2141 RomdirStart = (
const u8 *)ptr;
2147 unsigned int i, offset;
2148 u8 filename_temp[12];
2151 ((u32 *)filename_temp)[0] = 0;
2152 ((u32 *)filename_temp)[1] = 0;
2153 ((u32 *)filename_temp)[2] = 0;
2154 for ( i = 0; *filename >= 0x21 && i <
sizeof(filename_temp); i++ )
2156 filename_temp[i] = *filename;
2160 if ( RomdirStart != NULL )
2164 RomdirEntry = (
const struct RomDirEntry *)RomdirStart;
2169 ((u32 *)filename_temp)[0] == ((u32 *)RomdirEntry->name)[0]
2170 && ((u32 *)filename_temp)[1] == ((u32 *)RomdirEntry->name)[1]
2171 && (*(u16 *)&((u32 *)filename_temp)[2] == *(u16 *)&((u32 *)RomdirEntry->name)[2]) )
2173 return ImageStart + offset;
2176 offset += (RomdirEntry->size + 15) & ~15;
2178 }
while ( ((u32 *)RomdirEntry->name)[0] != 0x00000000 );
2190 static int linked_list_next_is_self(
const modload_ll_t *ll)
2192 return ll->next == ll;
2197 ll->next->prev = ll->prev;
2198 ll->prev->next = ll->next;
2202 static int linked_list_is_circular(
const modload_ll_t *ll)
2204 return ll->prev == ll->next;
2211 ll2->prev = ll1->prev;
2213 ll2->prev->next = ll2;