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.

nbi.c 12KB

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