/* * 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 #include "elf_abi.h" #include "sync.h" #include "string.h" /* ====================================================================== * Determine if a valid ELF image exists at the given memory location. * First looks at the ELF header magic field, the makes sure that it is * executable and makes sure that it is for a PowerPC. * ====================================================================== */ s32 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_type != ET_EXEC) return -1; if (ehdr->e_machine != EM_PPC) return -1; return 1; } /* ====================================================================== * A very simple elf loader, assumes the image is valid, returns the * entry point address. * ====================================================================== */ u32 load_elf_image (void *elfstart) { Elf32_Ehdr *ehdr; Elf32_Phdr *phdrs; u8 *image; int i; ehdr = (Elf32_Ehdr *) elfstart; if(ehdr->e_phoff == 0 || ehdr->e_phnum == 0) return 0; if(ehdr->e_phentsize != sizeof(Elf32_Phdr)) return 0; phdrs = (Elf32_Phdr*)(elfstart + ehdr->e_phoff); for(i=0;ie_phnum;i++) { if(phdrs[i].p_type != PT_LOAD) continue; phdrs[i].p_paddr &= 0x3FFFFFFF; phdrs[i].p_paddr |= 0x80000000; if(phdrs[i].p_filesz > phdrs[i].p_memsz) return 0; if(!phdrs[i].p_filesz) continue; image = (u8 *) (elfstart + phdrs[i].p_offset); memcpy ((void *) phdrs[i].p_paddr, (const void *) image, phdrs[i].p_filesz); sync_before_exec ((void *) phdrs[i].p_paddr, phdrs[i].p_memsz); //if(phdrs[i].p_flags & PF_X) //ICInvalidateRange ((void *) phdrs[i].p_paddr, phdrs[i].p_memsz); } return ((ehdr->e_entry & 0x3FFFFFFF) | 0x80000000); }