hbc/wiipax/stub/elf.c
2016-11-23 14:35:12 +09:00

114 lines
2.5 KiB
C

/*
* 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;
}