source: trunk/softs/tsar_boot/src/reset_utils.c @ 932

Last change on this file since 932 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: 5.7 KB
RevLine 
[425]1/**
[586]2 * \file    : reset_utils.c
[425]3 * \date    : August 2012
4 * \author  : Cesar Fuguet
5 *
[586]6 * Definition of utilities functions used by the TSAR pre-loader
[425]7 */
8
[586]9#include <reset_utils.h>
[758]10#include <reset_tty.h>
11#include <reset_ioc.h>
12#include <io.h>
[425]13
[930]14/*
15 * Cache block data buffer and cached block index
16 */
17struct aligned_blk blk_buf;
18int blk_buf_idx;
19
[758]20/**
[701]21 * \param file_offset: Disk relative offset of file
22 * \param buf: Destination buffer
23 * \param nbyte: Number of bytes to read
24 * \param offset: File relative offset
25 *
[758]26 * \brief read from disk into buffer "nbyte" bytes from (file_offset + offset)
27 *
[701]28 * \note Absolute disk offset (in bytes) is (file_offset + offset)
29 */
30int pread(size_t file_offset, void *buf, size_t nbyte, size_t offset) {
31    if (nbyte == 0) return 0;
32
33    char *dst;
34    int offset_blk;
35    int unaligned_nbyte;
36    int read_nbyte;
37
38    dst = (char*) buf;
39
40    /*
41     * Offset parameter is relative to file, therefore compute disk relative
42     * offset (in bytes)
43     */
44    offset += file_offset;
45
46    /*
47     * Read unaligned bytes at start of segment passing by block cache
48     */
49    offset_blk = (offset / BLOCK_SIZE);
50    offset = (offset % BLOCK_SIZE);
51    unaligned_nbyte = BLOCK_SIZE - offset;
52    read_nbyte = 0;
53    if (offset) {
54        /*
55         * Check cache block hit: if miss, read new block else, use cache block
56         * data
57         */
58        if (offset_blk != blk_buf_idx) {
59            if (reset_ioc_read(offset_blk, (void*)&blk_buf, 1)) {
[758]60                return -1;
[701]61            }
62        }
63        blk_buf_idx = offset_blk;
[758]64        read_nbyte = (nbyte > unaligned_nbyte) ? unaligned_nbyte : nbyte;
[701]65        memcpy((void*)dst, (void*)&blk_buf.b[offset], read_nbyte);
66        nbyte -= read_nbyte;
67        offset_blk += 1;
68    }
69
70    /*
71     * Read aligned bytes directly to buffer
72     */
[758]73    size_t nblk = nbyte / BLOCK_SIZE;
[701]74    if (nblk) {
75        if (reset_ioc_read(offset_blk, (void*)&dst[read_nbyte], nblk)) {
76            return -1;
77        }
78        read_nbyte += (nblk * BLOCK_SIZE);
[830]79        nbyte -= (nblk * BLOCK_SIZE);
[701]80        offset_blk += nblk;
81    }
82
83    /*
84     * Read unaligned bytes at the end of segment passing by block cache
85     */
86    if (nbyte) {
87        if (reset_ioc_read(offset_blk, (void*)&blk_buf, 1)) {
88            return -1;
89        }
90        blk_buf_idx = offset_blk;
91        memcpy((void*)&dst[read_nbyte], (void*)&blk_buf, nbyte);
92        read_nbyte += nbyte;
93    }
[758]94    return read_nbyte;
[701]95}
96
[758]97/**
98 * \param _dst   : Destination buffer base address
[425]99 * \param _src   : Source buffer base address
[758]100 * \param size   : Number of bytes to transfer
[425]101 *
[758]102 * \brief Transfer data between two memory buffers.
103 */
[701]104void* memcpy(void *_dst, const void *_src, size_t n)
[425]105{
106    unsigned int *dst = _dst;
107    const unsigned int *src = _src;
[703]108    if (!((unsigned int)dst & 3) && !((unsigned int)src & 3)) {
109        while (n > 3) {
[425]110            *dst++ = *src++;
[701]111            n -= 4;
[425]112        }
[655]113    }
[425]114
115    unsigned char *cdst = (unsigned char*) dst;
116    unsigned char *csrc = (unsigned char*) src;
[703]117    while (n--) {
[425]118        *cdst++ = *csrc++;
119    }
120    return _dst;
121}
122
[758]123/**
124 * \param _dst   : Destination buffer base address
125 * \param value  : Initialization value
[425]126 * \param size   : Number of bytes to initialize
127 *
[758]128 * \brief Initialize memory buffers with predefined value.
129 */
[701]130void* memset(void *_dst, int c, size_t len)
[425]131{
[701]132    if (len == 0) return _dst;
[425]133
[701]134    unsigned char val = (unsigned char) c;
135
[655]136    /*
[703]137     * Set not word aligned bytes at start of destination buffer
[655]138     */
[703]139    unsigned char* cdst = (unsigned char*) _dst;
140    while (((addr_t)cdst & 3) && len--) {
141        *cdst++ = val;
[655]142    }
[425]143
[655]144    /*
[703]145     * Set 4 bytes words on destination buffer
[655]146     */
[703]147    unsigned int word = (val << 24) | (val << 16) | (val << 8 ) | val;
148    addr_t *wdst = (addr_t*)cdst;
149    while (len > 3) {
150        *wdst++ = word;
151        len -= 4;
[655]152    }
153
[703]154    /*
155     * Set not word aligned bytes at end of destination buffer
156     */
157    cdst = (unsigned char*) wdst;
158    while(len--) {
159        *cdst++ = val;
160    }
[425]161    return _dst;
162}
163
[758]164/**
[701]165 * \param ehdr : ELF header pointer
166 *
[758]167 * \brief Verify that ELF file is valid and that the number of program headers
168 *        does not exceed the defined maximum
169 */
[701]170void check_elf_header(Elf32_Ehdr *ehdr)
171{
172    /*
173     * Verification of ELF Magic Number
174     */
175    if ((ehdr->e_ident[EI_MAG0] != ELFMAG0) ||
176        (ehdr->e_ident[EI_MAG1] != ELFMAG1) ||
177        (ehdr->e_ident[EI_MAG2] != ELFMAG2) ||
178        (ehdr->e_ident[EI_MAG3] != ELFMAG3))
179    {
180        reset_puts("[RESET ERROR] Unrecognized file format (not an ELF format)\n");
181        reset_exit();
182    }
183
184    /*
185     * Verification of Program Headers table size. It must be
186     * smaller than the work size allocated for the
[758]187     * elf_pht[RESET_PHDR_ARRAY_SIZE] array
[701]188     */
[758]189    if (ehdr->e_phnum > RESET_PHDR_ARRAY_SIZE)
[701]190    {
191        reset_puts("[RESET ERROR] ELF PHDR table size too large\n");
192        reset_exit();
193    }
194}
195
[758]196/**
[425]197 * \param elf_phdr_ptr : Pointer to the ELF program header to print
198 *
[758]199 * \brief Print some fields of a ELF program header
200 */
[586]201void reset_print_elf_phdr(Elf32_Phdr * elf_phdr_ptr)
[425]202{
[586]203    reset_puts("- type   : ");
204    reset_putx(elf_phdr_ptr->p_type);
205    reset_puts("\n- offset : ");
206    reset_putx(elf_phdr_ptr->p_offset);
207    reset_puts("\n- vaddr  : ");
208    reset_putx(elf_phdr_ptr->p_vaddr);
209    reset_puts("\n- paddr  : ");
210    reset_putx(elf_phdr_ptr->p_paddr);
211    reset_puts("\n- filesz : ");
212    reset_putx(elf_phdr_ptr->p_filesz);
213    reset_puts("\n- memsz  : ");
214    reset_putx(elf_phdr_ptr->p_memsz);
215    reset_puts("\n- flags  : ");
216    reset_putx(elf_phdr_ptr->p_flags);
217    reset_puts("\n- align  : ");
218    reset_putx(elf_phdr_ptr->p_align);
[701]219    reset_puts("\n");
[425]220}
221
[758]222/*
223 * vim: tabstop=4 : softtabstop=4 : shiftwidth=4 : expandtab
224 */
Note: See TracBrowser for help on using the repository browser.