Initial commit
This commit is contained in:
113
wiipax/stub/elf.c
Normal file
113
wiipax/stub/elf.c
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 2001 William L. Pitts
|
||||
* Modifications (c) 2004 Felix Domke
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are freely
|
||||
* permitted provided that the above copyright notice and this
|
||||
* paragraph and the following disclaimer are duplicated in all
|
||||
* such forms.
|
||||
*
|
||||
* This software is provided "AS IS" and without any express or
|
||||
* implied warranties, including, without limitation, the implied
|
||||
* warranties of merchantability and fitness for a particular
|
||||
* purpose.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "elf_abi.h"
|
||||
#include "string.h"
|
||||
|
||||
int valid_elf_image (void *addr) {
|
||||
Elf32_Ehdr *ehdr; /* Elf header structure pointer */
|
||||
|
||||
ehdr = (Elf32_Ehdr *) addr;
|
||||
|
||||
if (!IS_ELF (*ehdr))
|
||||
return 0;
|
||||
|
||||
if (ehdr->e_ident[EI_CLASS] != ELFCLASS32)
|
||||
return -1;
|
||||
|
||||
if (ehdr->e_ident[EI_DATA] != ELFDATA2MSB)
|
||||
return -1;
|
||||
|
||||
if (ehdr->e_ident[EI_VERSION] != EV_CURRENT)
|
||||
return -1;
|
||||
|
||||
if (ehdr->e_type != ET_EXEC)
|
||||
return -1;
|
||||
|
||||
if (ehdr->e_machine != EM_PPC)
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
u32 load_elf_image(void *addr) {
|
||||
Elf32_Ehdr *ehdr;
|
||||
Elf32_Phdr *phdrs;
|
||||
u8 *image;
|
||||
int i;
|
||||
|
||||
ehdr = (Elf32_Ehdr *)addr;
|
||||
|
||||
if(ehdr->e_phoff == 0 || ehdr->e_phnum == 0) {
|
||||
printf("ELF has no phdrs\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(ehdr->e_phentsize != sizeof(Elf32_Phdr)) {
|
||||
printf("Invalid ELF phdr size\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
phdrs = (Elf32_Phdr*)(addr + ehdr->e_phoff);
|
||||
|
||||
for(i = 0; i < ehdr->e_phnum; i++) {
|
||||
if(phdrs[i].p_type != PT_LOAD) {
|
||||
printf("skip PHDR %d of type %d\n", i, phdrs[i].p_type);
|
||||
continue;
|
||||
}
|
||||
|
||||
// translate paddr to this BAT setup
|
||||
phdrs[i].p_paddr &= 0x3FFFFFFF;
|
||||
phdrs[i].p_paddr |= 0x80000000;
|
||||
|
||||
printf("PHDR %d 0x%08x [0x%x] -> 0x%08x [0x%x] <", i,
|
||||
phdrs[i].p_offset, phdrs[i].p_filesz,
|
||||
phdrs[i].p_paddr, phdrs[i].p_memsz);
|
||||
|
||||
if(phdrs[i].p_flags & PF_R)
|
||||
printf("R");
|
||||
if(phdrs[i].p_flags & PF_W)
|
||||
printf("W");
|
||||
if(phdrs[i].p_flags & PF_X)
|
||||
printf("X");
|
||||
printf(">\n");
|
||||
|
||||
if(phdrs[i].p_filesz > phdrs[i].p_memsz) {
|
||||
printf("-> file size > mem size\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(phdrs[i].p_filesz) {
|
||||
printf("-> load 0x%x\n", phdrs[i].p_filesz);
|
||||
image = (u8 *)(addr + phdrs[i].p_offset);
|
||||
memcpy((void *)phdrs[i].p_paddr, (const void *)image,
|
||||
phdrs[i].p_filesz);
|
||||
memset((void *)image, 0, phdrs[i].p_filesz);
|
||||
|
||||
sync_after_write((void *)phdrs[i].p_paddr, phdrs[i].p_memsz);
|
||||
|
||||
if(phdrs[i].p_flags & PF_X)
|
||||
sync_before_exec((void *)phdrs[i].p_paddr, phdrs[i].p_memsz);
|
||||
} else {
|
||||
printf ("-> skip\n");
|
||||
}
|
||||
}
|
||||
|
||||
// entry point of the ELF _has_ to be correct - no translation done
|
||||
return ehdr->e_entry;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user