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

Last change on this file since 946 was 930, checked in by cfuguet, 10 years ago

tsar_boot: using global variable for the block device block cache

  • Some GCC versions have a problem to align as indicated with the attribute(aligned()) macro the functions' local variables. Therefore, using a global variable instead of a static local variable for the block cache because this last must be aligned to a cache line.
File size: 2.9 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
18extern int blk_buf_idx;
19
20///////////////////////////////////////////////////////////////////////////////
21void * reset_elf_loader(size_t lba)
22///////////////////////////////////////////////////////////////////////////////
23{
24    size_t file_offset = lba * BLOCK_SIZE;
25
26    reset_puts("\n[RESET] Start reset_elf_loader at cycle ");
27    reset_putd( proctime() );
28    reset_puts("\n");
29
30    /*
31     * Init the cache block index
32     */
33    blk_buf_idx = -1;
34
35    /*
36     * Load ELF HEADER
37     */
38    Elf32_Ehdr elf_header;
39    if (pread(file_offset, (void*)&elf_header, sizeof(Elf32_Ehdr), 0) < 0) {
40        goto error;
41    }
42    check_elf_header(&elf_header);
43
44    /*
45     * Load ELF PROGRAM HEADER TABLE
46     */
47    Elf32_Phdr elf_pht[RESET_PHDR_ARRAY_SIZE];
48    size_t phdr_nbyte = sizeof(Elf32_Phdr) * elf_header.e_phnum;
49    size_t phdr_off = elf_header.e_phoff;
50    if (pread(file_offset, (void*)&elf_pht, phdr_nbyte, phdr_off) < 0) {
51        goto error;
52    }
53
54    /*
55     * Search for loadable segments in the ELF file
56     */
57    int pseg;
58    for (pseg = 0; pseg < elf_header.e_phnum; pseg++)
59    {
60        if(elf_pht[pseg].p_type != PT_LOAD) continue;
61
62#if (RESET_DEBUG == 1)
63        reset_puts("[RESET DEBUG] Loadable segment found:\n");
64        reset_print_elf_phdr(&elf_pht[pseg]);
65#endif
66
67        addr_t p_paddr = elf_pht[pseg].p_paddr;
68        size_t p_filesz = elf_pht[pseg].p_filesz;
69        size_t p_memsz = elf_pht[pseg].p_memsz;
70        size_t p_offset = elf_pht[pseg].p_offset;
71
72        /*
73         * Copy program segment from ELF executable into corresponding physical
74         * address
75         */
76        if (pread(file_offset, (void*)p_paddr, p_filesz, p_offset) < 0) {
77            goto error;
78        }
79
80        /*
81         * Fill remaining bytes with zero (filesz < memsz)
82         */
83        char* pseg_ptr = (char*)p_paddr;
84        memset((void*)&pseg_ptr[p_filesz], 0, (p_memsz - p_filesz));
85
86        reset_puts("\n[RESET] Segment loaded : address = ");
87        reset_putx(p_paddr);
88        reset_puts(" / size = ");
89        reset_putx(p_filesz);
90        reset_puts("\n");
91    }
92
93    reset_puts("\n[RESET] Complete reset_elf_loader at cycle ");
94    reset_putd( proctime() );
95    reset_puts(" / boot entry = ");
96    reset_putx( (addr_t)(elf_header.e_entry) );
97    reset_puts("\n");
98
99    return ((void *) elf_header.e_entry);
100
101error:
102    reset_puts("\n[RESET ERROR] Error while loading ELF file");
103    reset_exit();
104    return 0;
105}
106
107// vim: tabstop=4 : softtabstop=4 : shiftwidth=4 : expandtab
Note: See TracBrowser for help on using the repository browser.