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