X-Git-Url: https://git.grml.org/?p=grml2usb.git;a=blobdiff_plain;f=mbr%2Fmbr.S;fp=mbr%2Fmbr.S;h=fc0400bb3e7a9119ec68cbdf70328c600536cf37;hp=0000000000000000000000000000000000000000;hb=b85e41124e1845c604af5e619b70e1e5c8edcdce;hpb=c5336118ff9281c2c23b77b1e9bcfe3ebe45e864 diff --git a/mbr/mbr.S b/mbr/mbr.S new file mode 100644 index 0000000..fc0400b --- /dev/null +++ b/mbr/mbr.S @@ -0,0 +1,292 @@ +/* $MirOS: src/sys/arch/i386/stand/mbr/mbr.S,v 1.12 2009/01/31 23:39:55 tg Exp $ */ + +/*- + * Copyright (c) 2009 + * Thorsten Glaser + * + * Provided that these terms and disclaimer and all copyright notices + * are retained or reproduced in an accompanying document, permission + * is granted to deal in this work without restriction, including un- + * limited rights to use, publicly perform, distribute, sell, modify, + * merge, give away, or sublicence. + * + * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to + * the utmost extent permitted by applicable law, neither express nor + * implied; without malicious intent or gross negligence. In no event + * may a licensor, author or contributor be held liable for indirect, + * direct, other damage, loss, or other issues arising in any way out + * of dealing in the work, even if advised of the possibility of such + * damage or existence of a defect, except proven that it results out + * of said person's immediate fault when using the work as intended. + *- + * Compile commands: + * $ gcc -D_ASM_SOURCE -DBOOTMANAGER -D__BOOT_VER=\"0AA6\" -c mbr.S + * $ ld -nostdlib -Ttext 0x0600 -N -Bstatic -e _start -o mbrmgr.elf mbr.o + * $ objcopy -O binary mbrmgr.elf mbrmgr + */ + + .intel_syntax noprefix + .code16 + .text + + .globl _start +_start: xor eax,eax + mov ss,ax + mov sp,offset Lstack + push eax + popfd + mov ds,ax + mov es,ax + mov si,offset Lbadr + mov di,offset _start + mov cx,0x0200 /* size of one sector */ + push si /* load / return address */ + push ax + push offset Lmain + rep movsb + lret + + /* entry message */ +Lemsg: .ascii "Mir-" + .ascii __BOOT_VER +#ifdef BOOTMANAGER + /* Lem are patch points */ + .ascii ": 0=" +Lem00: .ascii "00 1=" +Lem01: .ascii "00 2=" +Lem02: .ascii "00 3=" +Lem03: .ascii "00 4=hd0 5=fd0 Enter=default (timeout)\r\n" +#endif + .asciz ">" + + /* failure message */ +Lfmsg: .asciz "bad magic\r\n" + +#if 1 + /* okay boot message */ +Lbmsg: .asciz " OK\r" +#endif + + /* output NUL-terminated string from ds:si */ +Lotxt0: mov ah,0x0E + mov bx,7 + int 0x10 +Lotxt: lodsb + or al,al + jnz Lotxt0 + ret + +Lmain: sti +#ifdef BOOTMANAGER + /* patch the partition type values into the message */ + mov di,offset Lem00 + mov al,ds:[Lptab + 0x04] + call LpBY + mov di,offset Lem01 + mov al,ds:[Lptab + 0x14] + call LpBY + mov di,offset Lem02 + mov al,ds:[Lptab + 0x24] + call LpBY + mov di,offset Lem03 + mov al,ds:[Lptab + 0x34] + call LpBY + mov si,offset Lemsg + call Lotxt +#endif + + /* fake invalid partition entry for MBR/FDD boot */ + mov di,offset Lptab + 0x40 + xor eax,eax + stosw + inc ax + stosw + dec ax + stosd + stosd + + /* force bad magic if sector load fails */ + mov ds:[Lbmag],al + +#ifdef BOOTMANAGER +#if 0 /* see above, eax is already zero here */ + xor ax,ax /* read CMOS clock ticks since midnight */ +#endif + int 0x1A /* 32-bit result in cx:dx */ + mov di,cx /* save it in edi for later */ + shl edi,16 + mov di,dx + add edi,183 /* 10 seconds, rounded up one tick */ + Lptmo = . - 4 /* offset of the "183" above */ + + /* input loop with timeout */ +Lwkey: mov ah,1 + int 0x16 /* check if a key was pressed */ + jnz Lgkey /* yeap */ + /* delay loop */ + xor ax,ax + int 0x1A + shl ecx,16 + mov cx,dx + or al,al /* past midnight? */ + jz Lsday /* no */ + add ecx,1573040 /* should be 1572480, but according to RBIL… */ +Lsday: cmp ecx,edi /* time is over? */ + mov al,13 + ja Lfkey /* yep, fake a return keypress */ + jmp Lwkey + + /* input loop without timeout */ +Lgkey: mov ah,1 + int 0x16 /* check if a key was pressed */ + jz Lgkey + mov ah,0 + int 0x16 +#endif /* BOOTMANAGER */ +Lfkey: mov bx,offset Lptab + mov dl,0x80 /* drive to load from */ +#ifndef BOOTMANAGER + jmp Lscan +#else + sub al,13 + je Lscan /* CR / Return / Enter */ + jb Lgkey /* invalid input */ + sub al,('0' - 13) + jb Lgkey /* invalid input */ + cmp al,5 /* floppy */ + ja Lgkey /* invalid input */ + jb LdoHD /* hard disc */ + mov dl,0 /* drive to load from */ + dec ax /* 5 -> 4 */ +#endif +LdoHD: shl al,4 /* 0..4 where 4 is virtual partition */ + add bl,al /* we boot this one */ + jmp Lboot + + /* scan the partition table for an active partition */ +Lscan: mov al,[dpart] /* try hard-coded by fdisk(8) 'fdef' first */ + cmp al,3 + jbe LdoHD +Lspar: cmp byte ptr [bx],0x80 + je Lboot /* found an active partition */ + add bl,0x10 + cmp bl,0xFE /* BX = 0x07FE = Lptab + 0x40 */ + jb Lspar + /* boot the virtual partition #4 (MBR) */ + +Lboot: /* try to boot, first LBA (we're on a HDD) then CHS */ + mov [bx],dl /* drive (0x80 or 0x00) */ + mov si,offset Lpblk /* LBA parameter block */ + mov di,si + mov ax,0x0010 + stosw /* size of LBA parameter block */ + mov al,1 + stosw /* number of sectors to load */ + pop ax + push ax + push bx + stosw /* load address offset */ + xor ax,ax + stosw /* load address segment */ + mov eax,[bx+8] + stosd /* LBA offset of start sector (low 32 bit) */ + xor ax,ax + stosw /* high 32 bit */ + stosw /* high 32 bit */ + mov ah,0x42 /* LBA extended read */ + call Lload /* try to boot that */ + pop si /* edited partition table entry */ + pop bx /* load offset (ES=CS=SS=DS=0000h) */ + push bx + push si + mov ax,0x0201 /* CHS read 0x01 sectors */ + mov cx,[si+2] /* cylinder; sector number */ + mov dx,[si] /* head; drive number */ + call Lload + mov si,offset Lfmsg + call Lotxt +#if 0 +Lfail: jmp Lfail +#else + xor ax,ax + int 0x16 + ljmp 0xF000,0xFFF0 +#endif + +Lload: mov bp,4 /* number of tries */ +Lldlp: pusha + int 0x13 + popa + jc Lldre /* error, try again */ + cmp word ptr ds:[Lbmag],0xAA55 + jne Lldre /* bad magic, try again */ +#if 0 + mov ax,0x0E0D /* output a carriage return */ + xor bx,bx + int 0x10 +#else + mov si,offset Lbmsg + call Lotxt +#endif + pop si /* Lload return address */ + pop si /* partition table entry */ + mov dl,[si] + /* DS:SI point to partition table entry, DL is set */ + cli /* be nice :) */ + ret /* jump to 0000:7C00h */ +Lldre: pusha + xor ax,ax /* reset drive */ + int 0x13 + popa + dec bp /* another try left? */ + jnz Lldlp + ret + +#ifdef BOOTMANAGER +LpBY: mov ah,al + shr al,4 + and ah,0x0F + add ax,0x3030 + cmp al,0x39 + jbe LpBY1 + add al,7 +LpBY1: cmp ah,0x39 + jbe LpBY2 + add ah,7 +LpBY2: stosw + ret +#endif + + . = _start + 0x01B7 + .globl dpart + .size dpart,1 +dpart: .byte 0xFF /* default partition [0..3] or none */ + + . = _start + 0x01B8 +Lntid: .long 0 /* Microsoft® NT® volume identifier */ +Lpad1: .byte 0, 0 + + . = _start + 0x01BE + /* partition table */ +Lptab: .long 0, 0, 0, 0 /* partition entry #0 */ + .long 0, 0, 0, 0 /* partition entry #1 */ + .long 0, 0, 0, 0 /* partition entry #2 */ + /* partition entry #3 + pre-installation hint */ + .word 0, 0, 0, 0, 0 + . = _start + 0x01F8 + .size Lhint,2 +#ifdef BOOTMANAGER +Lhint: .word (Lptmo - _start) +#else +Lhint: .word 0xFFFF +#endif +Lpad2: .word 0, 0 + + . = _start + 0x01FE +Lpmag: .word 0xAA55 /* BIOS boot magic */ + + Lstack = 0x4000 + Lpblk = 0x5000 + + Lbadr = 0x7C00 + Lbmag = Lbadr + 0x01FE