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.

osloader.c 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. /**************************************************************************
  2. OS loader
  3. Author: Markus Gutschke (gutschk@math.uni-muenster.de)
  4. Date: Sep/95
  5. Modifications: Ken Yap (for Etherboot/16)
  6. Doug Ambrisko (ELF and a.out support)
  7. Klaus Espenlaub (rewrote ELF and a.out (did it really work before?) support,
  8. added ELF Multiboot images). Someone should merge the ELF and a.out
  9. loaders, as most of the code is now identical. Maybe even NBI could be
  10. rewritten and merged into the generic loading framework. This should
  11. save quite a few bytes of code if you have selected more than one format.
  12. Ken Yap (Jan 2001)
  13. Added support for linear entry addresses in tagged images,
  14. which allows a more efficient protected mode call instead of
  15. going to real mode and back. Also means entry addresses > 1 MB can
  16. be called. Conditional on the LINEAR_EXEC_ADDR bit.
  17. Added support for Etherboot extension calls. Conditional on the
  18. TAGGED_PROGRAM_RETURNS bit. Implies LINEAR_EXEC_ADDR.
  19. Added support for non-MULTIBOOT ELF which also supports Etherboot
  20. extension calls. Conditional on the ELF_PROGRAM_RETURNS bit.
  21. **************************************************************************/
  22. /*
  23. * This program is free software; you can redistribute it and/or
  24. * modify it under the terms of the GNU General Public License as
  25. * published by the Free Software Foundation; either version 2, or (at
  26. * your option) any later version.
  27. */
  28. #include "etherboot.h"
  29. #include "memsizes.h"
  30. #ifdef KEEP_IT_REAL
  31. #warning "All download mechanisms are broken under KEEP_IT_REAL"
  32. os_download_t probe_image(unsigned char *data, unsigned int len) {
  33. return 0;
  34. }
  35. int load_block(unsigned char *data, unsigned int block, unsigned int len, int eof) {
  36. return 1;
  37. }
  38. #else /* KEEP_IT_REAL */
  39. struct os_entry_regs os_regs;
  40. static struct ebinfo loaderinfo = {
  41. VERSION_MAJOR, VERSION_MINOR,
  42. 0
  43. };
  44. #define LOAD_DEBUG 0
  45. static int prep_segment(unsigned long start, unsigned long mid, unsigned long end,
  46. unsigned long istart, unsigned long iend);
  47. static unsigned long find_segment(unsigned long size, unsigned long align);
  48. static sector_t dead_download ( unsigned char *data, unsigned int len, int eof);
  49. static void done(int do_cleanup);
  50. #if defined(IMAGE_FREEBSD) && defined(ELF_IMAGE)
  51. static void elf_freebsd_probe(void);
  52. static void elf_freebsd_fixup_segment(void);
  53. static void elf_freebsd_find_segment_end(void);
  54. static int elf_freebsd_debug_loader(unsigned int offset);
  55. static void elf_freebsd_boot(unsigned long entry);
  56. #else
  57. #define elf_freebsd_probe() do {} while(0)
  58. #define elf_freebsd_fixup_segment() do {} while(0)
  59. #define elf_freebsd_find_segment_end() do {} while(0)
  60. #define elf_freebsd_debug_loader(off) (0)
  61. #define elf_freebsd_boot(entry) do {} while(0)
  62. #endif
  63. #if defined(IMAGE_FREEBSD) && defined(AOUT_IMAGE)
  64. static void aout_freebsd_probe(void);
  65. static void aout_freebsd_boot(void);
  66. #else
  67. #define aout_freebsd_probe() do {} while(0)
  68. #define aout_freebsd_boot() do {} while(0)
  69. #endif
  70. /**************************************************************************
  71. dead_download - Restart etherboot if probe image fails
  72. **************************************************************************/
  73. static sector_t dead_download ( unsigned char *data __unused, unsigned int len __unused, int eof __unused) {
  74. longjmp(restart_etherboot, -2);
  75. }
  76. #ifdef IMAGE_MULTIBOOT
  77. #include "../arch/i386/core/multiboot_loader.c"
  78. #else
  79. #define multiboot_probe(data, len) do {} while(0)
  80. #define multiboot_boot(entry) do {} while(0)
  81. #endif
  82. #ifdef WINCE_IMAGE
  83. #include "../arch/i386/core/wince_loader.c"
  84. #endif
  85. #ifdef AOUT_IMAGE
  86. #include "../arch/i386/core/aout_loader.c"
  87. #endif
  88. #ifdef TAGGED_IMAGE
  89. #include "../arch/i386/core/tagged_loader.c"
  90. #endif
  91. #if defined(ELF_IMAGE) || defined(ELF64_IMAGE)
  92. #include "elf_loader.c"
  93. #endif
  94. #if defined(COFF_IMAGE)
  95. #include "../arch/e1/core/coff_loader.c"
  96. #endif
  97. #ifdef IMAGE_FREEBSD
  98. #include "../arch/i386/core/freebsd_loader.c"
  99. #endif
  100. #ifdef PXE_IMAGE
  101. #include "../arch/i386/core/pxe_loader.c"
  102. #endif
  103. #ifdef RAW_IMAGE
  104. #include "../arch/armnommu/core/raw_loader.c"
  105. #endif
  106. static void done(int do_cleanup)
  107. {
  108. #ifdef SIZEINDICATOR
  109. printf("K ");
  110. #endif
  111. printf("done\n");
  112. /* We may not want to do the cleanup: when booting a PXE
  113. * image, for example, we need to leave the network card
  114. * enabled, and it helps debugging if the serial console
  115. * remains enabled. The call the cleanup() will be triggered
  116. * when the PXE stack is shut down.
  117. */
  118. if ( do_cleanup ) {
  119. cleanup();
  120. /* arch_on_exit(0); */
  121. }
  122. }
  123. static int prep_segment(unsigned long start, unsigned long mid, unsigned long end,
  124. unsigned long istart __unused, unsigned long iend __unused)
  125. {
  126. unsigned fit, i;
  127. #if LOAD_DEBUG
  128. printf ( "\nAbout to prepare segment [%lX,%lX)\n", start, end );
  129. sleep ( 3 );
  130. #endif
  131. if (mid > end) {
  132. printf("filesz > memsz\n");
  133. return 0;
  134. }
  135. if ((end > virt_to_phys(_text)) &&
  136. (start < virt_to_phys(_end))) {
  137. printf("segment [%lX, %lX) overlaps etherboot [%lX, %lX)\n",
  138. start, end,
  139. virt_to_phys(_text), virt_to_phys(_end)
  140. );
  141. return 0;
  142. }
  143. if ((end > heap_ptr) && (start < heap_bot)) {
  144. printf("segment [%lX, %lX) overlaps heap [%lX, %lX)\n",
  145. start, end,
  146. heap_ptr, heap_bot
  147. );
  148. return 0;
  149. }
  150. fit = 0;
  151. for(i = 0; i < meminfo.map_count; i++) {
  152. unsigned long long r_start, r_end;
  153. if (meminfo.map[i].type != E820_RAM)
  154. continue;
  155. r_start = meminfo.map[i].addr;
  156. r_end = r_start + meminfo.map[i].size;
  157. if ((start >= r_start) && (end <= r_end)) {
  158. fit = 1;
  159. break;
  160. }
  161. }
  162. if (!fit) {
  163. printf("\nsegment [%lX,%lX) does not fit in any memory region\n",
  164. start, end);
  165. #if LOAD_DEBUG
  166. printf("Memory regions(%d):\n", meminfo.map_count);
  167. for(i = 0; i < meminfo.map_count; i++) {
  168. unsigned long long r_start, r_end;
  169. if (meminfo.map[i].type != E820_RAM)
  170. continue;
  171. r_start = meminfo.map[i].addr;
  172. r_end = r_start + meminfo.map[i].size;
  173. printf("[%X%X, %X%X) type %d\n",
  174. (unsigned long)(r_start >> 32),
  175. (unsigned long)r_start,
  176. (unsigned long)(r_end >> 32),
  177. (unsigned long)r_end,
  178. meminfo.map[i].type);
  179. }
  180. #endif
  181. return 0;
  182. }
  183. #if LOAD_DEBUG
  184. /* Zap the whole lot. Do this so that if we're treading on
  185. * anything, it shows up now, when the debug message is
  186. * visible, rather than when we're partway through downloading
  187. * the file.
  188. *
  189. * If you see an entire screen full of exclamation marks, then
  190. * you've almost certainly written all over the display RAM.
  191. * This is likely to happen if the status of the A20 line gets
  192. * screwed up. Of course, if this happens, it's a good bet
  193. * that you've also trashed the whole of low memory, so expect
  194. * interesting things to happen...
  195. */
  196. memset(phys_to_virt(start), '!', mid - start);
  197. #endif
  198. /* Zero the bss */
  199. if (end > mid) {
  200. memset(phys_to_virt(mid), 0, end - mid);
  201. }
  202. return 1;
  203. }
  204. static unsigned long find_segment(unsigned long size, unsigned long align)
  205. {
  206. unsigned i;
  207. /* Verify I have a power of 2 alignment */
  208. if (align & (align - 1)) {
  209. return ULONG_MAX;
  210. }
  211. for(i = 0; i < meminfo.map_count; i++) {
  212. unsigned long r_start, r_end;
  213. if (meminfo.map[i].type != E820_RAM)
  214. continue;
  215. if ((meminfo.map[i].addr + meminfo.map[i].size) > ULONG_MAX) {
  216. continue;
  217. }
  218. r_start = meminfo.map[i].addr;
  219. r_end = r_start + meminfo.map[i].size;
  220. /* Don't allow the segment to overlap etherboot */
  221. if ((r_end > virt_to_phys(_text)) && (r_start < virt_to_phys(_text))) {
  222. r_end = virt_to_phys(_text);
  223. }
  224. if ((r_start > virt_to_phys(_text)) && (r_start < virt_to_phys(_end))) {
  225. r_start = virt_to_phys(_end);
  226. }
  227. /* Don't allow the segment to overlap the heap */
  228. if ((r_end > heap_ptr) && (r_start < heap_ptr)) {
  229. r_end = heap_ptr;
  230. }
  231. if ((r_start > heap_ptr) && (r_start < heap_bot)) {
  232. r_start = heap_ptr;
  233. }
  234. r_start = (r_start + align - 1) & ~(align - 1);
  235. if ((r_end >= r_start) && ((r_end - r_start) >= size)) {
  236. return r_start;
  237. }
  238. }
  239. /* I did not find anything :( */
  240. return ULONG_MAX;
  241. }
  242. /**************************************************************************
  243. PROBE_IMAGE - Detect image file type
  244. **************************************************************************/
  245. os_download_t probe_image(unsigned char *data, unsigned int len)
  246. {
  247. os_download_t os_download = 0;
  248. #ifdef AOUT_IMAGE
  249. if (!os_download) os_download = aout_probe(data, len);
  250. #endif
  251. #ifdef ELF_IMAGE
  252. if (!os_download) os_download = elf32_probe(data, len);
  253. #endif
  254. #ifdef ELF64_IMAGE
  255. if (!os_download) os_download = elf64_probe(data, len);
  256. #endif
  257. #ifdef COFF_IMAGE
  258. if (!os_download) os_download = coff_probe(data, len);
  259. #endif
  260. #ifdef WINCE_IMAGE
  261. if (!os_download) os_download = wince_probe(data, len);
  262. #endif
  263. #ifdef TAGGED_IMAGE
  264. if (!os_download) os_download = tagged_probe(data, len);
  265. #endif
  266. /* PXE_IMAGE must always be last */
  267. #ifdef PXE_IMAGE
  268. if (!os_download) os_download = pxe_probe(data, len);
  269. #endif
  270. #ifdef RAW_IMAGE
  271. if (!os_download) os_download = raw_probe(data, len);
  272. #endif
  273. return os_download;
  274. }
  275. /**************************************************************************
  276. LOAD_BLOCK - Try to load file
  277. **************************************************************************/
  278. int load_block(unsigned char *data, unsigned int block, unsigned int len, int eof)
  279. {
  280. static os_download_t os_download;
  281. static sector_t skip_sectors;
  282. static unsigned int skip_bytes;
  283. #ifdef SIZEINDICATOR
  284. static int rlen = 0;
  285. if (block == 1)
  286. {
  287. rlen=len;
  288. printf("XXXX");
  289. }
  290. if (!(block % 4) || eof) {
  291. int size;
  292. size = ((block-1) * rlen + len) / 1024;
  293. putchar('\b');
  294. putchar('\b');
  295. putchar('\b');
  296. putchar('\b');
  297. putchar('0' + (size/1000)%10);
  298. putchar('0' + (size/100)%10);
  299. putchar('0' + (size/10)%10);
  300. putchar('0' + (size/1)%10);
  301. }
  302. #endif
  303. if (block == 1)
  304. {
  305. skip_sectors = 0;
  306. skip_bytes = 0;
  307. os_download = probe_image(data, len);
  308. if (!os_download) {
  309. printf("error: not a valid image\n");
  310. #if 0
  311. printf("block: %d len: %d\n", block, len);
  312. printf("%hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx\n",
  313. data[0], data[1], data[2], data[3],
  314. data[4], data[5], data[6], data[7]);
  315. #endif
  316. return 0;
  317. }
  318. } /* end of block zero processing */
  319. /* Either len is greater or the skip is greater */
  320. if ((skip_sectors > (len >> 9)) ||
  321. ((skip_sectors == (len >> 9)) && (skip_bytes >= (len & 0x1ff)))) {
  322. /* If I don't have enough bytes borrow them from skip_sectors */
  323. if (skip_bytes < len) {
  324. skip_sectors -= (len - skip_bytes + 511) >> 9;
  325. skip_bytes += (len - skip_bytes + 511) & ~0x1ff;
  326. }
  327. skip_bytes -= len;
  328. }
  329. else {
  330. len -= (skip_sectors << 9) + skip_bytes;
  331. data += (skip_sectors << 9) + skip_bytes;
  332. }
  333. skip_sectors = os_download(data, len, eof);
  334. skip_bytes = 0;
  335. return 1;
  336. }
  337. /*
  338. * Local variables:
  339. * c-basic-offset: 8
  340. * End:
  341. */
  342. #endif /* KEEP_IT_REAL */