Changeset 425 for trunk/softs/tsar_boot/src/boot_elf_loader.c
- Timestamp:
- Jun 30, 2013, 8:28:58 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/softs/tsar_boot/src/boot_elf_loader.c
r415 r425 1 1 /** 2 * \file : boot_ loader_entry.c2 * \file : boot_elf_loader.c 3 3 * \date : August 2012 4 4 * \author : Cesar Fuguet … … 13 13 #include <elf-types.h> 14 14 #include <boot_tty.h> 15 #include <boot_ memcpy.h>15 #include <boot_utils.h> 16 16 #include <defs.h> 17 18 #if (BOOT_DEBUG == 1) 19 static char* init_state_str[] = { 20 "ELF_HEADER_STATE", 21 "ELF_PROGRAM_HEADER_STATE", 22 "ELF_OFFSET_STATE", 23 "ELF_SEGMENT_STATE", 24 "ELF_END_STATE" 25 }; 26 #endif 17 27 18 28 void * boot_elf_loader(unsigned int lba) 19 29 { 20 /* *30 /* 21 31 * Temporary variables used by the boot loader 22 32 */ … … 26 36 27 37 unsigned char * buffer_ptr; 28 Elf32_Ehdr * elf_ header_ptr;29 Elf32_Phdr * elf_ph t_ptr;38 Elf32_Ehdr * elf_ehdr_ptr; 39 Elf32_Phdr * elf_phdr_ptr; 30 40 31 41 unsigned int nb_available; … … 34 44 unsigned int nb_block; 35 45 unsigned int offset; 46 47 unsigned char * pseg_ptr; 48 unsigned int pseg_start; 49 unsigned int pseg_end; 50 unsigned int pseg_remainder; 36 51 unsigned int pseg; 37 unsigned int i;38 unsigned int segment_req;39 52 40 53 /* 41 54 * Loader state machine definition 42 55 */ 43 enum56 typedef enum 44 57 { 45 58 ELF_HEADER_STATE, … … 48 61 ELF_SEGMENT_STATE, 49 62 ELF_END_STATE 50 } init_state 51 #if (BOOT_DEBUG ==1) 52 , init_state_debug 53 #endif 54 ; 55 56 #if (BOOT_DEBUG == 1) 57 char* init_state_str[] = { 58 "ELF_HEADER_STATE", 59 "ELF_PROGRAM_HEADER_STATE", 60 "ELF_OFFSET_STATE", 61 "ELF_SEGMENT_STATE", 62 "ELF_END_STATE" 63 }; 64 #endif 65 63 } elf_loader_t; 64 65 elf_loader_t init_state; 66 init_state = ELF_HEADER_STATE; 67 68 #if (BOOT_DEBUG == 1) 69 elf_loader_t init_state_debug; 70 init_state_debug = ELF_END_STATE; 71 #endif 66 72 67 73 boot_puts("Starting boot_elf_loader function...\n\r"); 68 74 69 nb_block = lba; 70 71 pseg = 0; 72 nb_available = 0; 73 nb_rest = sizeof(Elf32_Ehdr); 74 offset = 0; 75 76 elf_header_ptr = (Elf32_Ehdr *) &elf_header; 77 elf_pht_ptr = (Elf32_Phdr *) &elf_pht[0]; 78 79 init_state = ELF_HEADER_STATE; 80 #if (BOOT_DEBUG == 1) 81 init_state_debug = ELF_END_STATE; 82 #endif 75 nb_block = lba; 76 nb_available = 0; 77 nb_rest = sizeof(Elf32_Ehdr); 78 pseg = 0; 79 offset = 0; 80 elf_ehdr_ptr = (Elf32_Ehdr *) &elf_header; 81 elf_phdr_ptr = (Elf32_Phdr *) &elf_pht[0]; 83 82 84 83 while(init_state != ELF_END_STATE) 85 84 { 86 if (nb_available == 0 )85 if (nb_available == 0 ) 87 86 { 88 87 buffer_ptr = &boot_elf_loader_buffer[0]; 89 88 90 if ( boot_ioc_read(nb_block , buffer_ptr, 1))89 if (boot_ioc_read(nb_block , buffer_ptr, 1)) 91 90 { 92 91 boot_puts ( 93 92 "ERROR: " 94 " IOC_FAILED"93 "boot_ioc_read() failed" 95 94 "\n" 96 95 ); … … 118 117 switch(init_state) 119 118 { 120 /* *119 /* 121 120 * Reading ELF executable header 122 121 */ 123 122 case ELF_HEADER_STATE: 124 boot_memcpy(elf_header_ptr, buffer_ptr, nb_read);123 memcpy(elf_ehdr_ptr, buffer_ptr, nb_read); 125 124 126 125 nb_rest -= nb_read; … … 128 127 if(nb_rest == 0) 129 128 { 130 nb_rest = elf_header_ptr->e_phnum * elf_header_ptr->e_phentsize; 131 132 /* Verification of ELF Magic Number */ 133 if ( 134 (elf_header_ptr->e_ident[EI_MAG0] != ELFMAG0) || 135 (elf_header_ptr->e_ident[EI_MAG1] != ELFMAG1) || 136 (elf_header_ptr->e_ident[EI_MAG2] != ELFMAG2) || 137 (elf_header_ptr->e_ident[EI_MAG3] != ELFMAG3) ) 129 nb_rest = elf_ehdr_ptr->e_phnum * elf_ehdr_ptr->e_phentsize; 130 131 /* 132 * Verification of ELF Magic Number 133 */ 134 if ( (elf_ehdr_ptr->e_ident[EI_MAG0] != ELFMAG0) || 135 (elf_ehdr_ptr->e_ident[EI_MAG1] != ELFMAG1) || 136 (elf_ehdr_ptr->e_ident[EI_MAG2] != ELFMAG2) || 137 (elf_ehdr_ptr->e_ident[EI_MAG3] != ELFMAG3) ) 138 138 { 139 139 boot_puts( … … 150 150 * smaller than the work size allocated for the 151 151 * elf_pht[PHDR_ARRAY_SIZE] array 152 * */153 if (elf_ header_ptr->e_phnum > PHDR_ARRAY_SIZE)152 */ 153 if (elf_ehdr_ptr->e_phnum > PHDR_ARRAY_SIZE) 154 154 { 155 155 boot_puts( 156 156 "ERROR: " 157 "ELF PHDR table size is bigger than "158 " the allocatedwork space"157 "ELF PHDR table size is bigger than the allocated" 158 "work space" 159 159 "\n" 160 160 ); … … 168 168 break; 169 169 170 /* *170 /* 171 171 * Reading ELF program headers 172 172 */ 173 173 case ELF_PROGRAM_HEADER_STATE: 174 boot_memcpy(elf_pht_ptr, buffer_ptr, nb_read); 175 176 elf_pht_ptr = (Elf32_Phdr *)((unsigned char *) elf_pht_ptr + nb_read); 177 nb_rest -= nb_read; 174 memcpy(elf_phdr_ptr, buffer_ptr, nb_read); 175 176 elf_phdr_ptr = 177 (Elf32_Phdr *)((unsigned char *) elf_phdr_ptr + nb_read); 178 179 nb_rest -= nb_read; 178 180 179 181 if(nb_rest == 0) 180 182 { 181 elf_ph t_ptr = (Elf32_Phdr *) &elf_pht[0];183 elf_phdr_ptr = (Elf32_Phdr *) &elf_pht[0]; 182 184 183 185 /* 184 186 * Search the first not NULL segment in the ELF file 185 187 */ 186 for (pseg = 0; pseg < elf_ header_ptr->e_phnum; pseg++)187 { 188 if(elf_ph t_ptr[pseg].p_type == PT_LOAD)188 for (pseg = 0; pseg < elf_ehdr_ptr->e_phnum; pseg++) 189 { 190 if(elf_phdr_ptr[pseg].p_type == PT_LOAD) 189 191 { 190 192 #if (BOOT_DEBUG == 1) 191 boot_puts("found a loadable segment:"); 192 boot_puts("\n- type : "); boot_putx(elf_pht_ptr[pseg].p_type); 193 boot_puts("\n- offset : "); boot_putx(elf_pht_ptr[pseg].p_offset); 194 boot_puts("\n- vaddr : "); boot_putx(elf_pht_ptr[pseg].p_vaddr); 195 boot_puts("\n- paddr : "); boot_putx(elf_pht_ptr[pseg].p_paddr); 196 boot_puts("\n- filesz : "); boot_putx(elf_pht_ptr[pseg].p_filesz); 197 boot_puts("\n- memsz : "); boot_putx(elf_pht_ptr[pseg].p_memsz); 198 boot_puts("\n- flags : "); boot_putx(elf_pht_ptr[pseg].p_flags); 199 boot_puts("\n- align : "); boot_putx(elf_pht_ptr[pseg].p_align); 200 #endif 201 if (elf_pht_ptr[pseg].p_offset < offset) 193 boot_puts("loadable segment found:\n"); 194 boot_print_elf_phdr(&elf_phdr_ptr[pseg]); 195 #endif 196 if (elf_phdr_ptr[pseg].p_offset < offset) 202 197 { 203 198 /* 204 * Case where the segment to load includes the elf205 * and program headers206 * */207 nb_rest = elf_ph t_ptr[pseg].p_filesz - offset;199 * Case where the segment to load includes the 200 * elf and program headers 201 */ 202 nb_rest = elf_phdr_ptr[pseg].p_filesz - offset; 208 203 init_state = ELF_SEGMENT_STATE; 209 204 } … … 212 207 /* 213 208 * Segment to load is further away in ELF file 214 * */215 nb_rest = elf_ph t_ptr[pseg].p_offset - offset;209 */ 210 nb_rest = elf_phdr_ptr[pseg].p_offset - offset; 216 211 init_state = ELF_OFFSET_STATE; 217 212 } … … 220 215 } 221 216 222 if (pseg == elf_ header_ptr->e_phnum)217 if (pseg == elf_ehdr_ptr->e_phnum) 223 218 { 224 219 boot_puts( … … 234 229 break; 235 230 236 /* *231 /* 237 232 * Go to the offset of the first not null program segment in the 238 233 * ELF file 234 * 235 * TODO: 236 * No need to read from the disk the useless bytes. Try to compute 237 * the next usefull lba 239 238 */ 240 239 case ELF_OFFSET_STATE: … … 243 242 if (nb_rest == 0) 244 243 { 245 nb_rest = elf_ph t_ptr[pseg].p_filesz;244 nb_rest = elf_phdr_ptr[pseg].p_filesz; 246 245 init_state = ELF_SEGMENT_STATE; 247 246 } … … 249 248 break; 250 249 251 /* *250 /* 252 251 * Reading ELF segments 252 * 253 * TODO: 254 * Do not pass by block buffer but write directly in target memory 255 * address 253 256 */ 254 257 case ELF_SEGMENT_STATE: 255 /* *256 * Copying ELF segment data in memory segments using the virtual257 * address got from the ELF file258 /* 259 * Verify that loadable segment does not conflict with 260 * pre-loader memory space 258 261 */ 259 segment_req = ((elf_pht_ptr[pseg].p_vaddr & 0xBFC00000) != 0xBFC00000); 260 261 if ( segment_req ) 262 { 263 boot_memcpy((unsigned char *) elf_pht_ptr[pseg].p_vaddr + 264 (elf_pht_ptr[pseg].p_filesz - nb_rest), 265 buffer_ptr, 266 nb_read); 267 } 262 pseg_start = elf_phdr_ptr[pseg].p_vaddr; 263 264 pseg_end = elf_phdr_ptr[pseg].p_vaddr + 265 elf_phdr_ptr[pseg].p_memsz; 266 267 if ((pseg_start >= 0xBFC00000 && pseg_start <= 0xBFC10000) || 268 (pseg_end >= 0xBFC00000 && pseg_end <= 0xBFC10000) || 269 (pseg_start < 0xBFC00000 && pseg_end > 0xBFC10000)) 270 { 271 boot_puts( 272 "ERROR: " 273 "Program segment conflits with pre-loader memory space" 274 "\n" 275 ); 276 boot_exit(); 277 } 278 279 /* 280 * Copy the ELF segment data in memory using the 281 * virtual address obtained from the ELF file 282 */ 283 pseg_ptr = (unsigned char *) 284 elf_phdr_ptr[pseg].p_vaddr + 285 elf_phdr_ptr[pseg].p_filesz - 286 nb_rest; 287 288 memcpy(pseg_ptr, buffer_ptr, nb_read); 268 289 269 290 nb_rest -= nb_read; 270 291 271 if ( nb_rest == 0 ) 272 { 273 if ( segment_req ) 274 { 275 boot_puts("Copied segment at address "); 276 boot_putx(elf_pht_ptr[pseg].p_vaddr); 277 boot_puts("\n"); 278 279 /* 280 * Fill remaining bytes with zeros (filesz < memsz) 281 */ 282 for ( i = 0 ; 283 i < (elf_pht_ptr[pseg].p_memsz - elf_pht_ptr[pseg].p_filesz) ; 284 i-- ) 292 if (nb_rest == 0) 293 { 294 /* 295 * Fill remaining bytes with zeros (filesz < memsz) 296 */ 297 pseg_remainder = 298 elf_phdr_ptr[pseg].p_memsz - 299 elf_phdr_ptr[pseg].p_filesz ; 300 301 pseg_ptr = (unsigned char *) 302 elf_phdr_ptr[pseg].p_vaddr + 303 elf_phdr_ptr[pseg].p_filesz ; 304 305 memset(pseg_ptr, 0, pseg_remainder); 306 307 boot_puts("Copied segment at address "); 308 boot_putx(elf_phdr_ptr[pseg].p_vaddr); 309 boot_puts("\n"); 310 311 /* 312 * Search the next first not NULL segment in the ELF file 313 */ 314 for (pseg += 1; pseg < elf_ehdr_ptr->e_phnum; pseg++) 315 { 316 if(elf_phdr_ptr[pseg].p_type == PT_LOAD) 285 317 { 286 *(unsigned char *) 287 (elf_pht_ptr[pseg].p_vaddr + elf_pht_ptr[pseg].p_filesz + i) = 0; 288 } 289 } 290 291 /* 292 * Search the first not NULL segment in the ELF file 293 */ 294 for ( pseg = pseg + 1; pseg < elf_header_ptr->e_phnum; pseg++) { 295 if(elf_pht_ptr[pseg].p_type == PT_LOAD) 296 { 297 nb_rest = elf_pht_ptr[pseg].p_offset - offset; 318 #if (BOOT_DEBUG == 1) 319 boot_puts("loadable segment found:\n"); 320 boot_print_elf_phdr(&elf_phdr_ptr[pseg]); 321 #endif 322 nb_rest = elf_phdr_ptr[pseg].p_offset - offset; 298 323 break; 299 324 } … … 303 328 * Program loading finished 304 329 */ 305 if(pseg == elf_ header_ptr->e_phnum)330 if(pseg == elf_ehdr_ptr->e_phnum) 306 331 { 307 332 init_state = ELF_END_STATE; … … 317 342 } 318 343 319 buffer_ptr 320 nb_available 344 buffer_ptr += nb_read; 345 nb_available -= nb_read; 321 346 } 322 347 … … 325 350 "Entry point address: " 326 351 ); 327 boot_putx(elf_header_ptr->e_entry); 352 353 boot_putx(elf_ehdr_ptr->e_entry); 328 354 boot_puts("\n"); 329 355 330 return ((void *) elf_ header_ptr->e_entry);356 return ((void *) elf_ehdr_ptr->e_entry); 331 357 } 358 359 // vim: tabstop=4 : softtabstop=4 : shiftwidth=4 : expandtab
Note: See TracChangeset
for help on using the changeset viewer.