;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Project: Bootstrap ;;
;; Module: rpboot.asm ;;
;; Date: 7-3-99 ;;
;; Purpose: This module contains the portion of the bootstrap that loads ;;
;; the kernel loader into memory. It is based on a bootstrap ;;
;; examples by Gareth Owen and Sean Tash. ;;
;; ;;
;; Created by Ben L. Titzer ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[BITS 16] ; bios starts out in 16-bit real mode
[ORG 0x7c00] ; data offset of zero
%define LOAD_SEGMENT 0x1000 ; load the loader to segment 0x1000
%define STACK_SEGMENT 0x9000 ; stack segment
jmp short start ; jump to beginning of code
nop
;============================================================================;
;============================ F A T I N F O ===============================;
;============================================================================;
bsOEM db "-Möbius-" ; OEM String
bsSectSize dw 512 ; Bytes per sector
bsClustSize db 1 ; Sectors per cluster
bsRessect dw 1 ; # of reserved sectors
bsFatCnt db 2 ; # of fat copies
bsRootSize dw 224 ; size of root directory
bsTotalSect dw 2880 ; total # of sectors if < 32 meg
bsMedia db 0xF0 ; Media Descriptor
bsFatSize dw 9 ; Size of each FAT
bsTrackSect dw 18 ; Sectors per track
bsHeadCnt dw 2 ; number of read-write heads
bsHidenSect dd 0 ; number of hidden sectors
bsHugeSect dd 0 ; if bsTotalSect is 0 this value is
; the number of sectors
bsBootDrv db 0 ; holds drive that the bs came from
bsReserv db 0 ; not used for anything
bsBootSign db 29h ; boot signature 29h
bsVolID dd 0 ; Disk volume ID also used for temp
; sector # / # sectors to load
bsVoLabel
root_strt db " " ; volume label is used internally
root_scts db " " ; while in memory for storage
file_strt db " " ; of other variables.
file_scts db " " ; this is just done to save space.
db " "
rs_fail db " "
bsFSType db "FAT12 " ; File System type
;============================================================================;
filename db 'MOBEL_PECOM'
rebootmsg db 'Press any key',13,10,0
diskerror db "Disk error.",0
loadmsg db "Loading...",0
;============================================================================;
;====================== B O O T S E C T O R C O D E ======================;
;============================================================================;
start:
cli ; clear interrupts while we setup a stack
mov [bsBootDrv], dl ; save what drive we booted from
mov ax,STACK_SEGMENT ; setup stack segment
mov ss,ax
mov sp,0xffff ; use the whole segment
; mov cx,[bsTrackSect] ; update int 1E FDC param table
; mov bx,0x0078
; lds si,[ds:bx]
; mov byte [si+4], cl
; mov byte [si+9], 0x0F
sti ; put interrupts back on
push ds
mov dl,[bsBootDrv] ; reset controller
xor ax,ax
int 0x13
pop ds
jc bootfail2 ; display error message
jmp cont
bootfail2: jmp bootfail
cont:
xor ax, ax ; clear ax
mov ds, ax ; set up data segment accordingly
mov es, ax
mov si,loadmsg ; display load message
call putstr
xor ax,ax ; find the root directory
mov al,[bsFatCnt]
mov bx,[bsFatSize]
mul bx
add ax,word [bsHidenSect]
adc ax,word [bsHidenSect+2]
add ax,word [bsRessect] ; ax holds root directory location
mov word [root_strt],ax
call findfile
xor ax,ax
add ax,word [root_scts]
add ax,word [file_strt] ; sector number
add ax,word [root_strt]
sub ax,2 ; correction for a mis-calc
mov cx,word [file_scts] ; number of sectors
mov bx,LOAD_SEGMENT+10h ; the 10h is because it's a com file
mov es,bx
nextsector:
push ax ; save registers
push cx
push dx
push es
xor bx,bx ; set zero offset
call readsect ; read a sector
pop es ; restore registers
pop dx
pop cx
pop ax
mov bx,es
add bx,20h ; increment address 512 bytes
mov es,bx
inc ax ; read next sector
loopnz nextsector
mov dl, [bsBootDrv]
mov ax,LOAD_SEGMENT ; set segment registers and jump
mov es,ax
mov ds,ax
push ax ; push the segment
mov ax,100h ; its a com file, execution starts at 100h
push ax ; push offset
retf ; call the second stage
findfile:
push ax ; save registers
push bx
push cx
push dx
push si
push di
mov ax,LOAD_SEGMENT ; put root directory at LOAD_SEGMENT
mov es,ax
mov ax,32 ; AX = ((32*RootSize)/512) + 2
mul word [bsRootSize]
div word [bsSectSize]
mov cx,ax ; cx holds # of sectors in root
mov word [root_scts],ax
mov ax,word [root_strt] ; get prev. saved loc. for root dir
searchrootsect:
xor bx,bx
push cx ; save count
push ax ; save sector number
push es
push dx
call readsect
xor bx,bx
checkentry:
mov di,bx ; set address to check from
mov cx,11 ; check 11 bytes
mov si,filename ; address of string to check with
repz cmpsb ; check string against filename
je foundit ; if equal, we found it
add bx,32 ; otherwise, check next entry
cmp bx,[bsSectSize] ; end of sector?
jne checkentry ; if not end, continue
pop dx ; restore registers
pop es
pop ax
pop cx
inc ax ; check next sector when we loop again
loopnz searchrootsect ; loop until either found or not
jmp bootfail ; couldn't find it: die
foundit:
pop dx ; get these off the stack
pop es
pop ax
pop cx
mov di,0x1A ; get clustor #
add di,bx
push bx ; save bx for finding # of sectors
mov ax,[es:di]
xor bx,bx ; calculate sector #
mov bl,[bsClustSize]
mul bx ; ax holds sector #
mov word [file_strt],ax
pop bx ; get location of directory entry
mov di,0x1C
add di,bx
mov ax,[es:di] ; put number of bytes in ax
xor dx,dx
mov bx,[bsSectSize] ; # of bytes / 512
div bx
inc ax
mov word [file_scts],ax ; save number of sectors to load
pop di ; restore registers
pop si
pop dx
pop cx
pop bx
pop ax
ret ; return to caller
bootfail:
mov si,diskerror ; display error message
call putstr
call reboot
;============================================================================;
;=========================== F U N C T I O N S ==============================;
;============================================================================;
readsect: ; ES:BX = Location ; AX = Sector
mov [rs_fail], byte 0 ; no failures yet
readsect2:
push ax ; store sector
mov si,[bsTrackSect]
div si ; divide logical sect by track size
inc dl ; sector # begins at 1
mov [bsReserv],dl ; sector to read
xor dx,dx ; logical track left in ax
div word [bsHeadCnt] ; leaves head in dl, cyl in ax
mov dh, [bsBootDrv] ;
xchg dl,dh ; head to dh, drive to dl
mov cx,ax ; cyl to cx
xchg cl,ch ; low 8 bits of cyl to ch, hi 2 bits
shl cl,6 ; shifted to bits 6 and 7
or cl, byte [bsReserv] ; or with sector number
mov al,1 ; number of sectors
mov ah,2 ; use read function of int 0x13
int 0x13 ; read sector
jc readfail ; display error message
pop ax
ret ; return to caller
readfail: ; read failed
inc byte [rs_fail]
cmp byte [rs_fail], 4 ; stop at 4 tries
je bootfail
mov dl,[bsBootDrv] ; reset controller
xor ax,ax
int 0x13
pop ax
jmp readsect2
;============================================================================;
%ifdef PUTINT
putint: ; print ax to screen
mov si, di ; if di is set, then print leading zeroes
mov bx, 10000
mov cx, ax ; store a copy of ax
pi1:
cmp bx, 1 ; if we are on last digit
jne cn
mov si, 1 ; make sure we print it (even if zero)
cn:
mov ax, cx ; get current num
xor dx, dx ; clear dx
div bx ; divide by decimal
mov cx, dx ; save remainder
or si, ax ; if si and ax are zero, it's a leading zero
jz nz
add ax, '0' ; make a character
mov ah, 0eh ; print character function
int 0x10 ; call BIOS
nz:
mov ax, bx ; we have to reduce the radix too
xor dx, dx ; clear dx
mov bx, 10 ; use 10 as new divider
div bx ; divide
mov bx, ax ; save result
or bx, bx ; if zero, we're done
jnz pi1
ret
%endif
;============================================================================;
putstr: ; Dump ds:si to screen.
lodsb ; load byte at ds:si into al
or al,al ; test if character is 0 (end)
jz done
mov ah,0eh ; put character
mov bx,0009 ; attribute
int 0x10 ; call BIOS
jmp putstr
done:
ret
;============================================================================;
reboot:
mov si, rebootmsg ; be polite, and say we're rebooting
call putstr
mov ah, 0 ; subfuction 0
int 016h ; call bios to wait for key
db 0EAh ; machine language to jump to FFFF:0000 (reboot)
dw 0000h
dw 0FFFFh
;============================================================================;
;============================ E N D C O D E ===============================;
;============================================================================;
padding times 510-($-$$) db 0 ; make the file the right size
BootSig dw 0xAA55 ; magic word for BIOS
;============================================================================;