您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

pxeprefix.S 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749
  1. #define PXENV_UNDI_SHUTDOWN 0x0005
  2. #define PXENV_UNDI_GET_NIC_TYPE 0x0012
  3. #define PXENV_UNDI_GET_IFACE_INFO 0x0013
  4. #define PXENV_STOP_UNDI 0x0015
  5. #define PXENV_UNLOAD_STACK 0x0070
  6. #define PXE_HACK_EB54 0x0001
  7. .text
  8. .arch i386
  9. .org 0
  10. .code16
  11. #include <undi.h>
  12. #define STACK_MAGIC ( 'L' + ( 'R' << 8 ) + ( 'E' << 16 ) + ( 'T' << 24 ) )
  13. #define EB_MAGIC_1 ( 'E' + ( 't' << 8 ) + ( 'h' << 16 ) + ( 'e' << 24 ) )
  14. #define EB_MAGIC_2 ( 'r' + ( 'b' << 8 ) + ( 'o' << 16 ) + ( 'o' << 24 ) )
  15. /*****************************************************************************
  16. * Entry point: set operating context, print welcome message
  17. *****************************************************************************
  18. */
  19. .section ".prefix", "ax", @progbits
  20. jmp $0x7c0, $1f
  21. 1:
  22. /* Preserve registers for possible return to PXE */
  23. pushfl
  24. pushal
  25. pushw %gs
  26. pushw %fs
  27. pushw %es
  28. pushw %ds
  29. /* Store magic word on PXE stack and remember PXE %ss:esp */
  30. pushl $STACK_MAGIC
  31. movw %ss, %cs:pxe_ss
  32. movl %esp, %cs:pxe_esp
  33. /* Set up segments */
  34. movw %cs, %ax
  35. movw %ax, %ds
  36. movw $0x40, %ax /* BIOS data segment access */
  37. movw %ax, %fs
  38. /* Set up stack just below 0x7c00 */
  39. xorw %ax, %ax
  40. movw %ax, %ss
  41. movl $0x7c00, %esp
  42. /* Clear direction flag, for the sake of sanity */
  43. cld
  44. /* Print welcome message */
  45. movw $10f, %si
  46. xorw %di, %di
  47. call print_message
  48. .section ".prefix.data", "aw", @progbits
  49. 10: .asciz "PXE->EB:"
  50. .previous
  51. /*****************************************************************************
  52. * Find us a usable !PXE or PXENV+ entry point
  53. *****************************************************************************
  54. */
  55. detect_pxe:
  56. /* Plan A: !PXE pointer from the stack */
  57. lgsl pxe_esp, %ebp /* %gs:%bp -> original stack */
  58. lesw %gs:52(%bp), %bx
  59. call is_valid_ppxe
  60. je have_ppxe
  61. /* Plan B: PXENV+ pointer from initial ES:BX */
  62. movw %gs:32(%bp),%bx
  63. movw %gs:8(%bp),%es
  64. call is_valid_pxenv
  65. je have_pxenv
  66. /* Plan C: PXENV+ structure via INT 1Ah */
  67. movw $0x5650, %ax
  68. int $0x1a
  69. jc 1f
  70. cmpw $0x564e, %ax
  71. jne 1f
  72. call is_valid_pxenv
  73. je have_pxenv
  74. 1:
  75. /* Plan D: scan base memory for !PXE */
  76. call memory_scan_ppxe
  77. je have_ppxe
  78. /* Plan E: scan base memory for PXENV+ */
  79. call memory_scan_pxenv
  80. jne stack_not_found
  81. have_pxenv:
  82. movw %bx, pxenv_offset
  83. movw %es, pxenv_segment
  84. cmpw $0x201, %es:6(%bx) /* API version >= 2.01 */
  85. jb 1f
  86. cmpb $0x2c, %es:8(%bx) /* ... and structure long enough */
  87. jb 2f
  88. lesw %es:0x28(%bx), %bx /* Find !PXE from PXENV+ */
  89. call is_valid_ppxe
  90. je have_ppxe
  91. 2:
  92. call memory_scan_ppxe /* We are *supposed* to have !PXE... */
  93. je have_ppxe
  94. 1:
  95. lesw pxenv_segoff, %bx /* Nope, we're stuck with PXENV+ */
  96. /* Record entry point and UNDI segments */
  97. pushl %es:0x0a(%bx) /* Entry point */
  98. pushw %es:0x24(%bx) /* UNDI code segment */
  99. pushw %es:0x26(%bx) /* UNDI code size */
  100. pushw %es:0x20(%bx) /* UNDI data segment */
  101. pushw %es:0x22(%bx) /* UNDI data size */
  102. /* Print "PXENV+ at <address>" */
  103. movw $10f, %si
  104. jmp check_have_stack
  105. .section ".prefix.data", "aw", @progbits
  106. 10: .asciz " PXENV+ at "
  107. .previous
  108. have_ppxe:
  109. movw %bx, ppxe_offset
  110. movw %es, ppxe_segment
  111. pushl %es:0x10(%bx) /* Entry point */
  112. pushw %es:0x30(%bx) /* UNDI code segment */
  113. pushw %es:0x36(%bx) /* UNDI code size */
  114. pushw %es:0x28(%bx) /* UNDI data segment */
  115. pushw %es:0x2e(%bx) /* UNDI data size */
  116. /* Print "!PXE at <address>" */
  117. movw $10f, %si
  118. jmp check_have_stack
  119. .section ".prefix.data", "aw", @progbits
  120. 10: .asciz " !PXE at "
  121. .previous
  122. is_valid_ppxe:
  123. cmpl $0x45585021, %es:(%bx)
  124. jne 1f
  125. movzbw %es:4(%bx), %cx
  126. cmpw $0x58, %cx
  127. jae is_valid_checksum
  128. 1:
  129. ret
  130. is_valid_pxenv:
  131. cmpl $0x4e455850, %es:(%bx)
  132. jne 1b
  133. cmpw $0x2b56, %es:4(%bx)
  134. jne 1b
  135. movzbw %es:8(%bx), %cx
  136. cmpw $0x28, %cx
  137. jb 1b
  138. is_valid_checksum:
  139. pushw %ax
  140. movw %bx, %si
  141. xorw %ax, %ax
  142. 2:
  143. es lodsb
  144. addb %al, %ah
  145. loopw 2b
  146. popw %ax
  147. ret
  148. memory_scan_ppxe:
  149. movw $is_valid_ppxe, %dx
  150. jmp memory_scan_common
  151. memory_scan_pxenv:
  152. movw $is_valid_pxenv, %dx
  153. memory_scan_common:
  154. movw %fs:(0x13), %ax
  155. shlw $6, %ax
  156. decw %ax
  157. 1: incw %ax
  158. cmpw $( 0xa000 - 1 ), %ax
  159. ja 2f
  160. movw %ax, %es
  161. xorw %bx, %bx
  162. call *%dx
  163. jne 1b
  164. 2: ret
  165. /*****************************************************************************
  166. * Sanity check: we must have an entry point
  167. *****************************************************************************
  168. */
  169. check_have_stack:
  170. /* Save common values pushed onto the stack */
  171. popl undi_data_segoff
  172. popl undi_code_segoff
  173. popl entry_segoff
  174. /* Print have !PXE/PXENV+ message; structure pointer in %es:%bx */
  175. call print_message
  176. call print_segoff
  177. movb $( ',' ), %al
  178. call print_character
  179. /* Check for entry point */
  180. movl entry_segoff, %eax
  181. testl %eax, %eax
  182. jnz 99f
  183. /* No entry point: print message and skip everything else */
  184. stack_not_found:
  185. movw $10f, %si
  186. call print_message
  187. jmp finished
  188. .section ".prefix.data", "aw", @progbits
  189. 10: .asciz " No PXE stack found!\n"
  190. .previous
  191. 99:
  192. /*****************************************************************************
  193. * Calculate base memory usage by UNDI
  194. *****************************************************************************
  195. */
  196. find_undi_basemem_usage:
  197. movw undi_code_segment, %ax
  198. movw undi_code_size, %bx
  199. movw undi_data_segment, %cx
  200. movw undi_data_size, %dx
  201. cmpw %ax, %cx
  202. ja 1f
  203. xchgw %ax, %cx
  204. xchgw %bx, %dx
  205. 1: /* %ax:%bx now describes the lower region, %cx:%dx the higher */
  206. shrw $6, %ax /* Round down to nearest kB */
  207. movw %ax, undi_fbms_start
  208. addw $0x0f, %dx /* Round up to next segment */
  209. shrw $4, %dx
  210. addw %dx, %cx
  211. addw $((1024 / 16) - 1), %cx /* Round up to next kB */
  212. shrw $6, %cx
  213. movw %cx, undi_fbms_end
  214. /*****************************************************************************
  215. * Print information about detected PXE stack
  216. *****************************************************************************
  217. */
  218. print_structure_information:
  219. /* Print entry point */
  220. movw $10f, %si
  221. call print_message
  222. les entry_segoff, %bx
  223. call print_segoff
  224. .section ".prefix.data", "aw", @progbits
  225. 10: .asciz " entry point at "
  226. .previous
  227. /* Print UNDI code segment */
  228. movw $10f, %si
  229. call print_message
  230. les undi_code_segoff, %bx
  231. call print_segoff
  232. .section ".prefix.data", "aw", @progbits
  233. 10: .asciz "\n UNDI code segment "
  234. .previous
  235. /* Print UNDI data segment */
  236. movw $10f, %si
  237. call print_message
  238. les undi_data_segoff, %bx
  239. call print_segoff
  240. .section ".prefix.data", "aw", @progbits
  241. 10: .asciz ", data segment "
  242. .previous
  243. /* Print UNDI memory usage */
  244. movw $10f, %si
  245. call print_message
  246. movw undi_fbms_start, %ax
  247. call print_word
  248. movb $( '-' ), %al
  249. call print_character
  250. movw undi_fbms_end, %ax
  251. call print_word
  252. movw $20f, %si
  253. call print_message
  254. .section ".prefix.data", "aw", @progbits
  255. 10: .asciz " ("
  256. 20: .asciz "kB)\n"
  257. .previous
  258. /*****************************************************************************
  259. * Determine physical device
  260. *****************************************************************************
  261. */
  262. get_physical_device:
  263. /* Issue PXENV_UNDI_GET_NIC_TYPE */
  264. movw $PXENV_UNDI_GET_NIC_TYPE, %bx
  265. call pxe_call
  266. jnc 1f
  267. call print_pxe_error
  268. jmp no_physical_device
  269. 1: /* Determine physical device type */
  270. movb ( pxe_parameter_structure + 0x02 ), %al
  271. cmpb $2, %al
  272. je pci_physical_device
  273. jmp no_physical_device
  274. pci_physical_device:
  275. /* Record PCI bus:dev.fn and vendor/device IDs */
  276. movl ( pxe_parameter_structure + 0x03 ), %eax
  277. movl %eax, pci_vendor
  278. movw ( pxe_parameter_structure + 0x0b ), %ax
  279. movw %ax, pci_busdevfn
  280. movw $10f, %si
  281. call print_message
  282. call print_pci_busdevfn
  283. jmp 99f
  284. .section ".prefix.data", "aw", @progbits
  285. 10: .asciz " UNDI device is PCI "
  286. .previous
  287. no_physical_device:
  288. /* No device found, or device type not understood */
  289. movw $10f, %si
  290. call print_message
  291. .section ".prefix.data", "aw", @progbits
  292. 10: .asciz " Unable to determine UNDI physical device"
  293. .previous
  294. 99:
  295. /*****************************************************************************
  296. * Determine interface type
  297. *****************************************************************************
  298. */
  299. get_iface_type:
  300. /* Issue PXENV_UNDI_GET_IFACE_INFO */
  301. movw $PXENV_UNDI_GET_IFACE_INFO, %bx
  302. call pxe_call
  303. jnc 1f
  304. call print_pxe_error
  305. jmp 99f
  306. 1: /* Print interface type */
  307. movw $10f, %si
  308. call print_message
  309. leaw ( pxe_parameter_structure + 0x02 ), %si
  310. call print_message
  311. .section ".prefix.data", "aw", @progbits
  312. 10: .asciz ", type "
  313. .previous
  314. /* Check for "Etherboot" interface type */
  315. cmpl $EB_MAGIC_1, ( pxe_parameter_structure + 0x02 )
  316. jne 99f
  317. cmpl $EB_MAGIC_2, ( pxe_parameter_structure + 0x06 )
  318. jne 99f
  319. movw $10f, %si
  320. call print_message
  321. .section ".prefix.data", "aw", @progbits
  322. 10: .asciz " (workaround enabled)"
  323. .previous
  324. /* Flag Etherboot workarounds as required */
  325. orw $PXE_HACK_EB54, pxe_hacks
  326. 99: movb $0x0a, %al
  327. call print_character
  328. /*****************************************************************************
  329. * Leave NIC in a safe state
  330. *****************************************************************************
  331. */
  332. #ifndef PXELOADER_KEEP_PXE
  333. shutdown_nic:
  334. /* Issue PXENV_UNDI_SHUTDOWN */
  335. movw $PXENV_UNDI_SHUTDOWN, %bx
  336. call pxe_call
  337. jnc 1f
  338. call print_pxe_error
  339. 1:
  340. unload_base_code:
  341. /* Etherboot treats PXENV_UNLOAD_STACK as PXENV_STOP_UNDI, so
  342. * we must not issue this call if the underlying stack is
  343. * Etherboot and we were not intending to issue a PXENV_STOP_UNDI.
  344. */
  345. #ifdef PXELOADER_KEEP_UNDI
  346. testw $PXE_HACK_EB54, pxe_hacks
  347. jnz 99f
  348. #endif /* PXELOADER_KEEP_UNDI */
  349. /* Issue PXENV_UNLOAD_STACK */
  350. movw $PXENV_UNLOAD_STACK, %bx
  351. call pxe_call
  352. jnc 1f
  353. call print_pxe_error
  354. jmp 99f
  355. 1: /* Free base memory used by PXE base code */
  356. movw undi_fbms_start, %ax
  357. movw %fs:(0x13), %bx
  358. call free_basemem
  359. 99:
  360. andw $~( UNDI_FL_INITIALIZED | UNDI_FL_KEEP_ALL ), flags
  361. #endif /* PXELOADER_KEEP_PXE */
  362. /*****************************************************************************
  363. * Unload UNDI driver
  364. *****************************************************************************
  365. */
  366. #ifndef PXELOADER_KEEP_UNDI
  367. unload_undi:
  368. /* Issue PXENV_STOP_UNDI */
  369. movw $PXENV_STOP_UNDI, %bx
  370. call pxe_call
  371. jnc 1f
  372. call print_pxe_error
  373. jmp 99f
  374. 1: /* Free base memory used by UNDI */
  375. movw undi_fbms_end, %ax
  376. movw undi_fbms_start, %bx
  377. call free_basemem
  378. /* Clear UNDI_FL_STARTED */
  379. andw $~UNDI_FL_STARTED, flags
  380. 99:
  381. #endif /* PXELOADER_KEEP_UNDI */
  382. /*****************************************************************************
  383. * Print remaining free base memory
  384. *****************************************************************************
  385. */
  386. print_free_basemem:
  387. movw $10f, %si
  388. call print_message
  389. movw %fs:(0x13), %ax
  390. call print_word
  391. movw $20f, %si
  392. call print_message
  393. .section ".prefix.data", "aw", @progbits
  394. 10: .asciz " "
  395. 20: .asciz "kB free base memory after PXE unload\n"
  396. .previous
  397. /*****************************************************************************
  398. * Exit point
  399. *****************************************************************************
  400. */
  401. finished:
  402. jmp run_gpxe
  403. /*****************************************************************************
  404. * Subroutine: print segment:offset address
  405. *
  406. * Parameters:
  407. * %es:%bx : segment:offset address to print
  408. * %ds:di : output buffer (or %di=0 to print to console)
  409. * Returns:
  410. * %ds:di : next character in output buffer (if applicable)
  411. *****************************************************************************
  412. */
  413. print_segoff:
  414. /* Preserve registers */
  415. pushw %ax
  416. /* Print "<segment>:offset" */
  417. movw %es, %ax
  418. call print_hex_word
  419. movb $( ':' ), %al
  420. call print_character
  421. movw %bx, %ax
  422. call print_hex_word
  423. /* Restore registers and return */
  424. popw %ax
  425. ret
  426. /*****************************************************************************
  427. * Subroutine: print decimal word
  428. *
  429. * Parameters:
  430. * %ax : word to print
  431. * %ds:di : output buffer (or %di=0 to print to console)
  432. * Returns:
  433. * %ds:di : next character in output buffer (if applicable)
  434. *****************************************************************************
  435. */
  436. print_word:
  437. /* Preserve registers */
  438. pushw %ax
  439. pushw %bx
  440. pushw %cx
  441. pushw %dx
  442. /* Build up digit sequence on stack */
  443. movw $10, %bx
  444. xorw %cx, %cx
  445. 1: xorw %dx, %dx
  446. divw %bx, %ax
  447. pushw %dx
  448. incw %cx
  449. testw %ax, %ax
  450. jnz 1b
  451. /* Print digit sequence */
  452. 1: popw %ax
  453. call print_hex_nibble
  454. loop 1b
  455. /* Restore registers and return */
  456. popw %dx
  457. popw %cx
  458. popw %bx
  459. popw %ax
  460. ret
  461. /*****************************************************************************
  462. * Subroutine: zero 1kB block of base memory
  463. *
  464. * Parameters:
  465. * %bx : block to zero (in kB)
  466. * Returns:
  467. * Nothing
  468. *****************************************************************************
  469. */
  470. zero_kb:
  471. /* Preserve registers */
  472. pushw %ax
  473. pushw %cx
  474. pushw %di
  475. pushw %es
  476. /* Zero block */
  477. movw %bx, %ax
  478. shlw $6, %ax
  479. movw %ax, %es
  480. movw $0x400, %cx
  481. xorw %di, %di
  482. xorw %ax, %ax
  483. rep stosb
  484. /* Restore registers and return */
  485. popw %es
  486. popw %di
  487. popw %cx
  488. popw %ax
  489. ret
  490. /*****************************************************************************
  491. * Subroutine: free and zero base memory
  492. *
  493. * Parameters:
  494. * %ax : Desired new free base memory counter (in kB)
  495. * %bx : Expected current free base memory counter (in kB)
  496. * %fs : BIOS data segment (0x40)
  497. * Returns:
  498. * None
  499. *
  500. * The base memory from %bx kB to %ax kB is unconditionally zeroed.
  501. * It will be freed if and only if the expected current free base
  502. * memory counter (%bx) matches the actual current free base memory
  503. * counter in 0x40:0x13; if this does not match then the memory will
  504. * be leaked.
  505. *****************************************************************************
  506. */
  507. free_basemem:
  508. /* Zero base memory */
  509. pushw %bx
  510. 1: cmpw %bx, %ax
  511. je 2f
  512. call zero_kb
  513. incw %bx
  514. jmp 1b
  515. 2: popw %bx
  516. /* Free base memory */
  517. cmpw %fs:(0x13), %bx /* Update FBMS only if "old" value */
  518. jne 1f /* is correct */
  519. 1: movw %ax, %fs:(0x13)
  520. ret
  521. /*****************************************************************************
  522. * Subroutine: make a PXE API call. Works with either !PXE or PXENV+ API.
  523. *
  524. * Parameters:
  525. * %bx : PXE API call number
  526. * %ds:pxe_parameter_structure : Parameters for PXE API call
  527. * Returns:
  528. * %ax : PXE status code (not exit code)
  529. * CF set if %ax is non-zero
  530. *****************************************************************************
  531. */
  532. pxe_call:
  533. /* Preserve registers */
  534. pushw %di
  535. pushw %es
  536. /* Set up registers for PXENV+ API. %bx already set up */
  537. pushw %ds
  538. popw %es
  539. movw $pxe_parameter_structure, %di
  540. /* Set up stack for !PXE API */
  541. pushw %es
  542. pushw %di
  543. pushw %bx
  544. /* Make the API call */
  545. lcall *entry_segoff
  546. /* Reset the stack */
  547. addw $6, %sp
  548. movw pxe_parameter_structure, %ax
  549. clc
  550. testw %ax, %ax
  551. jz 1f
  552. stc
  553. 1: /* Clear direction flag, for the sake of sanity */
  554. cld
  555. /* Restore registers and return */
  556. popw %es
  557. popw %di
  558. ret
  559. /*****************************************************************************
  560. * Subroutine: print PXE API call error message
  561. *
  562. * Parameters:
  563. * %ax : PXE status code
  564. * %bx : PXE API call number
  565. * Returns:
  566. * Nothing
  567. *****************************************************************************
  568. */
  569. print_pxe_error:
  570. pushw %si
  571. movw $10f, %si
  572. call print_message
  573. xchgw %ax, %bx
  574. call print_hex_word
  575. movw $20f, %si
  576. call print_message
  577. xchgw %ax, %bx
  578. call print_hex_word
  579. movw $30f, %si
  580. call print_message
  581. popw %si
  582. ret
  583. .section ".prefix.data", "aw", @progbits
  584. 10: .asciz " UNDI API call "
  585. 20: .asciz " failed: status code "
  586. 30: .asciz "\n"
  587. .previous
  588. /*****************************************************************************
  589. * PXE data structures
  590. *****************************************************************************
  591. */
  592. .section ".prefix.data"
  593. pxe_esp: .long 0
  594. pxe_ss: .word 0
  595. pxe_parameter_structure: .fill 64
  596. undi_code_segoff:
  597. undi_code_size: .word 0
  598. undi_code_segment: .word 0
  599. undi_data_segoff:
  600. undi_data_size: .word 0
  601. undi_data_segment: .word 0
  602. pxe_hacks: .word 0
  603. /* The following fields are part of a struct undi_device */
  604. undi_device:
  605. pxenv_segoff:
  606. pxenv_offset: .word 0
  607. pxenv_segment: .word 0
  608. ppxe_segoff:
  609. ppxe_offset: .word 0
  610. ppxe_segment: .word 0
  611. entry_segoff:
  612. entry_offset: .word 0
  613. entry_segment: .word 0
  614. undi_fbms_start: .word 0
  615. undi_fbms_end: .word 0
  616. pci_busdevfn: .word UNDI_NO_PCI_BUSDEVFN
  617. isapnp_csn: .word UNDI_NO_ISAPNP_CSN
  618. isapnp_read_port: .word UNDI_NO_ISAPNP_READ_PORT
  619. pci_vendor: .word 0
  620. pci_device: .word 0
  621. flags:
  622. .word ( UNDI_FL_INITIALIZED | UNDI_FL_STARTED | UNDI_FL_KEEP_ALL )
  623. .equ undi_device_size, ( . - undi_device )
  624. /*****************************************************************************
  625. * Run gPXE main code
  626. *****************************************************************************
  627. */
  628. .section ".prefix"
  629. run_gpxe:
  630. /* Install gPXE */
  631. call install
  632. /* Set up real-mode stack */
  633. movw %bx, %ss
  634. movw $_estack16, %sp
  635. #ifdef PXELOADER_KEEP_UNDI
  636. /* Copy our undi_device structure to the preloaded_undi variable */
  637. movw %bx, %es
  638. movw $preloaded_undi, %di
  639. movw $undi_device, %si
  640. movw $undi_device_size, %cx
  641. rep movsb
  642. #endif
  643. /* Retrieve PXE %ss:esp */
  644. movw pxe_ss, %di
  645. movl pxe_esp, %ebp
  646. /* Jump to .text16 segment with %ds pointing to .data16 */
  647. movw %bx, %ds
  648. pushw %ax
  649. pushw $1f
  650. lret
  651. .section ".text16", "ax", @progbits
  652. 1:
  653. /* Run main program */
  654. pushl $main
  655. pushw %cs
  656. call prot_call
  657. popl %ecx /* discard */
  658. /* Uninstall gPXE */
  659. call uninstall
  660. /* Restore PXE stack */
  661. movw %di, %ss
  662. movl %ebp, %esp
  663. /* Check PXE stack magic */
  664. popl %eax
  665. cmpl $STACK_MAGIC, %eax
  666. jne 1f
  667. /* PXE stack OK: return to caller */
  668. popw %ds
  669. popw %es
  670. popw %fs
  671. popw %gs
  672. popal
  673. popfl
  674. xorw %ax, %ax /* Return success */
  675. lret
  676. 1: /* PXE stack corrupt or removed: use INT 18 */
  677. int $0x18
  678. .previous