11#include "elf_loader_common.h"
18extern int size_ldrsrc;
34 else if ( ehdr->e_entry < 0x80000 || ehdr->e_entry > (32 * 1024 * 1024) )
38 else if ( ehdr->e_ident[4] != 1 )
42 else if ( ehdr->e_ident[5] != 1 )
46 else if ( ehdr->e_type != 2 )
50 else if ( ehdr->e_machine != 8 )
62 else if ( ehdr->e_phnum > ELF_LOADER_MAX_PROGRAM_HEADERS )
66 else if ( ehdr->e_shnum && ehdr->e_shentsize != 40 )
73int elf_loader_is_elf_valid_for_loading(
const void *buf,
size_t buf_size)
87 ret = elf_loader_is_elf_ehdr_valid(ehdr);
95 highest_vaddr = 0x80000;
97 for ( i = 0; i < ehdr->e_phnum; i += 1 )
99 if ( phdr[i].p_type == 1 && phdr[i].p_filesz != 0 )
102 if ( phdr[i].p_vaddr < highest_vaddr || phdr[i].p_offset < highest_offset )
106 highest_vaddr = phdr[i].p_vaddr;
107 highest_offset = phdr[i].p_offset;
108 if ( ehdr->e_entry >= phdr[i].p_vaddr && (phdr[i].p_vaddr + phdr[i].p_filesz) > ehdr->e_entry )
110 entrypoint_in_ph = 1;
115 if ( !ph_count || ph_count > ELF_LOADER_MAX_PROGRAM_HEADERS )
119 if ( !entrypoint_in_ph )
123 if ( buf_size < highest_offset )
128int elf_loader_exec_elf_prepare_loadinfo(
elf_loader_execinfo_t *execinfo,
const void *buf,
size_t buf_size)
139 ret = elf_loader_is_elf_valid_for_loading(buf, buf_size);
144 memsize = GetMemorySize();
146 min_load_addr = 0xFFFFFFFF;
147 max_load_addr = 0x00100000;
150 for ( i = 0; i < ehdr->e_phnum; i += 1 )
152 if ( phdr[i].p_type == 1 && phdr[i].p_filesz != 0 )
155 execinfo->loaderinfo.items[info_count].dest_addr = (
void *)(phdr[i].p_vaddr);
156 execinfo->loaderinfo.items[info_count].src_addr = (
void *)(((u8 *)buf) + phdr[i].p_offset);
157 execinfo->loaderinfo.items[info_count].size = phdr[i].p_filesz;
160 u32 end_load_address;
161 load_address = phdr[i].p_vaddr;
162 end_load_address = load_address + phdr[i].p_filesz;
163 if ( load_address < min_load_addr )
165 min_load_addr = load_address;
167 if ( end_load_address > max_load_addr )
169 max_load_addr = end_load_address;
173 (u8 *)(execinfo->loaderinfo.items[info_count].dest_addr)
174 >= ((u8 *)execinfo->loaderinfo.items[info_count].src_addr) )
179 for ( i = ehdr->e_phnum - 1; i >= 0; i -= 1 )
181 if ( phdr[i].p_type == 1 && phdr[i].p_filesz != 0 )
184 execinfo->loaderinfo.items[info_count].dest_addr = (
void *)(phdr[i].p_vaddr);
185 execinfo->loaderinfo.items[info_count].src_addr = (
void *)(((u8 *)buf) + phdr[i].p_offset);
186 execinfo->loaderinfo.items[info_count].size = phdr[i].p_filesz;
189 u32 end_load_address;
190 load_address = phdr[i].p_vaddr;
191 end_load_address = load_address + phdr[i].p_filesz;
192 if ( load_address < min_load_addr )
194 min_load_addr = load_address;
196 if ( end_load_address > max_load_addr )
198 max_load_addr = end_load_address;
202 (u8 *)(execinfo->loaderinfo.items[info_count].dest_addr)
203 <= ((u8 *)execinfo->loaderinfo.items[info_count].src_addr) )
208 if ( min_load_addr != 0xFFFFFFFF )
211 wanted_size = min_load_addr - 0x00100000;
212 if ( wanted_size != 0 )
215 execinfo->loaderinfo.items[info_count].dest_addr = (
void *)0x00100000;
216 execinfo->loaderinfo.items[info_count].src_addr = (
void *)NULL;
217 execinfo->loaderinfo.items[info_count].size = wanted_size;
221 if ( max_load_addr != 0x00100000 )
224 wanted_size = memsize - (uiptr)max_load_addr;
226 if ( wanted_size != 0 )
228 execinfo->loaderinfo.items[info_count].dest_addr = (
void *)max_load_addr;
229 execinfo->loaderinfo.items[info_count].src_addr = (
void *)NULL;
230 execinfo->loaderinfo.items[info_count].size = wanted_size;
235 execinfo->loaderinfo.items[info_count].dest_addr = (
void *)(ehdr->e_entry);
236 execinfo->loaderinfo.items[info_count].src_addr = (
void *)NULL;
237 execinfo->loaderinfo.items[info_count].size = 0;
242int elf_loader_exec_elf_prepare_arginfo(
248 ptr = execinfo->arginfo.payload;
249 argc = (argc > 15) ? 15 : argc;
250 execinfo->arginfo.argc = argc + 1;
252 execinfo->arginfo.argv[0] = (
char *)((uiptr)ptr - (uiptr)(execinfo->arginfo.payload));
256 if ( ((ptr - execinfo->arginfo.payload) + len) >
sizeof(execinfo->arginfo.payload) )
261 len = strlen(filename) + 1;
262 if ( ((ptr - execinfo->arginfo.payload) + len) >
sizeof(execinfo->arginfo.payload) )
264 memcpy(ptr, filename, len);
266 for ( i = 0; i < argc; i += 1 )
268 execinfo->arginfo.argv[i + 1] = (
char *)((uiptr)ptr - (uiptr)(execinfo->arginfo.payload));
269 len = strlen(argv[i]) + 1;
270 if ( ((ptr - execinfo->arginfo.payload) + len) >
sizeof(execinfo->arginfo.payload) )
272 memcpy(ptr, argv[i], len);
278static void elf_loader_ldr_entrypoint_stack();
280static char args_storage[1024];
285static void elf_loader_ldr_entrypoint(
void)
288 __asm__ __volatile__(
294 "lui $5, 0x7000" "\n"
297 "ori $6, $6, 0x4000" "\n"
301 "la $8, ExitThread \n"
303 "addiu $3, $0, 60 \n"
309 :
"R"(args_storage),
"Csy"(elf_loader_ldr_entrypoint_stack));
313typedef void *(*ldr_getinternalinfo_callback)(void);
314#define LDR_ENTRYPOINT_ADDR 0x00084000
316static void elf_loader_ldr_entrypoint_stack()
318 ldr_getinternalinfo_callback cb;
321 SetupHeap((
void *)0x1100C000, 0x4000);
325 memcpy((
void *)LDR_ENTRYPOINT_ADDR, ldrsrc, size_ldrsrc);
332 cb = (
void *)LDR_ENTRYPOINT_ADDR;
343 if ( execinfo->arginfo.argc == 0 )
347 low_arginfo = (
void *)0x00088000;
350 for ( i = 0; i < low_arginfo->argc; i += 1 )
352 low_arginfo->argv[i] = (
char *)((uiptr)(low_arginfo->argv[i]) + (uiptr)(low_arginfo->payload));
354 ExecPS2(&elf_loader_ldr_entrypoint, NULL, 0, NULL);