/** * \file : reset_elf_loader.c * \date : August 2012 * \author : Cesar Fuguet * * This file defines an elf file loader which reads an executable .elf file * starting at a sector passed as argument on a disk and copy the different * ELF program segments in the appropriate memory address using as information * the virtual address read from the .elf file. */ #include #include #include #include #include /////////////////////////////////////////////////////////////////////////////// void * reset_elf_loader(size_t lba) /////////////////////////////////////////////////////////////////////////////// { size_t file_offset = lba * BLOCK_SIZE; reset_puts("\n[RESET] Start reset_elf_loader at cycle "); reset_putd( proctime() ); reset_puts("\n"); /* * Load ELF HEADER */ Elf32_Ehdr elf_header; if (pread(file_offset, (void*)&elf_header, sizeof(Elf32_Ehdr), 0) < 0) { goto error; } check_elf_header(&elf_header); /* * Load ELF PROGRAM HEADER TABLE */ Elf32_Phdr elf_pht[RESET_PHDR_ARRAY_SIZE]; size_t phdr_nbyte = sizeof(Elf32_Phdr) * elf_header.e_phnum; size_t phdr_off = elf_header.e_phoff; if (pread(file_offset, (void*)&elf_pht, phdr_nbyte, phdr_off) < 0) { goto error; } /* * Search for loadable segments in the ELF file */ int pseg; for (pseg = 0; pseg < elf_header.e_phnum; pseg++) { if(elf_pht[pseg].p_type != PT_LOAD) continue; #if (RESET_DEBUG == 1) reset_puts("[RESET DEBUG] Loadable segment found:\n"); reset_print_elf_phdr(&elf_pht[pseg]); #endif addr_t p_paddr = elf_pht[pseg].p_paddr; size_t p_filesz = elf_pht[pseg].p_filesz; size_t p_memsz = elf_pht[pseg].p_memsz; size_t p_offset = elf_pht[pseg].p_offset; /* * Copy program segment from ELF executable into corresponding physical * address */ if (pread(file_offset, (void*)p_paddr, p_filesz, p_offset) < 0) { goto error; } /* * Fill remaining bytes with zero (filesz < memsz) */ char* pseg_ptr = (char*)p_paddr; memset((void*)&pseg_ptr[p_filesz], 0, (p_memsz - p_filesz)); reset_puts("\n[RESET] Segment loaded : address = "); reset_putx(p_paddr); reset_puts(" / size = "); reset_putx(p_filesz); reset_puts("\n"); } reset_puts("\n[RESET] Complete reset_elf_loader at cycle "); reset_putd( proctime() ); reset_puts(" / boot entry = "); reset_putx( (addr_t)(elf_header.e_entry) ); reset_puts("\n"); return ((void *) elf_header.e_entry); error: reset_puts("\n[RESET ERROR] Error while loading ELF file"); reset_exit(); return 0; } // vim: tabstop=4 : softtabstop=4 : shiftwidth=4 : expandtab