Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. #include <errno.h>
  2. #include <assert.h>
  3. #include <realmode.h>
  4. #include <memsizes.h>
  5. #include <basemem_packet.h>
  6. #include <ipxe/uaccess.h>
  7. #include <ipxe/segment.h>
  8. #include <ipxe/init.h>
  9. #include <ipxe/netdevice.h>
  10. #include <ipxe/fakedhcp.h>
  11. #include <ipxe/image.h>
  12. #include <ipxe/features.h>
  13. /** @file
  14. *
  15. * NBI image format.
  16. *
  17. * The Net Boot Image format is defined by the "Draft Net Boot Image
  18. * Proposal 0.3" by Jamie Honan, Gero Kuhlmann and Ken Yap. It is now
  19. * considered to be a legacy format, but it still included because a
  20. * large amount of software (e.g. nymph, LTSP) makes use of NBI files.
  21. *
  22. * Etherboot does not implement the INT 78 callback interface
  23. * described by the NBI specification. For a callback interface on
  24. * x86 architecture, use PXE.
  25. *
  26. */
  27. FEATURE ( FEATURE_IMAGE, "NBI", DHCP_EB_FEATURE_NBI, 1 );
  28. struct image_type nbi_image_type __image_type ( PROBE_NORMAL );
  29. /**
  30. * An NBI image header
  31. *
  32. * Note that the length field uses a peculiar encoding; use the
  33. * NBI_LENGTH() macro to decode the actual header length.
  34. *
  35. */
  36. struct imgheader {
  37. unsigned long magic; /**< Magic number (NBI_MAGIC) */
  38. union {
  39. unsigned char length; /**< Nibble-coded header length */
  40. unsigned long flags; /**< Image flags */
  41. };
  42. segoff_t location; /**< 16-bit seg:off header location */
  43. union {
  44. segoff_t segoff; /**< 16-bit seg:off entry point */
  45. unsigned long linear; /**< 32-bit entry point */
  46. } execaddr;
  47. } __attribute__ (( packed ));
  48. /** NBI magic number */
  49. #define NBI_MAGIC 0x1B031336UL
  50. /* Interpretation of the "length" fields */
  51. #define NBI_NONVENDOR_LENGTH(len) ( ( (len) & 0x0f ) << 2 )
  52. #define NBI_VENDOR_LENGTH(len) ( ( (len) & 0xf0 ) >> 2 )
  53. #define NBI_LENGTH(len) ( NBI_NONVENDOR_LENGTH(len) + NBI_VENDOR_LENGTH(len) )
  54. /* Interpretation of the "flags" fields */
  55. #define NBI_PROGRAM_RETURNS(flags) ( (flags) & ( 1 << 8 ) )
  56. #define NBI_LINEAR_EXEC_ADDR(flags) ( (flags) & ( 1 << 31 ) )
  57. /** NBI header length */
  58. #define NBI_HEADER_LENGTH 512
  59. /**
  60. * An NBI segment header
  61. *
  62. * Note that the length field uses a peculiar encoding; use the
  63. * NBI_LENGTH() macro to decode the actual header length.
  64. *
  65. */
  66. struct segheader {
  67. unsigned char length; /**< Nibble-coded header length */
  68. unsigned char vendortag; /**< Vendor-defined private tag */
  69. unsigned char reserved;
  70. unsigned char flags; /**< Segment flags */
  71. unsigned long loadaddr; /**< Load address */
  72. unsigned long imglength; /**< Segment length in NBI file */
  73. unsigned long memlength; /**< Segment length in memory */
  74. };
  75. /* Interpretation of the "flags" fields */
  76. #define NBI_LOADADDR_FLAGS(flags) ( (flags) & 0x03 )
  77. #define NBI_LOADADDR_ABS 0x00
  78. #define NBI_LOADADDR_AFTER 0x01
  79. #define NBI_LOADADDR_END 0x02
  80. #define NBI_LOADADDR_BEFORE 0x03
  81. #define NBI_LAST_SEGHEADER(flags) ( (flags) & ( 1 << 2 ) )
  82. /* Define a type for passing info to a loaded program */
  83. struct ebinfo {
  84. uint8_t major, minor; /* Version */
  85. uint16_t flags; /* Bit flags */
  86. };
  87. /** Info passed to NBI image */
  88. static struct ebinfo loaderinfo = {
  89. VERSION_MAJOR, VERSION_MINOR,
  90. 0
  91. };
  92. /**
  93. * Prepare a segment for an NBI image
  94. *
  95. * @v image NBI image
  96. * @v offset Offset within NBI image
  97. * @v filesz Length of initialised-data portion of the segment
  98. * @v memsz Total length of the segment
  99. * @v src Source for initialised data
  100. * @ret rc Return status code
  101. */
  102. static int nbi_prepare_segment ( struct image *image, size_t offset __unused,
  103. userptr_t dest, size_t filesz, size_t memsz ){
  104. int rc;
  105. if ( ( rc = prep_segment ( dest, filesz, memsz ) ) != 0 ) {
  106. DBGC ( image, "NBI %p could not prepare segment: %s\n",
  107. image, strerror ( rc ) );
  108. return rc;
  109. }
  110. return 0;
  111. }
  112. /**
  113. * Load a segment for an NBI image
  114. *
  115. * @v image NBI image
  116. * @v offset Offset within NBI image
  117. * @v filesz Length of initialised-data portion of the segment
  118. * @v memsz Total length of the segment
  119. * @v src Source for initialised data
  120. * @ret rc Return status code
  121. */
  122. static int nbi_load_segment ( struct image *image, size_t offset,
  123. userptr_t dest, size_t filesz,
  124. size_t memsz __unused ) {
  125. memcpy_user ( dest, 0, image->data, offset, filesz );
  126. return 0;
  127. }
  128. /**
  129. * Process segments of an NBI image
  130. *
  131. * @v image NBI image
  132. * @v imgheader Image header information
  133. * @v process Function to call for each segment
  134. * @ret rc Return status code
  135. */
  136. static int nbi_process_segments ( struct image *image,
  137. struct imgheader *imgheader,
  138. int ( * process ) ( struct image *image,
  139. size_t offset,
  140. userptr_t dest,
  141. size_t filesz,
  142. size_t memsz ) ) {
  143. struct segheader sh;
  144. size_t offset = 0;
  145. size_t sh_off;
  146. userptr_t dest;
  147. size_t filesz;
  148. size_t memsz;
  149. int rc;
  150. /* Copy image header to target location */
  151. dest = real_to_user ( imgheader->location.segment,
  152. imgheader->location.offset );
  153. filesz = memsz = NBI_HEADER_LENGTH;
  154. if ( ( rc = process ( image, offset, dest, filesz, memsz ) ) != 0 )
  155. return rc;
  156. offset += filesz;
  157. /* Process segments in turn */
  158. sh_off = NBI_LENGTH ( imgheader->length );
  159. do {
  160. /* Read segment header */
  161. copy_from_user ( &sh, image->data, sh_off, sizeof ( sh ) );
  162. if ( sh.length == 0 ) {
  163. /* Avoid infinite loop? */
  164. DBGC ( image, "NBI %p invalid segheader length 0\n",
  165. image );
  166. return -ENOEXEC;
  167. }
  168. /* Calculate segment load address */
  169. switch ( NBI_LOADADDR_FLAGS ( sh.flags ) ) {
  170. case NBI_LOADADDR_ABS:
  171. dest = phys_to_user ( sh.loadaddr );
  172. break;
  173. case NBI_LOADADDR_AFTER:
  174. dest = userptr_add ( dest, memsz + sh.loadaddr );
  175. break;
  176. case NBI_LOADADDR_BEFORE:
  177. dest = userptr_add ( dest, -sh.loadaddr );
  178. break;
  179. case NBI_LOADADDR_END:
  180. /* Not correct according to the spec, but
  181. * maintains backwards compatibility with
  182. * previous versions of Etherboot.
  183. */
  184. dest = phys_to_user ( ( extmemsize() + 1024 ) * 1024
  185. - sh.loadaddr );
  186. break;
  187. default:
  188. /* Cannot be reached */
  189. assert ( 0 );
  190. }
  191. /* Process this segment */
  192. filesz = sh.imglength;
  193. memsz = sh.memlength;
  194. if ( ( offset + filesz ) > image->len ) {
  195. DBGC ( image, "NBI %p segment outside file\n", image );
  196. return -ENOEXEC;
  197. }
  198. if ( ( rc = process ( image, offset, dest,
  199. filesz, memsz ) ) != 0 ) {
  200. return rc;
  201. }
  202. offset += filesz;
  203. /* Next segheader */
  204. sh_off += NBI_LENGTH ( sh.length );
  205. if ( sh_off >= NBI_HEADER_LENGTH ) {
  206. DBGC ( image, "NBI %p header overflow\n", image );
  207. return -ENOEXEC;
  208. }
  209. } while ( ! NBI_LAST_SEGHEADER ( sh.flags ) );
  210. if ( offset != image->len ) {
  211. DBGC ( image, "NBI %p length wrong (file %zd, metadata %zd)\n",
  212. image, image->len, offset );
  213. return -ENOEXEC;
  214. }
  215. return 0;
  216. }
  217. /**
  218. * Load an NBI image into memory
  219. *
  220. * @v image NBI image
  221. * @ret rc Return status code
  222. */
  223. static int nbi_load ( struct image *image ) {
  224. struct imgheader imgheader;
  225. int rc;
  226. /* If we don't have enough data give up */
  227. if ( image->len < NBI_HEADER_LENGTH ) {
  228. DBGC ( image, "NBI %p too short for an NBI image\n", image );
  229. return -ENOEXEC;
  230. }
  231. /* Check image header */
  232. copy_from_user ( &imgheader, image->data, 0, sizeof ( imgheader ) );
  233. if ( imgheader.magic != NBI_MAGIC ) {
  234. DBGC ( image, "NBI %p has no NBI signature\n", image );
  235. return -ENOEXEC;
  236. }
  237. /* This is an NBI image, valid or otherwise */
  238. if ( ! image->type )
  239. image->type = &nbi_image_type;
  240. DBGC ( image, "NBI %p placing header at %hx:%hx\n", image,
  241. imgheader.location.segment, imgheader.location.offset );
  242. /* NBI files can have overlaps between segments; the bss of
  243. * one segment may overlap the initialised data of another. I
  244. * assume this is a design flaw, but there are images out
  245. * there that we need to work with. We therefore do two
  246. * passes: first to initialise the segments, then to copy the
  247. * data. This avoids zeroing out already-copied data.
  248. */
  249. if ( ( rc = nbi_process_segments ( image, &imgheader,
  250. nbi_prepare_segment ) ) != 0 )
  251. return rc;
  252. if ( ( rc = nbi_process_segments ( image, &imgheader,
  253. nbi_load_segment ) ) != 0 )
  254. return rc;
  255. /* Record header address in image private data field */
  256. image->priv.user = real_to_user ( imgheader.location.segment,
  257. imgheader.location.offset );
  258. return 0;
  259. }
  260. /**
  261. * Boot a 16-bit NBI image
  262. *
  263. * @v imgheader Image header information
  264. * @ret rc Return status code, if image returns
  265. */
  266. static int nbi_boot16 ( struct image *image, struct imgheader *imgheader ) {
  267. int discard_D, discard_S, discard_b;
  268. int rc;
  269. DBGC ( image, "NBI %p executing 16-bit image at %04x:%04x\n", image,
  270. imgheader->execaddr.segoff.segment,
  271. imgheader->execaddr.segoff.offset );
  272. __asm__ __volatile__ (
  273. REAL_CODE ( "pushw %%ds\n\t" /* far pointer to bootp data */
  274. "pushw %%bx\n\t"
  275. "pushl %%esi\n\t" /* location */
  276. "pushw %%cs\n\t" /* lcall execaddr */
  277. "call 1f\n\t"
  278. "jmp 2f\n\t"
  279. "\n1:\n\t"
  280. "pushl %%edi\n\t"
  281. "lret\n\t"
  282. "\n2:\n\t"
  283. "addw $8,%%sp\n\t" /* clean up stack */ )
  284. : "=a" ( rc ), "=D" ( discard_D ), "=S" ( discard_S ),
  285. "=b" ( discard_b )
  286. : "D" ( imgheader->execaddr.segoff ),
  287. "S" ( imgheader->location ),
  288. "b" ( __from_data16 ( basemem_packet ) )
  289. : "ecx", "edx", "ebp" );
  290. return rc;
  291. }
  292. /**
  293. * Boot a 32-bit NBI image
  294. *
  295. * @v imgheader Image header information
  296. * @ret rc Return status code, if image returns
  297. */
  298. static int nbi_boot32 ( struct image *image, struct imgheader *imgheader ) {
  299. int discard_D, discard_S, discard_b;
  300. int rc;
  301. DBGC ( image, "NBI %p executing 32-bit image at %lx\n",
  302. image, imgheader->execaddr.linear );
  303. /* Jump to OS with flat physical addressing */
  304. __asm__ __volatile__ (
  305. PHYS_CODE ( "pushl %%ebx\n\t" /* bootp data */
  306. "pushl %%esi\n\t" /* imgheader */
  307. "pushl %%eax\n\t" /* loaderinfo */
  308. "call *%%edi\n\t"
  309. "addl $12, %%esp\n\t" /* clean up stack */ )
  310. : "=a" ( rc ), "=D" ( discard_D ), "=S" ( discard_S ),
  311. "=b" ( discard_b )
  312. : "D" ( imgheader->execaddr.linear ),
  313. "S" ( ( imgheader->location.segment << 4 ) +
  314. imgheader->location.offset ),
  315. "b" ( virt_to_phys ( basemem_packet ) ),
  316. "a" ( virt_to_phys ( &loaderinfo ) )
  317. : "ecx", "edx", "ebp", "memory" );
  318. return rc;
  319. }
  320. /**
  321. * Prepare DHCP parameter block for NBI image
  322. *
  323. * @v image NBI image
  324. * @ret rc Return status code
  325. */
  326. static int nbi_prepare_dhcp ( struct image *image ) {
  327. struct net_device *boot_netdev;
  328. int rc;
  329. boot_netdev = last_opened_netdev();
  330. if ( ! boot_netdev ) {
  331. DBGC ( image, "NBI %p could not identify a network device\n",
  332. image );
  333. return -ENODEV;
  334. }
  335. if ( ( rc = create_fakedhcpack ( boot_netdev, basemem_packet,
  336. sizeof ( basemem_packet ) ) ) != 0 ) {
  337. DBGC ( image, "NBI %p failed to build DHCP packet\n", image );
  338. return rc;
  339. }
  340. return 0;
  341. }
  342. /**
  343. * Execute a loaded NBI image
  344. *
  345. * @v image NBI image
  346. * @ret rc Return status code
  347. */
  348. static int nbi_exec ( struct image *image ) {
  349. struct imgheader imgheader;
  350. int may_return;
  351. int rc;
  352. copy_from_user ( &imgheader, image->priv.user, 0,
  353. sizeof ( imgheader ) );
  354. /* Prepare DHCP option block */
  355. if ( ( rc = nbi_prepare_dhcp ( image ) ) != 0 )
  356. return rc;
  357. /* Shut down now if NBI image will not return */
  358. may_return = NBI_PROGRAM_RETURNS ( imgheader.flags );
  359. if ( ! may_return )
  360. shutdown_boot();
  361. /* Execute NBI image */
  362. if ( NBI_LINEAR_EXEC_ADDR ( imgheader.flags ) ) {
  363. rc = nbi_boot32 ( image, &imgheader );
  364. } else {
  365. rc = nbi_boot16 ( image, &imgheader );
  366. }
  367. if ( ! may_return ) {
  368. /* Cannot continue after shutdown() called */
  369. DBGC ( image, "NBI %p returned %d from non-returnable image\n",
  370. image, rc );
  371. while ( 1 ) {}
  372. }
  373. DBGC ( image, "NBI %p returned %d\n", image, rc );
  374. return rc;
  375. }
  376. /** NBI image type */
  377. struct image_type nbi_image_type __image_type ( PROBE_NORMAL ) = {
  378. .name = "NBI",
  379. .load = nbi_load,
  380. .exec = nbi_exec,
  381. };