Annotation of qemu/roms/ipxe/src/arch/i386/prefix/romprefix.S, revision 1.1

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

unix.superglobalmegacorp.com

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