; BOOTEASY, version 1.7.1 ; Developed from BOOTANY, with many improvements. ; The main idea was to simplify the installation ; procedure and to remove unnecessary partition type switching. ; Second hard disk switching added. ; Author: Serge Vakulenko, F1_scancode equ 59 ; scancode of 'F1' key Enter_scancode equ 28 ; scancode of 'Enter' key Timeout equ 5 ; wait up to 5 seconds for reply StdBase equ 7c00h ; address where DOS loads us Base equ 600h ; address where we rewrite itself Partab equ 1beh ; partition table offset NumDisks equ 475h ; number of disk drives (BIOS data area) BootIndicator equ 0 ; partition record: boot indicator BeginHead equ 1 ; first partition sector: head number BeginSector equ 2 ; sector and cylinder SystemId equ 4 ; system type ; ------------------------------- dummy segment at 0 assume cs:dummy org Base ; address where we rewrite itself BaseEntry: org StdBase ; address where DOS loads us StdBaseEntry: dummy ends ; ------------------------------- code segment assume cs:code, ds:code, es:code, ss:code org 0 Boot: ; ; Setup the stack and segment registers ; xor AX,AX ; Zero register mov ES,AX ; ES := 0 mov DS,AX ; DS := 0 mov SS,AX ; disables intrs up to the next command mov SP,StdBase ; SP at 7c00 ; ; DOS loads this pgm at 0000:7C00. Any boot routine ; we call also expects to execute there so the first ; exercise is to move this code somewhere else. ; cld ; Clear direction mov SI,SP ; Copy from 7c00h... mov DI,Base ; ...to 600h... mov CX,256 ; ...512 bytes, or 256 words repne movsw ; Move itself to new location jmp FAR PTR BaseEntry+(Entry-Boot) ; ------------------------------- ; ; A valid function key was depressed (or defaulted) ; Attempt to boot the corresponding partition. ; Load: mov DX,BP ; restore drive number pop AX ; key '1'..'5' mov Base+default,AL ; save function key number cmp AL,'5' je SwitchDrive mov AH,16 mul AH ; AX = key * 16 add AX,Base+Partab-'1'*16 ; subtract '1' mov SI,AX ; ; Check if the partition is empty. ; cmp BYTE PTR SystemId[SI],0 je Menu ; Empty - display menu again cmp BYTE PTR SystemId[SI],05h je Menu ; DOS extended type - never load mov BYTE PTR BootIndicator[SI],80h ; Mark partition as bootable call SaveBoot ; ; Read in and validate the partition's boot sector. ; mov DH,BeginHead[SI] ; head from partition table mov CX,BeginSector[SI] jmp loadboot ; ; Read in the boot sector from second disk. ; SwitchDrive: call SaveBoot mov CX,0001h ; cylinder 0, sector 1 xor DL,CL ; (DL ^= 1) switch drive loadboot: mov BX,StdBase ; ES already == 0 mov AX,0201h ; function, # of sectors int 13h ; read system boot record jc Menu ; exit if error cmp WORD PTR 510[BX],0aa55h ; test signature jne Menu ; reprompt if invalid ; ; Jump to secondary boot. ; DL now contains boot disk number (80h or 81h); ; ES:SI contains the address of partition table ; entry to boot. ; jmp FAR PTR StdBaseEntry ; ------------------------------- ; ; The main entry to the boot ; Entry: cmp DL,81h ; DL contains current drive number je driveok ; is it valid? mov DL,80h ; no - use the default value driveok: mov BP,DX ; save the drive number inc DX ; 80h -> 81h, 81h -> 82h xor DL,80h+'3' ; 80h -> '2', 81h -> '1' mov Base+diskNum,DL ; ; Display the menu ; Menu: mov DI,Base+Partab ; set index mov CX,4 ; set loop count mov Base+key,'1' ; set key number in message xor DH,DH ; count of partitions menuloop: mov BYTE PTR BootIndicator[DI],CH ; Clear active flag mov AL,SystemId[DI] cmp AL,0 ; unused partition? je next cmp AL,5 ; extended DOS partition? je next cmp AL,0Fh ; extended LBA partition? je next inc DH ; increment partition count lea SI,Base+FkeyMsg ; get msg addr call Output lea SI,Base+nameTable-2 nameloop: inc SI inc SI mov BX,[SI] or BH,BH je endnameloop xor BH,SystemId[DI] jne nameloop endnameloop: lea SI,Base+namtab[BX] call Output next: add DI,16 ; next entry address inc Base+key loop menuloop cmp BYTE PTR DS:NumDisks,2 ; is the second disk present? je have2disks ; have disk 2 lea SI,Base+defaultMsg ; prepare 'Default' message or DH,DH ; no disk 2; do we have valid partitions? jne prompt ; several partitions, wait for reply int 18h ; no partitions, load ROM basic jmp Menu ; repeat, if no ROM basic have2disks: lea SI,Base+FkeyMsg ; print 'F5' call Output ; now SI points to "disk 2\nDefault..." prompt: call Output ; print 'Default' message reprompt: xor AH,AH ; GetTickCount int 1ah ; BiosTimerService mov BX,DX ; lo-order tick count add BX,192*Timeout/10 ; timeout value in ticks ; ; Get the reply ; waitkey: mov AH,1 ; keyboard status int 16h ; keybd bios service mov AH,0 ; GetTickCount jnz reply ; jump if reply int 1ah ; BiosTimerService cmp DX,BX ; check for timeout jb waitkey ; wait for scancode loaddefault: mov AL,Base+default ; prior system id jmp testkey ; boot default system reply: int 16h ; AH=0, keybd bios service mov AL,AH ; Copy to AL cmp AL,Enter_scancode je loaddefault add AL,'1'-F1_scancode ; Turn into index testkey: cmp AL,'1' ; max Function key jb reprompt ; Invalid code check cmp AL,'5' ; max Function key jnbe reprompt ; if not F1..F5, branch push AX lea SI,Base+newLine ; new line lea BX,Base+Load push BX ; call Output; jmp Load ; ------------------------------- ; ; Output line [SI] to screen, end of line marked with 80h ; Output: cld ; reset direction flag lodsb ; load argument from string push AX ; save byte and AL,7fh ; insure valid character mov AH,14 ; write tty int 10h ; bios video service pop AX ; restore byte test AL,80h ; test for end of string jz Output ; do until end of string ret ; return to caller ; ------------------------------- ; ; Save boot block default partition settings ; SaveBoot: push SI mov AX,0301h ; write sector mov BX,Base ; ES already == 0 mov CX,0001h ; cylinder 0, sector 1 xor DH,DH ; drive #, head 0 int 13h ; replace boot record pop SI mov Base+default,'?' ; reset default ret ; ------------------------------- newLine db 13,10+80h FkeyMsg db 13,10,'F' key db '0 . . .',' '+80h,'disk ' diskNum db '1' defaultMsg db 13,10,10,'Default: F' default db '?',' '+80h nameTable db dos -namtab, 1 db dos -namtab, 4 db dos -namtab, 6 db win -namtab, 7 db win -namtab, 0Bh db win -namtab, 0Ch db plan -namtab, 39h db unix -namtab, 63h db linux -namtab, 81h db linux -namtab, 82h db linux -namtab, 83h db bsdi -namtab, 9fh db freebsd -namtab, 0A5h db openbsd -namtab, 0A6h db netbsd -namtab, 0A9h db noname -namtab, 0 namtab: dos db 'DO','S'+80h win db 'Window','s'+80h plan db 'Plan ','9'+80h unix db 'Uni','x'+80h linux db 'Linu','x'+80h bsdi db 'BSD','i'+80h freebsd db 'FreeBS','D'+80h openbsd db 'OpenBS','D'+80h netbsd db 'NetBS','D'+80h noname db '?','?'+80h used equ $ - Boot db (1beh - used + 1) dup (0) ; error if code too big db 63 dup (0) ; clear rest of record dw 0aa55h ; magic code ends end