123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- /*
- * Hard disc boot block. Loaded at 0x7C00, relocates to 0x0600:
- * 8a mbr.s; 8l -o mbr -l -H3 -T0x0600 mbr.8
- */
- #include "x16.h"
- /*#define FLOPPY 1 /* test on a floppy */
- #define TRACE(C) PUSHA;\
- CLR(rBX);\
- MOVB $C, AL;\
- LBI(0x0E, rAH);\
- BIOSCALL(0x10);\
- POPA
- /*
- * We keep data on the stack, indexed by BP.
- */
- #define Xdap 0x00 /* disc address packet */
- #define Xtable 0x10 /* partition table entry */
- #define Xdrive 0x12 /* starting disc */
- #define Xtotal 0x14 /* sum of allocated data above */
- /*
- * Start: loaded at 0000:7C00, relocate to 0000:0600.
- * Boot drive is in rDL.
- */
- TEXT _start(SB), $0
- CLI
- CLR(rAX)
- MTSR(rAX, rSS) /* 0000 -> rSS */
- LWI((0x7C00-Xtotal), rSP) /* 7Bxx -> rSP */
- MW(rSP, rBP) /* set the indexed-data pointer */
- MTSR(rAX, rDS) /* 0000 -> rDS, source segment */
- LWI(0x7C00, rSI) /* 7C00 -> rSI, source offset */
- MTSR(rAX, rES) /* 0000 -> rES, destination segment */
- LWI(0x600, rDI) /* 0600 -> rDI, destination offset */
- LWI(0x100, rCX) /* 0100 -> rCX, loop count (words) */
- CLD
- REP; MOVSL /* MOV DS:[(E)SI] -> ES:[(E)DI] */
- FARJUMP16(0x0000, _start0600(SB))
- TEXT _start0600(SB), $0
- #ifdef FLOPPY
- LBI(0x80, rDL)
- #else
- CLRB(rAL) /* some systems pass 0 */
- CMPBR(rAL, rDL)
- JNE _save
- LBI(0x80, rDL)
- #endif /* FLOPPY */
- _save:
- SXB(rDL, Xdrive, xBP) /* save disc */
- LWI(confidence(SB), rSI) /* for that warm, fuzzy feeling */
- CALL16(BIOSputs(SB))
- LWI(_start+0x01BE(SB), rSI) /* address of partition table */
- LWI(0x04, rCX) /* 4 entries in table */
- LBI(0x80, rAH) /* active entry value */
- CLRB(rAL) /* inactive entry value */
- _activeloop0:
- LXB(0x00, xSI, rBL) /* get active entry from table */
- CMPBR(rBL, rAH) /* is this an active entry? */
- JEQ _active
- CMPBR(rBL, rAL) /* if not active it should be 0 */
- JNE _invalidMBR
- ADDI(0x10, rSI) /* next table entry */
- DEC(rCX)
- JNE _activeloop0
- LWI(noentry(SB), rSI)
- CALL16(buggery(SB))
- _active:
- MW(rSI, rDI) /* save table address */
- _activeloop1:
- ADDI(0x10, rSI) /* next table entry */
- DEC(rCX)
- JEQ _readsector
- LXB(0x00, xSI, rBL) /* get active entry from table */
- CMPBR(rBL, rAH) /* is this an active entry? */
- JNE _activeloop1 /* should only be one active */
- _invalidMBR:
- LWI(invalidMBR(SB), rSI)
- CALL16(buggery(SB))
- _readsector:
- LBI(0x41, rAH) /* check extensions present */
- LWI(0x55AA, rBX)
- LXB(Xdrive, xBP, rDL) /* drive */
- BIOSCALL(0x13) /* CF set on failure */
- JCS _readsector2
- CMPI(0xAA55, rBX)
- JNE _readsector2
- ANDI(0x0001, rCX)
- JEQ _readsector2
- _readsector42:
- SBPBI(0x10, Xdap+0) /* packet size */
- SBPBI(0x00, Xdap+1) /* reserved */
- SBPBI(0x01, Xdap+2) /* number of blocks to transfer */
- SBPBI(0x00, Xdap+3) /* reserved */
- SBPWI(0x7C00, Xdap+4) /* transfer buffer :offset */
- SBPWI(0x0000, Xdap+6) /* transfer buffer seg: */
- LXW(0x08, xDI, rAX) /* LBA (64-bits) */
- SBPW(rAX, Xdap+8)
- LXW(0x0A, xDI, rAX)
- SBPW(rAX, Xdap+10)
- SBPWI(0x0000, Xdap+12)
- SBPWI(0x0000, Xdap+14)
- MW(rBP, rSI) /* disk address packet */
- LBI(0x42, rAH) /* extended read */
- BIOSCALL(0x13) /* CF set on failure */
- JCC _readsectorok
- LWI(ioerror(SB), rSI)
- CALL16(buggery(SB))
- /*
- * Read a sector from a disc using the traditional BIOS call.
- * For BIOSCALL(0x13/AH=0x02):
- * rAH 0x02
- * rAL number of sectors to read (1)
- * rCH low 8 bits of cylinder
- * rCL high 2 bits of cylinder (7-6), sector (5-0)
- * rDH head
- * rDL drive
- * rES:rBX buffer address
- */
- _readsector2:
- LXB(0x01, xDI, rDH) /* head */
- LXW(0x02, xDI, rCX) /* save active cylinder/sector */
- LWI(0x0201, rAX) /* read one sector */
- LXB(Xdrive, xBP, rDL) /* drive */
- LWI(0x7C00, rBX) /* buffer address (rES already OK) */
- BIOSCALL(0x13) /* CF set on failure */
- JCC _readsectorok
- LWI(ioerror(SB), rSI)
- CALL16(buggery(SB))
- _readsectorok:
- LWI(0x7C00, rBX) /* buffer address (rES already OK) */
- LXW(0x1FE, xBX, rAX)
- CMPI(0xAA55, rAX)
- JNE _bbnotok
- /*
- * Jump to the loaded PBS.
- * rDL and rSI should still contain the drive
- * and partition table pointer respectively.
- */
- MW(rDI, rSI)
- FARJUMP16(0x0000, 0x7C00)
- _bbnotok:
- LWI(invalidPBS(SB), rSI)
- TEXT buggery(SB), $0
- CALL16(BIOSputs(SB))
- LWI(reboot(SB), rSI)
- CALL16(BIOSputs(SB))
- _wait:
- CLR(rAX) /* wait for any key */
- BIOSCALL(0x16)
- _reset:
- CLR(rBX) /* set ES segment for BIOS area */
- MTSR(rBX, rES)
- LWI(0x0472, rBX) /* warm-start code address */
- LWI(0x1234, rAX) /* warm-start code */
- POKEW /* MOVW AX, ES:[BX] */
- FARJUMP16(0xFFFF, 0x0000) /* reset */
- /*
- * Output a string to the display.
- * String argument is in rSI.
- */
- TEXT BIOSputs(SB), $0
- PUSHA
- CLR(rBX)
- _BIOSputs:
- LODSB
- ORB(rAL, rAL)
- JEQ _BIOSputsret
- LBI(0x0E, rAH)
- BIOSCALL(0x10)
- JMP _BIOSputs
- _BIOSputsret:
- POPA
- RET
- /* "No active entry in MBR" */
- TEXT noentry(SB), $0
- BYTE $'N'; BYTE $'o'; BYTE $' '; BYTE $'a';
- BYTE $'c'; BYTE $'t'; BYTE $'i'; BYTE $'v';
- BYTE $'e'; BYTE $' '; BYTE $'e'; BYTE $'n';
- BYTE $'t'; BYTE $'r'; BYTE $'y'; BYTE $' ';
- BYTE $'i'; BYTE $'n'; BYTE $' '; BYTE $'M';
- BYTE $'B'; BYTE $'R';
- BYTE $'\z';
- /* "Invalid MBR" */
- TEXT invalidMBR(SB), $0
- BYTE $'I'; BYTE $'n'; BYTE $'v'; BYTE $'a';
- BYTE $'l'; BYTE $'i'; BYTE $'d'; BYTE $' ';
- BYTE $'M'; BYTE $'B'; BYTE $'R';
- BYTE $'\z';
- /* "I/O error" */
- TEXT ioerror(SB), $0
- BYTE $'I'; BYTE $'/'; BYTE $'O'; BYTE $' ';
- BYTE $'e'; BYTE $'r'; BYTE $'r'; BYTE $'o';
- BYTE $'r';
- BYTE $'\z';
- /* "Invalid PBS" */
- TEXT invalidPBS(SB), $0
- BYTE $'I'; BYTE $'n'; BYTE $'v'; BYTE $'a';
- BYTE $'l'; BYTE $'i'; BYTE $'d'; BYTE $' ';
- BYTE $'P'; BYTE $'B'; BYTE $'S';
- BYTE $'\z';
- /* "\r\nPress almost any key to reboot..." */
- TEXT reboot(SB), $0
- BYTE $'\r';BYTE $'\n';
- BYTE $'P'; BYTE $'r'; BYTE $'e'; BYTE $'s';
- BYTE $'s'; BYTE $' '; BYTE $'a'; BYTE $'l';
- BYTE $'m'; BYTE $'o'; BYTE $'s'; BYTE $'t';
- BYTE $' '; BYTE $'a'; BYTE $'n'; BYTE $'y';
- BYTE $' '; BYTE $'k'; BYTE $'e'; BYTE $'y';
- BYTE $' '; BYTE $'t'; BYTE $'o'; BYTE $' ';
- BYTE $'r'; BYTE $'e'; BYTE $'b'; BYTE $'o';
- BYTE $'o'; BYTE $'t'; BYTE $'.'; BYTE $'.';
- BYTE $'.';
- BYTE $'\z';
- /* "MBR..." */
- TEXT confidence(SB), $0
- BYTE $'M'; BYTE $'B'; BYTE $'R'; BYTE $'.';
- BYTE $'.'; BYTE $'.';
- BYTE $'\z';
|