1 /* $MirOS: src/sys/arch/i386/stand/mbr/mbr.S,v 1.12 2009/01/31 23:39:55 tg Exp $ */
5 * Thorsten Glaser <tg@mirbsd.org>
7 * Provided that these terms and disclaimer and all copyright notices
8 * are retained or reproduced in an accompanying document, permission
9 * is granted to deal in this work without restriction, including un-
10 * limited rights to use, publicly perform, distribute, sell, modify,
11 * merge, give away, or sublicence.
13 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
14 * the utmost extent permitted by applicable law, neither express nor
15 * implied; without malicious intent or gross negligence. In no event
16 * may a licensor, author or contributor be held liable for indirect,
17 * direct, other damage, loss, or other issues arising in any way out
18 * of dealing in the work, even if advised of the possibility of such
19 * damage or existence of a defect, except proven that it results out
20 * of said person's immediate fault when using the work as intended.
23 * $ gcc -D_ASM_SOURCE -DBOOTMANAGER -D__BOOT_VER=\"0AA6\" -c mbr.S
24 * $ ld -nostdlib -Ttext 0x0600 -N -Bstatic -e _start -o mbrmgr.elf mbr.o
25 * $ objcopy -O binary mbrmgr.elf mbrmgr
28 .intel_syntax noprefix
42 mov cx,0x0200 /* size of one sector */
43 push si /* load / return address */
53 /* Lem<nn> are patch points */
58 Lem03: .ascii "00 4=hd0 5=fd0 Enter=default (timeout)\r\n"
63 Lfmsg: .asciz "bad magic\r\n"
66 /* okay boot message */
70 /* output NUL-terminated string from ds:si */
81 /* patch the partition type values into the message */
83 mov al,ds:[Lptab + 0x04]
86 mov al,ds:[Lptab + 0x14]
89 mov al,ds:[Lptab + 0x24]
92 mov al,ds:[Lptab + 0x34]
98 /* fake invalid partition entry for MBR/FDD boot */
99 mov di,offset Lptab + 0x40
108 /* force bad magic if sector load fails */
112 #if 0 /* see above, eax is already zero here */
113 xor ax,ax /* read CMOS clock ticks since midnight */
115 int 0x1A /* 32-bit result in cx:dx */
116 mov di,cx /* save it in edi for later */
119 add edi,183 /* 10 seconds, rounded up one tick */
120 Lptmo = . - 4 /* offset of the "183" above */
122 /* input loop with timeout */
124 int 0x16 /* check if a key was pressed */
131 or al,al /* past midnight? */
133 add ecx,1573040 /* should be 1572480, but according to RBIL… */
134 Lsday: cmp ecx,edi /* time is over? */
136 ja Lfkey /* yep, fake a return keypress */
139 /* input loop without timeout */
141 int 0x16 /* check if a key was pressed */
145 #endif /* BOOTMANAGER */
146 Lfkey: mov bx,offset Lptab
147 mov dl,0x80 /* drive to load from */
152 je Lscan /* CR / Return / Enter */
153 jb Lgkey /* invalid input */
155 jb Lgkey /* invalid input */
156 cmp al,5 /* floppy */
157 ja Lgkey /* invalid input */
158 jb LdoHD /* hard disc */
159 mov dl,0 /* drive to load from */
162 LdoHD: shl al,4 /* 0..4 where 4 is virtual partition */
163 add bl,al /* we boot this one */
166 /* scan the partition table for an active partition */
167 Lscan: mov al,[dpart] /* try hard-coded by fdisk(8) 'fdef' first */
170 Lspar: cmp byte ptr [bx],0x80
171 je Lboot /* found an active partition */
173 cmp bl,0xFE /* BX = 0x07FE = Lptab + 0x40 */
175 /* boot the virtual partition #4 (MBR) */
177 Lboot: /* try to boot, first LBA (we're on a HDD) then CHS */
178 mov [bx],dl /* drive (0x80 or 0x00) */
179 mov si,offset Lpblk /* LBA parameter block */
182 stosw /* size of LBA parameter block */
184 stosw /* number of sectors to load */
188 stosw /* load address offset */
190 stosw /* load address segment */
192 stosd /* LBA offset of start sector (low 32 bit) */
194 stosw /* high 32 bit */
195 stosw /* high 32 bit */
196 mov ah,0x42 /* LBA extended read */
197 call Lload /* try to boot that */
198 pop si /* edited partition table entry */
199 pop bx /* load offset (ES=CS=SS=DS=0000h) */
202 mov ax,0x0201 /* CHS read 0x01 sectors */
203 mov cx,[si+2] /* cylinder; sector number */
204 mov dx,[si] /* head; drive number */
216 Lload: mov bp,4 /* number of tries */
220 jc Lldre /* error, try again */
221 cmp word ptr ds:[Lbmag],0xAA55
222 jne Lldre /* bad magic, try again */
224 mov ax,0x0E0D /* output a carriage return */
231 pop si /* Lload return address */
232 pop si /* partition table entry */
234 /* DS:SI point to partition table entry, DL is set */
236 ret /* jump to 0000:7C00h */
238 xor ax,ax /* reset drive */
241 dec bp /* another try left? */
263 dpart: .byte 0xFF /* default partition [0..3] or none */
266 Lntid: .long 0 /* Microsoft® NT® volume identifier */
270 /* partition table */
271 Lptab: .long 0, 0, 0, 0 /* partition entry #0 */
272 .long 0, 0, 0, 0 /* partition entry #1 */
273 .long 0, 0, 0, 0 /* partition entry #2 */
274 /* partition entry #3 + pre-installation hint */
279 Lhint: .word (Lptmo - _start)
286 Lpmag: .word 0xAA55 /* BIOS boot magic */
292 Lbmag = Lbadr + 0x01FE