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

1.1       root        1: /* NOTE: this boot sector contains instructions that need at least an 80186.
                      2:  * Yes, as86 has a bug somewhere in the valid instruction set checks.
                      3:  *
                      4:  */
                      5: 
                      6: /*     floppyload.S Copyright (C) 1991, 1992 Linus Torvalds
                      7:  *     modified by Drew Eckhardt
                      8:  *     modified by Bruce Evans (bde)
                      9:  *
                     10:  * floppyprefix.S is loaded at 0x0000:0x7c00 by the bios-startup routines.
                     11:  *
                     12:  * It then loads the system at SYSSEG<<4, using BIOS interrupts.
                     13:  *
                     14:  * The loader has been made as simple as possible, and continuous read errors
                     15:  * will result in a unbreakable loop. Reboot by hand. It loads pretty fast by
                     16:  * getting whole tracks at a time whenever possible.
                     17:  */
                     18: 
                     19: FILE_LICENCE ( GPL2_ONLY )
                     20: 
                     21: .equ   BOOTSEG, 0x07C0                 /* original address of boot-sector */
                     22: 
                     23: .equ   SYSSEG, 0x1000                  /* system loaded at SYSSEG<<4 */
                     24: 
                     25:        .org    0
                     26:        .arch i386
                     27:        .text
                     28:        .section ".prefix", "ax", @progbits
                     29:        .code16
                     30:        .globl  _dsk_start
                     31: _dsk_start:
                     32: 
                     33:        jmp     $BOOTSEG, $go           /* reload cs:ip to match relocation addr */
                     34: go: 
                     35:        movw    $0x2000-12, %di         /* 0x2000 is arbitrary value >= length */
                     36:                                        /* of bootsect + room for stack + 12 for */
                     37:                                        /* saved disk parm block */
                     38: 
                     39:        movw    $BOOTSEG, %ax
                     40:        movw    %ax,%ds
                     41:        movw    %ax,%es
                     42:        movw    %ax,%ss                 /* put stack at BOOTSEG:0x4000-12. */
                     43:        movw    %di,%sp
                     44: 
                     45: /* Many BIOS's default disk parameter tables will not recognize multi-sector
                     46:  * reads beyond the maximum sector number specified in the default diskette
                     47:  * parameter tables - this may mean 7 sectors in some cases.
                     48:  *
                     49:  * Since single sector reads are slow and out of the question, we must take care
                     50:  * of this by creating new parameter tables (for the first disk) in RAM.  We
                     51:  * will set the maximum sector count to 36 - the most we will encounter on an
                     52:  * ED 2.88.  High doesn't hurt.        Low does.
                     53:  *
                     54:  * Segments are as follows: ds=es=ss=cs - BOOTSEG
                     55:  */
                     56: 
                     57:        xorw    %cx,%cx
                     58:        movw    %cx,%es                 /* access segment 0 */
                     59:        movw    $0x78, %bx              /* 0:bx is parameter table address */
                     60:        pushw   %ds                     /* save ds */
                     61: /* 0:bx is parameter table address */
                     62:        ldsw    %es:(%bx),%si           /* loads ds and si */
                     63: 
                     64:        movw    %ax,%es                 /* ax is BOOTSECT (loaded above) */
                     65:        movb    $6, %cl                 /* copy 12 bytes */
                     66:        cld
                     67:        pushw   %di                     /* keep a copy for later */
                     68:        rep
                     69:        movsw                           /* ds:si is source, es:di is dest */
                     70:        popw    %di
                     71: 
                     72:        movb    $36,%es:4(%di)
                     73: 
                     74:        movw    %cx,%ds                 /* access segment 0 */
                     75:        xchgw   %di,(%bx)
                     76:        movw    %es,%si
                     77:        xchgw   %si,2(%bx)
                     78:        popw    %ds                     /* restore ds */
                     79:        movw    %di, dpoff              /* save old parameters */
                     80:        movw    %si, dpseg              /* to restore just before finishing */
                     81:        pushw   %ds
                     82:        popw    %es                     /* reload es */
                     83: 
                     84: /* Note that es is already set up.  Also cx is 0 from rep movsw above. */
                     85: 
                     86:        xorb    %ah,%ah                 /* reset FDC */
                     87:        xorb    %dl,%dl
                     88:        int     $0x13
                     89: 
                     90: /* Get disk drive parameters, specifically number of sectors/track.
                     91:  *
                     92:  * It seems that there is no BIOS call to get the number of sectors.  Guess
                     93:  * 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read,
                     94:  * 15 if sector 15 can be read.        Otherwise guess 9.
                     95:  */
                     96: 
                     97:        movw    $disksizes, %si         /* table of sizes to try */
                     98: 
                     99: probe_loop: 
                    100:        lodsb
                    101:        cbtw                            /* extend to word */
                    102:        movw    %ax, sectors
                    103:        cmpw    $disksizes+4, %si
                    104:        jae     got_sectors             /* if all else fails, try 9 */
                    105:        xchgw   %cx,%ax                 /* cx = track and sector */
                    106:        xorw    %dx,%dx                 /* drive 0, head 0 */
                    107:        movw    $0x0200, %bx            /* address after boot sector */
                    108:                                        /*   (512 bytes from origin, es = cs) */
                    109:        movw    $0x0201, %ax            /* service 2, 1 sector */
                    110:        int     $0x13
                    111:        jc      probe_loop              /* try next value */
                    112: 
                    113: got_sectors: 
                    114:        movw    $msg1end-msg1, %cx
                    115:        movw    $msg1, %si
                    116:        call    print_str
                    117: 
                    118: /* ok, we've written the Loading... message, now we want to load the system */
                    119: 
                    120:        movw    $SYSSEG, %ax
                    121:        movw    %ax,%es                 /* segment of SYSSEG<<4 */
                    122:        pushw   %es
                    123:        call    read_it
                    124: 
                    125: /* This turns off the floppy drive motor, so that we enter the kernel in a
                    126:  * known state, and don't have to worry about it later.
                    127:  */
                    128:        movw    $0x3f2, %dx
                    129:        xorb    %al,%al
                    130:        outb    %al,%dx
                    131: 
                    132:        call    print_nl
                    133:        pop     %es                     /* = SYSSEG */
                    134: 
                    135: /* Restore original disk parameters */
                    136:        movw    $0x78, %bx
                    137:        movw    dpoff, %di
                    138:        movw    dpseg, %si
                    139:        xorw    %ax,%ax
                    140:        movw    %ax,%ds
                    141:        movw    %di,(%bx)
                    142:        movw    %si,2(%bx)
                    143: 
                    144:        /* Everything now loaded.  %es = SYSSEG, so %es:0000 points to
                    145:         * start of loaded image.
                    146:         */
                    147: 
                    148:        /* Jump to loaded copy */
                    149:        ljmp    $SYSSEG, $start_runtime
                    150: 
                    151: endseg:        .word SYSSEG
                    152:        .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
                    153:        .ascii  "ADDW"
                    154:        .long   endseg
                    155:        .long   16
                    156:        .long   0
                    157:        .previous
                    158: 
                    159: /* This routine loads the system at address SYSSEG<<4, making sure no 64kB
                    160:  * boundaries are crossed. We try to load it as fast as possible, loading whole
                    161:  * tracks whenever we can.
                    162:  *
                    163:  * in: es - starting address segment (normally SYSSEG)
                    164:  */
                    165: read_it: 
                    166:        movw    $0,sread                /* load whole image including prefix */
                    167:        movw    %es,%ax
                    168:        testw   $0x0fff, %ax
                    169: die:   jne     die                     /* es must be at 64kB boundary */
                    170:        xorw    %bx,%bx                 /* bx is starting address within segment */
                    171: rp_read: 
                    172:        movw    %es,%ax
                    173:        movw    %bx,%dx
                    174:        movb    $4, %cl
                    175:        shrw    %cl,%dx                 /* bx is always divisible by 16 */
                    176:        addw    %dx,%ax
                    177:        cmpw    endseg, %ax     /* have we loaded all yet? */
                    178:        jb      ok1_read
                    179:        ret
                    180: ok1_read: 
                    181:        movw    sectors, %ax
                    182:        subw    sread, %ax
                    183:        movw    %ax,%cx
                    184:        shlw    $9, %cx
                    185:        addw    %bx,%cx
                    186:        jnc     ok2_read
                    187:        je      ok2_read
                    188:        xorw    %ax,%ax
                    189:        subw    %bx,%ax
                    190:        shrw    $9, %ax
                    191: ok2_read: 
                    192:        call    read_track
                    193:        movw    %ax,%cx
                    194:        addw    sread, %ax
                    195:        cmpw    sectors, %ax
                    196:        jne     ok3_read
                    197:        movw    $1, %ax
                    198:        subw    head, %ax
                    199:        jne     ok4_read
                    200:        incw    track
                    201: ok4_read: 
                    202:        movw    %ax, head
                    203:        xorw    %ax,%ax
                    204: ok3_read: 
                    205:        movw    %ax, sread
                    206:        shlw    $9, %cx
                    207:        addw    %cx,%bx
                    208:        jnc     rp_read
                    209:        movw    %es,%ax
                    210:        addb    $0x10, %ah
                    211:        movw    %ax,%es
                    212:        xorw    %bx,%bx
                    213:        jmp     rp_read
                    214: 
                    215: read_track: 
                    216:        pusha
                    217:        pushw   %ax
                    218:        pushw   %bx
                    219:        pushw   %bp                     /* just in case the BIOS is buggy */
                    220:        movw    $0x0e2e, %ax            /* 0x2e = . */
                    221:        movw    $0x0007, %bx
                    222:        int     $0x10
                    223:        popw    %bp
                    224:        popw    %bx
                    225:        popw    %ax
                    226: 
                    227:        movw    track, %dx
                    228:        movw    sread, %cx
                    229:        incw    %cx
                    230:        movb    %dl,%ch
                    231:        movw    head, %dx
                    232:        movb    %dl,%dh
                    233:        andw    $0x0100, %dx
                    234:        movb    $2, %ah
                    235: 
                    236:        pushw   %dx                     /* save for error dump */
                    237:        pushw   %cx
                    238:        pushw   %bx
                    239:        pushw   %ax
                    240: 
                    241:        int     $0x13
                    242:        jc      bad_rt
                    243:        addw    $8, %sp
                    244:        popa
                    245:        ret
                    246: 
                    247: bad_rt: pushw  %ax                     /* save error code */
                    248:        call    print_all               /* ah = error, al = read */
                    249: 
                    250:        xorb    %ah,%ah
                    251:        xorb    %dl,%dl
                    252:        int     $0x13
                    253: 
                    254:        addw    $10, %sp
                    255:        popa
                    256:        jmp     read_track
                    257: 
                    258: /* print_all is for debugging purposes.        It will print out all of the registers.
                    259:  * The assumption is that this is called from a routine, with a stack frame like
                    260:  *     dx
                    261:  *     cx
                    262:  *     bx
                    263:  *     ax
                    264:  *     error
                    265:  *     ret <- sp
                    266:  */
                    267: 
                    268: print_all: 
                    269:        call    print_nl                /* nl for readability */
                    270:        movw    $5, %cx                 /* error code + 4 registers */
                    271:        movw    %sp,%bp
                    272: 
                    273: print_loop: 
                    274:        pushw   %cx                     /* save count left */
                    275: 
                    276:        cmpb    $5, %cl
                    277:        jae     no_reg                  /* see if register name is needed */
                    278: 
                    279:        movw    $0x0007, %bx            /* page 0, attribute 7 (normal) */
                    280:        movw    $0xe05+0x41-1, %ax
                    281:        subb    %cl,%al
                    282:        int     $0x10
                    283: 
                    284:        movb    $0x58, %al              /* 'X' */
                    285:        int     $0x10
                    286: 
                    287:        movb    $0x3A, %al              /* ':' */
                    288:        int     $0x10
                    289: 
                    290: no_reg: 
                    291:        addw    $2, %bp                 /* next register */
                    292:        call    print_hex               /* print it */
                    293:        movb    $0x20, %al              /* print a space */
                    294:        int     $0x10
                    295:        popw    %cx
                    296:        loop    print_loop
                    297:        call    print_nl                /* nl for readability */
                    298:        ret
                    299: 
                    300: print_str: 
                    301:        movw    $0x0007, %bx            /* page 0, attribute 7 (normal) */
                    302:        movb    $0x0e, %ah              /* write char, tty mode */
                    303: prloop: 
                    304:        lodsb
                    305:        int     $0x10
                    306:        loop    prloop
                    307:        ret
                    308: 
                    309: print_nl: 
                    310:        movw    $0x0007, %bx            /* page 0, attribute 7 (normal) */
                    311:        movw    $0xe0d, %ax             /* CR */
                    312:        int     $0x10
                    313:        movb    $0xa, %al               /* LF */
                    314:        int     $0x10
                    315:        ret
                    316: 
                    317: /* print_hex prints the word pointed to by ss:bp in hexadecimal. */
                    318: 
                    319: print_hex: 
                    320:        movw    (%bp),%dx               /* load word into dx */
                    321:        movb    $4, %cl
                    322:        movb    $0x0e, %ah              /* write char, tty mode */
                    323:        movw    $0x0007, %bx            /* page 0, attribute 7 (normal) */
                    324:        call    print_digit
                    325:        call    print_digit
                    326:        call    print_digit
                    327: /* fall through */
                    328: print_digit: 
                    329:        rol     %cl,%dx                 /* rotate so that lowest 4 bits are used */
                    330:        movb    $0x0f, %al              /* mask for nybble */
                    331:        andb    %dl,%al
                    332:        addb    $0x90, %al              /* convert al to ascii hex (four instructions) */
                    333:        daa
                    334:        adcb    $0x40, %al
                    335:        daa
                    336:        int     $0x10
                    337:        ret
                    338: 
                    339: sread: .word 0                         /* sectors read of current track */
                    340: head:  .word 0                         /* current head */
                    341: track: .word 0                         /* current track */
                    342: 
                    343: sectors: 
                    344:        .word 0
                    345: 
                    346: dpseg: .word 0
                    347: dpoff: .word 0
                    348: 
                    349: disksizes: 
                    350:        .byte 36,18,15,9
                    351: 
                    352: msg1: 
                    353:        .ascii "Loading ROM image"
                    354: msg1end: 
                    355: 
                    356:        .org 510, 0
                    357:        .word 0xAA55
                    358: 
                    359: start_runtime:
                    360:        /* Install iPXE */
                    361:        call    install
                    362: 
                    363:        /* Set up real-mode stack */
                    364:        movw    %bx, %ss
                    365:        movw    $_estack16, %sp
                    366: 
                    367:        /* Jump to .text16 segment */
                    368:        pushw   %ax
                    369:        pushw   $1f
                    370:        lret
                    371:        .section ".text16", "awx", @progbits
                    372: 1:
                    373:        pushl   $main
                    374:        pushw   %cs
                    375:        call    prot_call
                    376:        popl    %ecx /* discard */
                    377: 
                    378:        /* Uninstall iPXE */
                    379:        call    uninstall
                    380: 
                    381:        /* Boot next device */
                    382:        int $0x18
                    383: 

unix.superglobalmegacorp.com

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