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