435 lines
9.6 KiB
NASM
435 lines
9.6 KiB
NASM
|
;++
|
||
|
;
|
||
|
;Copyright (c) 1995 Microsoft Corporation
|
||
|
;
|
||
|
;Module Name:
|
||
|
;
|
||
|
; bioschk.asm
|
||
|
;
|
||
|
;Abstract:
|
||
|
;
|
||
|
; The code in this "image" is responsible for checking if is appropriate
|
||
|
; for us to start setupldr.bin. We consider this appropriate when we pass
|
||
|
; BIOS checkings. Setupldr.bin is binary appended at the end of this image.
|
||
|
;
|
||
|
;Author:
|
||
|
;
|
||
|
; Calin Negreanu (calinn) 16-Dec-1999
|
||
|
;
|
||
|
;Environment:
|
||
|
;
|
||
|
; Real mode
|
||
|
; Case 1:
|
||
|
; Complete image has been loaded at 2000:0000 by the boot code
|
||
|
; DL = meaningfull data
|
||
|
; Case 2:
|
||
|
; First 512 bytes of this image has been loaded at 2000:000 by the boot code
|
||
|
; BX = meaningfull data
|
||
|
; DL = meaningfull data
|
||
|
; DS:SI -> points to a structure containing meaningfull data
|
||
|
; DS:DI -> points to a structure containing meaningfull data
|
||
|
;
|
||
|
;Revision History:
|
||
|
;
|
||
|
;--
|
||
|
page ,132
|
||
|
title boot - BIOS check
|
||
|
name bioschk
|
||
|
|
||
|
.8086
|
||
|
|
||
|
CODE SEGMENT
|
||
|
ASSUME CS:CODE,DS:CODE,SS:NOTHING,ES:NOTHING
|
||
|
|
||
|
ORG 0000H
|
||
|
|
||
|
_BiosChk label byte
|
||
|
|
||
|
BiosChkDestSeg EQU 1000h
|
||
|
SetupLdrDestSeg EQU 2000h
|
||
|
MaxCodeSize EQU 0800h ;number of paragraphs (32k)
|
||
|
MaxSetupLdrSize EQU 4000h ;number of paragraphs (256k)
|
||
|
|
||
|
StackSeg EQU 1000h ;stack goes from here
|
||
|
|
||
|
MAXREAD EQU 10000h
|
||
|
MAXSECTORS EQU MAXREAD/0200h
|
||
|
|
||
|
DoubleWord struc
|
||
|
lsw dw ?
|
||
|
msw dw ?
|
||
|
DoubleWord ends
|
||
|
|
||
|
SHARED struc
|
||
|
ReadClusters dd ?
|
||
|
ReadSectors dd ?
|
||
|
SectorBase dd ?
|
||
|
SHARED ends
|
||
|
|
||
|
BPB struc
|
||
|
BytesPerSector dw ?
|
||
|
SectorsPerCluster db ?
|
||
|
ReservedSectors dw ?
|
||
|
Fats db ?
|
||
|
DirectoryEntries dw ?
|
||
|
Sectors dw ?
|
||
|
Media db ?
|
||
|
FatSectors dw ?
|
||
|
SectorsPerTrack dw ?
|
||
|
Heads dw ?
|
||
|
HiddenSectors dd ?
|
||
|
SectorsLong dd ?
|
||
|
BootDriveNumber db ?
|
||
|
BPB ends
|
||
|
|
||
|
JMPFAR MACRO DestOfs,DestSeg
|
||
|
db 0eah
|
||
|
dw OFFSET DestOfs
|
||
|
dw DestSeg
|
||
|
endm
|
||
|
|
||
|
START:
|
||
|
; If we boot from FAT drives, the next instruction is not executed.
|
||
|
jmp RealStart
|
||
|
|
||
|
FatBegin:
|
||
|
.386
|
||
|
;
|
||
|
; If we're here, we've booted off a FAT system and we must load the rest
|
||
|
; of the binary image at 2000:0200 (right behind this sector).
|
||
|
;
|
||
|
|
||
|
;
|
||
|
; Save away meaningfull data
|
||
|
;
|
||
|
push dx
|
||
|
push bx
|
||
|
|
||
|
.386
|
||
|
push 06000h
|
||
|
.8086
|
||
|
pop es
|
||
|
xor bx,bx
|
||
|
mov cx,ds:[si].ReservedSectors
|
||
|
mov ds:[di].SectorBase.msw,0
|
||
|
mov ds:[di].SectorBase.lsw,cx
|
||
|
|
||
|
mov ax,ds:[si].FatSectors
|
||
|
cmp ax,080h
|
||
|
jbe FatLt64k
|
||
|
push cx
|
||
|
mov ax,080h
|
||
|
call ds:[di].ReadSectors
|
||
|
pop cx
|
||
|
.386
|
||
|
push 07000h
|
||
|
.8086
|
||
|
pop es
|
||
|
xor bx,bx
|
||
|
mov ax,ds:[si].FatSectors
|
||
|
sub ax,080h
|
||
|
add cx,080h
|
||
|
mov ds:[di].SectorBase.lsw,cx
|
||
|
adc ds:[di].SectorBase.msw,0
|
||
|
FatLt64k:
|
||
|
call ds:[di].ReadSectors
|
||
|
pop dx
|
||
|
xor bx,bx
|
||
|
.386
|
||
|
mov ax,6000h
|
||
|
mov fs,ax
|
||
|
mov ax,7000h
|
||
|
mov gs,ax
|
||
|
.8086
|
||
|
push cs
|
||
|
pop es
|
||
|
mov ah,MAXSECTORS
|
||
|
FatLoop:
|
||
|
push dx
|
||
|
mov al,ds:[si].SectorsPerCluster
|
||
|
sub ah,ds:[si].SectorsPerCluster
|
||
|
cmp dx,0ffffh
|
||
|
jne Fat10
|
||
|
pop dx
|
||
|
pop dx
|
||
|
jmp RealStart
|
||
|
Fat10:
|
||
|
mov cx,dx
|
||
|
call NextFatEntry
|
||
|
inc cx
|
||
|
cmp dx,cx
|
||
|
jne LncLoad
|
||
|
cmp ah,0
|
||
|
jne Lnc20
|
||
|
mov ah,MAXSECTORS
|
||
|
jmp short LncLoad
|
||
|
Lnc20:
|
||
|
add al,ds:[si].SectorsPerCluster
|
||
|
sub ah,ds:[si].SectorsPerCluster
|
||
|
jmp short Fat10
|
||
|
LncLoad:
|
||
|
pop cx
|
||
|
push dx
|
||
|
mov dx,cx
|
||
|
mov cx,10
|
||
|
FatRetry:
|
||
|
push bx
|
||
|
push ax
|
||
|
push dx
|
||
|
push cx
|
||
|
call [di].ReadClusters
|
||
|
jnc ReadOk
|
||
|
mov ax,01h
|
||
|
mov al,ds:[si].BootDriveNumber
|
||
|
int 13h
|
||
|
xor ax,ax
|
||
|
mov al,ds:[si].BootDriveNumber
|
||
|
int 13h
|
||
|
xor ax,ax
|
||
|
FatPause:
|
||
|
dec ax
|
||
|
jnz FatPause
|
||
|
|
||
|
pop cx
|
||
|
pop dx
|
||
|
pop ax
|
||
|
pop bx
|
||
|
|
||
|
dec cx
|
||
|
jnz FatRetry
|
||
|
push cs
|
||
|
pop ds
|
||
|
mov si,offset FAT_ERROR
|
||
|
FatErrPrint:
|
||
|
lodsb
|
||
|
or al,al
|
||
|
jz FatErrDone
|
||
|
mov ah,14
|
||
|
mov bx,7
|
||
|
int 10h
|
||
|
jmp FatErrPrint
|
||
|
FatErrDone:
|
||
|
jmp $
|
||
|
|
||
|
FAT_ERROR db 13,10,"Disk I/O error",0dh,0ah,0
|
||
|
|
||
|
ReadOk:
|
||
|
pop cx
|
||
|
pop dx
|
||
|
pop ax
|
||
|
pop bx
|
||
|
pop dx
|
||
|
.386
|
||
|
mov cl,al
|
||
|
xor ch,ch
|
||
|
shl cx,9
|
||
|
.8086
|
||
|
add bx,cx
|
||
|
jz FatLoopDone
|
||
|
jmp FatLoop
|
||
|
FatLoopDone:
|
||
|
mov ax,es
|
||
|
add ax,01000h
|
||
|
mov es,ax
|
||
|
mov ah,MAXSECTORS
|
||
|
jmp FatLoop
|
||
|
|
||
|
NextFatEntry proc near
|
||
|
push bx
|
||
|
call IsFat12
|
||
|
jnc Next16Fat
|
||
|
Next12Fat:
|
||
|
mov bx,dx
|
||
|
shr dx,1
|
||
|
pushf
|
||
|
add bx,dx
|
||
|
.386
|
||
|
mov dx,fs:[bx]
|
||
|
.8086
|
||
|
popf
|
||
|
jc shift
|
||
|
and dx,0fffh
|
||
|
jmp short N12Tail
|
||
|
shift:
|
||
|
.386
|
||
|
shr dx,4
|
||
|
.8086
|
||
|
N12Tail:
|
||
|
cmp dx,0ff8h
|
||
|
jb NfeDone
|
||
|
mov dx,0ffffh
|
||
|
jmp short NfeDone
|
||
|
Next16Fat:
|
||
|
add dx,dx
|
||
|
jc N16high
|
||
|
mov bx,dx
|
||
|
.386
|
||
|
mov dx,fs:[bx]
|
||
|
.8086
|
||
|
jmp short N16Tail
|
||
|
N16high:
|
||
|
mov bx,dx
|
||
|
.386
|
||
|
mov dx,gs:[bx]
|
||
|
.8086
|
||
|
N16Tail:
|
||
|
cmp dx,0fff8h
|
||
|
jb NfeDone
|
||
|
mov dx,0ffffh
|
||
|
NfeDone:
|
||
|
pop bx
|
||
|
ret
|
||
|
NextFatEntry endp
|
||
|
|
||
|
IsFat12 proc near
|
||
|
.386
|
||
|
push eax
|
||
|
push ebx
|
||
|
push ecx
|
||
|
push edx
|
||
|
|
||
|
movzx ecx, ds:[si].Sectors
|
||
|
or cx,cx
|
||
|
jnz if10
|
||
|
mov ecx, ds:[si].SectorsLong
|
||
|
if10:
|
||
|
movzx ebx, byte ptr ds:[si].Fats
|
||
|
movzx eax, word ptr ds:[si].FatSectors
|
||
|
mul ebx
|
||
|
sub ecx,eax
|
||
|
movzx eax, word ptr ds:[si].DirectoryEntries
|
||
|
shl eax, 5
|
||
|
mov edx,eax
|
||
|
and edx,0ffff0000h
|
||
|
div word ptr ds:[si].BytesPerSector
|
||
|
sub ecx,eax
|
||
|
movzx eax, word ptr ds:[si].ReservedSectors
|
||
|
sub ecx, eax
|
||
|
mov eax, ecx
|
||
|
movzx ecx, byte ptr ds:[si].SectorsPerCluster
|
||
|
xor edx,edx
|
||
|
div ecx
|
||
|
cmp eax, 4087
|
||
|
jae if20
|
||
|
stc
|
||
|
jmp short if30
|
||
|
if20:
|
||
|
clc
|
||
|
if30:
|
||
|
pop edx
|
||
|
pop ecx
|
||
|
pop ebx
|
||
|
pop eax
|
||
|
ret
|
||
|
.8086
|
||
|
IsFat12 endp
|
||
|
|
||
|
Free EQU 512-($-Start)
|
||
|
if Free lt 0
|
||
|
%out FATAL PROBLEM: FAT-specific startup code is greater than
|
||
|
%out 512 bytes. Fix it!
|
||
|
.err
|
||
|
endif
|
||
|
|
||
|
|
||
|
|
||
|
RealStart:
|
||
|
;
|
||
|
; we are completely done with the boot sector, we can party on it's memory as we like.
|
||
|
; set up the stack
|
||
|
;
|
||
|
mov ax,StackSeg
|
||
|
mov ss,ax
|
||
|
xor sp,sp
|
||
|
|
||
|
mov ax,cs
|
||
|
mov ds,ax
|
||
|
mov es,ax
|
||
|
|
||
|
;
|
||
|
; save setupldr data
|
||
|
;
|
||
|
mov Preserve, dl
|
||
|
|
||
|
; move ourselves from 2000:0000 to 1000:0000, one paragraph at a time.
|
||
|
|
||
|
mov ax, BiosChkDestSeg
|
||
|
mov es, ax
|
||
|
mov dx, MaxCodeSize
|
||
|
cld
|
||
|
Again1:
|
||
|
xor di, di
|
||
|
xor si, si
|
||
|
mov cx, 10h
|
||
|
rep movsb
|
||
|
mov ax, ds
|
||
|
inc ax
|
||
|
mov ds, ax
|
||
|
mov ax, es
|
||
|
inc ax
|
||
|
mov es, ax
|
||
|
dec dx
|
||
|
jnz Again1
|
||
|
mov ax, BiosChkDestSeg
|
||
|
mov ds, ax
|
||
|
mov es, ax
|
||
|
JMPFAR Continue1, BiosChkDestSeg
|
||
|
|
||
|
Continue1:
|
||
|
|
||
|
; insert your BIOS check code here
|
||
|
; instead of a real BIOS check we will check if the user holds down CTRL.
|
||
|
; If yes, we will behave like BIOS check failed
|
||
|
|
||
|
mov ah,02h
|
||
|
int 16h
|
||
|
and al,00000100b
|
||
|
jz MoveSetupLdr
|
||
|
|
||
|
; at this point, the BIOS check failed. You can add whatever code you want here
|
||
|
; to give a message or to make the computer crash. If you don't do anything, the
|
||
|
; code will jump to 2000:0000 so an infinite loop is going to happen.
|
||
|
jmp Continue2
|
||
|
|
||
|
MoveSetupLdr:
|
||
|
; move Setupldr code from 2000+MaxCodeSize:0000 to 2000:0000, one paragraph at a time.
|
||
|
|
||
|
push ds
|
||
|
push es
|
||
|
mov ax, SetupLdrDestSeg
|
||
|
mov es, ax
|
||
|
add ax, MaxCodeSize
|
||
|
mov ds, ax
|
||
|
mov dx, MaxSetupLdrSize
|
||
|
cld
|
||
|
Again2:
|
||
|
xor di, di
|
||
|
xor si, si
|
||
|
mov cx, 10h
|
||
|
rep movsb
|
||
|
mov ax, ds
|
||
|
inc ax
|
||
|
mov ds, ax
|
||
|
mov ax, es
|
||
|
inc ax
|
||
|
mov es, ax
|
||
|
dec dx
|
||
|
jnz Again2
|
||
|
pop es
|
||
|
pop ds
|
||
|
|
||
|
Continue2:
|
||
|
mov dl, Preserve
|
||
|
JMPFAR 0,SetupLdrDestSeg
|
||
|
|
||
|
Preserve db ?
|
||
|
|
||
|
.errnz ($-_BiosChk) GT (MaxCodeSize*16 - 2) ;FATAL: BiosChk code is too large
|
||
|
|
||
|
org MaxCodeSize*16 - 2
|
||
|
db 55h,0aah
|
||
|
|
||
|
|
||
|
CODE ENDS
|
||
|
END START
|