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.

romprefix.S 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911
  1. /* At entry, the processor is in 16 bit real mode and the code is being
  2. * executed from an address it was not linked to. Code must be pic and
  3. * 32 bit sensitive until things are fixed up.
  4. *
  5. * Also be very careful as the stack is at the rear end of the interrupt
  6. * table so using a noticeable amount of stack space is a no-no.
  7. */
  8. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
  9. #include <librm.h>
  10. #include <config/general.h>
  11. #include <config/branding.h>
  12. #define PNP_SIGNATURE ( '$' + ( 'P' << 8 ) + ( 'n' << 16 ) + ( 'P' << 24 ) )
  13. #define PMM_SIGNATURE ( '$' + ( 'P' << 8 ) + ( 'M' << 16 ) + ( 'M' << 24 ) )
  14. #define PCI_SIGNATURE ( 'P' + ( 'C' << 8 ) + ( 'I' << 16 ) + ( ' ' << 24 ) )
  15. #define STACK_MAGIC ( 'L' + ( 'R' << 8 ) + ( 'E' << 16 ) + ( 'T' << 24 ) )
  16. #define PMM_ALLOCATE 0x0000
  17. #define PMM_FIND 0x0001
  18. #define PMM_HANDLE_BASE ( ( ( 'F' - 'A' + 1 ) << 26 ) + \
  19. ( ( 'E' - 'A' + 1 ) << 21 ) + \
  20. ( ( 'N' - 'A' + 1 ) << 16 ) )
  21. #define PMM_HANDLE_BASE_IMAGE_SOURCE \
  22. ( PMM_HANDLE_BASE | 0x00001000 )
  23. #define PMM_HANDLE_BASE_DECOMPRESS_TO \
  24. ( PMM_HANDLE_BASE | 0x00002000 )
  25. #define PCI_FUNC_MASK 0x07
  26. /* ROM banner timeout, converted to a number of (18Hz) timer ticks. */
  27. #define ROM_BANNER_TIMEOUT_TICKS ( ( 18 * ROM_BANNER_TIMEOUT ) / 10 )
  28. /* Allow payload to be excluded from ROM size
  29. */
  30. #if ROMPREFIX_EXCLUDE_PAYLOAD
  31. #define ZINFO_TYPE_ADxB "ADHB"
  32. #define ZINFO_TYPE_ADxW "ADHW"
  33. #else
  34. #define ZINFO_TYPE_ADxB "ADDB"
  35. #define ZINFO_TYPE_ADxW "ADDW"
  36. #endif
  37. /* Allow ROM to be marked as containing multiple images
  38. */
  39. #if ROMPREFIX_MORE_IMAGES
  40. #define INDICATOR 0x00
  41. #else
  42. #define INDICATOR 0x80
  43. #endif
  44. /* Default to building a PCI ROM if no bus type is specified
  45. */
  46. #ifndef BUSTYPE
  47. #define BUSTYPE "PCIR"
  48. #endif
  49. .text
  50. .code16
  51. .arch i386
  52. .section ".prefix", "ax", @progbits
  53. .globl _rom_start
  54. _rom_start:
  55. .org 0x00
  56. romheader:
  57. .word 0xAA55 /* BIOS extension signature */
  58. romheader_size: .byte 0 /* Size in 512-byte blocks */
  59. jmp init /* Initialisation vector */
  60. checksum:
  61. .byte 0
  62. .org 0x10
  63. .word ipxeheader
  64. .org 0x16
  65. .word undiheader
  66. .ifeqs BUSTYPE, "PCIR"
  67. .org 0x18
  68. .word pciheader
  69. .endif
  70. .org 0x1a
  71. .word pnpheader
  72. .size romheader, . - romheader
  73. .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
  74. .ascii ZINFO_TYPE_ADxB
  75. .long romheader_size
  76. .long 512
  77. .long 0
  78. .previous
  79. .ifeqs BUSTYPE, "PCIR"
  80. .align 4
  81. pciheader:
  82. .ascii "PCIR" /* Signature */
  83. .word pci_vendor_id /* Vendor identification */
  84. .word pci_device_id /* Device identification */
  85. .word ( pci_devlist - pciheader ) /* Device list pointer */
  86. .word pciheader_len /* PCI data structure length */
  87. .byte 0x03 /* PCI data structure revision */
  88. .byte 0x00, 0x00, 0x02 /* Class code */
  89. pciheader_image_length:
  90. .word 0 /* Image length */
  91. .word 0x0001 /* Revision level */
  92. .byte 0x00 /* Code type */
  93. .byte INDICATOR /* Last image indicator */
  94. pciheader_runtime_length:
  95. .word 0 /* Maximum run-time image length */
  96. .word 0x0000 /* Configuration utility code header */
  97. .word 0x0000 /* DMTF CLP entry point */
  98. .equ pciheader_len, . - pciheader
  99. .size pciheader, . - pciheader
  100. /* PCI additional device list (filled in by linker) */
  101. .section ".pci_devlist.00000000", "a", @progbits
  102. pci_devlist:
  103. .previous
  104. .section ".pci_devlist.ffffffff", "a", @progbits
  105. pci_devlist_end:
  106. .short 0x0000 /* List terminator */
  107. .previous
  108. /* Ensure that terminator is always present */
  109. .reloc pciheader, RELOC_TYPE_NONE, pci_devlist_end
  110. .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
  111. .ascii ZINFO_TYPE_ADxW
  112. .long pciheader_image_length
  113. .long 512
  114. .long 0
  115. .ascii "ADHW"
  116. .long pciheader_runtime_length
  117. .long 512
  118. .long 0
  119. .previous
  120. .endif /* PCIR */
  121. /* PnP doesn't require any particular alignment, but IBM
  122. * BIOSes will scan on 16-byte boundaries rather than using
  123. * the offset stored at 0x1a
  124. */
  125. .align 16
  126. pnpheader:
  127. .ascii "$PnP" /* Signature */
  128. .byte 0x01 /* Structure revision */
  129. .byte ( pnpheader_len / 16 ) /* Length (in 16 byte increments) */
  130. .word 0x0000 /* Offset of next header */
  131. .byte 0x00 /* Reserved */
  132. .byte 0x00 /* Checksum */
  133. .long 0x00000000 /* Device identifier */
  134. .word mfgstr /* Manufacturer string */
  135. .word prodstr /* Product name */
  136. .byte 0x02 /* Device base type code */
  137. .byte 0x00 /* Device sub-type code */
  138. .byte 0x00 /* Device interface type code */
  139. .byte 0xf4 /* Device indicator */
  140. .word 0x0000 /* Boot connection vector */
  141. .word 0x0000 /* Disconnect vector */
  142. .word bev_entry /* Boot execution vector */
  143. .word 0x0000 /* Reserved */
  144. .word 0x0000 /* Static resource information vector*/
  145. .equ pnpheader_len, . - pnpheader
  146. .size pnpheader, . - pnpheader
  147. /* Manufacturer string */
  148. mfgstr:
  149. .asciz "http://ipxe.org"
  150. .size mfgstr, . - mfgstr
  151. /* Product string
  152. *
  153. * Defaults to PRODUCT_SHORT_NAME. If the ROM image is writable at
  154. * initialisation time, it will be filled in to include the PCI
  155. * bus:dev.fn number of the card as well.
  156. */
  157. prodstr:
  158. .ascii PRODUCT_SHORT_NAME
  159. .ifeqs BUSTYPE, "PCIR"
  160. prodstr_separator:
  161. .byte 0
  162. .ascii "(PCI "
  163. prodstr_pci_id:
  164. .ascii "xx:xx.x)" /* Filled in by init code */
  165. .endif /* PCIR */
  166. .byte 0
  167. .size prodstr, . - prodstr
  168. .globl undiheader
  169. .weak undiloader
  170. .align 4
  171. undiheader:
  172. .ascii "UNDI" /* Signature */
  173. .byte undiheader_len /* Length of structure */
  174. .byte 0 /* Checksum */
  175. .byte 0 /* Structure revision */
  176. .byte 0,1,2 /* PXE version: 2.1.0 */
  177. .word undiloader /* Offset to loader routine */
  178. .word _data16_memsz /* Stack segment size */
  179. .word _data16_memsz /* Data segment size */
  180. .word _text16_memsz /* Code segment size */
  181. .ascii BUSTYPE /* Bus type */
  182. .equ undiheader_len, . - undiheader
  183. .size undiheader, . - undiheader
  184. .align 4
  185. ipxeheader:
  186. .ascii "iPXE" /* Signature */
  187. .byte ipxeheader_len /* Length of structure */
  188. .byte 0 /* Checksum */
  189. shrunk_rom_size:
  190. .byte 0 /* Shrunk size (in 512-byte blocks) */
  191. .byte 0 /* Reserved */
  192. build_id:
  193. .long _build_id /* Randomly-generated build ID */
  194. .equ ipxeheader_len, . - ipxeheader
  195. .size ipxeheader, . - ipxeheader
  196. .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
  197. .ascii "ADHB"
  198. .long shrunk_rom_size
  199. .long 512
  200. .long 0
  201. .previous
  202. /* Initialisation (called once during POST)
  203. *
  204. * Determine whether or not this is a PnP system via a signature
  205. * check. If it is PnP, return to the PnP BIOS indicating that we are
  206. * a boot-capable device; the BIOS will call our boot execution vector
  207. * if it wants to boot us. If it is not PnP, hook INT 19.
  208. */
  209. init:
  210. /* Preserve registers, clear direction flag, set %ds=%cs */
  211. pushaw
  212. pushw %ds
  213. pushw %es
  214. pushw %fs
  215. pushw %gs
  216. cld
  217. pushw %cs
  218. popw %ds
  219. /* Print message as early as possible */
  220. movw $init_message, %si
  221. xorw %di, %di
  222. call print_message
  223. /* Store PCI 3.0 runtime segment address for later use, if
  224. * applicable.
  225. */
  226. .ifeqs BUSTYPE, "PCIR"
  227. movw %bx, %gs
  228. .endif
  229. /* Store PCI bus:dev.fn address, print PCI bus:dev.fn, and add
  230. * PCI bus:dev.fn to product name string, if applicable.
  231. */
  232. .ifeqs BUSTYPE, "PCIR"
  233. xorw %di, %di
  234. call print_space
  235. movw %ax, init_pci_busdevfn
  236. call print_pci_busdevfn
  237. movw $prodstr_pci_id, %di
  238. call print_pci_busdevfn
  239. movb $( ' ' ), prodstr_separator
  240. .endif
  241. /* Print segment address */
  242. xorw %di, %di
  243. call print_space
  244. movw %cs, %ax
  245. call print_hex_word
  246. /* Check for PCI BIOS version, if applicable */
  247. .ifeqs BUSTYPE, "PCIR"
  248. pushl %ebx
  249. pushl %edx
  250. pushl %edi
  251. stc
  252. movw $0xb101, %ax
  253. int $0x1a
  254. jc no_pci3
  255. cmpl $PCI_SIGNATURE, %edx
  256. jne no_pci3
  257. testb %ah, %ah
  258. jnz no_pci3
  259. movw $init_message_pci, %si
  260. xorw %di, %di
  261. call print_message
  262. movb %bh, %al
  263. call print_hex_nibble
  264. movb $( '.' ), %al
  265. call print_character
  266. movb %bl, %al
  267. call print_hex_byte
  268. cmpb $3, %bh
  269. jb no_pci3
  270. /* PCI >=3.0: leave %gs as-is if sane */
  271. movw %gs, %ax
  272. cmpw $0xa000, %ax /* Insane if %gs < 0xa000 */
  273. jb pci3_insane
  274. movw %cs, %bx /* Sane if %cs == %gs */
  275. cmpw %bx, %ax
  276. je 1f
  277. movzbw romheader_size, %cx /* Sane if %cs+len <= %gs */
  278. shlw $5, %cx
  279. addw %cx, %bx
  280. cmpw %bx, %ax
  281. jae 1f
  282. movw %cs, %bx /* Sane if %gs+len <= %cs */
  283. addw %cx, %ax
  284. cmpw %bx, %ax
  285. jbe 1f
  286. pci3_insane: /* PCI 3.0 with insane %gs value: print error and ignore %gs */
  287. movb $( '!' ), %al
  288. call print_character
  289. movw %gs, %ax
  290. call print_hex_word
  291. no_pci3:
  292. /* PCI <3.0: set %gs (runtime segment) = %cs (init-time segment) */
  293. pushw %cs
  294. popw %gs
  295. 1: popl %edi
  296. popl %edx
  297. popl %ebx
  298. .endif /* PCIR */
  299. /* Check for PnP BIOS. Although %es:di should point to the
  300. * PnP BIOS signature on entry, some BIOSes fail to do this.
  301. */
  302. movw $( 0xf000 - 1 ), %bx
  303. pnp_scan:
  304. incw %bx
  305. jz no_pnp
  306. movw %bx, %es
  307. cmpl $PNP_SIGNATURE, %es:0
  308. jne pnp_scan
  309. xorw %dx, %dx
  310. xorw %si, %si
  311. movzbw %es:5, %cx
  312. 1: es lodsb
  313. addb %al, %dl
  314. loop 1b
  315. jnz pnp_scan
  316. /* Is PnP: print PnP message */
  317. movw $init_message_pnp, %si
  318. xorw %di, %di
  319. call print_message
  320. jmp pnp_done
  321. no_pnp: /* Not PnP-compliant - hook INT 19 */
  322. #ifdef NONPNP_HOOK_INT19
  323. movw $init_message_int19, %si
  324. xorw %di, %di
  325. call print_message
  326. xorw %ax, %ax
  327. movw %ax, %es
  328. pushl %es:( 0x19 * 4 )
  329. popl orig_int19
  330. pushw %gs /* %gs contains runtime %cs */
  331. pushw $int19_entry
  332. popl %es:( 0x19 * 4 )
  333. #endif /* NONPNP_HOOK_INT19 */
  334. pnp_done:
  335. /* Check for PMM */
  336. movw $( 0xe000 - 1 ), %bx
  337. pmm_scan:
  338. incw %bx
  339. jz no_pmm
  340. movw %bx, %es
  341. cmpl $PMM_SIGNATURE, %es:0
  342. jne pmm_scan
  343. xorw %dx, %dx
  344. xorw %si, %si
  345. movzbw %es:5, %cx
  346. 1: es lodsb
  347. addb %al, %dl
  348. loop 1b
  349. jnz pmm_scan
  350. /* PMM found: print PMM message */
  351. movw $init_message_pmm, %si
  352. xorw %di, %di
  353. call print_message
  354. /* We have PMM and so a 1kB stack: preserve whole registers */
  355. pushal
  356. /* Allocate image source PMM block. Round up the size to the
  357. * nearest 4kB (8 512-byte sectors) to work around AMI BIOS bugs.
  358. */
  359. movzbl romheader_size, %ecx
  360. addw extra_size, %cx
  361. addw $0x0007, %cx /* Round up to multiple of 8 512-byte sectors */
  362. andw $0xfff8, %cx
  363. shll $5, %ecx
  364. movl $PMM_HANDLE_BASE_IMAGE_SOURCE, %ebx
  365. movw $get_pmm_image_source, %bp
  366. call get_pmm
  367. movl %esi, image_source
  368. jz 1f
  369. /* Copy ROM to image source PMM block */
  370. pushw %es
  371. xorw %ax, %ax
  372. movw %ax, %es
  373. movl %esi, %edi
  374. xorl %esi, %esi
  375. movzbl romheader_size, %ecx
  376. shll $7, %ecx
  377. addr32 rep movsl /* PMM presence implies flat real mode */
  378. popw %es
  379. /* Shrink ROM */
  380. movb shrunk_rom_size, %al
  381. movb %al, romheader_size
  382. 1: /* Allocate decompression PMM block. Allow 4kB for page
  383. * alignment and round up the size to the nearest 128kB, then
  384. * use the size within the PMM handle; this allows the same
  385. * decompression area to be shared between multiple iPXE ROMs
  386. * even with differing build IDs
  387. */
  388. movl $_textdata_memsz_pgh, %ecx
  389. addl $( 0x00000100 /* 4kB */ + 0x00001fff /* 128kB - 1 */ ), %ecx
  390. andl $( 0xffffe000 /* ~( 128kB - 1 ) */ ), %ecx
  391. movl %ecx, %ebx
  392. shrw $12, %bx
  393. orl $PMM_HANDLE_BASE_DECOMPRESS_TO, %ebx
  394. movw $get_pmm_decompress_to, %bp
  395. call get_pmm
  396. addl $( 0x00000fff /* 4kB - 1 */ ), %esi
  397. andl $( 0xfffff000 /* ~( 4kB - 1 ) */ ), %esi
  398. movl %esi, decompress_to
  399. /* Restore registers */
  400. popal
  401. no_pmm:
  402. /* Update checksum */
  403. xorw %bx, %bx
  404. xorw %si, %si
  405. movzbw romheader_size, %cx
  406. shlw $9, %cx
  407. 1: lodsb
  408. addb %al, %bl
  409. loop 1b
  410. subb %bl, checksum
  411. /* Copy self to option ROM space, if applicable. Required for
  412. * PCI3.0, which loads us to a temporary location in low
  413. * memory. Will be a no-op for lower PCI versions.
  414. */
  415. .ifeqs BUSTYPE, "PCIR"
  416. /* Get runtime segment address and length */
  417. movw %gs, %ax
  418. movw %ax, %es
  419. movzbw romheader_size, %cx
  420. /* Print runtime segment address */
  421. xorw %di, %di
  422. call print_space
  423. call print_hex_word
  424. /* Fail if we have insufficient space in final location */
  425. movw %cs, %si
  426. cmpw %si, %ax
  427. je 1f
  428. cmpw pciheader_runtime_length, %cx
  429. jbe 1f
  430. movb $( '!' ), %al
  431. call print_character
  432. xorw %cx, %cx
  433. 1: /* Copy to final location */
  434. shlw $9, %cx
  435. xorw %si, %si
  436. xorw %di, %di
  437. cs rep movsb
  438. .endif
  439. /* Skip prompt if this is not the first PCI function, if applicable */
  440. .ifeqs BUSTYPE, "PCIR"
  441. testb $PCI_FUNC_MASK, init_pci_busdevfn
  442. jnz no_shell
  443. .endif
  444. /* Prompt for POST-time shell */
  445. movw $init_message_prompt, %si
  446. xorw %di, %di
  447. call print_message
  448. movw $prodstr, %si
  449. call print_message
  450. movw $init_message_dots, %si
  451. call print_message
  452. /* Wait for Ctrl-B */
  453. movw $0xff02, %bx
  454. call wait_for_key
  455. /* Clear prompt */
  456. pushf
  457. xorw %di, %di
  458. call print_kill_line
  459. movw $init_message_done, %si
  460. call print_message
  461. popf
  462. jnz no_shell
  463. /* Ctrl-B was pressed: invoke iPXE. The keypress will be
  464. * picked up by the initial shell prompt, and we will drop
  465. * into a shell.
  466. */
  467. xorl %ebp, %ebp /* Inhibit use of INT 15,e820 and INT 15,e801 */
  468. pushw %cs
  469. call exec
  470. no_shell:
  471. movb $( '\n' ), %al
  472. xorw %di, %di
  473. call print_character
  474. /* Restore registers */
  475. popw %gs
  476. popw %fs
  477. popw %es
  478. popw %ds
  479. popaw
  480. /* Indicate boot capability to PnP BIOS, if present */
  481. movw $0x20, %ax
  482. lret
  483. .size init, . - init
  484. /* Attempt to find or allocate PMM block
  485. *
  486. * Parameters:
  487. * %ecx : size of block to allocate, in paragraphs
  488. * %ebx : PMM handle base
  489. * %bp : routine to check acceptability of found blocks
  490. * %es:0000 : PMM structure
  491. * Returns:
  492. * %ebx : PMM handle
  493. * %esi : allocated block address, or zero (with ZF set) if allocation failed
  494. */
  495. get_pmm:
  496. /* Preserve registers */
  497. pushl %eax
  498. pushw %di
  499. movw $( ' ' ), %di
  500. get_pmm_find:
  501. /* Try to find existing block */
  502. pushl %ebx /* PMM handle */
  503. pushw $PMM_FIND
  504. lcall *%es:7
  505. addw $6, %sp
  506. pushw %dx
  507. pushw %ax
  508. popl %esi
  509. /* Treat 0xffffffff (not supported) as 0x00000000 (not found) */
  510. incl %esi
  511. jz get_pmm_allocate
  512. decl %esi
  513. jz get_pmm_allocate
  514. /* Block found - check acceptability */
  515. call *%bp
  516. jnc get_pmm_done
  517. /* Block not acceptable - increment handle and retry */
  518. incl %ebx
  519. jmp get_pmm_find
  520. get_pmm_allocate:
  521. /* Block not found - try to allocate new block */
  522. pushw $0x0002 /* Extended memory */
  523. pushl %ebx /* PMM handle */
  524. pushl %ecx /* Length */
  525. pushw $PMM_ALLOCATE
  526. lcall *%es:7
  527. addw $12, %sp
  528. pushw %dx
  529. pushw %ax
  530. popl %esi
  531. movw $( '+' ), %di /* Indicate allocation attempt */
  532. get_pmm_done:
  533. /* Print block address */
  534. movw %di, %ax
  535. xorw %di, %di
  536. call print_character
  537. movl %esi, %eax
  538. call print_hex_dword
  539. /* Treat 0xffffffff (not supported) as 0x00000000 (allocation
  540. * failed), and set ZF to indicate a zero result.
  541. */
  542. incl %esi
  543. jz 1f
  544. decl %esi
  545. 1: /* Restore registers and return */
  546. popw %di
  547. popl %eax
  548. ret
  549. .size get_pmm, . - get_pmm
  550. /* Check acceptability of image source block */
  551. get_pmm_image_source:
  552. pushw %es
  553. xorw %ax, %ax
  554. movw %ax, %es
  555. movl build_id, %eax
  556. addr32 cmpl %es:build_id(%esi), %eax
  557. je 1f
  558. stc
  559. 1: popw %es
  560. ret
  561. .size get_pmm_image_source, . - get_pmm_image_source
  562. /* Check acceptability of decompression block */
  563. get_pmm_decompress_to:
  564. clc
  565. ret
  566. .size get_pmm_decompress_to, . - get_pmm_decompress_to
  567. /*
  568. * Note to hardware vendors:
  569. *
  570. * If you wish to brand this boot ROM, please do so by defining the
  571. * strings PRODUCT_NAME and PRODUCT_SHORT_NAME in config/branding.h.
  572. *
  573. * While nothing in the GPL prevents you from removing all references
  574. * to iPXE or http://ipxe.org, we prefer you not to do so.
  575. *
  576. * If you have an OEM-mandated branding requirement that cannot be
  577. * satisfied simply by defining PRODUCT_NAME and PRODUCT_SHORT_NAME,
  578. * please contact us.
  579. *
  580. * [ Including an ASCII NUL in PRODUCT_NAME is considered to be
  581. * bypassing the spirit of this request! ]
  582. */
  583. init_message:
  584. .ascii "\n"
  585. .ascii PRODUCT_NAME
  586. .ascii "\n"
  587. .ascii PRODUCT_SHORT_NAME
  588. .ascii " ("
  589. .ascii PRODUCT_URI
  590. .asciz ")"
  591. .size init_message, . - init_message
  592. .ifeqs BUSTYPE, "PCIR"
  593. init_message_pci:
  594. .asciz " PCI"
  595. .size init_message_pci, . - init_message_pci
  596. .endif /* PCIR */
  597. init_message_pnp:
  598. .asciz " PnP"
  599. .size init_message_pnp, . - init_message_pnp
  600. init_message_pmm:
  601. .asciz " PMM"
  602. .size init_message_pmm, . - init_message_pmm
  603. init_message_int19:
  604. .asciz " INT19"
  605. .size init_message_int19, . - init_message_int19
  606. init_message_prompt:
  607. .asciz "\nPress Ctrl-B to configure "
  608. .size init_message_prompt, . - init_message_prompt
  609. init_message_dots:
  610. .asciz "..."
  611. .size init_message_dots, . - init_message_dots
  612. init_message_done:
  613. .asciz "\n\n"
  614. .size init_message_done, . - init_message_done
  615. /* PCI bus:dev.fn
  616. *
  617. */
  618. .ifeqs BUSTYPE, "PCIR"
  619. init_pci_busdevfn:
  620. .word 0
  621. .size init_pci_busdevfn, . - init_pci_busdevfn
  622. .endif /* PCIR */
  623. /* Image source area
  624. *
  625. * May be either zero (indicating to use option ROM space as source),
  626. * or within a PMM-allocated block.
  627. */
  628. .globl image_source
  629. image_source:
  630. .long 0
  631. .size image_source, . - image_source
  632. /* Additional image source size (in 512-byte sectors)
  633. *
  634. */
  635. extra_size:
  636. .word 0
  637. .size extra_size, . - extra_size
  638. /* Temporary decompression area
  639. *
  640. * May be either zero (indicating to use default decompression area in
  641. * high memory), or within a PMM-allocated block.
  642. */
  643. .globl decompress_to
  644. decompress_to:
  645. .long 0
  646. .size decompress_to, . - decompress_to
  647. /* Boot Execution Vector entry point
  648. *
  649. * Called by the PnP BIOS when it wants to boot us.
  650. */
  651. bev_entry:
  652. orl $0xffffffff, %ebp /* Allow arbitrary relocation */
  653. pushw %cs
  654. call exec
  655. lret
  656. .size bev_entry, . - bev_entry
  657. /* INT19 entry point
  658. *
  659. * Called via the hooked INT 19 if we detected a non-PnP BIOS. We
  660. * attempt to return via the original INT 19 vector (if we were able
  661. * to store it).
  662. */
  663. int19_entry:
  664. pushw %cs
  665. popw %ds
  666. /* Prompt user to press B to boot */
  667. movw $int19_message_prompt, %si
  668. xorw %di, %di
  669. call print_message
  670. movw $prodstr, %si
  671. call print_message
  672. movw $int19_message_dots, %si
  673. call print_message
  674. movw $0xdf4e, %bx
  675. call wait_for_key
  676. pushf
  677. xorw %di, %di
  678. call print_kill_line
  679. movw $int19_message_done, %si
  680. call print_message
  681. popf
  682. jz 1f
  683. /* Leave keypress in buffer and start iPXE. The keypress will
  684. * cause the usual initial Ctrl-B prompt to be skipped.
  685. */
  686. orl $0xffffffff, %ebp /* Allow arbitrary relocation */
  687. pushw %cs
  688. call exec
  689. 1: /* Try to call original INT 19 vector */
  690. movl %cs:orig_int19, %eax
  691. testl %eax, %eax
  692. je 2f
  693. ljmp *%cs:orig_int19
  694. 2: /* No chained vector: issue INT 18 as a last resort */
  695. int $0x18
  696. .size int19_entry, . - int19_entry
  697. orig_int19:
  698. .long 0
  699. .size orig_int19, . - orig_int19
  700. int19_message_prompt:
  701. .asciz "Press N to skip booting from "
  702. .size int19_message_prompt, . - int19_message_prompt
  703. int19_message_dots:
  704. .asciz "..."
  705. .size int19_message_dots, . - int19_message_dots
  706. int19_message_done:
  707. .asciz "\n\n"
  708. .size int19_message_done, . - int19_message_done
  709. /* Execute as a boot device
  710. *
  711. */
  712. exec: /* Set %ds = %cs */
  713. pushw %cs
  714. popw %ds
  715. /* Print message as soon as possible */
  716. movw $prodstr, %si
  717. xorw %di, %di
  718. call print_message
  719. movw $exec_message_pre_install, %si
  720. call print_message
  721. /* Store magic word on BIOS stack and remember BIOS %ss:sp */
  722. pushl $STACK_MAGIC
  723. movw %ss, %cx
  724. movw %sp, %dx
  725. /* Obtain a reasonably-sized temporary stack */
  726. xorw %bx, %bx
  727. movw %bx, %ss
  728. movw $0x7c00, %sp
  729. /* Install iPXE */
  730. call alloc_basemem
  731. movl image_source, %esi
  732. movl decompress_to, %edi
  733. call install_prealloc
  734. /* Print message indicating successful installation */
  735. movw $exec_message_post_install, %si
  736. xorw %di, %di
  737. call print_message
  738. /* Set up real-mode stack */
  739. movw %bx, %ss
  740. movw $_estack16, %sp
  741. /* Jump to .text16 segment */
  742. pushw %ax
  743. pushw $1f
  744. lret
  745. .section ".text16", "awx", @progbits
  746. 1:
  747. /* Retrieve PCI bus:dev.fn, if applicable */
  748. .ifeqs BUSTYPE, "PCIR"
  749. movw init_pci_busdevfn, %ax
  750. .endif
  751. /* Set up %ds for access to .data16 */
  752. movw %bx, %ds
  753. /* Store PCI bus:dev.fn, if applicable */
  754. .ifeqs BUSTYPE, "PCIR"
  755. #ifdef AUTOBOOT_ROM_FILTER
  756. movw %ax, autoboot_busdevfn
  757. #endif /* AUTOBOOT_ROM_FILTER */
  758. .endif
  759. /* Run iPXE */
  760. virtcall main
  761. /* Set up flat real mode for return to BIOS */
  762. call flatten_real_mode
  763. /* Uninstall iPXE */
  764. call uninstall
  765. /* Restore BIOS stack */
  766. movw %cx, %ss
  767. movw %dx, %sp
  768. /* Check magic word on BIOS stack */
  769. popl %eax
  770. cmpl $STACK_MAGIC, %eax
  771. jne 1f
  772. /* BIOS stack OK: return to caller */
  773. lret
  774. 1: /* BIOS stack corrupt: use INT 18 */
  775. int $0x18
  776. .previous
  777. exec_message_pre_install:
  778. .asciz " starting execution..."
  779. .size exec_message_pre_install, . - exec_message_pre_install
  780. exec_message_post_install:
  781. .asciz "ok\n"
  782. .size exec_message_post_install, . - exec_message_post_install
  783. /* Wait for key press specified by %bl (masked by %bh)
  784. *
  785. * Used by init and INT19 code when prompting user. If the specified
  786. * key is pressed, it is left in the keyboard buffer.
  787. *
  788. * Returns with ZF set iff specified key is pressed.
  789. */
  790. wait_for_key:
  791. /* Preserve registers */
  792. pushw %cx
  793. pushw %ax
  794. 1: /* Empty the keyboard buffer before waiting for input */
  795. movb $0x01, %ah
  796. int $0x16
  797. jz 2f
  798. xorw %ax, %ax
  799. int $0x16
  800. jmp 1b
  801. 2: /* Wait for a key press */
  802. movw $ROM_BANNER_TIMEOUT_TICKS, %cx
  803. 3: decw %cx
  804. js 99f /* Exit with ZF clear */
  805. /* Wait for timer tick to be updated */
  806. call wait_for_tick
  807. /* Check to see if a key was pressed */
  808. movb $0x01, %ah
  809. int $0x16
  810. jz 3b
  811. /* Check to see if key was the specified key */
  812. andb %bh, %al
  813. cmpb %al, %bl
  814. je 99f /* Exit with ZF set */
  815. /* Not the specified key: remove from buffer and stop waiting */
  816. pushfw
  817. xorw %ax, %ax
  818. int $0x16
  819. popfw /* Exit with ZF clear */
  820. 99: /* Restore registers and return */
  821. popw %ax
  822. popw %cx
  823. ret
  824. .size wait_for_key, . - wait_for_key
  825. /* Wait for timer tick
  826. *
  827. * Used by wait_for_key
  828. */
  829. wait_for_tick:
  830. pushl %eax
  831. pushw %fs
  832. movw $0x40, %ax
  833. movw %ax, %fs
  834. movl %fs:(0x6c), %eax
  835. 1: pushf
  836. sti
  837. hlt
  838. popf
  839. cmpl %fs:(0x6c), %eax
  840. je 1b
  841. popw %fs
  842. popl %eax
  843. ret
  844. .size wait_for_tick, . - wait_for_tick
  845. /* Drag in objects via _rom_start */
  846. REQUIRING_SYMBOL ( _rom_start )
  847. /* Drag in ROM configuration */
  848. REQUIRE_OBJECT ( config_romprefix )