Annotation of lucent/sys/src/boot/pc/bb.s, revision 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.