; ============================================================================
;
; Litos Boot Sector (Floppy disk)
;
; ============================================================================
DISKTAB_SIZE EQU 16 ; size of disk table (with extra bytes)
SECTOR_SIZE EQU 512 ; sector size
BOOTSEG EQU 100h ; booting segment (=2nd 4KB page)
; ----------------------------------------------------------------------------
; Start of the boot sector (starting at 0000:7C00)
; ----------------------------------------------------------------------------
SECTION .text
BITS 16
org 7C00h ; booting address of boot sector
Start: jmp Init ; jump to starting routine
; ------------- Setup data (this can be set by the installator)
SectRead dw 800 ; 3: number of sectors to read
Disk db 0 ; 5: system disk (0=A:, 80h=C:)
Heads db 2 ; 6: number of heads
Sectors db 18 ; 7: number of sectors per track
Message db "Error loading system.",13,10
db "Press any key...",13,10,0
DiskTab: ; disk table (16 bytes)
; ------------- Init temporary stack (for calling int 12h)
Init: cli ; disable interrupts
xor ax,ax ; AX <- 0
mov ds,ax ; DS <- 0 this segment
mov si,7C00h ; SI <- offset of the boot sector
mov ss,ax ; SS <- 0
mov sp,si ; SP <- end of stack
sti ; enable interrupt
; ------------- Determining top of memory (usualy 0A000h)
int 12h ; AX <- get memory size in 1 KB blocks
mov cl,6 ; number of rotations
shl ax,cl ; segment address of the top of memory
sub ax,7E0h ; correction of the segment address
; ------------- Init stack (lies below new beginning of the boot sector)
cli ; disable interrupts
mov ss,ax ; SS <- destination segment
mov es,ax ; ES <- destination segment
; ------------- Moving loader high
mov di,si ; DI <- offset of the boot sector
mov cx,100h ; CX <- 256 length of sector in words
cld ; direction up
rep movsw ; moving sector up
; ------------- Jump to new boot sector
push es ; segment of far jump
push word Continue ; offset of far jump
retf ; jump to new sector
; ------------- Load disk param table
Continue: mov bx,4*1eh ; address of INT 1Eh vector
lds si,[bx] ; DS:SI <- address of disk param table
push ds ; push old address DS of table
push si ; push old address SI of table
mov cl,DISKTAB_SIZE ; CX <- length of disk param table
mov di,DiskTab ; DI <- buffer for disk param table
rep movsb ; load disk param table
; From this point DS:SI (original disk param table) is pushed in the stack!!!
; ------------- Set address of new disk param table
mov ds,cx ; DS <- 0
mov word [bx],DiskTab; offset of new disk table
mov [bx+2],es ; segment of new disk table
; ------------- Set new parameters of disk param table
mov ds,ax ; DS <- this segment
mov al,[Sectors] ; number of sectors per track
mov [di+4-DISKTAB_SIZE],al; number of last sector on track
mov byte [di+9-DISKTAB_SIZE],15 ; start-up time for floppy
sti ; enable interrupt
; ------------- Reset disk system
xor ax,ax ; AX <- 0
mov dl,[Disk] ; DL <- disk to reset
int 13h ; reset disk system
; ------------- Prepare to read system
mov bx,BOOTSEG ; BX <- start segment to read system to
mov si,[SectRead] ; Sectors to read
mov cx,2 ; CL <- 2 sector, CH <- 0 cylinder
mov dh,0 ; DH <- 0 head
; ------------- Determine number of sectors in one read
Read: mov di,3 ; DI <- 3 error counter
mov ah,0 ; AH <- 0
mov al,[Sectors] ; AL <- number of sectors per track
inc ax ; AL = number of sectors + 1
sub al,cl ; AL = sectors to the end of track
cmp ax,si ; compare to sectors to read
jbe Read1 ; number of sectors is OK
mov ax,si ; limit number of sectors
; ------------- Limit number of sectors to not overlap 64 KB boundary
Read1: mov ah,al ; AH <- number of sectors to read
mov bp,bx ; BP <- destination segment
shl bp,1
shl bp,1
shl bp,1
shl bp,1 ; BP * 16 (offset)
mov al,0 ; AL <- sector counter
Read2: inc ax ; increase number of sectors
add bp,SECTOR_SIZE ; add 1 sector
jc Read3 ; next sector will be behind 64 KB
cmp al,ah ; will there be next sector?
jb Read2 ; test next sector
; ------------- Push registers
Read3: push ax ; push AX (number of sectors to read)
push bx ; push BX (destination segment)
push cx ; push CX (sector and cylinder)
push dx ; push DX (head)
push si ; push SI (sectors to read)
push di ; push DI (error counter)
; ------------- Read group of sectors (AL=num, CH=cyl, CL=sect, DH=head, BX=seg)
mov ah,2 ; function to read sectors
mov dl,[Disk] ; DL <- disk to read from
mov es,bx ; ES <- destination segment
xor bx,bx ; BX <- 0 destination offset
int 13h ; read sectors
; ------------- Pop register
pop di ; pop DI (error counter)
pop si ; pop SI (sectors to read)
pop dx ; pop DX (head)
pop cx ; pop CX (sector and cylinder)
pop bx ; pop BX (destination segment)
pop ax ; pop AX (number of sectors to read)
jc Error ; error
; ------------- Test first data sector
cmp bx,BOOTSEG ; is it first data sector?
jne Read4 ; it is not first data sector
cmp word [es:4],8A26h ; test identifier
jne ErrorLast ; error, invalid sector
; ------------- Count sectors
Read4: mov ah,0 ; AX = number of sectors in one read
sub si,ax ; SI <- decrement number of sectors
jz AllOK ; all sectors are loaded
; ------------- Increase sector number
add cl,al ; CL = new sector number
; ------------- Increase destination segment
push cx ; push CX
mov cl,5 ; CL <- rotations
shl ax,cl ; AX = segment shift
add bx,ax ; BX = increase segment address
pop cx ; pop CX
; ------------- Check destination segment
mov ax,cs ; AX <- this segment
sub ax,(SECTOR_SIZE+128)/16 ; reserve for stack
cmp ax,bx ; memory error?
jbe ErrorLast ; memory error
; ------------- Next sectors
cmp cl,[Sectors] ; is it last sector on track?
jbe Read ; there are another sectors on track
mov cl,1 ; CL <- 1 sector of next track
inc dh ; DH = next head
cmp dh,[Heads] ; overflow number of heads?
jb Read ; number of head is OK
mov dh,0 ; head on next track
inc ch ; CH = next cylinder
jmp Read ; read next sectors
; ------------- ALL OK: Return old disk param table
AllOK: mov dl,[Disk] ; DL <- disk number
xor ax,ax ; AX <- 0
mov ds,ax ; DS <- 0
pop ax ; AX <- offset of old disk param table
mov [4*1Eh],ax ; pop offset of old disk param table
pop ax ; AX <- segmnet of old disk param table
mov [4*1Eh+2],ax ; pop segment of old disk param table
; ------------- Kill motor of floppy disks
push dx ; push DX
mov dx,3F2h ; DX <- diskette port
mov al,0 ; AL <- 0
out dx,al ; switch motors off
pop dx ; pop DX
; ------------- Jump to system in memory (jump to Start in LITOS.ASM)
push ds ; push 0, segment of new system
mov ax,BOOTSEG*16 ; AX <- destination segment as offset
push ax ; push AX, offset of new system
retf ; jump to new system
; ------------- ERROR: next attempt
Error: dec di ; error counter
jz ErrorLast ; it was last error
; ------------- Reset disk and try again
push ax ; push AX (number of sectors)
push dx ; push DX (head)
xor ax,ax ; AX <- 0
mov dl,[Disk] ; DL <- disk to reset
int 13h ; reset disk system
pop dx ; pop DX (head)
pop ax ; pop AX (number of sectors)
jmp Read3 ; next attempt
; ------------- Return old disk param table
ErrorLast: xor ax,ax ; AX <- 0
mov ds,ax ; DS <- 0
pop ax ; AX <- offset of old disk param table
mov [4*1Eh],ax ; pop offset of old disk param table
pop ax ; AX <- segmnet of old disk param table
mov [4*1Eh+2],ax ; pop segment of old disk param table
; ------------- ERROR: Display error message
push cs ; push CS
pop ds ; DS <- this segment
mov si,Message ; information message
NextChar: cld ; set direction up
lodsb ; AL <- load next character from DS:SI
or al,al ; AL == 0? (is it end of text?)
jz KeyPress ; end of text
mov ah,0eh ; AH <- function code
mov bx,7 ; BL <- color of text, BH <- page 0
push si ; push SI
int 10h ; print character
pop si ; pop SI
jmp short NextChar ; next character
; ------------- ERROR: Waiting for a key
KeyPress: mov ah,0 ; AH <- function code
int 16h ; waiting for a key
; ------------- ERROR: Repeat booting
int 19h ; repeat booting
; ------------- Align to sector size
times 512 - 2 - ($ - Start) db 0
dw 0aa55h ; Boot sector magic
|