Annotation of qemu/roms/ipxe/src/arch/i386/prefix/pxeprefix.S, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.