2 * Hard disc boot block. Loaded at 0x7C00, relocates to 0x0600:
3 * 8a mbr.s; 8l -o mbr -l -H3 -T0x0600 mbr.8
8 /*#define FLOPPY 1 /* test on a floppy */
9 #define TRACE(C) PUSHA;\
17 * We keep data on the stack, indexed by BP.
19 #define Xdap 0x00 /* disc address packet */
20 #define Xtable 0x10 /* partition table entry */
21 #define Xdrive 0x12 /* starting disc */
22 #define Xtotal 0x14 /* sum of allocated data above */
25 * Start: loaded at 0000:7C00, relocate to 0000:0600.
26 * Boot drive is in rDL.
31 MTSR(rAX, rSS) /* 0000 -> rSS */
32 LWI((0x7C00-Xtotal), rSP) /* 7Bxx -> rSP */
33 MW(rSP, rBP) /* set the indexed-data pointer */
35 MTSR(rAX, rDS) /* 0000 -> rDS, source segment */
36 LWI(0x7C00, rSI) /* 7C00 -> rSI, source offset */
37 MTSR(rAX, rES) /* 0000 -> rES, destination segment */
38 LWI(0x600, rDI) /* 0600 -> rDI, destination offset */
39 LWI(0x100, rCX) /* 0100 -> rCX, loop count (words) */
42 REP; MOVSL /* MOV DS:[(E)SI] -> ES:[(E)DI] */
44 FARJUMP16(0x0000, _start0600(SB))
46 TEXT _start0600(SB), $0
50 CLRB(rAL) /* some systems pass 0 */
56 SXB(rDL, Xdrive, xBP) /* save disc */
58 LWI(confidence(SB), rSI) /* for that warm, fuzzy feeling */
61 LWI(_start+0x01BE(SB), rSI) /* address of partition table */
62 LWI(0x04, rCX) /* 4 entries in table */
63 LBI(0x80, rAH) /* active entry value */
64 CLRB(rAL) /* inactive entry value */
67 LXB(0x00, xSI, rBL) /* get active entry from table */
68 CMPBR(rBL, rAH) /* is this an active entry? */
71 CMPBR(rBL, rAL) /* if not active it should be 0 */
74 ADDI(0x10, rSI) /* next table entry */
82 MW(rSI, rDI) /* save table address */
85 ADDI(0x10, rSI) /* next table entry */
89 LXB(0x00, xSI, rBL) /* get active entry from table */
90 CMPBR(rBL, rAH) /* is this an active entry? */
91 JNE _activeloop1 /* should only be one active */
94 LWI(invalidMBR(SB), rSI)
98 LBI(0x41, rAH) /* check extensions present */
100 LXB(Xdrive, xBP, rDL) /* drive */
101 BIOSCALL(0x13) /* CF set on failure */
109 SBPBI(0x10, Xdap+0) /* packet size */
110 SBPBI(0x00, Xdap+1) /* reserved */
111 SBPBI(0x01, Xdap+2) /* number of blocks to transfer */
112 SBPBI(0x00, Xdap+3) /* reserved */
113 SBPWI(0x7C00, Xdap+4) /* transfer buffer :offset */
114 SBPWI(0x0000, Xdap+6) /* transfer buffer seg: */
115 LXW(0x08, xDI, rAX) /* LBA (64-bits) */
119 SBPWI(0x0000, Xdap+12)
120 SBPWI(0x0000, Xdap+14)
122 MW(rBP, rSI) /* disk address packet */
123 LBI(0x42, rAH) /* extended read */
124 BIOSCALL(0x13) /* CF set on failure */
127 LWI(ioerror(SB), rSI)
131 * Read a sector from a disc using the traditional BIOS call.
132 * For BIOSCALL(0x13/AH=0x02):
134 * rAL number of sectors to read (1)
135 * rCH low 8 bits of cylinder
136 * rCL high 2 bits of cylinder (7-6), sector (5-0)
139 * rES:rBX buffer address
142 LXB(0x01, xDI, rDH) /* head */
143 LXW(0x02, xDI, rCX) /* save active cylinder/sector */
145 LWI(0x0201, rAX) /* read one sector */
146 LXB(Xdrive, xBP, rDL) /* drive */
147 LWI(0x7C00, rBX) /* buffer address (rES already OK) */
148 BIOSCALL(0x13) /* CF set on failure */
151 LWI(ioerror(SB), rSI)
155 LWI(0x7C00, rBX) /* buffer address (rES already OK) */
161 * Jump to the loaded PBS.
162 * rDL and rSI should still contain the drive
163 * and partition table pointer respectively.
166 FARJUMP16(0x0000, 0x7C00)
169 LWI(invalidPBS(SB), rSI)
177 CLR(rAX) /* wait for any key */
181 CLR(rBX) /* set ES segment for BIOS area */
184 LWI(0x0472, rBX) /* warm-start code address */
185 LWI(0x1234, rAX) /* warm-start code */
186 POKEW /* MOVW AX, ES:[BX] */
188 FARJUMP16(0xFFFF, 0x0000) /* reset */
191 * Output a string to the display.
192 * String argument is in rSI.
194 TEXT BIOSputs(SB), $0
210 /* "No active entry in MBR" */
212 BYTE $'N'; BYTE $'o'; BYTE $' '; BYTE $'a';
213 BYTE $'c'; BYTE $'t'; BYTE $'i'; BYTE $'v';
214 BYTE $'e'; BYTE $' '; BYTE $'e'; BYTE $'n';
215 BYTE $'t'; BYTE $'r'; BYTE $'y'; BYTE $' ';
216 BYTE $'i'; BYTE $'n'; BYTE $' '; BYTE $'M';
217 BYTE $'B'; BYTE $'R';
221 TEXT invalidMBR(SB), $0
222 BYTE $'I'; BYTE $'n'; BYTE $'v'; BYTE $'a';
223 BYTE $'l'; BYTE $'i'; BYTE $'d'; BYTE $' ';
224 BYTE $'M'; BYTE $'B'; BYTE $'R';
229 BYTE $'I'; BYTE $'/'; BYTE $'O'; BYTE $' ';
230 BYTE $'e'; BYTE $'r'; BYTE $'r'; BYTE $'o';
235 TEXT invalidPBS(SB), $0
236 BYTE $'I'; BYTE $'n'; BYTE $'v'; BYTE $'a';
237 BYTE $'l'; BYTE $'i'; BYTE $'d'; BYTE $' ';
238 BYTE $'P'; BYTE $'B'; BYTE $'S';
241 /* "\r\nPress almost any key to reboot..." */
243 BYTE $'\r';BYTE $'\n';
244 BYTE $'P'; BYTE $'r'; BYTE $'e'; BYTE $'s';
245 BYTE $'s'; BYTE $' '; BYTE $'a'; BYTE $'l';
246 BYTE $'m'; BYTE $'o'; BYTE $'s'; BYTE $'t';
247 BYTE $' '; BYTE $'a'; BYTE $'n'; BYTE $'y';
248 BYTE $' '; BYTE $'k'; BYTE $'e'; BYTE $'y';
249 BYTE $' '; BYTE $'t'; BYTE $'o'; BYTE $' ';
250 BYTE $'r'; BYTE $'e'; BYTE $'b'; BYTE $'o';
251 BYTE $'o'; BYTE $'t'; BYTE $'.'; BYTE $'.';
256 TEXT confidence(SB), $0
257 BYTE $'M'; BYTE $'B'; BYTE $'R'; BYTE $'.';
258 BYTE $'.'; BYTE $'.';