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 21KB

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