Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

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