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.

freebsd_loader.c 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. /* bootinfo */
  2. #define BOOTINFO_VERSION 1
  3. #define NODEV (-1) /* non-existent device */
  4. #define PAGE_SHIFT 12 /* LOG2(PAGE_SIZE) */
  5. #define PAGE_SIZE (1<<PAGE_SHIFT) /* bytes/page */
  6. #define PAGE_MASK (PAGE_SIZE-1)
  7. #define N_BIOS_GEOM 8
  8. struct bootinfo {
  9. unsigned int bi_version;
  10. const unsigned char *bi_kernelname;
  11. struct nfs_diskless *bi_nfs_diskless;
  12. /* End of fields that are always present. */
  13. #define bi_endcommon bi_n_bios_used
  14. unsigned int bi_n_bios_used;
  15. unsigned long bi_bios_geom[N_BIOS_GEOM];
  16. unsigned int bi_size;
  17. unsigned char bi_memsizes_valid;
  18. unsigned char bi_pad[3];
  19. unsigned long bi_basemem;
  20. unsigned long bi_extmem;
  21. unsigned long bi_symtab;
  22. unsigned long bi_esymtab;
  23. /* Note that these are in the FreeBSD headers but were not here... */
  24. unsigned long bi_kernend; /* end of kernel space */
  25. unsigned long bi_envp; /* environment */
  26. unsigned long bi_modulep; /* preloaded modules */
  27. };
  28. static struct bootinfo bsdinfo;
  29. #ifdef ELF_IMAGE
  30. static Elf32_Shdr *shdr; /* To support the FreeBSD kludge! */
  31. static Address symtab_load;
  32. static Address symstr_load;
  33. static int symtabindex;
  34. static int symstrindex;
  35. #endif
  36. static enum {
  37. Unknown, Tagged, Aout, Elf, Aout_FreeBSD, Elf_FreeBSD,
  38. } image_type = Unknown;
  39. static unsigned int off;
  40. #ifdef ELF_IMAGE
  41. static void elf_freebsd_probe(void)
  42. {
  43. image_type = Elf;
  44. if ( (estate.e.elf32.e_entry & 0xf0000000) &&
  45. (estate.e.elf32.e_type == ET_EXEC))
  46. {
  47. image_type = Elf_FreeBSD;
  48. printf("/FreeBSD");
  49. off = -(estate.e.elf32.e_entry & 0xff000000);
  50. estate.e.elf32.e_entry += off;
  51. }
  52. /* Make sure we have a null to start with... */
  53. shdr = 0;
  54. /* Clear the symbol index values... */
  55. symtabindex = -1;
  56. symstrindex = -1;
  57. /* ...and the load addresses of the symbols */
  58. symtab_load = 0;
  59. symstr_load = 0;
  60. }
  61. static void elf_freebsd_fixup_segment(void)
  62. {
  63. if (image_type == Elf_FreeBSD) {
  64. estate.p.phdr32[estate.segment].p_paddr += off;
  65. }
  66. }
  67. static void elf_freebsd_find_segment_end(void)
  68. {
  69. /* Count the bytes read even for the last block
  70. * as we will need to know where the last block
  71. * ends in order to load the symbols correctly.
  72. * (plus it could be useful elsewhere...)
  73. * Note that we need to count the actual size,
  74. * not just the end of the disk image size.
  75. */
  76. estate.curaddr +=
  77. (estate.p.phdr32[estate.segment].p_memsz -
  78. estate.p.phdr32[estate.segment].p_filesz);
  79. }
  80. static int elf_freebsd_debug_loader(unsigned int offset)
  81. {
  82. /* No more segments to be loaded - time to start the
  83. * nasty state machine to support the loading of
  84. * FreeBSD debug symbols due to the fact that FreeBSD
  85. * uses/exports the kernel's debug symbols in order
  86. * to make much of the system work! Amazing (arg!)
  87. *
  88. * We depend on the fact that for the FreeBSD kernel,
  89. * there is only one section of debug symbols and that
  90. * the section is after all of the loaded sections in
  91. * the file. This assumes a lot but is somewhat required
  92. * to make this code not be too annoying. (Where do you
  93. * load symbols when the code has not loaded yet?)
  94. * Since this function is actually just a callback from
  95. * the network data transfer code, we need to be able to
  96. * work with the data as it comes in. There is no chance
  97. * for doing a seek other than forwards.
  98. *
  99. * The process we use is to first load the section
  100. * headers. Once they are loaded (shdr != 0) we then
  101. * look for where the symbol table and symbol table
  102. * strings are and setup some state that we found
  103. * them and fall into processing the first one (which
  104. * is the symbol table) and after that has been loaded,
  105. * we try the symbol strings. Note that the order is
  106. * actually required as the memory image depends on
  107. * the symbol strings being loaded starting at the
  108. * end of the symbol table. The kernel assumes this
  109. * layout of the image.
  110. *
  111. * At any point, if we get to the end of the load file
  112. * or the section requested is earlier in the file than
  113. * the current file pointer, we just end up falling
  114. * out of this and booting the kernel without this
  115. * information.
  116. */
  117. /* Make sure that the next address is long aligned... */
  118. /* Assumes size of long is a power of 2... */
  119. estate.curaddr = (estate.curaddr + sizeof(long) - 1) & ~(sizeof(long) - 1);
  120. /* If we have not yet gotten the shdr loaded, try that */
  121. if (shdr == 0)
  122. {
  123. estate.toread = estate.e.elf32.e_shnum * estate.e.elf32.e_shentsize;
  124. estate.skip = estate.e.elf32.e_shoff - (estate.loc + offset);
  125. if (estate.toread)
  126. {
  127. #if ELF_DEBUG
  128. printf("shdr *, size %lX, curaddr %lX\n",
  129. estate.toread, estate.curaddr);
  130. #endif
  131. /* Start reading at the curaddr and make that the shdr */
  132. shdr = (Elf32_Shdr *)phys_to_virt(estate.curaddr);
  133. /* Start to read... */
  134. return 1;
  135. }
  136. }
  137. else
  138. {
  139. /* We have the shdr loaded, check if we have found
  140. * the indexs where the symbols are supposed to be */
  141. if ((symtabindex == -1) && (symstrindex == -1))
  142. {
  143. int i;
  144. /* Make sure that the address is page aligned... */
  145. /* Symbols need to start in their own page(s)... */
  146. estate.curaddr = (estate.curaddr + 4095) & ~4095;
  147. /* Need to make new indexes... */
  148. for (i=0; i < estate.e.elf32.e_shnum; i++)
  149. {
  150. if (shdr[i].sh_type == SHT_SYMTAB)
  151. {
  152. int j;
  153. for (j=0; j < estate.e.elf32.e_phnum; j++)
  154. {
  155. /* Check only for loaded sections */
  156. if ((estate.p.phdr32[j].p_type | 0x80) == (PT_LOAD | 0x80))
  157. {
  158. /* Only the extra symbols */
  159. if ((shdr[i].sh_offset >= estate.p.phdr32[j].p_offset) &&
  160. ((shdr[i].sh_offset + shdr[i].sh_size) <=
  161. (estate.p.phdr32[j].p_offset + estate.p.phdr32[j].p_filesz)))
  162. {
  163. shdr[i].sh_offset=0;
  164. shdr[i].sh_size=0;
  165. break;
  166. }
  167. }
  168. }
  169. if ((shdr[i].sh_offset != 0) && (shdr[i].sh_size != 0))
  170. {
  171. symtabindex = i;
  172. symstrindex = shdr[i].sh_link;
  173. }
  174. }
  175. }
  176. }
  177. /* Check if we have a symbol table index and have not loaded it */
  178. if ((symtab_load == 0) && (symtabindex >= 0))
  179. {
  180. /* No symbol table yet? Load it first... */
  181. /* This happens to work out in a strange way.
  182. * If we are past the point in the file already,
  183. * we will skip a *large* number of bytes which
  184. * ends up bringing us to the end of the file and
  185. * an old (default) boot. Less code and lets
  186. * the state machine work in a cleaner way but this
  187. * is a nasty side-effect trick... */
  188. estate.skip = shdr[symtabindex].sh_offset - (estate.loc + offset);
  189. /* And we need to read this many bytes... */
  190. estate.toread = shdr[symtabindex].sh_size;
  191. if (estate.toread)
  192. {
  193. #if ELF_DEBUG
  194. printf("db sym, size %lX, curaddr %lX\n",
  195. estate.toread, estate.curaddr);
  196. #endif
  197. /* Save where we are loading this... */
  198. symtab_load = phys_to_virt(estate.curaddr);
  199. *((long *)phys_to_virt(estate.curaddr)) = estate.toread;
  200. estate.curaddr += sizeof(long);
  201. /* Start to read... */
  202. return 1;
  203. }
  204. }
  205. else if ((symstr_load == 0) && (symstrindex >= 0))
  206. {
  207. /* We have already loaded the symbol table, so
  208. * now on to the symbol strings... */
  209. /* Same nasty trick as above... */
  210. estate.skip = shdr[symstrindex].sh_offset - (estate.loc + offset);
  211. /* And we need to read this many bytes... */
  212. estate.toread = shdr[symstrindex].sh_size;
  213. if (estate.toread)
  214. {
  215. #if ELF_DEBUG
  216. printf("db str, size %lX, curaddr %lX\n",
  217. estate.toread, estate.curaddr);
  218. #endif
  219. /* Save where we are loading this... */
  220. symstr_load = phys_to_virt(estate.curaddr);
  221. *((long *)phys_to_virt(estate.curaddr)) = estate.toread;
  222. estate.curaddr += sizeof(long);
  223. /* Start to read... */
  224. return 1;
  225. }
  226. }
  227. }
  228. /* all done */
  229. return 0;
  230. }
  231. static void elf_freebsd_boot(unsigned long entry)
  232. {
  233. if (image_type != Elf_FreeBSD)
  234. return;
  235. memset(&bsdinfo, 0, sizeof(bsdinfo));
  236. bsdinfo.bi_basemem = meminfo.basememsize;
  237. bsdinfo.bi_extmem = meminfo.memsize;
  238. bsdinfo.bi_memsizes_valid = 1;
  239. bsdinfo.bi_version = BOOTINFO_VERSION;
  240. bsdinfo.bi_kernelname = virt_to_phys(KERNEL_BUF);
  241. bsdinfo.bi_nfs_diskless = NULL;
  242. bsdinfo.bi_size = sizeof(bsdinfo);
  243. #define RB_BOOTINFO 0x80000000 /* have `struct bootinfo *' arg */
  244. if(freebsd_kernel_env[0] != '\0'){
  245. freebsd_howto |= RB_BOOTINFO;
  246. bsdinfo.bi_envp = (unsigned long)freebsd_kernel_env;
  247. }
  248. /* Check if we have symbols loaded, and if so,
  249. * made the meta_data needed to pass those to
  250. * the kernel. */
  251. if ((symtab_load !=0) && (symstr_load != 0))
  252. {
  253. unsigned long *t;
  254. bsdinfo.bi_symtab = symtab_load;
  255. /* End of symbols (long aligned...) */
  256. /* Assumes size of long is a power of 2... */
  257. bsdinfo.bi_esymtab = (symstr_load +
  258. sizeof(long) +
  259. *((long *)symstr_load) +
  260. sizeof(long) - 1) & ~(sizeof(long) - 1);
  261. /* Where we will build the meta data... */
  262. t = phys_to_virt(bsdinfo.bi_esymtab);
  263. #if ELF_DEBUG
  264. printf("Metadata at %lX\n",t);
  265. #endif
  266. /* Set up the pointer to the memory... */
  267. bsdinfo.bi_modulep = virt_to_phys(t);
  268. /* The metadata structure is an array of 32-bit
  269. * words where we store some information about the
  270. * system. This is critical, as FreeBSD now looks
  271. * only for the metadata for the extended symbol
  272. * information rather than in the bootinfo.
  273. */
  274. /* First, do the kernel name and the kernel type */
  275. /* Note that this assumed x86 byte order... */
  276. /* 'kernel\0\0' */
  277. *t++=MODINFO_NAME; *t++= 7; *t++=0x6E72656B; *t++=0x00006C65;
  278. /* 'elf kernel\0\0' */
  279. *t++=MODINFO_TYPE; *t++=11; *t++=0x20666C65; *t++=0x6E72656B; *t++ = 0x00006C65;
  280. /* Now the symbol start/end - note that they are
  281. * here in local/physical address - the Kernel
  282. * boot process will relocate the addresses. */
  283. *t++=MODINFOMD_SSYM | MODINFO_METADATA; *t++=sizeof(*t); *t++=bsdinfo.bi_symtab;
  284. *t++=MODINFOMD_ESYM | MODINFO_METADATA; *t++=sizeof(*t); *t++=bsdinfo.bi_esymtab;
  285. *t++=MODINFO_END; *t++=0; /* end of metadata */
  286. /* Since we have symbols we need to make
  287. * sure that the kernel knows its own end
  288. * of memory... It is not _end but after
  289. * the symbols and the metadata... */
  290. bsdinfo.bi_kernend = virt_to_phys(t);
  291. /* Signal locore.s that we have a valid bootinfo
  292. * structure that was completely filled in. */
  293. freebsd_howto |= 0x80000000;
  294. }
  295. xstart32(entry, freebsd_howto, NODEV, 0, 0, 0,
  296. virt_to_phys(&bsdinfo), 0, 0, 0);
  297. longjmp(restart_etherboot, -2);
  298. }
  299. #endif
  300. #ifdef AOUT_IMAGE
  301. static void aout_freebsd_probe(void)
  302. {
  303. image_type = Aout;
  304. if (((astate.head.a_midmag >> 16) & 0xffff) == 0) {
  305. /* Some other a.out variants have a different
  306. * value, and use other alignments (e.g. 1K),
  307. * not the 4K used by FreeBSD. */
  308. image_type = Aout_FreeBSD;
  309. printf("/FreeBSD");
  310. off = -(astate.head.a_entry & 0xff000000);
  311. astate.head.a_entry += off;
  312. }
  313. }
  314. static void aout_freebsd_boot(void)
  315. {
  316. if (image_type == Aout_FreeBSD) {
  317. memset(&bsdinfo, 0, sizeof(bsdinfo));
  318. bsdinfo.bi_basemem = meminfo.basememsize;
  319. bsdinfo.bi_extmem = meminfo.memsize;
  320. bsdinfo.bi_memsizes_valid = 1;
  321. bsdinfo.bi_version = BOOTINFO_VERSION;
  322. bsdinfo.bi_kernelname = virt_to_phys(KERNEL_BUF);
  323. bsdinfo.bi_nfs_diskless = NULL;
  324. bsdinfo.bi_size = sizeof(bsdinfo);
  325. xstart32(astate.head.a_entry, freebsd_howto, NODEV, 0, 0, 0,
  326. virt_to_phys(&bsdinfo), 0, 0, 0);
  327. longjmp(restart_etherboot, -2);
  328. }
  329. }
  330. #endif