1 /* $MirOS: src/sys/arch/i386/stand/mbr/mbr.S,v 1.13 2009/03/04 10:50:28 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
26 * $ gcc -D_ASM_SOURCE -DBOOT_QUIET -D__BOOT_VER=\"0AA6\" -c mbr.S
27 * $ ld -nostdlib -Ttext 0x0600 -N -Bstatic -e _start -o mbrldr.elf mbr.o
28 * $ objcopy -O binary mbrldr.elf mbrldr
31 .intel_syntax noprefix
45 mov cx,0x0200 /* size of one sector */
46 push si /* load / return address */
56 /* Lem<nn> are patch points */
61 Lem03: .ascii "00 4=hd0 5=fd0 Enter=default (timeout)\r\n"
66 Lfmsg: .asciz "bad magic\r\n"
69 /* okay boot message */
73 /* output NUL-terminated string from ds:si */
84 /* patch the partition type values into the message */
86 mov al,ds:[Lptab + 0x04]
89 mov al,ds:[Lptab + 0x14]
92 mov al,ds:[Lptab + 0x24]
95 mov al,ds:[Lptab + 0x34]
98 #if !defined(BOOT_QUIET) || defined(BOOTMANAGER)
103 /* fake invalid partition entry for MBR/FDD boot */
104 mov di,offset Lptab + 0x40
113 /* force bad magic if sector load fails */
117 #if 0 /* see above, eax is already zero here */
118 xor ax,ax /* read CMOS clock ticks since midnight */
120 int 0x1A /* 32-bit result in cx:dx */
121 mov di,cx /* save it in edi for later */
124 add edi,183 /* 10 seconds, rounded up one tick */
125 Lptmo = . - 4 /* offset of the "183" above */
127 /* input loop with timeout */
129 int 0x16 /* check if a key was pressed */
136 or al,al /* past midnight? */
138 add ecx,1573040 /* should be 1572480, but according to RBIL… */
139 Lsday: cmp ecx,edi /* time is over? */
141 ja Lfkey /* yep, fake a return keypress */
144 /* input loop without timeout */
146 int 0x16 /* check if a key was pressed */
150 #endif /* BOOTMANAGER */
151 Lfkey: mov bx,offset Lptab
152 mov dl,0x80 /* drive to load from */
157 je Lscan /* CR / Return / Enter */
158 jb Lgkey /* invalid input */
160 jb Lgkey /* invalid input */
161 cmp al,5 /* floppy */
162 ja Lgkey /* invalid input */
163 jb LdoHD /* hard disc */
164 mov dl,0 /* drive to load from */
167 LdoHD: shl al,4 /* 0..4 where 4 is virtual partition */
168 add bl,al /* we boot this one */
171 /* scan the partition table for an active partition */
172 Lscan: mov al,[dpart] /* try hard-coded by fdisk(8) 'fdef' first */
175 Lspar: cmp byte ptr [bx],0x80
176 je Lboot /* found an active partition */
178 cmp bl,0xFE /* BX = 0x07FE = Lptab + 0x40 */
180 /* boot the virtual partition #4 (MBR) */
182 Lboot: /* try to boot, first LBA (we're on a HDD) then CHS */
183 mov [bx],dl /* drive (0x80 or 0x00) */
184 mov si,offset Lpblk /* LBA parameter block */
187 stosw /* size of LBA parameter block */
189 stosw /* number of sectors to load */
193 stosw /* load address offset */
195 stosw /* load address segment */
197 stosd /* LBA offset of start sector (low 32 bit) */
199 stosw /* high 32 bit */
200 stosw /* high 32 bit */
201 mov ah,0x42 /* LBA extended read */
202 call Lload /* try to boot that */
203 pop si /* edited partition table entry */
204 pop bx /* load offset (ES=CS=SS=DS=0000h) */
207 mov ax,0x0201 /* CHS read 0x01 sectors */
208 mov cx,[si+2] /* cylinder; sector number */
209 mov dx,[si] /* head; drive number */
221 Lload: mov bp,4 /* number of tries */
225 jc Lldre /* error, try again */
226 cmp word ptr ds:[Lbmag],0xAA55
227 jne Lldre /* bad magic, try again */
229 mov ax,0x0E0D /* output a carriage return */
236 pop si /* Lload return address */
237 pop si /* partition table entry */
239 /* DS:SI point to partition table entry, DL is set */
241 ret /* jump to 0000:7C00h */
243 xor ax,ax /* reset drive */
246 dec bp /* another try left? */
268 dpart: .byte 0xFF /* default partition [0..3] or none */
271 Lntid: .long 0 /* Microsoft® NT® volume identifier */
275 /* partition table */
276 Lptab: .long 0, 0, 0, 0 /* partition entry #0 */
277 .long 0, 0, 0, 0 /* partition entry #1 */
278 .long 0, 0, 0, 0 /* partition entry #2 */
279 /* partition entry #3 + pre-installation hint */
284 Lhint: .word (Lptmo - _start)
291 Lpmag: .word 0xAA55 /* BIOS boot magic */
297 Lbmag = Lbadr + 0x01FE