source: trunk/softs/tsar_boot/src/reset_elf_loader.c @ 737

Last change on this file since 737 was 701, checked in by cfuguet, 10 years ago

tsar_boot:

  • Important optimization in the reset_elf_loader function.
  • Implementation of pread function which uses bytes addressing to read disk.
  • pread function alternates between direct tranfer from disk to memory and from disk to a memory cache block based on alignment of byte address, i.e., when file offset is aligned to disk block (512 bytes), pread uses DMA capacity of disk to transfer directly to memory, otherwise it passes before by a memory cache block and then performs a memcpy to transfer data to final destination.
  • the cache block used by pread function, allows to treat succeeding reads on the same block without accessing the disk.
File size: 2.8 KB
Line 
1/**
2 * \file    : reset_elf_loader.c
3 * \date    : August 2012
4 * \author  : Cesar Fuguet
5 *
6 * This file defines an elf file loader which reads an executable .elf file
7 * starting at a sector passed as argument on a disk and copy the different
8 * ELF program segments in the appropriate memory address using as information
9 * the virtual address read from the .elf file.
10 */
11
12#include <reset_ioc.h>
13#include <elf-types.h>
14#include <reset_tty.h>
15#include <reset_utils.h>
16#include <defs.h>
17
18///////////////////////////////////////////////////////////////////////////////
19void * reset_elf_loader(size_t lba)
20///////////////////////////////////////////////////////////////////////////////
21{
22    size_t file_offset = lba * BLOCK_SIZE;
23
24    reset_puts("\n[RESET] Start reset_elf_loader at cycle ");
25    reset_putd( proctime() );
26    reset_puts("\n");
27
28    /*
29     * Load ELF HEADER
30     */
31    Elf32_Ehdr elf_header;
32    if (pread(file_offset, (void*)&elf_header, sizeof(Elf32_Ehdr), 0) < 0) {
33        goto error;
34    }
35    check_elf_header(&elf_header);
36
37    /*
38     * Load ELF PROGRAM HEADER TABLE
39     */
40    Elf32_Phdr elf_pht[PHDR_ARRAY_SIZE];
41    size_t phdr_nbyte = sizeof(Elf32_Phdr) * elf_header.e_phnum;
42    size_t phdr_off = elf_header.e_phoff;
43    if (pread(file_offset, (void*)&elf_pht, phdr_nbyte, phdr_off) < 0) {
44        goto error;
45    }
46
47    /*
48     * Search for loadable segments in the ELF file
49     */
50    int pseg;
51    for (pseg = 0; pseg < elf_header.e_phnum; pseg++)
52    {
53        if(elf_pht[pseg].p_type != PT_LOAD) continue;
54
55#if (RESET_DEBUG == 1)
56        reset_puts("[RESET DEBUG] Loadable segment found:\n");
57        reset_print_elf_phdr(&elf_pht[pseg]);
58#endif
59
60        addr_t p_paddr = elf_pht[pseg].p_paddr;
61        size_t p_filesz = elf_pht[pseg].p_filesz;
62        size_t p_memsz = elf_pht[pseg].p_memsz;
63        size_t p_offset = elf_pht[pseg].p_offset;
64
65        /*
66         * Copy program segment from ELF executable into corresponding physical
67         * address
68         */
69        if (pread(file_offset, (void*)p_paddr, p_filesz, p_offset) < 0) {
70            goto error;
71        }
72
73        /*
74         * Fill remaining bytes with zero (filesz < memsz)
75         */
76        char* pseg_ptr = (char*)p_paddr;
77        memset((void*)&pseg_ptr[p_filesz], 0, (p_memsz - p_filesz));
78
79        reset_puts("\n[RESET] Segment loaded : address = ");
80        reset_putx(p_paddr);
81        reset_puts(" / size = ");
82        reset_putx(p_filesz);
83        reset_puts("\n");
84    }
85
86    reset_puts("\n[RESET] Complete reset_elf_loader at cycle ");
87    reset_putd( proctime() );
88    reset_puts(" / boot entry = ");
89    reset_putx( (addr_t)(elf_header.e_entry) );
90    reset_puts("\n");
91
92    return ((void *) elf_header.e_entry);
93
94error:
95    reset_puts("\n[RESET ERROR] Error while loading ELF file");
96    reset_exit();
97    return 0;
98}
99
100// vim: tabstop=4 : softtabstop=4 : shiftwidth=4 : expandtab
Note: See TracBrowser for help on using the repository browser.