4 #error ELF_CHECK_ARCH not defined
19 unsigned char dummy
[1024];
21 unsigned long curaddr
;
22 int segment
; /* current segment number, -1 for none */
23 uint64_t loc
; /* start offset of current block */
24 uint64_t skip
; /* padding to be skipped to current segment */
25 unsigned long toread
; /* remaining data to be read in the segment */
27 int check_ip_checksum
;
29 unsigned long ip_checksum_offset
;
33 static struct elf_state estate
;
35 static unsigned long find_segment(unsigned long size
, unsigned long align
)
38 /* Verify I have a power of 2 alignment */
39 if (align
& (align
- 1)) {
42 for(i
= 0; i
< meminfo
.map_count
; i
++) {
43 unsigned long r_start
, r_end
;
44 if (meminfo
.map
[i
].type
!= E820_RAM
)
46 if ((meminfo
.map
[i
].addr
+ meminfo
.map
[i
].size
) > ULONG_MAX
) {
49 r_start
= meminfo
.map
[i
].addr
;
50 r_end
= r_start
+ meminfo
.map
[i
].size
;
51 /* Don't allow the segment to overlap etherboot */
52 if ((r_end
> virt_to_phys(_text
)) && (r_start
< virt_to_phys(_text
))) {
53 r_end
= virt_to_phys(_text
);
55 if ((r_start
> virt_to_phys(_text
)) && (r_start
< virt_to_phys(_end
))) {
56 r_start
= virt_to_phys(_end
);
58 /* Don't allow the segment to overlap the heap */
59 if ((r_end
> heap_ptr
) && (r_start
< heap_ptr
)) {
62 if ((r_start
> heap_ptr
) && (r_start
< heap_bot
)) {
65 r_start
= (r_start
+ align
- 1) & ~(align
- 1);
66 if ((r_end
>= r_start
) && ((r_end
- r_start
) >= size
)) {
70 /* I did not find anything :( */
74 static void elf_boot(unsigned long machine
, unsigned long entry
)
78 multiboot_boot(entry
);
79 /* We cleanup unconditionally, and then reawaken the network
80 * adapter after the longjmp.
82 hdr
= prepare_boot_params(&estate
.e
);
83 result
= elf_start(machine
, entry
, virt_to_phys(hdr
));
87 printf("Secondary program returned %d\n", result
);
88 longjmp(restart_etherboot
, result
);
92 static int elf_prep_segment(
93 unsigned long start __unused
, unsigned long mid __unused
, unsigned long end __unused
,
94 unsigned long istart
, unsigned long iend
)
97 if (estate
.check_ip_checksum
) {
98 if ((istart
<= estate
.ip_checksum_offset
) &&
99 (iend
> estate
.ip_checksum_offset
)) {
100 /* The checksum note is also loaded in a
101 * PT_LOAD segment, so the computed checksum
104 estate
.ip_checksum
= 0;
110 #define elf_prep_segment(start, mid, end, istart, iend) (1)
115 static void process_elf_notes(unsigned char *header
,
116 unsigned long offset
, unsigned long length
)
118 unsigned char *note
, *end
;
119 char *program
, *version
;
121 estate
.check_ip_checksum
= 0;
122 note
= header
+ offset
;
124 program
= version
= 0;
127 unsigned char *n_name
, *n_desc
, *next
;
128 hdr
= (Elf_Nhdr
*)note
;
129 n_name
= note
+ sizeof(*hdr
);
130 n_desc
= n_name
+ ((hdr
->n_namesz
+ 3) & ~3);
131 next
= n_desc
+ ((hdr
->n_descsz
+ 3) & ~3);
135 if ((hdr
->n_namesz
== sizeof(ELF_NOTE_BOOT
)) &&
136 (memcmp(n_name
, ELF_NOTE_BOOT
, sizeof(ELF_NOTE_BOOT
)) == 0)) {
137 switch(hdr
->n_type
) {
138 case EIN_PROGRAM_NAME
:
139 if (n_desc
[hdr
->n_descsz
-1] == 0) {
143 case EIN_PROGRAM_VERSION
:
144 if (n_desc
[hdr
->n_descsz
-1] == 0) {
148 case EIN_PROGRAM_CHECKSUM
:
149 estate
.check_ip_checksum
= 1;
150 estate
.ip_checksum
= *((uint16_t *)n_desc
);
151 /* Remember where the segment is so
152 * I can detect segment overlaps.
154 estate
.ip_checksum_offset
= n_desc
- header
;
156 printf("Checksum: %hx\n", estate
.ip_checksum
);
163 printf("n_type: %x n_name(%d): %s n_desc(%d): %s\n",
165 hdr
->n_namesz
, n_name
,
166 hdr
->n_descsz
, n_desc
);
170 if (program
&& version
) {
171 printf("\nLoading %s version: %s\n", program
, version
);
177 static sector_t
elf32_download(unsigned char *data
, unsigned int len
, int eof
);
178 static inline os_download_t
elf32_probe(unsigned char *data
, unsigned int len
)
180 unsigned long phdr_size
;
181 if (len
< sizeof(estate
.e
.elf32
)) {
184 memcpy(&estate
.e
.elf32
, data
, sizeof(estate
.e
.elf32
));
185 if ((estate
.e
.elf32
.e_ident
[EI_MAG0
] != ELFMAG0
) ||
186 (estate
.e
.elf32
.e_ident
[EI_MAG1
] != ELFMAG1
) ||
187 (estate
.e
.elf32
.e_ident
[EI_MAG2
] != ELFMAG2
) ||
188 (estate
.e
.elf32
.e_ident
[EI_MAG3
] != ELFMAG3
) ||
189 (estate
.e
.elf32
.e_ident
[EI_CLASS
] != ELFCLASS32
) ||
190 (estate
.e
.elf32
.e_ident
[EI_DATA
] != ELFDATA_CURRENT
) ||
191 (estate
.e
.elf32
.e_ident
[EI_VERSION
] != EV_CURRENT
) ||
192 ( (estate
.e
.elf32
.e_type
!= ET_EXEC
) &&
193 (estate
.e
.elf32
.e_type
!= ET_DYN
)) ||
194 (estate
.e
.elf32
.e_version
!= EV_CURRENT
) ||
195 (estate
.e
.elf32
.e_ehsize
!= sizeof(Elf32_Ehdr
)) ||
196 (estate
.e
.elf32
.e_phentsize
!= sizeof(Elf32_Phdr
)) ||
197 !ELF_CHECK_ARCH(estate
.e
.elf32
)) {
203 phdr_size
= estate
.e
.elf32
.e_phnum
* estate
.e
.elf32
.e_phentsize
;
204 if (estate
.e
.elf32
.e_phoff
+ phdr_size
> len
) {
205 printf("ELF header outside first block\n");
206 return dead_download
;
208 if (phdr_size
> sizeof(estate
.p
.dummy
)) {
209 printf("Program header too big\n");
210 return dead_download
;
212 memcpy(&estate
.p
.phdr32
, data
+ estate
.e
.elf32
.e_phoff
, phdr_size
);
213 if (estate
.e
.elf32
.e_type
== ET_DYN
) {
214 Elf32_Addr min
, max
, base_addr
, delta
, align
;
218 for(estate
.segment
= 0; estate
.segment
< estate
.e
.elf32
.e_phnum
; estate
.segment
++) {
220 if (estate
.p
.phdr32
[estate
.segment
].p_type
!= PT_LOAD
)
222 val
= estate
.p
.phdr32
[estate
.segment
].p_paddr
;
226 val
+= estate
.p
.phdr32
[estate
.segment
].p_memsz
;
230 if (estate
.p
.phdr32
[estate
.segment
].p_align
> align
) {
231 align
= estate
.p
.phdr32
[estate
.segment
].p_align
;
234 if (align
& (align
-1)) {
235 printf("ELF base address alignment is not a power of 2\n");
236 return dead_download
;
238 base_addr
= find_segment(max
- min
, align
);
239 if (base_addr
== ULONG_MAX
) {
240 printf("ELF base address not available for size %ld\n", max
- min
);
241 return dead_download
;
243 /* Compute the change in base address and fix up the addresses */
244 delta
= base_addr
- min
;
245 for(estate
.segment
= 0; estate
.segment
< estate
.e
.elf32
.e_phnum
; estate
.segment
++) {
246 /* Change the base address of the object to load */
247 estate
.p
.phdr32
[estate
.segment
].p_paddr
+= delta
;
249 estate
.e
.elf32
.e_entry
+= delta
;
252 /* Load ELF notes from the image */
253 estate
.check_ip_checksum
= 0;
254 for(estate
.segment
= 0; estate
.segment
< estate
.e
.elf32
.e_phnum
; estate
.segment
++) {
255 if (estate
.p
.phdr32
[estate
.segment
].p_type
!= PT_NOTE
)
257 if (estate
.p
.phdr32
[estate
.segment
].p_offset
+ estate
.p
.phdr32
[estate
.segment
].p_filesz
> len
) {
258 /* Ignore ELF notes outside of the first block */
261 process_elf_notes(data
,
262 estate
.p
.phdr32
[estate
.segment
].p_offset
, estate
.p
.phdr32
[estate
.segment
].p_filesz
);
265 /* Check for Etherboot related limitations. Memory
266 * between _text and _end is not allowed.
267 * Reasons: the Etherboot code/data area.
269 for (estate
.segment
= 0; estate
.segment
< estate
.e
.elf32
.e_phnum
; estate
.segment
++) {
270 unsigned long start
, mid
, end
, istart
, iend
;
271 if (estate
.p
.phdr32
[estate
.segment
].p_type
!= PT_LOAD
)
274 elf_freebsd_fixup_segment();
276 start
= estate
.p
.phdr32
[estate
.segment
].p_paddr
;
277 mid
= start
+ estate
.p
.phdr32
[estate
.segment
].p_filesz
;
278 end
= start
+ estate
.p
.phdr32
[estate
.segment
].p_memsz
;
279 istart
= estate
.p
.phdr32
[estate
.segment
].p_offset
;
280 iend
= istart
+ estate
.p
.phdr32
[estate
.segment
].p_filesz
;
281 if (!prep_segment(start
, mid
, end
, istart
, iend
)) {
282 return dead_download
;
284 if (!elf_prep_segment(start
, mid
, end
, istart
, iend
)) {
285 return dead_download
;
293 return elf32_download
;
296 static sector_t
elf32_download(unsigned char *data
, unsigned int len
, int eof
)
298 unsigned long skip_sectors
= 0;
299 unsigned int offset
; /* working offset in the current data block */
304 if (estate
.segment
!= -1) {
306 if (estate
.skip
>= len
- offset
) {
307 estate
.skip
-= len
- offset
;
310 offset
+= estate
.skip
;
316 cplen
= len
- offset
;
317 if (cplen
>= estate
.toread
) {
318 cplen
= estate
.toread
;
320 memcpy(phys_to_virt(estate
.curaddr
), data
+offset
, cplen
);
321 estate
.curaddr
+= cplen
;
322 estate
.toread
-= cplen
;
326 elf_freebsd_find_segment_end();
330 /* Data left, but current segment finished - look for the next
331 * segment (in file offset order) that needs to be loaded.
332 * We can only seek forward, so select the program headers,
333 * in the correct order.
336 for (i
= 0; i
< estate
.e
.elf32
.e_phnum
; i
++) {
337 if (estate
.p
.phdr32
[i
].p_type
!= PT_LOAD
)
339 if (estate
.p
.phdr32
[i
].p_filesz
== 0)
341 if (estate
.p
.phdr32
[i
].p_offset
< estate
.loc
+ offset
)
342 continue; /* can't go backwards */
343 if ((estate
.segment
!= -1) &&
344 (estate
.p
.phdr32
[i
].p_offset
>= estate
.p
.phdr32
[estate
.segment
].p_offset
))
345 continue; /* search minimum file offset */
348 if (estate
.segment
== -1) {
349 if (elf_freebsd_debug_loader(offset
)) {
350 estate
.segment
= 0; /* -1 makes it not read anymore */
353 /* No more segments to be loaded, so just start the
354 * kernel. This saves a lot of network bandwidth if
355 * debug info is in the kernel but not loaded. */
356 goto elf_startkernel
;
359 estate
.curaddr
= estate
.p
.phdr32
[estate
.segment
].p_paddr
;
360 estate
.skip
= estate
.p
.phdr32
[estate
.segment
].p_offset
- (estate
.loc
+ offset
);
361 estate
.toread
= estate
.p
.phdr32
[estate
.segment
].p_filesz
;
363 printf("PHDR %d, size %#lX, curaddr %#lX\n",
364 estate
.segment
, estate
.toread
, estate
.curaddr
);
366 } while (offset
< len
);
368 estate
.loc
+= len
+ (estate
.skip
& ~0x1ff);
369 skip_sectors
= estate
.skip
>> 9;
370 estate
.skip
&= 0x1ff;
374 unsigned long machine
;
376 entry
= estate
.e
.elf32
.e_entry
;
377 machine
= estate
.e
.elf32
.e_machine
;
380 if (estate
.check_ip_checksum
) {
381 unsigned long bytes
= 0;
382 uint16_t sum
, new_sum
;
384 sum
= ipchksum(&estate
.e
.elf32
, sizeof(estate
.e
.elf32
));
385 bytes
= sizeof(estate
.e
.elf32
);
387 printf("Ehdr: %hx %hx sz: %lx bytes: %lx\n",
388 sum
, sum
, bytes
, bytes
);
391 new_sum
= ipchksum(estate
.p
.phdr32
, sizeof(estate
.p
.phdr32
[0]) * estate
.e
.elf32
.e_phnum
);
392 sum
= add_ipchksums(bytes
, sum
, new_sum
);
393 bytes
+= sizeof(estate
.p
.phdr32
[0]) * estate
.e
.elf32
.e_phnum
;
395 printf("Phdr: %hx %hx sz: %lx bytes: %lx\n",
397 sizeof(estate
.p
.phdr32
[0]) * estate
.e
.elf32
.e_phnum
, bytes
);
400 for(i
= 0; i
< estate
.e
.elf32
.e_phnum
; i
++) {
401 if (estate
.p
.phdr32
[i
].p_type
!= PT_LOAD
)
403 new_sum
= ipchksum(phys_to_virt(estate
.p
.phdr32
[i
].p_paddr
),
404 estate
.p
.phdr32
[i
].p_memsz
);
405 sum
= add_ipchksums(bytes
, sum
, new_sum
);
406 bytes
+= estate
.p
.phdr32
[i
].p_memsz
;
408 printf("seg%d: %hx %hx sz: %x bytes: %lx\n",
410 estate
.p
.phdr32
[i
].p_memsz
, bytes
);
414 if (estate
.ip_checksum
!= sum
) {
415 printf("\nImage checksum: %hx != computed checksum: %hx\n",
416 estate
.ip_checksum
, sum
);
417 longjmp(restart_etherboot
, -2);
422 /* Fixup the offset to the program header so you can find the program headers from
423 * the ELF header mknbi needs this.
425 estate
.e
.elf32
.e_phoff
= (char *)&estate
.p
- (char *)&estate
.e
;
426 elf_freebsd_boot(entry
);
427 elf_boot(machine
,entry
);
431 #endif /* ELF_IMAGE */
434 static sector_t
elf64_download(unsigned char *data
, unsigned int len
, int eof
);
435 static inline os_download_t
elf64_probe(unsigned char *data
, unsigned int len
)
437 unsigned long phdr_size
;
438 if (len
< sizeof(estate
.e
.elf64
)) {
441 memcpy(&estate
.e
.elf64
, data
, sizeof(estate
.e
.elf64
));
442 if ((estate
.e
.elf64
.e_ident
[EI_MAG0
] != ELFMAG0
) ||
443 (estate
.e
.elf64
.e_ident
[EI_MAG1
] != ELFMAG1
) ||
444 (estate
.e
.elf64
.e_ident
[EI_MAG2
] != ELFMAG2
) ||
445 (estate
.e
.elf64
.e_ident
[EI_MAG3
] != ELFMAG3
) ||
446 (estate
.e
.elf64
.e_ident
[EI_CLASS
] != ELFCLASS64
) ||
447 (estate
.e
.elf64
.e_ident
[EI_DATA
] != ELFDATA_CURRENT
) ||
448 (estate
.e
.elf64
.e_ident
[EI_VERSION
] != EV_CURRENT
) ||
449 ( (estate
.e
.elf64
.e_type
!= ET_EXEC
) &&
450 (estate
.e
.elf64
.e_type
!= ET_DYN
)) ||
451 (estate
.e
.elf64
.e_version
!= EV_CURRENT
) ||
452 (estate
.e
.elf64
.e_ehsize
!= sizeof(Elf64_Ehdr
)) ||
453 (estate
.e
.elf64
.e_phentsize
!= sizeof(Elf64_Phdr
)) ||
454 !ELF_CHECK_ARCH(estate
.e
.elf64
)) {
457 printf("(ELF64)... ");
458 phdr_size
= estate
.e
.elf64
.e_phnum
* estate
.e
.elf64
.e_phentsize
;
459 if (estate
.e
.elf64
.e_phoff
+ phdr_size
> len
) {
460 printf("ELF header outside first block\n");
461 return dead_download
;
463 if (phdr_size
> sizeof(estate
.p
.dummy
)) {
464 printf("Program header to big\n");
465 return dead_download
;
467 if (estate
.e
.elf64
.e_entry
> ULONG_MAX
) {
468 printf("ELF entry point exceeds address space\n");
469 return dead_download
;
471 memcpy(&estate
.p
.phdr64
, data
+ estate
.e
.elf64
.e_phoff
, phdr_size
);
472 if (estate
.e
.elf64
.e_type
== ET_DYN
) {
473 Elf64_Addr min
, max
, base_addr
, delta
, align
;
477 for(estate
.segment
= 0; estate
.segment
< estate
.e
.elf64
.e_phnum
; estate
.segment
++) {
479 if (estate
.p
.phdr64
[estate
.segment
].p_type
!= PT_LOAD
)
481 val
= estate
.p
.phdr64
[estate
.segment
].p_paddr
;
485 val
+= estate
.p
.phdr64
[estate
.segment
].p_memsz
;
489 if (estate
.p
.phdr64
[estate
.segment
].p_align
> align
) {
490 align
= estate
.p
.phdr64
[estate
.segment
].p_align
;
493 if (align
> ULONG_MAX
) {
494 printf("ELF base address alignment exceeds address space\n");
495 return dead_download
;
497 if (align
& (align
-1)) {
498 printf("ELF base address alignment is not a power of 2\n");
499 return dead_download
;
501 if ((max
- min
) > ULONG_MAX
) {
502 printf("ELF size exceeds address space\n");
503 return dead_download
;
505 base_addr
= find_segment(max
- min
, align
);
506 if (base_addr
== ULONG_MAX
) {
507 printf("ELF base address not available for size %ld\n", max
- min
);
508 return dead_download
;
510 /* Compute the change in base address and fix up the addresses */
511 delta
= base_addr
- min
;
512 for(estate
.segment
= 0; estate
.segment
< estate
.e
.elf64
.e_phnum
; estate
.segment
++) {
513 /* Change the base address of the object to load */
514 estate
.p
.phdr64
[estate
.segment
].p_paddr
+= delta
;
516 estate
.e
.elf64
.e_entry
+= delta
;
519 /* Load ELF notes from the image */
520 estate
.check_ip_checksum
= 0;
521 for(estate
.segment
= 0; estate
.segment
< estate
.e
.elf64
.e_phnum
; estate
.segment
++) {
522 if (estate
.p
.phdr64
[estate
.segment
].p_type
!= PT_NOTE
)
524 if (estate
.p
.phdr64
[estate
.segment
].p_offset
+ estate
.p
.phdr64
[estate
.segment
].p_filesz
> len
) {
525 /* Ignore ELF notes outside of the first block */
528 process_elf_notes(data
,
529 estate
.p
.phdr64
[estate
.segment
].p_offset
, estate
.p
.phdr64
[estate
.segment
].p_filesz
);
532 /* Check for Etherboot related limitations. Memory
533 * between _text and _end is not allowed.
534 * Reasons: the Etherboot code/data area.
536 for (estate
.segment
= 0; estate
.segment
< estate
.e
.elf64
.e_phnum
; estate
.segment
++) {
537 unsigned long start
, mid
, end
, istart
, iend
;
538 if (estate
.p
.phdr64
[estate
.segment
].p_type
!= PT_LOAD
)
540 if ((estate
.p
.phdr64
[estate
.segment
].p_paddr
> ULONG_MAX
) ||
541 ((estate
.p
.phdr64
[estate
.segment
].p_paddr
+ estate
.p
.phdr64
[estate
.segment
].p_filesz
) > ULONG_MAX
) ||
542 ((estate
.p
.phdr64
[estate
.segment
].p_paddr
+ estate
.p
.phdr64
[estate
.segment
].p_memsz
) > ULONG_MAX
)) {
543 printf("ELF segment exceeds address space\n");
544 return dead_download
;
546 start
= estate
.p
.phdr64
[estate
.segment
].p_paddr
;
547 mid
= start
+ estate
.p
.phdr64
[estate
.segment
].p_filesz
;
548 end
= start
+ estate
.p
.phdr64
[estate
.segment
].p_memsz
;
549 istart
= iend
= ULONG_MAX
;
550 if ((estate
.p
.phdr64
[estate
.segment
].p_offset
< ULONG_MAX
) &&
551 ((estate
.p
.phdr64
[estate
.segment
].p_offset
+ estate
.p
.phdr64
[estate
.segment
].p_filesz
) < ULONG_MAX
))
553 istart
= estate
.p
.phdr64
[estate
.segment
].p_offset
;
554 iend
= istart
+ estate
.p
.phdr64
[estate
.segment
].p_filesz
;
556 if (!prep_segment(start
, mid
, end
, istart
, iend
)) {
557 return dead_download
;
559 if (!elf_prep_segment(start
, mid
, end
, istart
, iend
)) {
560 return dead_download
;
567 return elf64_download
;
570 static sector_t
elf64_download(unsigned char *data
, unsigned int len
, int eof
)
572 unsigned long skip_sectors
= 0;
573 unsigned int offset
; /* working offset in the current data block */
578 if (estate
.segment
!= -1) {
580 if (estate
.skip
>= len
- offset
) {
581 estate
.skip
-= len
- offset
;
584 offset
+= estate
.skip
;
590 cplen
= len
- offset
;
591 if (cplen
>= estate
.toread
) {
592 cplen
= estate
.toread
;
594 memcpy(phys_to_virt(estate
.curaddr
), data
+offset
, cplen
);
595 estate
.curaddr
+= cplen
;
596 estate
.toread
-= cplen
;
603 /* Data left, but current segment finished - look for the next
604 * segment (in file offset order) that needs to be loaded.
605 * We can only seek forward, so select the program headers,
606 * in the correct order.
609 for (i
= 0; i
< estate
.e
.elf64
.e_phnum
; i
++) {
610 if (estate
.p
.phdr64
[i
].p_type
!= PT_LOAD
)
612 if (estate
.p
.phdr64
[i
].p_filesz
== 0)
614 if (estate
.p
.phdr64
[i
].p_offset
< estate
.loc
+ offset
)
615 continue; /* can't go backwards */
616 if ((estate
.segment
!= -1) &&
617 (estate
.p
.phdr64
[i
].p_offset
>= estate
.p
.phdr64
[estate
.segment
].p_offset
))
618 continue; /* search minimum file offset */
621 if (estate
.segment
== -1) {
622 /* No more segments to be loaded, so just start the
623 * kernel. This saves a lot of network bandwidth if
624 * debug info is in the kernel but not loaded. */
625 goto elf_startkernel
;
628 estate
.curaddr
= estate
.p
.phdr64
[estate
.segment
].p_paddr
;
629 estate
.skip
= estate
.p
.phdr64
[estate
.segment
].p_offset
- (estate
.loc
+ offset
);
630 estate
.toread
= estate
.p
.phdr64
[estate
.segment
].p_filesz
;
632 printf("PHDR %d, size %#lX, curaddr %#lX\n",
633 estate
.segment
, estate
.toread
, estate
.curaddr
);
635 } while (offset
< len
);
637 estate
.loc
+= len
+ (estate
.skip
& ~0x1ff);
638 skip_sectors
= estate
.skip
>> 9;
639 estate
.skip
&= 0x1ff;
643 unsigned long machine
;
645 entry
= estate
.e
.elf64
.e_entry
;
646 machine
= estate
.e
.elf64
.e_machine
;
648 if (estate
.check_ip_checksum
) {
649 unsigned long bytes
= 0;
650 uint16_t sum
, new_sum
;
652 sum
= ipchksum(&estate
.e
.elf64
, sizeof(estate
.e
.elf64
));
653 bytes
= sizeof(estate
.e
.elf64
);
655 printf("Ehdr: %hx %hx sz: %lx bytes: %lx\n",
656 sum
, sum
, bytes
, bytes
);
659 new_sum
= ipchksum(estate
.p
.phdr64
, sizeof(estate
.p
.phdr64
[0]) * estate
.e
.elf64
.e_phnum
);
660 sum
= add_ipchksums(bytes
, sum
, new_sum
);
661 bytes
+= sizeof(estate
.p
.phdr64
[0]) * estate
.e
.elf64
.e_phnum
;
663 printf("Phdr: %hx %hx sz: %lx bytes: %lx\n",
665 sizeof(estate
.p
.phdr64
[0]) * estate
.e
.elf64
.e_phnum
, bytes
);
668 for(i
= 0; i
< estate
.e
.elf64
.e_phnum
; i
++) {
669 if (estate
.p
.phdr64
[i
].p_type
!= PT_LOAD
)
671 new_sum
= ipchksum(phys_to_virt(estate
.p
.phdr64
[i
].p_paddr
),
672 estate
.p
.phdr64
[i
].p_memsz
);
673 sum
= add_ipchksums(bytes
, sum
, new_sum
);
674 bytes
+= estate
.p
.phdr64
[i
].p_memsz
;
676 printf("seg%d: %hx %hx sz: %x bytes: %lx\n",
678 estate
.p
.phdr64
[i
].p_memsz
, bytes
);
682 if (estate
.ip_checksum
!= sum
) {
683 printf("\nImage checksum: %hx != computed checksum: %hx\n",
684 estate
.ip_checksum
, sum
);
685 longjmp(restart_etherboot
, -2);
690 /* Fixup the offset to the program header so you can find the program headers from
691 * the ELF header mknbi needs this.
693 estate
.e
.elf64
.e_phoff
= (char *)&estate
.p
- (char *)&estate
.e
;
694 elf_boot(machine
,entry
);
699 #endif /* ELF64_IMAGE */