; SMBNEW.ASM ; modified version of ; smbmbr.asm Small Multi-Boot Master-Boot-Record ; see http://www.execpc.com/~geezer/johnfine/ ; New provisional personal version on 3/3/2002 ; I have only changed some lines in the original John S. Fine's version ; ; Modifications to the version 3.0 ( ** indicate the main modifications) : ; Can boot on a partition above the 8 Go limit (use int 13h extended 42 read) ; Is compatible with Windows XP (disk signature in the MBR) ; ; Only four choices: ; Type 1 to boot on the first partition, ; Type 2 to boot on the second partition, ; Type 3 to boot on the third partition ; Type 4 to boot on the fourth partition ; If no entry : boot on the last partition used ; ; Cannot boot on extended partition ; The boot disk must be chosen in the bios ; Before to boot on a floppy (or CD ROM), boot before on the disk partition which must be active ; (even if not yet bootable : it is only to activate this partition in the MBR) ; At boot are displayed: ; -the last partition used (To boot on another partition enter the partition number) ; -"SMBMBR" (If you have several disks it is recommended to replace "SMBMBR" ; by the name of the disk. This can be done directly in the file smbnew.bin ; without compiling and linking) ; -a beep is emitted to ask for a key ; -the partition effectively booted (or error messages) ; Error messages: ; "1 2 3 or 4 only " : you have entered a key which is not 1 2 3 or 4 try again ; "no partition " the key is accepted but no partition exists on the disk for this key, try again ; "disk error" : cannot read or write the disk ; other messages are from the bios or from the booted partition. ; ; smbnew.bin compiled with nasm16 version 0.98 and linked with JLOC version 0.6 ; Georges Jullien ___gljullien@numericable.fr___ ;_____________________________________________________________________________ ; Original comments for the version 3.0 by John S. Fine : ;_________quote begin___________ ; smbmbr.asm Small Multi-Boot Master-Boot-Record ; Version 3.0, Dec 17, 1997 ; Sample code ; by John S. Fine johnfine@erols.com ; I do not place any restrictions on your use of this source code ; I do not provide any warranty of the correctness of this source code ; ; See detailed documentation in smbmbr.txt ; See memory layout in smbmbr.lnk ; ; To build: ; ; NASM -f obj smbmbr.asm ; JLOC smbmbr.lnk smbmbr.bin smbmbr.map ; ; (I used NASM version 0.97 and JLOC version 0.3 in testing) ;___________quote end______________________________________ struc PT_ENT ;Partition table entry BootFlag resb 1 BeginHead resb 1 BeginSector resb 1 BeginCyl resb 1 SystemID resb 1 EndHead resb 1 EndSector resb 1 EndCyl resb 1 RelSectorLow resw 1 RelSectorHigh resw 1 NumSectorsLow resw 1 NumSectorsHigh resw 1 endstruc struc CHOICE ;Choice table entry drive resb 1 letter resb 1 endstruc extern reloc_start ;.LNK file defines relocation address (0:7A00) tick equ 0x46C ;Location where the BIOS keeps the tick count SEGMENT START USE16 ;At 0:7C00 start: xor cx, cx ;Set segment registers to zero mov es, cx mov ds, cx mov ss, cx mov sp, reloc_start ;Top of stack mov di, sp ; is bottom of relocation point mov si, start cld mov ch, 1 ;cx = 256 rep movsw ;Copy self to 0:7A00 jmp continue ;near JMP to copy of self SEGMENT MAIN USE16 ;At 0:7A00 + START.length continue: sti mov si, message ;Main message mov ax, 0x0E0D ;Start with CR ** mov bx, 7 ;Normal display attribute int 10h ;Display one character ** mov al, [last_boot] ;display last boot ** int 10h ;Display one character again: mov ax, 0x0E0D ;Start with CR disp: int 10h ;Display one character lodsb ;Get next char of message test al, al ;Null terminated jnz disp mov bx, 182*5/10 ;Allow up to five seconds add bx, [tick] ; beyond current tick count keywait: mov ah, 1 ;Test for keystroke int 16h jnz getkey ;Got one cmp bx, [tick] ;Check current tick count jns keywait ;Keep waiting mov al, [last_boot] ;Timeout: Get default jmp short gotkey getkey: mov ah, 0 ;Read the key int 16h gotkey: cmp al, 'a' ;Convert to upper case jb .10 sub al, 'a'-'A' .10: mov ah, 0x0E ; ** mov bx, 7 ; ** int 10h ;display the key ** mov di, PartitionTable-0x0A ;Start of partition table-(dummy length=10) ** mov si, di ; is also end of choice table .20: sub si, byte CHOICE_size ;Loop through choice table cmp [si+letter], al ;Found it? je found ;Yes cmp byte [si+letter], 0 ;Done whole table? jne .20 ;No erreur: mov si, wrong ;Error message jmp short again ;Try again nopar: mov si,nopart ;no partition for the key ** jmp short again ; ** found: mov dl, [si+drive] ;Get drive or partition Number mov ch, 0 ;Cylinder 0 mov dh, 0 ;Head 0 cmp dl, 0xFC ;Is it a partition code? jb erreur ;no 1 no 2 no 3 no 4 ** mov cl, al ;Save choice ** mov ax, PT_ENT_size ;Compute location of partition entry mul dx add ax, PartitionTable - (0xFC * PT_ENT_size) mov di,ax ; ** cmp byte [di+0x04],0 ;is there a partition? ** je nopar ;partition does not exist ** mov [last_boot], cl ;Save choice as new default mov cl, 1 ;Sector 1 ** mov di, PartitionTable ;Start of partition table mov [di], ch ;Mark all four partitions nonactive mov [di+PT_ENT_size], ch mov [di+2*PT_ENT_size], ch mov [di+3*PT_ENT_size], ch mov [N_parti_loc], ax ;save boot partition location ** xchg ax, di ;DI = selected entry mov dl, 0x80 ;hard-drive-0 / head 0 mov dh, 0 mov [di], dl ;Mark it active mov bx, reloc_start ;0:7A00 mov ch, 0 mov cl, 1 ;Sector 1 / Cylinder 0 ** mov ax, 0x301 ;Command to write one sector int 13h ;Rewrite boot block jc fail ;Failed mov ax, [N_parti_loc] ; ** xchg ax, di ; ** mov cx, [di+RelSectorHigh] ;Sector ** mov ax, [di+RelSectorLow] ;Sector ** mov dx, [di+BootFlag] ;Drive / Head ** go: mov si, 3 ;Three tries try: mov bx, start ;Read it into 0:7C00 push si ; ** xor si,si ; ** push si ;0 ** push si ;0 ** push cx ;sector high ** push ax ;sector low ** push es ;segment memory block ** push bx ;offset memory block 7C00 ** mov si,1 ; transfert one sector ** push si ; ** mov si,0x10 ; ** push si ; ** mov si,sp ; ** pusha ; ** mov ax, 0x4200 ;Command to read one sector (extended) ** int 13h ; ** popa ; ** lea sp,[si+0x10] ;16 octets to compensate 8 push ** pop si ; ** jnc ok ;Success dec si ;retry count jnz try fail: mov si, failed ;Error message jmp again ; ok: mov bx, 182*1/10 ;Allow up to 1 seconds ** add bx, [tick] ; beyond current tick count waitkey: cmp bx, [tick] ;time left to press key ** jns waitkey ;during system boot (F8..) ** jmp start ;Start partition boot block last_boot db '1' ;Default for next boot N_parti_loc dw 0x7BBE ;Default for partition table location ** failed db 10,'Disk error',13 wrong db 10,'1 2 3 or 4 only ',13,10,0 nopart db 10,'no partition ',13,10,0 ; ** SEGMENT FINAL USE16 ;.LNK file aligns this to end of sector ;Choice table is accessed backwards from the (start of the partition table-10) ** ; (to leave place for XP disk signature) ** ;You should edit the choice table to represent the choices that make ;sense on your system. The first byte of each choice represents the ** ;action: ; 0xFC - 0xFF -> First through fourth entry in partition table. ; 0 -> A: ; 1 -> B: ; 0x81 -> Hard drive 1 ; ;Note that fdisk generally doesn't number partitions according to their ;position in the partition table, so you need to find out some other ;way. ; ;The second byte in each choice entry is the key used to select it. ;_____________________________________________________________________________ message db 10,7,'SMBMBR ',10,13,0 ;7 = beep replace "SMBMBR " by your disk name ** db 'A' ;not used ** db 0 ;not used ** db 0,0 ;not used ** db 0 ;Flag (backwards) end of table db 0xFC, '1' ;boot on first partition db 0xFD, '2' ; second db 0xFE, '3' ; third db 0xFF, '4' ; fourth db 0,0,0,0,0 ; dummy zone for XP length=10 (copy only ** db 0,0,0,0,0 ; 0 to 1B3 on MBR to avoid XP disk ** ; signature and partitions) ; : partcopy xxx.bin 0 1b4 -h0 PartitionTable resb 4*PT_ENT_size dw 0AA55h