windows-nt/Source/XPSP1/NT/base/boot/bootcode/etfs/i386/bootfix.asm
2020-09-26 16:20:57 +08:00

312 lines
6.4 KiB
NASM

;++
;
;Copyright (c) 1995 Microsoft Corporation
;
;Module Name:
;
; bootfix.asm
;
;Abstract:
;
; The code in this "image" is responsible for checking if is appropriate
; for us to boot from CD. We want to boot from CD whenever we don't have
; a valid active partition or when the user pressed CTRL key during the
; boot process.
;
;Author:
;
; Calin Negreanu (calinn) 25-May-1998
;
;Environment:
;
; Image has been loaded at 2000:0000 by ETFS boot code.
; Real mode
; ISO 9660 El Torito no-emulation CD-ROM Boot support
; DL = El Torito drive number we booted from
;
;Revision History:
;
; Calin Negreanu (calinn) 18-Feb-1999
;
;--
page ,132
title bootfix
name bootfix
.8086
CODE SEGMENT
ASSUME CS:CODE,DS:CODE,SS:NOTHING,ES:NOTHING
ORG 0000H
_BootFix label byte
MaxCodeSize EQU 1024
Part_Active EQU 0
Part_Type EQU 4
Data_PartType EQU 0 ;address of partition type inside BootData structure
LoadSeg EQU 3000H ;we load MBR here
SectSize EQU 512
EntriesOnMbr EQU 4
MbrDataOff EQU 01BEH
VolbootOrg EQU 7c00h
JMPFAR MACRO DestOfs,DestSeg
db 0eah
dw OFFSET DestOfs
dw DestSeg
endm
START:
;
; we already have a valid stack set by the original ETFS boot sector
; we only need to set ds and es
;
push ds
push es
mov ax,cs
mov ds,ax
mov es,ax
;
; read partition table from hdd 80h at LoadSeg:0000
;
push es
mov ax,LoadSeg
mov es,ax
mov bx,0000h
mov ax,0201h ;read function, one sector
mov cx,0001h
mov dx,0080h
int 13h
jnc MbrOk
;
; there was an error, boot from CD
;
pop es
jmp CdBoot
MbrOk:
pop es
;
; now it's the time to loop and find the active partition table
;
push es
mov ax,LoadSeg
mov es,ax
mov cx,EntriesOnMbr ;number of partitions in partition table
mov bp,MbrDataOff ;01beh
LoopActive:
;
; 00 - inactive, 80h active, others-invalid
;
cmp BYTE PTR es:[bp].Part_Active,00H
jl CheckInactive
jne BadMbr
add bp,16
loop LoopActive
;
; no active partition found. boot from CD
;
pop es
jmp CdBoot
CheckInactive:
push bp
InactiveLoop:
add bp,16
dec cx
jz ActiveFound
cmp BYTE PTR es:[bp].Part_Active,00H
je InactiveLoop
pop bp
BadMbr:
;
; bad mbr was found. boot from CD
;
pop es
jmp CdBoot
ActiveFound:
pop bp
pop es
;
; let's see if we can display UI (that is if MsgPressKey is not empty
;
mov si, OFFSET MsgPressKey
lodsb
mov UIAllowed, al
push si
mov si,OFFSET MsgPressKey
call PrintMsg
pop si
;
; read all available keys from the queue (prevents us from booting from CD when there
; is some garbage there
;
mov cx, 80h
FlushQueue:
mov ah, 01h
int 16h
jz QueueEmpty
mov ah, 00h
int 16h
loop FlushQueue
QueueEmpty:
;
; hook int08
;
cli
push es
xor ax,ax
mov es,ax
mov bx,08h * 4
mov ax,es:[bx]
mov WORD PTR [OldInt08 ], ax
mov ax,es:[bx+2]
mov WORD PTR [OldInt08+2], ax
mov WORD PTR es:[bx],OFFSET NewInt08
mov WORD PTR es:[bx+2],cs
pop es
sti
;
; loop until the delay ticks is 0. Check for a key pressed (if UI), or for CTRL pressed (if no UI)
;
CheckKey:
cmp UIAllowed, 0
je CheckCTRL
mov ah, 01h
int 16h
jnz KeyPressed
CheckCTRL:
mov ah,02h
int 16h
and al,00000100b
jnz KeyPressed
NotPressed:
cmp DotTicks, 0
jg AddDot
push si
mov si,OFFSET MsgDot
call PrintMsg
pop si
mov DotTicks, 18
AddDot:
cmp DelayTicks, 0
jne CheckKey
call UnhookInt08
jmp BootFromHD
UnhookInt08:
cli
push es
xor ax,ax
mov es,ax
mov bx,08h * 4
mov ax,WORD PTR [OldInt08]
mov es:[bx],ax
mov ax,WORD PTR [OldInt08+2]
mov es:[bx+2],ax
pop es
sti
ret
KeyPressed:
call UnhookInt08
jmp CdBoot
BootFromHD:
;
; let's move the mbr code to 0000:7c00 and jump there
;
mov ax,LoadSeg
mov ds,ax
xor ax,ax
mov es,ax
xor si,si
mov di,VolBootOrg
mov cx,SectSize
cld
rep movsb
mov dl,80h
JMPFAR VolbootOrg,0000H
CdBoot:
;
; return to caller code
;
pop es
pop ds
retf
NewInt08:
pushf
cli
cmp WORD PTR cs:[DelayTicks], 0
je default08
dec WORD PTR cs:[DotTicks]
dec WORD PTR cs:[DelayTicks]
default08:
popf
push WORD PTR cs:[OldInt08+2]
push WORD PTR cs:[OldInt08]
retf
;
;EXPECTS DS:SI - MESSAGE ADDR
;
PrintMsg proc near
push ax
push bx
cmp UIAllowed, 0
je PrintMsgEnd
PrintMsgLoop:
lodsb
cmp al,0
je PrintMsgEnd
mov ah,0eh
mov bx,0007h
int 10h
jmp PrintMsgLoop
PrintMsgEnd:
pop bx
pop ax
ret
PrintMsg endp
include bootfix.inc ; message text
UIAllowed db 0
MsgDot db "."
db 0
OldInt08 dd ?
DelayTicks dw 4*18+1 ; 4 seconds
DotTicks dw 18
.errnz ($-_BootFix) GT (MaxCodeSize - 2) ;FATAL: bootfix code is too large
org MaxCodeSize - 2
db 55h,0aah
CODE ENDS
END START