Annotation of qemu/roms/ipxe/src/arch/i386/prefix/pxeprefix.S, revision 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.