source: trunk/softs/tsar_boot/src/boot_elf_loader.c@ 292

Last change on this file since 292 was 292, checked in by cfuguet, 14 years ago

Changing directory structure of the TSAR boot loader.
A README.txt file has been included to explain the new structure
and the MAKEFILE parameters.

Erasing the heap segment for the boot elf loader. All the work space
is allocated in the stack.

The stack size is defined in the include/defs.h.

Important modification in the reset.S file. The non-boot
processors (processor id != 0) wait in a low comsumption energy
mode to be wake up by processor 0 using an IPI. Each processor
has a private mailbox in the local XICU. The value written in
the mailbox will be used as address to jump by the processors.

The waking up of non-boot processors is not done in this boot loader
so it must be done in the application loaded.

The boot_loader_elf function loads into memory an executable .elf file
which must be placed in the BOOT_LOADER_LBA block of the disk. This
constant can be defined in the include/defs.h file.

File size: 7.5 KB
Line 
1/**
2 * \file : boot_loader_entry.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 of 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 <boot_ioc.h>
13#include <elf-types.h>
14#include <boot_tty.h>
15#include <boot_memcpy.h>
16#include <defs.h>
17
18void * boot_elf_loader(unsigned int lba)
19{
20 /**
21 * Temporary variables used by the boot loader
22 */
23 unsigned char boot_elf_loader_buffer[512];
24 Elf32_Ehdr elf_header;
25 Elf32_Phdr elf_pht[PHDR_ARRAY_SIZE];
26
27 unsigned char * buffer_ptr;
28 Elf32_Ehdr * elf_header_ptr;
29 Elf32_Phdr * elf_pht_ptr;
30
31 unsigned int nb_available;
32 unsigned int nb_rest;
33 unsigned int nb_read;
34 unsigned int nb_block;
35 unsigned int offset;
36 unsigned int pseg;
37 unsigned int i;
38 unsigned int segment_req;
39
40 /*
41 * Loader state machine definition
42 */
43 enum
44 {
45 ELF_HEADER_STATE,
46 ELF_PROGRAM_HEADER_STATE,
47 ELF_OFFSET_STATE,
48 ELF_SEGMENT_STATE,
49 ELF_END_STATE
50 } init_state;
51
52 boot_puts("Starting boot_elf_loader function...\n\r");
53
54 nb_block = lba;
55
56 pseg = 0;
57 nb_available = 0;
58 nb_rest = sizeof(Elf32_Ehdr);
59 offset = 0;
60
61 elf_header_ptr = (Elf32_Ehdr *) &elf_header;
62 elf_pht_ptr = (Elf32_Phdr *) &elf_pht[0];
63
64 init_state = ELF_HEADER_STATE;
65
66 while(init_state != ELF_END_STATE)
67 {
68 if (nb_available == 0)
69 {
70 buffer_ptr = &boot_elf_loader_buffer[0];
71
72 if ( boot_ioc_read(nb_block , buffer_ptr, 1) )
73 {
74 boot_puts (
75 "ERROR: "
76 "IOC_FAILED"
77 "\n"
78 );
79
80 boot_exit();
81 }
82
83 nb_block += 1;
84 nb_available = 512;
85 }
86
87 nb_read = (nb_rest <= nb_available) ? nb_rest : nb_available;
88 offset += nb_read;
89
90 switch(init_state)
91 {
92 /**
93 * Reading ELF executable header
94 */
95 case ELF_HEADER_STATE:
96 boot_memcpy(elf_header_ptr, buffer_ptr, nb_read);
97
98 nb_rest -= nb_read;
99
100 if(nb_rest == 0)
101 {
102 nb_rest = elf_header_ptr->e_phnum * elf_header_ptr->e_phentsize;
103
104 /* Verification of ELF Magic Number */
105 if (
106 (elf_header_ptr->e_ident[EI_MAG0] != ELFMAG0) ||
107 (elf_header_ptr->e_ident[EI_MAG1] != ELFMAG1) ||
108 (elf_header_ptr->e_ident[EI_MAG2] != ELFMAG2) ||
109 (elf_header_ptr->e_ident[EI_MAG3] != ELFMAG3) )
110 {
111 boot_puts(
112 "ERROR: "
113 "Input file does not use ELF format"
114 "\n"
115 );
116
117 boot_exit();
118 }
119
120 /*
121 * Verification of Program Headers table size. It must be
122 * smaller than the work size allocated for the
123 * elf_pht[PHDR_ARRAY_SIZE] array
124 **/
125 if (elf_header_ptr->e_phnum > PHDR_ARRAY_SIZE)
126 {
127 boot_puts(
128 "ERROR: "
129 "ELF PHDR table size is bigger than "
130 "the allocated work space"
131 "\n"
132 );
133
134 boot_exit();
135 }
136
137 init_state = ELF_PROGRAM_HEADER_STATE;
138 }
139
140 break;
141
142 /**
143 * Reading ELF program headers
144 */
145 case ELF_PROGRAM_HEADER_STATE:
146 boot_memcpy(elf_pht_ptr, buffer_ptr, nb_read);
147
148 elf_pht_ptr = (Elf32_Phdr *)((unsigned char *) elf_pht_ptr + nb_read);
149 nb_rest -= nb_read;
150
151 if(nb_rest == 0)
152 {
153 elf_pht_ptr = (Elf32_Phdr *) &elf_pht[0];
154
155 /*
156 * Search the first not NULL segment in the ELF file
157 */
158 for (pseg = 0; pseg < elf_header_ptr->e_phnum; pseg++)
159 {
160 if(elf_pht_ptr[pseg].p_type == PT_LOAD)
161 {
162 nb_rest = elf_pht_ptr[pseg].p_offset - offset;
163 break;
164 }
165 }
166
167 init_state = ELF_OFFSET_STATE;
168 }
169
170 break;
171
172 /**
173 * Go to the offset of the first not null program segment in the ELF file
174 */
175 case ELF_OFFSET_STATE:
176 nb_rest -= nb_read;
177
178 if (nb_rest == 0)
179 {
180 nb_rest = elf_pht_ptr[pseg].p_filesz;
181 init_state = ELF_SEGMENT_STATE;
182 }
183
184 break;
185
186 /**
187 * Reading ELF segments
188 */
189 case ELF_SEGMENT_STATE:
190 /**
191 * Copying ELF segment data in memory segments using the virtual
192 * address got from the ELF file
193 */
194 segment_req = ((elf_pht_ptr[pseg].p_vaddr & 0xBFC00000) != 0xBFC00000);
195
196 if ( segment_req )
197 {
198 boot_memcpy((unsigned char *) elf_pht_ptr[pseg].p_vaddr +
199 (elf_pht_ptr[pseg].p_filesz - nb_rest),
200 buffer_ptr,
201 nb_read);
202 }
203
204 nb_rest -= nb_read;
205
206 if ( nb_rest == 0 )
207 {
208 if ( segment_req )
209 {
210 boot_puts("Copied segment at address ");
211 boot_putx(elf_pht_ptr[pseg].p_vaddr);
212 boot_puts("\n");
213
214 /*
215 * Fill remaining bytes with zeros (filesz < memsz)
216 */
217 for ( i = 0 ;
218 i < (elf_pht_ptr[pseg].p_memsz - elf_pht_ptr[pseg].p_filesz) ;
219 i-- )
220 {
221 *(unsigned char *)
222 (elf_pht_ptr[pseg].p_vaddr + elf_pht_ptr[pseg].p_filesz + i) = 0;
223 }
224 }
225
226 /*
227 * Search the first not NULL segment in the ELF file
228 */
229 for ( pseg = pseg + 1; pseg < elf_header_ptr->e_phnum; pseg++) {
230 if(elf_pht_ptr[pseg].p_type == PT_LOAD)
231 {
232 nb_rest = elf_pht_ptr[pseg].p_offset - offset;
233 break;
234 }
235 }
236
237 /*
238 * Program loading finished
239 */
240 if(pseg == elf_header_ptr->e_phnum)
241 {
242 init_state = ELF_END_STATE;
243 break;
244 }
245
246 init_state = ELF_OFFSET_STATE;
247 }
248 break;
249
250 default:
251 break;
252 }
253
254 buffer_ptr += nb_read;
255 nb_available -= nb_read;
256 }
257
258 boot_puts (
259 "Finishing boot_elf_loader function.\n"
260 "Entry point address: "
261 );
262 boot_putx(elf_header_ptr->e_entry);
263 boot_puts("\n");
264
265 return ((void *) elf_header_ptr->e_entry);
266}
Note: See TracBrowser for help on using the repository browser.