;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 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 ;============================================================================;