Annotation of lucent/sys/src/boot/pc/bb.s, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Boot block. Loaded at 0x7C00
                      3:  *     8a bb.s; 8l -o bb -l -H3 -T0x7C00 bb.8
                      4:  */
                      5: /*
                      6:  * Can't write 16-bit code for 8a without getting into
                      7:  * lots of bother, so define some simple commands and
                      8:  * output the code directly.
                      9:  * This was a mistake in so many ways it's not true.
                     10:  * But I don't ever, ever have to do it again.
                     11:  */
                     12: #define rAX            0               /* rX  */
                     13: #define rCX            1
                     14: #define rDX            2
                     15: #define rBX            3
                     16: #define rSP            4               /* SP */
                     17: #define rBP            5               /* BP */
                     18: #define rSI            6               /* SI */
                     19: #define rDI            7               /* DI */
                     20: 
                     21: #define rAL            0               /* rL  */
                     22: #define rCL            1
                     23: #define rDL            2
                     24: #define rBL            3
                     25: #define rAH            4               /* rH */
                     26: #define rCH            5
                     27: #define rDH            6
                     28: #define rBH            7
                     29: 
                     30: #define rES            0               /* rS */
                     31: #define rCS            1
                     32: #define rSS            2
                     33: #define rDS            3
                     34: #define rFS            4
                     35: #define rGS            5
                     36: 
                     37: #define OP(o, m, r, rm)        BYTE $o;                /* op + modr/m byte */  \
                     38:                        BYTE $((m<<6)|(r<<3)|rm)
                     39: #define OPrm(o, r, m)  OP(o, 0x00, r, 0x06);   /* general r <-> m */   \
                     40:                        WORD $m;
                     41: #define OPrr(o, r0, r1)        OP(o, 0x03, r0, r1);    /* general r -> r */    \
                     42: 
                     43: #define LW(m, rX)      OPrm(0x8B, rX, m)       /* m -> rX */
                     44: #define LBPW(x, r)     OP(0x8B, 0x02, r, 0x06);/* x(rBP) -> r */       \
                     45:                        WORD $x
                     46: #define LB(m, rB)      OPrm(0x8A, rB, m)       /* m -> r[HL] */
                     47: #define LBPB(x, r)     OP(0x8A, 0x01, r, 0x06);/* x(rBP) -> r */       \
                     48:                        BYTE $x
                     49: #define SW(rX, m)      OPrm(0x89, rX, m)       /* rX -> m */
                     50: #define SBPW(r, x)     OP(0x89, 0x02, r, 0x06);/* r -> x(rBP) */       \
                     51:                        WORD $x
                     52: #define STB(rB, m)     OPrm(0x88, rB, m)       /* rB -> m */
                     53: #define SBPB(r, x)     OP(0x88, 0x01, r, 0x06);/* r -> x(rBP) */       \
                     54:                        BYTE $x
                     55: #define LWI(i, rX)     BYTE $(0xB8+rX);        /* i -> rX */           \
                     56:                        WORD $i;
                     57: #define LBI(i, rB)     BYTE $(0xB0+rB);        /* i -> r[HL] */        \
                     58:                        BYTE $i
                     59: 
                     60: #define MW(r0, r1)     OPrr(0x89, r0, r1)      /* r0 -> r1 */
                     61: #define MFSR(rS, rX)   OPrr(0x8C, rS, rX)      /* rS -> rX */
                     62: #define MTSR(rX, rS)   OPrr(0x8E, rS, rX)      /* rX -> rS */
                     63: 
                     64: #define ADC(r0, r1)    OPrr(0x11, r0, r1)      /* r0 + r1 -> r1 */
                     65: #define ADD(r0, r1)    OPrr(0x01, r0, r1)      /* r0 + r1 -> r1 */
                     66: #define AND(r0, r1)    OPrr(0x21, r0, r1)      /* r0 & r1 -> r1 */
                     67: #define ANDI(i, r)     OP(0x81, 0x03, 0x04, r);/* i & r -> r */        \
                     68:                        WORD $i;
                     69: #define CLR(r)         OPrr(0x31, r, r)        /* r^r -> r */
                     70: #define CLRB(r)                OPrr(0x30, r, r)        /* r^r -> r */
                     71: #define CMP(r0, r1)    OPrr(0x39, r0, r1)      /* r1 - r0 -> flags */
                     72: #define CMPB(r0, r1)   OPrr(0x38, r0, r1)      /* r1 - r0 -> flags */
                     73: #define DEC(r)         BYTE $(0x48|r)          /* r-1 -> r */
                     74: #define DIV(r)         OPrr(0xF7, 0x06, r)     /* rAX/r -> rDX:rAX */
                     75: #define INC(r)         BYTE $(0x40|r)          /* r+1 -> r */
                     76: #define MUL(r)         OPrr(0xF7, 0x04, r)     /* r * rAX -> rDX:rAX */
                     77: #define OR(r0, r1)     OPrr(0x09, r0, r1)      /* r0|r1 -> r1 */
                     78: #define ORB(r0, r1)    OPrr(0x08, r0, r1)      /* r0|r1 -> r1 */
                     79: #define ROLI(i, r)     OPrr(0xC1, 0x00, r);    /* r<<>>i -> r */       \
                     80:                        BYTE $i;
                     81: #define SHLI(i, r)     OPrr(0xC1, 0x04, r);    /* r<<i -> r */         \
                     82:                        BYTE $i;
                     83: #define SHLBI(i, r)    OPrr(0xC0, 0x04, r);    /* r<<i -> r */         \
                     84:                        BYTE $i;
                     85: 
                     86: #define CALL(f)                LWI(f, rDI);            /* &f -> rDI */         \
                     87:                        BYTE $0xFF;             /* (*rDI) */            \
                     88:                        BYTE $0xD7;
                     89: #define FARJUMP(s, o)  BYTE $0xEA;             /* far jump to s:o */   \
                     90:                        WORD $o; WORD $s
                     91: #define        DELAY           BYTE $0xEB;             /* jmp .+2 */           \
                     92:                        BYTE $0x00
                     93: #define SYSCALL(b)     INT $b                  /* INT $b */
                     94: 
                     95: #define POKEW          BYTE $0x26;             /* MOVW rAX, rES:[rBX] */       \
                     96:                        BYTE $0x89; BYTE $0x07
                     97: #define OUTB(p, d)     LBI(d, rAL);            /* d -> I/O port p */   \
                     98:                        BYTE $0xE6;                                     \
                     99:                        BYTE $p; DELAY
                    100: #define PUSHA          BYTE $0x60
                    101: #define PUSHW(r)       BYTE $(0x50|r)          /* r  -> (--rSP) */
                    102: #define POPA           BYTE $0x61
                    103: #define POPW(r)                BYTE $(0x58|r)          /* (rSP++) -> r */
                    104: #define NOP            BYTE $0x90              /* nop */
                    105: 
                    106: /*
                    107:  * Now on to the real work.
                    108:  * If you're stilll reading, you have a
                    109:  * stomach of steel.
                    110:  */
                    111: #define RDIRBUF                0x00200         /* where to read the root directory (offset) */
                    112: #define CODEBUF                0x10000         /* where to load code (64Kb) */
                    113: 
                    114: /*
                    115:  * MS-DOS directory entry.
                    116:  */
                    117: #define Dname          0x00
                    118: #define Dext           0x08
                    119: #define Dattr          0x0B
                    120: #define Dtime          0x16
                    121: #define Ddate          0x18
                    122: #define Dstart         0x1A
                    123: #define Dlengthlo      0x1C
                    124: #define Dlengthhi      0x1E
                    125: 
                    126: #define Dirsz          0x20
                    127: 
                    128: /*
                    129:  * We keep data on the stack, indexed by rBP.
                    130:  */
                    131: #define Xdrive         0x00            /* boot drive, passed by BIOS in rDL */
                    132: #define Xrootlo                0x02            /* offset of root directory */
                    133: #define Xroothi                0x04
                    134: #define Xrootsz                0x06            /* file data area */
                    135: #define Xtotal         0x08            /* sum of allocated data above */
                    136: 
                    137: TEXT _magic(SB), $0
                    138:        BYTE $0xEB; BYTE $0x3C;         /* jmp .+ 0x3C  (_start0x3E) */
                    139:        BYTE $0x90                      /* nop */
                    140: TEXT _version(SB), $0
                    141:        BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
                    142:        BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
                    143: TEXT _sectsize(SB), $0
                    144:        BYTE $0x00; BYTE $0x00
                    145: TEXT _clustsize(SB), $0
                    146:        BYTE $0x00
                    147: TEXT _nresrv(SB), $0
                    148:        BYTE $0x00; BYTE $0x00
                    149: TEXT _nfats(SB), $0
                    150:        BYTE $0x00
                    151: TEXT _rootsize(SB), $0
                    152:        BYTE $0x00; BYTE $0x00
                    153: TEXT _volsize(SB), $0
                    154:        BYTE $0x00; BYTE $0x00
                    155: TEXT _mediadesc(SB), $0
                    156:        BYTE $0x00
                    157: TEXT _fatsize(SB), $0
                    158:        BYTE $0x00; BYTE $0x00
                    159: TEXT _trksize(SB), $0
                    160:        BYTE $0x00; BYTE $0x00
                    161: TEXT _nheads(SB), $0
                    162:        BYTE $0x00; BYTE $0x00
                    163: TEXT _nhiddenlo(SB), $0
                    164:        BYTE $0x00; BYTE $0x00
                    165: TEXT _nhiddenhi(SB), $0
                    166:        BYTE $0x00; BYTE $0x00;
                    167: TEXT _bigvolsize(SB), $0
                    168:        BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
                    169: TEXT _driveno(SB), $0
                    170:        BYTE $0x00
                    171: TEXT _reserved0(SB), $0
                    172:        BYTE $0x00
                    173: TEXT _bootsig(SB), $0
                    174:        BYTE $0x00
                    175: TEXT _volid(SB), $0
                    176:        BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
                    177: TEXT _label(SB), $0
                    178:        BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
                    179:        BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
                    180:        BYTE $0x00; BYTE $0x00; BYTE $0x00
                    181: TEXT _type(SB), $0
                    182:        BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
                    183:        BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
                    184: 
                    185: _start0x3E:
                    186:        CLI
                    187:        MFSR(rCS, rAX)                  /* set the data and stack segments */
                    188:        MTSR(rAX, rDS)
                    189:        MTSR(rAX, rSS)
                    190:        MTSR(rAX, rES)
                    191:        LWI(_magic-Xtotal(SB), rSP)
                    192:        MW(rSP, rBP)                    /* set the indexed-data pointer */
                    193: 
                    194:        SBPB(rDL, Xdrive)               /* save the boot drive */
                    195: 
                    196:        STI
                    197: 
                    198:        LWI(confidence(SB), rSI)        /* for that warm, fuzzy feeling */
                    199:        CALL(BIOSputs(SB))
                    200: 
                    201:        CLR(rAX)                        /* rAH == 0 == reset disc system */
                    202:        PUSHW(rBP)                      /* may be trashed by SYSCALL */
                    203:        SYSCALL(0x13)                   /* rDL == boot drive */
                    204:        POPW(rBP)
                    205:        ORB(rAH, rAH)                   /* status (0 == successful completion) */
                    206:        JEQ _jmp00                      /* can't rely on 8l doing other than short jumps */
                    207:        CALL(buggery(SB))
                    208: 
                    209: _jmp00:
                    210:        CLR(rAX)
                    211: 
                    212:        LB(_nfats(SB), rAL)             /* calculate root directory offset */
                    213:        LW(_fatsize(SB), rCX)
                    214:        MUL(rCX)
                    215:        LW(_nhiddenlo(SB), rCX)
                    216:        ADD(rCX, rAX)
                    217:        LW(_nhiddenhi(SB), rCX)
                    218:        ADC(rCX, rDX)
                    219:        LW(_nresrv(SB), rCX)
                    220:        ADD(rCX, rAX)
                    221:        LWI(0x0000, rCX)                /* don't set flags */
                    222:        ADC(rCX, rDX)
                    223: 
                    224:        SBPW(rAX, Xrootlo)              /* save */
                    225:        SBPW(rDX, Xroothi)
                    226: 
                    227:        LWI(_magic+RDIRBUF(SB), rBX)
                    228:        CALL(BIOSread(SB))              /* read the root directory */
                    229: 
                    230:        LWI(_magic+RDIRBUF(SB), rDI)    /* compare first directory entry */
                    231:        LWI(bootfile(SB), rSI)
                    232:        LWI(Dattr, rCX)
                    233:        REP
                    234:        CMPSB
                    235:        JEQ _jmp02
                    236:        CALL(buggery(SB))
                    237: 
                    238: _jmp02:
                    239:        CLR(rBX)                        /* a handy value */
                    240:        LW(_rootsize(SB), rAX)          /* calculate and save Xrootsz */
                    241:        LWI(Dirsz, rCX)
                    242:        MUL(rCX)
                    243:        LW(_sectsize(SB), rCX)
                    244:        DEC(rCX)
                    245:        ADD(rCX, rAX)
                    246:        ADC(rBX, rDX);
                    247:        LW(_sectsize(SB), rCX)
                    248:        DIV(rCX)
                    249:        SBPW(rAX, Xrootsz)
                    250: 
                    251:        LW(_magic+(RDIRBUF+Dstart)(SB), rAX)    /* calculate starting sector address */
                    252:        DEC(rAX)                                /* that's just the way it is... */
                    253:        DEC(rAX)
                    254:        LB(_clustsize(SB), rCL)
                    255:        CLRB(rCH)
                    256:        MUL(rCX)
                    257:        LBPW(Xrootlo, rCX)
                    258:        ADD(rCX, rAX)
                    259:        LBPW(Xroothi, rCX)
                    260:        ADC(rCX, rDX)
                    261:        LBPW(Xrootsz, rCX)
                    262:        ADD(rCX, rAX)
                    263:        ADC(rBX, rDX);
                    264: 
                    265:        PUSHW(rAX)
                    266:        PUSHW(rDX)
                    267:        LW(_magic+(RDIRBUF+Dlengthlo)(SB), rAX) /* calculate how many sectors to read */
                    268:        LW(_magic+(RDIRBUF+Dlengthhi)(SB), rDX)
                    269:        LW(_sectsize(SB), rCX)
                    270:        DEC(rCX)
                    271:        ADD(rCX, rAX)
                    272:        ADC(rBX, rDX);
                    273:        LW(_sectsize(SB), rCX)
                    274:        DIV(rCX)
                    275:        MW(rAX, rCX)
                    276:        POPW(rDX)
                    277:        POPW(rAX)
                    278: 
                    279:        LWI((CODEBUF/16), rBX)          /* address to load into (seg + offset) */
                    280:        MTSR(rBX, rES)
                    281:        LWI(0x0100, rBX)
                    282: 
                    283: _readboot:
                    284:        CALL(BIOSread(SB))              /* read the sector */
                    285: 
                    286:        LW(_sectsize(SB), rDI)          /* bump addresses/counts */
                    287:        ADD(rDI, rBX)
                    288:        INC(rAX)
                    289:        LWI(0x0000, rDI)                /* don't set flags */
                    290:        ADC(rDI, rDX)
                    291:        LOOP _readboot
                    292: 
                    293:        LWI((CODEBUF/16), rDI)          /* set rDS for loaded code */
                    294:        MTSR(rDI, rDS)
                    295:        FARJUMP((CODEBUF/16), 0x0100)   /* no deposit, no return */
                    296: 
                    297: TEXT buggery(SB), $0
                    298:        LWI(error(SB), rSI)
                    299:        CALL(BIOSputs(SB))
                    300: 
                    301: _wait:
                    302:        CLR(rAX)                        /* wait for any key */
                    303:        SYSCALL(0x16)
                    304: 
                    305: _reset:
                    306:        CLR(rBX)                        /* set ES segment for BIOS area */
                    307:        MTSR(rBX, rES)
                    308: 
                    309:        LWI(0x0472, rBX)                /* warm-start code address */
                    310:        LWI(0x1234, rAX)                /* warm-start code */
                    311:        POKEW                           /* MOVW AX, ES:[BX] */
                    312: 
                    313:        FARJUMP(0xFFFF, 0x0000)         /* reset */
                    314: 
                    315: 
                    316: /*
                    317:  * Read a sector from a disc. On entry:
                    318:  *   rDX:rAX   sector number
                    319:  *   rES:rBX   buffer address
                    320:  * For SYSCALL(0x13):
                    321:  *   rAH       0x02
                    322:  *   rAL       number of sectors to read (1)
                    323:  *   rCH       low 8 bits of cylinder
                    324:  *   rCL       high 2 bits of cylinder (7-6), sector (5-0)
                    325:  *   rDH       head
                    326:  *   rDL       drive
                    327:  *   rES:rBX   buffer address
                    328:  */
                    329: TEXT BIOSread(SB), $0
                    330:        PUSHA                           /* may be trashed by SYSCALL */
                    331: 
                    332:        LW(_trksize(SB), rDI)           /* rDI is scratch */
                    333:        DIV(rDI)                        /* track -> rAX, sector -> rDX */
                    334: 
                    335:        INC(rDX)                        /* sector numbers are 1-based */
                    336:        MW(rDX, rCX)
                    337:        ANDI(0x003F, rCX)               /* form sector bits in rCL */
                    338: 
                    339:        CLR(rDX)
                    340:        LW(_nheads(SB), rDI)
                    341:        DIV(rDI)                        /* cylinder -> rAX, head -> rDX */
                    342: 
                    343:        SHLBI(0x06, rAH)                /* form cylinder hi and lo bits */
                    344:        ROLI(0x08, rAX)                 /* swap rA[HL] */
                    345:        OR(rAX, rCX)                    /* rCH, rCL now set */
                    346: 
                    347:        SHLI(0x08, rDX)                 /* form head */
                    348:        LBPB(Xdrive, rDL)               /* form drive */
                    349: 
                    350:        LWI(0x0201, rAX)                /* form command and sectors */
                    351:        SYSCALL(0x13)                   /* CF set on failure */
                    352:        JCC _BIOSreadret
                    353:        CALL(buggery(SB))
                    354: 
                    355: _BIOSreadret:
                    356:        POPA
                    357:        RET
                    358: 
                    359: /*
                    360:  * Output a string to the display.
                    361:  * String argument is in rSI.
                    362:  */
                    363: TEXT BIOSputs(SB), $0
                    364:        PUSHA
                    365:        CLR(rBX)
                    366: _BIOSputs:
                    367:        LODSB
                    368:        ORB(rAL, rAL)
                    369:        JEQ _BIOSputsret
                    370: 
                    371:        LBI(0x0E, rAH)
                    372:        SYSCALL(0x10)
                    373:        JMP _BIOSputs
                    374: 
                    375: _BIOSputsret:
                    376:        POPA
                    377:        RET
                    378: 
                    379: TEXT error(SB), $0
                    380:        BYTE $'N'; BYTE $'o'; BYTE $'t'; BYTE $' '; BYTE $'a'; BYTE $' '; BYTE $'b'; BYTE $'o';
                    381:        BYTE $'o'; BYTE $'t'; BYTE $'a'; BYTE $'b'; BYTE $'l'; BYTE $'e'; BYTE $' '; BYTE $'d';
                    382:        BYTE $'i'; BYTE $'s'; BYTE $'c'; BYTE $' '; BYTE $'o'; BYTE $'r'; BYTE $' '; BYTE $'d';
                    383:        BYTE $'i'; BYTE $'s'; BYTE $'c'; BYTE $' '; BYTE $'e'; BYTE $'r'; BYTE $'r'; BYTE $'o';
                    384:        BYTE $'r'; BYTE $'\r';BYTE $'\n';BYTE $'P'; BYTE $'r'; BYTE $'e'; BYTE $'s'; BYTE $'s';
                    385:        BYTE $' '; BYTE $'a'; BYTE $'l'; BYTE $'m'; BYTE $'o'; BYTE $'s'; BYTE $'t'; BYTE $' ';
                    386:        BYTE $'a'; BYTE $'n'; BYTE $'y'; BYTE $' '; BYTE $'k'; BYTE $'e'; BYTE $'y'; BYTE $' ';
                    387:        BYTE $'t'; BYTE $'o'; BYTE $' '; BYTE $'r'; BYTE $'e'; BYTE $'b'; BYTE $'o'; BYTE $'o'; 
                    388:        BYTE $'t'; BYTE $'.'; BYTE $'.'; BYTE $'.';
                    389:        BYTE $'\z';
                    390: 
                    391: TEXT bootfile(SB), $0
                    392:        BYTE $'B'; BYTE $' '; BYTE $' '; BYTE $' '; BYTE $' '; BYTE $' '; BYTE $' '; BYTE $' ';
                    393:        BYTE $'C'; BYTE $'O'; BYTE $'M';
                    394:        BYTE $'\z';
                    395: 
                    396: TEXT confidence(SB), $0
                    397:        BYTE $'B'; BYTE $'o'; BYTE $'o'; BYTE $'t'; BYTE $'i'; BYTE $'n'; BYTE $'g'; BYTE $'.';
                    398:        BYTE $'.'; BYTE $'.'; BYTE $'\r';BYTE $'\n';
                    399:        BYTE $'\z';

unix.superglobalmegacorp.com

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