18extern int size_ldrsrc;
20int elf_loader_is_elf_ehdr_valid(
const elf_loader_elf32_ehdr_t *ehdr)
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 )
54 else if ( ehdr->e_ehsize !=
sizeof(elf_loader_elf32_ehdr_t) )
58 else if ( ehdr->e_phentsize !=
sizeof(elf_loader_elf32_phdr_t) )
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)
81 const elf_loader_elf32_ehdr_t *ehdr;
82 const elf_loader_elf32_phdr_t *phdr;
84 if ( buf_size <
sizeof(elf_loader_elf32_ehdr_t) )
86 ehdr = (
const elf_loader_elf32_ehdr_t *)buf;
87 ret = elf_loader_is_elf_ehdr_valid(ehdr);
90 if ( buf_size < (ehdr->e_phoff +
sizeof(elf_loader_elf32_ehdr_t)) )
92 phdr = (
const elf_loader_elf32_phdr_t *)(((
const u8 *)buf) + ehdr->e_phoff);
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)
131 const elf_loader_elf32_ehdr_t *ehdr;
132 const elf_loader_elf32_phdr_t *phdr;
139 ret = elf_loader_is_elf_valid_for_loading(buf, buf_size);
142 ehdr = (
const elf_loader_elf32_ehdr_t *)buf;
143 phdr = (
const elf_loader_elf32_phdr_t *)(((
const u8 *)buf) + ehdr->e_phoff);
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(
243 elf_loader_execinfo_t *execinfo,
const char *filename,
const char *
partition,
int argc,
char *argv[])
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);
279static void elf_loader_ldr_entrypoint_stack()
__attribute__((used));
281static
char args_storage[1024];
282static elf_loader_loaderinfo_t sg_loaderinfo;
286static
void elf_loader_ldr_entrypoint(
void)
289 __asm__ __volatile__(
295 "lui $5, 0x7000" "\n"
298 "ori $6, $6, 0x4000" "\n"
302 "la $8, ExitThread \n"
304 "addiu $3, $0, 60 \n"
308 "j elf_loader_ldr_entrypoint_stack \n"
310 :
"R"(args_storage));
314typedef void *(*ldr_getinternalinfo_callback)(void);
315#define LDR_ENTRYPOINT_ADDR 0x00084000
317static void elf_loader_ldr_entrypoint_stack()
319 ldr_getinternalinfo_callback cb;
322 SetupHeap((
void *)0x1100C000, 0x4000);
326 memcpy((
void *)LDR_ENTRYPOINT_ADDR, ldrsrc, size_ldrsrc);
328 memcpy((
void *)0x11004000, &sg_loaderinfo,
sizeof(elf_loader_loaderinfo_t));
333 cb = (
void *)LDR_ENTRYPOINT_ADDR;
339int elf_loader_exec_elf(elf_loader_execinfo_t *execinfo)
341 elf_loader_arginfo_t *low_arginfo;
344 if ( execinfo->arginfo.argc == 0 )
346 memcpy(&sg_loaderinfo, &(execinfo->loaderinfo),
sizeof(elf_loader_loaderinfo_t));
348 low_arginfo = (
void *)0x00088000;
349 memcpy((
void *)low_arginfo, &(execinfo->arginfo),
sizeof(elf_loader_execinfo_t));
351 for ( i = 0; i < low_arginfo->argc; i += 1 )
353 low_arginfo->argv[i] = (
char *)((uiptr)(low_arginfo->argv[i]) + (uiptr)(low_arginfo->payload));
355 ExecPS2(&elf_loader_ldr_entrypoint, NULL, 0, NULL);