You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

elf_loader.c 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. #include "elf.h"
  2. #ifndef ELF_CHECK_ARCH
  3. #error ELF_CHECK_ARCH not defined
  4. #endif
  5. #define ELF_NOTES 1
  6. #define ELF_DEBUG 0
  7. struct elf_state
  8. {
  9. union {
  10. Elf32_Ehdr elf32;
  11. Elf64_Ehdr elf64;
  12. } e;
  13. union {
  14. Elf32_Phdr phdr32[1];
  15. Elf64_Phdr phdr64[1];
  16. unsigned char dummy[1024];
  17. } p;
  18. unsigned long curaddr;
  19. int segment; /* current segment number, -1 for none */
  20. uint64_t loc; /* start offset of current block */
  21. uint64_t skip; /* padding to be skipped to current segment */
  22. unsigned long toread; /* remaining data to be read in the segment */
  23. #if ELF_NOTES
  24. int check_ip_checksum;
  25. uint16_t ip_checksum;
  26. unsigned long ip_checksum_offset;
  27. #endif
  28. };
  29. static struct elf_state estate;
  30. static void elf_boot(unsigned long machine, unsigned long entry)
  31. {
  32. int result;
  33. struct Elf_Bhdr *hdr;
  34. multiboot_boot(entry);
  35. /* We cleanup unconditionally, and then reawaken the network
  36. * adapter after the longjmp.
  37. */
  38. hdr = prepare_boot_params(&estate.e);
  39. result = elf_start(machine, entry, virt_to_phys(hdr));
  40. if (result == 0) {
  41. result = -1;
  42. }
  43. printf("Secondary program returned %d\n", result);
  44. longjmp(restart_etherboot, result);
  45. }
  46. #if ELF_NOTES
  47. static int elf_prep_segment(
  48. unsigned long start __unused, unsigned long mid __unused, unsigned long end __unused,
  49. unsigned long istart, unsigned long iend)
  50. {
  51. if (estate.check_ip_checksum) {
  52. if ((istart <= estate.ip_checksum_offset) &&
  53. (iend > estate.ip_checksum_offset)) {
  54. /* The checksum note is also loaded in a
  55. * PT_LOAD segment, so the computed checksum
  56. * should be 0.
  57. */
  58. estate.ip_checksum = 0;
  59. }
  60. }
  61. return 1;
  62. }
  63. #else
  64. #define elf_prep_segment(start, mid, end, istart, iend) (1)
  65. #endif
  66. #if ELF_NOTES
  67. static void process_elf_notes(unsigned char *header,
  68. unsigned long offset, unsigned long length)
  69. {
  70. unsigned char *note, *end;
  71. char *program, *version;
  72. estate.check_ip_checksum = 0;
  73. note = header + offset;
  74. end = note + length;
  75. program = version = 0;
  76. while(note < end) {
  77. Elf_Nhdr *hdr;
  78. unsigned char *n_name, *n_desc, *next;
  79. hdr = (Elf_Nhdr *)note;
  80. n_name = note + sizeof(*hdr);
  81. n_desc = n_name + ((hdr->n_namesz + 3) & ~3);
  82. next = n_desc + ((hdr->n_descsz + 3) & ~3);
  83. if (next > end) {
  84. break;
  85. }
  86. if ((hdr->n_namesz == sizeof(ELF_NOTE_BOOT)) &&
  87. (memcmp(n_name, ELF_NOTE_BOOT, sizeof(ELF_NOTE_BOOT)) == 0)) {
  88. switch(hdr->n_type) {
  89. case EIN_PROGRAM_NAME:
  90. if (n_desc[hdr->n_descsz -1] == 0) {
  91. program = n_desc;
  92. }
  93. break;
  94. case EIN_PROGRAM_VERSION:
  95. if (n_desc[hdr->n_descsz -1] == 0) {
  96. version = n_desc;
  97. }
  98. break;
  99. case EIN_PROGRAM_CHECKSUM:
  100. estate.check_ip_checksum = 1;
  101. estate.ip_checksum = *((uint16_t *)n_desc);
  102. /* Remember where the segment is so
  103. * I can detect segment overlaps.
  104. */
  105. estate.ip_checksum_offset = n_desc - header;
  106. #if ELF_DEBUG
  107. printf("Checksum: %hx\n", estate.ip_checksum);
  108. #endif
  109. break;
  110. }
  111. }
  112. #if ELF_DEBUG
  113. printf("n_type: %x n_name(%d): %s n_desc(%d): %s\n",
  114. hdr->n_type,
  115. hdr->n_namesz, n_name,
  116. hdr->n_descsz, n_desc);
  117. #endif
  118. note = next;
  119. }
  120. if (program && version) {
  121. printf("\nLoading %s version: %s\n", program, version);
  122. }
  123. }
  124. #endif
  125. #ifdef ELF_IMAGE
  126. static sector_t elf32_download(unsigned char *data, unsigned int len, int eof);
  127. static inline os_download_t elf32_probe(unsigned char *data, unsigned int len)
  128. {
  129. unsigned long phdr_size;
  130. if (len < sizeof(estate.e.elf32)) {
  131. return 0;
  132. }
  133. memcpy(&estate.e.elf32, data, sizeof(estate.e.elf32));
  134. if ((estate.e.elf32.e_ident[EI_MAG0] != ELFMAG0) ||
  135. (estate.e.elf32.e_ident[EI_MAG1] != ELFMAG1) ||
  136. (estate.e.elf32.e_ident[EI_MAG2] != ELFMAG2) ||
  137. (estate.e.elf32.e_ident[EI_MAG3] != ELFMAG3) ||
  138. (estate.e.elf32.e_ident[EI_CLASS] != ELFCLASS32) ||
  139. (estate.e.elf32.e_ident[EI_DATA] != ELFDATA_CURRENT) ||
  140. (estate.e.elf32.e_ident[EI_VERSION] != EV_CURRENT) ||
  141. ( (estate.e.elf32.e_type != ET_EXEC) &&
  142. (estate.e.elf32.e_type != ET_DYN)) ||
  143. (estate.e.elf32.e_version != EV_CURRENT) ||
  144. (estate.e.elf32.e_ehsize != sizeof(Elf32_Ehdr)) ||
  145. (estate.e.elf32.e_phentsize != sizeof(Elf32_Phdr)) ||
  146. !ELF_CHECK_ARCH(estate.e.elf32)) {
  147. return 0;
  148. }
  149. printf("(ELF");
  150. elf_freebsd_probe();
  151. multiboot_probe(data, len);
  152. printf(")... ");
  153. phdr_size = estate.e.elf32.e_phnum * estate.e.elf32.e_phentsize;
  154. if (estate.e.elf32.e_phoff + phdr_size > len) {
  155. printf("ELF header outside first block\n");
  156. return dead_download;
  157. }
  158. if (phdr_size > sizeof(estate.p.dummy)) {
  159. printf("Program header to big\n");
  160. return dead_download;
  161. }
  162. memcpy(&estate.p.phdr32, data + estate.e.elf32.e_phoff, phdr_size);
  163. if (estate.e.elf32.e_type == ET_DYN) {
  164. Elf32_Addr min, max, base_addr, delta, align;
  165. min = -1;
  166. max = 0;
  167. align = 1;
  168. for(estate.segment = 0; estate.segment < estate.e.elf32.e_phnum; estate.segment++) {
  169. Elf32_Addr val;
  170. if (estate.p.phdr32[estate.segment].p_type != PT_LOAD)
  171. continue;
  172. val = estate.p.phdr32[estate.segment].p_paddr;
  173. if (val < min) {
  174. min = val;
  175. }
  176. val += estate.p.phdr32[estate.segment].p_memsz;
  177. if (val > max) {
  178. max = val;
  179. }
  180. if (estate.p.phdr32[estate.segment].p_align > align) {
  181. align = estate.p.phdr32[estate.segment].p_align;
  182. }
  183. }
  184. if (align & (align -1)) {
  185. printf("ELF base address alignment is not a power of 2\n");
  186. return dead_download;
  187. }
  188. base_addr = find_segment(max - min, align);
  189. if (base_addr == ULONG_MAX) {
  190. printf("ELF base address not available for size %ld\n", max - min);
  191. return dead_download;
  192. }
  193. /* Compute the change in base address and fix up the addresses */
  194. delta = base_addr - min;
  195. for(estate.segment = 0; estate.segment < estate.e.elf32.e_phnum; estate.segment++) {
  196. /* Change the base address of the object to load */
  197. estate.p.phdr32[estate.segment].p_paddr += delta;
  198. }
  199. estate.e.elf32.e_entry += delta;
  200. }
  201. #if ELF_NOTES
  202. /* Load ELF notes from the image */
  203. for(estate.segment = 0; estate.segment < estate.e.elf32.e_phnum; estate.segment++) {
  204. if (estate.p.phdr32[estate.segment].p_type != PT_NOTE)
  205. continue;
  206. if (estate.p.phdr32[estate.segment].p_offset + estate.p.phdr32[estate.segment].p_filesz > len) {
  207. /* Ignore ELF notes outside of the first block */
  208. continue;
  209. }
  210. process_elf_notes(data,
  211. estate.p.phdr32[estate.segment].p_offset, estate.p.phdr32[estate.segment].p_filesz);
  212. }
  213. #endif
  214. /* Check for Etherboot related limitations. Memory
  215. * between _text and _end is not allowed.
  216. * Reasons: the Etherboot code/data area.
  217. */
  218. for (estate.segment = 0; estate.segment < estate.e.elf32.e_phnum; estate.segment++) {
  219. unsigned long start, mid, end, istart, iend;
  220. if (estate.p.phdr32[estate.segment].p_type != PT_LOAD)
  221. continue;
  222. elf_freebsd_fixup_segment();
  223. start = estate.p.phdr32[estate.segment].p_paddr;
  224. mid = start + estate.p.phdr32[estate.segment].p_filesz;
  225. end = start + estate.p.phdr32[estate.segment].p_memsz;
  226. istart = estate.p.phdr32[estate.segment].p_offset;
  227. iend = istart + estate.p.phdr32[estate.segment].p_filesz;
  228. if (!prep_segment(start, mid, end, istart, iend)) {
  229. return dead_download;
  230. }
  231. if (!elf_prep_segment(start, mid, end, istart, iend)) {
  232. return dead_download;
  233. }
  234. }
  235. estate.segment = -1;
  236. estate.loc = 0;
  237. estate.skip = 0;
  238. estate.toread = 0;
  239. return elf32_download;
  240. }
  241. static sector_t elf32_download(unsigned char *data, unsigned int len, int eof)
  242. {
  243. unsigned long skip_sectors = 0;
  244. unsigned int offset; /* working offset in the current data block */
  245. int i;
  246. offset = 0;
  247. do {
  248. if (estate.segment != -1) {
  249. if (estate.skip) {
  250. if (estate.skip >= len - offset) {
  251. estate.skip -= len - offset;
  252. break;
  253. }
  254. offset += estate.skip;
  255. estate.skip = 0;
  256. }
  257. if (estate.toread) {
  258. unsigned int cplen;
  259. cplen = len - offset;
  260. if (cplen >= estate.toread) {
  261. cplen = estate.toread;
  262. }
  263. memcpy(phys_to_virt(estate.curaddr), data+offset, cplen);
  264. estate.curaddr += cplen;
  265. estate.toread -= cplen;
  266. offset += cplen;
  267. if (estate.toread)
  268. break;
  269. elf_freebsd_find_segment_end();
  270. }
  271. }
  272. /* Data left, but current segment finished - look for the next
  273. * segment (in file offset order) that needs to be loaded.
  274. * We can only seek forward, so select the program headers,
  275. * in the correct order.
  276. */
  277. estate.segment = -1;
  278. for (i = 0; i < estate.e.elf32.e_phnum; i++) {
  279. if (estate.p.phdr32[i].p_type != PT_LOAD)
  280. continue;
  281. if (estate.p.phdr32[i].p_filesz == 0)
  282. continue;
  283. if (estate.p.phdr32[i].p_offset < estate.loc + offset)
  284. continue; /* can't go backwards */
  285. if ((estate.segment != -1) &&
  286. (estate.p.phdr32[i].p_offset >= estate.p.phdr32[estate.segment].p_offset))
  287. continue; /* search minimum file offset */
  288. estate.segment = i;
  289. }
  290. if (estate.segment == -1) {
  291. if (elf_freebsd_debug_loader(offset)) {
  292. estate.segment = 0; /* -1 makes it not read anymore */
  293. continue;
  294. }
  295. /* No more segments to be loaded, so just start the
  296. * kernel. This saves a lot of network bandwidth if
  297. * debug info is in the kernel but not loaded. */
  298. goto elf_startkernel;
  299. break;
  300. }
  301. estate.curaddr = estate.p.phdr32[estate.segment].p_paddr;
  302. estate.skip = estate.p.phdr32[estate.segment].p_offset - (estate.loc + offset);
  303. estate.toread = estate.p.phdr32[estate.segment].p_filesz;
  304. #if ELF_DEBUG
  305. printf("PHDR %d, size %#lX, curaddr %#lX\n",
  306. estate.segment, estate.toread, estate.curaddr);
  307. #endif
  308. } while (offset < len);
  309. estate.loc += len + (estate.skip & ~0x1ff);
  310. skip_sectors = estate.skip >> 9;
  311. estate.skip &= 0x1ff;
  312. if (eof) {
  313. unsigned long entry;
  314. unsigned long machine;
  315. elf_startkernel:
  316. entry = estate.e.elf32.e_entry;
  317. machine = estate.e.elf32.e_machine;
  318. #if ELF_NOTES
  319. if (estate.check_ip_checksum) {
  320. unsigned long bytes = 0;
  321. uint16_t sum, new_sum;
  322. sum = ipchksum(&estate.e.elf32, sizeof(estate.e.elf32));
  323. bytes = sizeof(estate.e.elf32);
  324. #if ELF_DEBUG
  325. printf("Ehdr: %hx %hx sz: %lx bytes: %lx\n",
  326. sum, sum, bytes, bytes);
  327. #endif
  328. new_sum = ipchksum(estate.p.phdr32, sizeof(estate.p.phdr32[0]) * estate.e.elf32.e_phnum);
  329. sum = add_ipchksums(bytes, sum, new_sum);
  330. bytes += sizeof(estate.p.phdr32[0]) * estate.e.elf32.e_phnum;
  331. #if ELF_DEBUG
  332. printf("Phdr: %hx %hx sz: %lx bytes: %lx\n",
  333. new_sum, sum,
  334. sizeof(estate.p.phdr32[0]) * estate.e.elf32.e_phnum, bytes);
  335. #endif
  336. for(i = 0; i < estate.e.elf32.e_phnum; i++) {
  337. if (estate.p.phdr32[i].p_type != PT_LOAD)
  338. continue;
  339. new_sum = ipchksum(phys_to_virt(estate.p.phdr32[i].p_paddr),
  340. estate.p.phdr32[i].p_memsz);
  341. sum = add_ipchksums(bytes, sum, new_sum);
  342. bytes += estate.p.phdr32[i].p_memsz;
  343. #if ELF_DEBUG
  344. printf("seg%d: %hx %hx sz: %x bytes: %lx\n",
  345. i, new_sum, sum,
  346. estate.p.phdr32[i].p_memsz, bytes);
  347. #endif
  348. }
  349. if (estate.ip_checksum != sum) {
  350. printf("\nImage checksum: %hx != computed checksum: %hx\n",
  351. estate.ip_checksum, sum);
  352. longjmp(restart_etherboot, -2);
  353. }
  354. }
  355. #endif
  356. done(1);
  357. /* Fixup the offset to the program header so you can find the program headers from
  358. * the ELF header mknbi needs this.
  359. */
  360. estate.e.elf32.e_phoff = (char *)&estate.p - (char *)&estate.e;
  361. elf_freebsd_boot(entry);
  362. elf_boot(machine,entry);
  363. }
  364. return skip_sectors;
  365. }
  366. #endif /* ELF_IMAGE */
  367. #ifdef ELF64_IMAGE
  368. static sector_t elf64_download(unsigned char *data, unsigned int len, int eof);
  369. static inline os_download_t elf64_probe(unsigned char *data, unsigned int len)
  370. {
  371. unsigned long phdr_size;
  372. if (len < sizeof(estate.e.elf64)) {
  373. return 0;
  374. }
  375. memcpy(&estate.e.elf64, data, sizeof(estate.e.elf64));
  376. if ((estate.e.elf64.e_ident[EI_MAG0] != ELFMAG0) ||
  377. (estate.e.elf64.e_ident[EI_MAG1] != ELFMAG1) ||
  378. (estate.e.elf64.e_ident[EI_MAG2] != ELFMAG2) ||
  379. (estate.e.elf64.e_ident[EI_MAG3] != ELFMAG3) ||
  380. (estate.e.elf64.e_ident[EI_CLASS] != ELFCLASS64) ||
  381. (estate.e.elf64.e_ident[EI_DATA] != ELFDATA_CURRENT) ||
  382. (estate.e.elf64.e_ident[EI_VERSION] != EV_CURRENT) ||
  383. ( (estate.e.elf64.e_type != ET_EXEC) &&
  384. (estate.e.elf64.e_type != ET_DYN)) ||
  385. (estate.e.elf64.e_version != EV_CURRENT) ||
  386. (estate.e.elf64.e_ehsize != sizeof(Elf64_Ehdr)) ||
  387. (estate.e.elf64.e_phentsize != sizeof(Elf64_Phdr)) ||
  388. !ELF_CHECK_ARCH(estate.e.elf64)) {
  389. return 0;
  390. }
  391. printf("(ELF64)... ");
  392. phdr_size = estate.e.elf64.e_phnum * estate.e.elf64.e_phentsize;
  393. if (estate.e.elf64.e_phoff + phdr_size > len) {
  394. printf("ELF header outside first block\n");
  395. return dead_download;
  396. }
  397. if (phdr_size > sizeof(estate.p.dummy)) {
  398. printf("Program header to big\n");
  399. return dead_download;
  400. }
  401. if (estate.e.elf64.e_entry > ULONG_MAX) {
  402. printf("ELF entry point exceeds address space\n");
  403. return dead_download;
  404. }
  405. memcpy(&estate.p.phdr64, data + estate.e.elf64.e_phoff, phdr_size);
  406. if (estate.e.elf64.e_type == ET_DYN) {
  407. Elf64_Addr min, max, base_addr, delta, align;
  408. min = -1;
  409. max = 0;
  410. align = 1;
  411. for(estate.segment = 0; estate.segment < estate.e.elf64.e_phnum; estate.segment++) {
  412. Elf64_Addr val;
  413. if (estate.p.phdr64[estate.segment].p_type != PT_LOAD)
  414. continue;
  415. val = estate.p.phdr64[estate.segment].p_paddr;
  416. if (val < min) {
  417. min = val;
  418. }
  419. val += estate.p.phdr64[estate.segment].p_memsz;
  420. if (val > max) {
  421. max = val;
  422. }
  423. if (estate.p.phdr64[estate.segment].p_align > align) {
  424. align = estate.p.phdr64[estate.segment].p_align;
  425. }
  426. }
  427. if (align > ULONG_MAX) {
  428. printf("ELF base address alignment exceeds address space\n");
  429. return dead_download;
  430. }
  431. if (align & (align -1)) {
  432. printf("ELF base address alignment is not a power of 2\n");
  433. return dead_download;
  434. }
  435. if ((max - min) > ULONG_MAX) {
  436. printf("ELF size exceeds address space\n");
  437. return dead_download;
  438. }
  439. base_addr = find_segment(max - min, align);
  440. if (base_addr == ULONG_MAX) {
  441. printf("ELF base address not available for size %ld\n", max - min);
  442. return dead_download;
  443. }
  444. /* Compute the change in base address and fix up the addresses */
  445. delta = base_addr - min;
  446. for(estate.segment = 0; estate.segment < estate.e.elf64.e_phnum; estate.segment++) {
  447. /* Change the base address of the object to load */
  448. estate.p.phdr64[estate.segment].p_paddr += delta;
  449. }
  450. estate.e.elf64.e_entry += delta;
  451. }
  452. #if ELF_NOTES
  453. /* Load ELF notes from the image */
  454. for(estate.segment = 0; estate.segment < estate.e.elf64.e_phnum; estate.segment++) {
  455. if (estate.p.phdr64[estate.segment].p_type != PT_NOTE)
  456. continue;
  457. if (estate.p.phdr64[estate.segment].p_offset + estate.p.phdr64[estate.segment].p_filesz > len) {
  458. /* Ignore ELF notes outside of the first block */
  459. continue;
  460. }
  461. process_elf_notes(data,
  462. estate.p.phdr64[estate.segment].p_offset, estate.p.phdr64[estate.segment].p_filesz);
  463. }
  464. #endif
  465. /* Check for Etherboot related limitations. Memory
  466. * between _text and _end is not allowed.
  467. * Reasons: the Etherboot code/data area.
  468. */
  469. for (estate.segment = 0; estate.segment < estate.e.elf64.e_phnum; estate.segment++) {
  470. unsigned long start, mid, end, istart, iend;
  471. if (estate.p.phdr64[estate.segment].p_type != PT_LOAD)
  472. continue;
  473. if ((estate.p.phdr64[estate.segment].p_paddr > ULONG_MAX) ||
  474. ((estate.p.phdr64[estate.segment].p_paddr + estate.p.phdr64[estate.segment].p_filesz) > ULONG_MAX) ||
  475. ((estate.p.phdr64[estate.segment].p_paddr + estate.p.phdr64[estate.segment].p_memsz) > ULONG_MAX)) {
  476. printf("ELF segment exceeds address space\n");
  477. return dead_download;
  478. }
  479. start = estate.p.phdr64[estate.segment].p_paddr;
  480. mid = start + estate.p.phdr64[estate.segment].p_filesz;
  481. end = start + estate.p.phdr64[estate.segment].p_memsz;
  482. istart = iend = ULONG_MAX;
  483. if ((estate.p.phdr64[estate.segment].p_offset < ULONG_MAX) &&
  484. ((estate.p.phdr64[estate.segment].p_offset + estate.p.phdr64[estate.segment].p_filesz) < ULONG_MAX))
  485. {
  486. istart = estate.p.phdr64[estate.segment].p_offset;
  487. iend = istart + estate.p.phdr64[estate.segment].p_filesz;
  488. }
  489. if (!prep_segment(start, mid, end, istart, iend)) {
  490. return dead_download;
  491. }
  492. if (!elf_prep_segment(start, mid, end, istart, iend)) {
  493. return dead_download;
  494. }
  495. }
  496. estate.segment = -1;
  497. estate.loc = 0;
  498. estate.skip = 0;
  499. estate.toread = 0;
  500. return elf64_download;
  501. }
  502. static sector_t elf64_download(unsigned char *data, unsigned int len, int eof)
  503. {
  504. unsigned long skip_sectors = 0;
  505. unsigned int offset; /* working offset in the current data block */
  506. int i;
  507. offset = 0;
  508. do {
  509. if (estate.segment != -1) {
  510. if (estate.skip) {
  511. if (estate.skip >= len - offset) {
  512. estate.skip -= len - offset;
  513. break;
  514. }
  515. offset += estate.skip;
  516. estate.skip = 0;
  517. }
  518. if (estate.toread) {
  519. unsigned int cplen;
  520. cplen = len - offset;
  521. if (cplen >= estate.toread) {
  522. cplen = estate.toread;
  523. }
  524. memcpy(phys_to_virt(estate.curaddr), data+offset, cplen);
  525. estate.curaddr += cplen;
  526. estate.toread -= cplen;
  527. offset += cplen;
  528. if (estate.toread)
  529. break;
  530. }
  531. }
  532. /* Data left, but current segment finished - look for the next
  533. * segment (in file offset order) that needs to be loaded.
  534. * We can only seek forward, so select the program headers,
  535. * in the correct order.
  536. */
  537. estate.segment = -1;
  538. for (i = 0; i < estate.e.elf64.e_phnum; i++) {
  539. if (estate.p.phdr64[i].p_type != PT_LOAD)
  540. continue;
  541. if (estate.p.phdr64[i].p_filesz == 0)
  542. continue;
  543. if (estate.p.phdr64[i].p_offset < estate.loc + offset)
  544. continue; /* can't go backwards */
  545. if ((estate.segment != -1) &&
  546. (estate.p.phdr64[i].p_offset >= estate.p.phdr64[estate.segment].p_offset))
  547. continue; /* search minimum file offset */
  548. estate.segment = i;
  549. }
  550. if (estate.segment == -1) {
  551. /* No more segments to be loaded, so just start the
  552. * kernel. This saves a lot of network bandwidth if
  553. * debug info is in the kernel but not loaded. */
  554. goto elf_startkernel;
  555. break;
  556. }
  557. estate.curaddr = estate.p.phdr64[estate.segment].p_paddr;
  558. estate.skip = estate.p.phdr64[estate.segment].p_offset - (estate.loc + offset);
  559. estate.toread = estate.p.phdr64[estate.segment].p_filesz;
  560. #if ELF_DEBUG
  561. printf("PHDR %d, size %#lX, curaddr %#lX\n",
  562. estate.segment, estate.toread, estate.curaddr);
  563. #endif
  564. } while (offset < len);
  565. estate.loc += len + (estate.skip & ~0x1ff);
  566. skip_sectors = estate.skip >> 9;
  567. estate.skip &= 0x1ff;
  568. if (eof) {
  569. unsigned long entry;
  570. unsigned long machine;
  571. elf_startkernel:
  572. entry = estate.e.elf64.e_entry;
  573. machine = estate.e.elf64.e_machine;
  574. #if ELF_NOTES
  575. if (estate.check_ip_checksum) {
  576. unsigned long bytes = 0;
  577. uint16_t sum, new_sum;
  578. sum = ipchksum(&estate.e.elf64, sizeof(estate.e.elf64));
  579. bytes = sizeof(estate.e.elf64);
  580. #if ELF_DEBUG
  581. printf("Ehdr: %hx %hx sz: %lx bytes: %lx\n",
  582. sum, sum, bytes, bytes);
  583. #endif
  584. new_sum = ipchksum(estate.p.phdr64, sizeof(estate.p.phdr64[0]) * estate.e.elf64.e_phnum);
  585. sum = add_ipchksums(bytes, sum, new_sum);
  586. bytes += sizeof(estate.p.phdr64[0]) * estate.e.elf64.e_phnum;
  587. #if ELF_DEBUG
  588. printf("Phdr: %hx %hx sz: %lx bytes: %lx\n",
  589. new_sum, sum,
  590. sizeof(estate.p.phdr64[0]) * estate.e.elf64.e_phnum, bytes);
  591. #endif
  592. for(i = 0; i < estate.e.elf64.e_phnum; i++) {
  593. if (estate.p.phdr64[i].p_type != PT_LOAD)
  594. continue;
  595. new_sum = ipchksum(phys_to_virt(estate.p.phdr64[i].p_paddr),
  596. estate.p.phdr64[i].p_memsz);
  597. sum = add_ipchksums(bytes, sum, new_sum);
  598. bytes += estate.p.phdr64[i].p_memsz;
  599. #if ELF_DEBUG
  600. printf("seg%d: %hx %hx sz: %x bytes: %lx\n",
  601. i, new_sum, sum,
  602. estate.p.phdr64[i].p_memsz, bytes);
  603. #endif
  604. }
  605. if (estate.ip_checksum != sum) {
  606. printf("\nImage checksum: %hx != computed checksum: %hx\n",
  607. estate.ip_checksum, sum);
  608. longjmp(restart_etherboot, -2);
  609. }
  610. }
  611. #endif
  612. done(1);
  613. /* Fixup the offset to the program header so you can find the program headers from
  614. * the ELF header mknbi needs this.
  615. */
  616. estate.e.elf64.e_phoff = (char *)&estate.p - (char *)&estate.e;
  617. elf_boot(machine,entry);
  618. }
  619. return skip_sectors;
  620. }
  621. #endif /* ELF64_IMAGE */