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