2012年3月26日 星期一

benwei的bos

benwei的bos
https://github.com/benwei/bos
以下是bootldr.s

;*********************************************
; bootldr.s
; - Bootloader for loading MYOS.BIN
;
; Modify the source from
; Operating Systems Development Tutorial
;*********************************************
bits 16 ; we are in 16 bit real mode
org 0 ; we will set regisers later
start: jmp main ; jump to start of bootloader
;*********************************************
; BIOS Parameter Block
;*********************************************
; BPB Begins 3 bytes from start. We do a far jump, which is 3 bytes in size.
; If you use a short jump, add a "nop" after it to offset the 3rd byte.
bpbOEM db "My OS "
bpbBytesPerSector: DW 512
bpbSectorsPerCluster: DB 1
bpbReservedSectors: DW 1
bpbNumberOfFATs: DB 2
bpbRootEntries: DW 224
bpbTotalSectors: DW 2880
bpbMedia: DB 0xf0 ;; 0xF1
bpbSectorsPerFAT: DW 9
bpbSectorsPerTrack: DW 18
bpbHeadsPerCylinder: DW 2
bpbHiddenSectors: DD 0
bpbTotalSectorsBig: DD 0
bsDriveNumber: DB 0
bsUnused: DB 0
bsExtBootSignature: DB 0x29
bsSerialNumber: DD 0xa0a1a2a3
bsVolumeLabel: DB "BOS FLOPPY "
bsFileSystem: DB "FAT12 "
;************************************************;
; Prints a string
; DS=>SI: 0 terminated string
;************************************************;
Print:
lodsb ; load next byte from string from SI to AL
or al, al ; Does AL=0?
jz PrintDone ; Yep, null terminator found-bail out
mov ah, 0eh ; Nope-Print the character
int 10h
jmp Print ; Repeat until null terminator found
PrintDone:
ret ; we are done, so return
absoluteSector db 0x00
absoluteHead db 0x00
absoluteTrack db 0x00
;************************************************;
; Convert CHS to LBA
; LBA = (cluster - 2) * sectors per cluster
;************************************************;
ClusterLBA:
          sub ax, 0x0002 ; zero base cluster number
          xor cx, cx
          mov cl, BYTE [bpbSectorsPerCluster] ; convert byte to word
          mul cx
          add ax, WORD [datasector] ; base data sector
          ret
;************************************************;
; Convert LBA to CHS
; AX=>LBA Address to convert
;
; absolute sector = (logical sector / sectors per track) + 1
; absolute head = (logical sector / sectors per track) MOD number of heads
; absolute track = logical sector / (sectors per track * number of heads)
;
;************************************************;
LBACHS:
          xor dx, dx ; prepare dx:ax for operation
          div WORD [bpbSectorsPerTrack] ; calculate
          inc dl ; adjust for sector 0
          mov BYTE [absoluteSector], dl
          xor dx, dx ; prepare dx:ax for operation
          div WORD [bpbHeadsPerCylinder] ; calculate
          mov BYTE [absoluteHead], dl
          mov BYTE [absoluteTrack], al
          ret
;************************************************;
; Reads a series of sectors
; CX=>Number of sectors to read
; AX=>Starting sector
; ES:BX=>Buffer to read to
;************************************************;
ReadSectors:
     .MAIN:
          mov di, 0x0005 ; five retries for error
     .SECTORLOOP:
          push ax
          push bx
          push cx
          call LBACHS ; convert starting sector to CHS
          mov ah, 0x02 ; BIOS read sector
          mov al, 0x01 ; read one sector
          mov ch, BYTE [absoluteTrack] ; track
          mov cl, BYTE [absoluteSector] ; sector
          mov dh, BYTE [absoluteHead] ; head
          mov dl, BYTE [bsDriveNumber] ; drive
          int 0x13 ; invoke BIOS
          jnc .SUCCESS ; test for read error
          xor ax, ax ; BIOS reset disk
          int 0x13 ; invoke BIOS
          dec di ; decrement error counter
          pop cx
          pop bx
          pop ax
          jnz .SECTORLOOP ; attempt to read again
          int 0x18
     .SUCCESS:
          mov si, msgProgress
          call Print
          pop cx
          pop bx
          pop ax
          add bx, WORD [bpbBytesPerSector] ; queue next buffer
          inc ax ; queue next sector
          loop .MAIN ; read next sector
          ret
;*********************************************
; Bootloader Entry Point
;*********************************************
main:
     ;----------------------------------------------------
     ; code located at 0000:7C00, adjust segment registers
     ;----------------------------------------------------
     
          cli ; disable interrupts
          mov ax, 0x07C0 ; setup registers to point to our segment
          mov ds, ax
          mov es, ax
          mov fs, ax
          mov gs, ax
     ;----------------------------------------------------
     ; create stack
     ;----------------------------------------------------
     
          mov ax, 0x0000 ; set the stack
          mov ss, ax
          mov sp, 0xFFFF
          sti ; restore interrupts
     ;----------------------------------------------------
     ; Display loading message
     ;----------------------------------------------------
     
          mov si, msgLoading
          call Print
          
     ;----------------------------------------------------
     ; Load root directory table
     ;----------------------------------------------------
     LOAD_ROOT:
     
     ; compute size of root directory and store in "cx"
     
          xor cx, cx
          xor dx, dx
          mov ax, 0x0020 ; 32 byte directory entry
          mul WORD [bpbRootEntries] ; total size of directory (ax = 0x0020 * 224)
          div WORD [bpbBytesPerSector] ; sectors used by directory (ax = 0x0020 * 224 / 512)
          xchg ax, cx ; swap(ax, cx) cx=14
          
     ; compute location of root directory and store in "ax"
     
          mov al, BYTE [bpbNumberOfFATs] ; number of FATs (2, ax = 2)
          mul WORD [bpbSectorsPerFAT] ; sectors used by FATs (9, ax = 18)
          add ax, WORD [bpbReservedSectors] ; adjust for bootsector(1, ax = 19)
          mov WORD [datasector], ax ; base of root directory([datasector] = 19)
          add WORD [datasector], cx ; [datasector] = 19 + 14 = 33
          
     ; read root directory into memory (7C00:0200)
     
          mov bx, 0x0200 ; copy root dir above bootcode
          call ReadSectors
     ;----------------------------------------------------
     ; Find stage 2
     ;----------------------------------------------------
     ; browse root directory for binary image
          mov cx, WORD [bpbRootEntries] ; load loop counter
          mov di, 0x0200 ; locate first root entry
     .LOOP:
          push cx
          mov cx, 0x000B ; eleven character name
          mov si, ImageName ; image name to find
          push di
     rep cmpsb ; test for entry match
          pop di
          je LOAD_FAT
          pop cx
          add di, 0x0020 ; queue next directory entry
          loop .LOOP
          jmp FAILURE
     ;----------------------------------------------------
     ; Load FAT
     ;----------------------------------------------------
     LOAD_FAT:
     
     ; save starting cluster of boot image
     
          mov dx, WORD [di + 0x001A]
          mov WORD [cluster], dx ; file first cluster
          
     ; compute size of FAT and store in "cx"
     
          xor ax, ax
          mov al, BYTE [bpbNumberOfFATs] ; number of FATs
          mul WORD [bpbSectorsPerFAT] ; sectors used by FATs
          mov cx, ax
mul WORD [bpbBytesPerSector] ; fatsize = sectors used by FATS * bpbBytesPerSector (512)
mov WORD [fatsize], ax
     ; compute location of FAT and store in "ax"
          mov ax, WORD [bpbReservedSectors] ; adjust for bootsector
          
     ; read FAT into memory (7C00:0200)
          mov bx, 0x0200 ; copy FAT above bootcode
          call ReadSectors
     ; read image file into memory (0050:0000)
     
          mov ax, 0x0050
          mov es, ax ; destination for image
          mov bx, 0x0000 ; destination for image
          push bx
     ;----------------------------------------------------
     ; Load Stage 2
     ;----------------------------------------------------
     LOAD_IMAGE:
     
          mov ax, WORD [cluster] ; cluster to read
          pop bx ; buffer to read into
          call ClusterLBA ; convert cluster to LBA
          xor cx, cx
          mov cl, BYTE [bpbSectorsPerCluster] ; sectors to read
          call ReadSectors
          push bx
          
     ; compute next cluster
     
          mov ax, WORD [cluster] ; identify current cluster
          mov cx, ax ; copy current cluster
          mov dx, ax ; copy current cluster
          shr dx, 0x0001 ; divide by two
          add cx, dx ; sum for (3/2)
          mov bx, 0x0200 ; location of FAT in memory
          add bx, cx ; index into FAT
          mov dx, WORD [bx] ; read two bytes from FAT
          test ax, 0x0001
          jnz .ODD_CLUSTER
          
     .EVEN_CLUSTER:
     
          and dx, 0000111111111111b ; take low twelve bits
         jmp .DONE
         
     .ODD_CLUSTER:
     
          shr dx, 0x0004 ; take high twelve bits
          
     .DONE:
     
          mov WORD [cluster], dx ; store new cluster
          cmp dx, 0x0FF0 ; test for end of file
          jb LOAD_IMAGE
          
     DONE:
mov ax, 0x1000
mov es, ax
mov cx, 2 ; read 32 sectors
mov ax, 19 ; starting sector
mov bx, 0 ; to 0x10000
          call ReadSectors
%if 0
; backup the FAT
; ES
mov cx, word [fatsize]
mov si, 0x0200
mov ax, 0x1000
mov es, ax
mov di, 0
.loopfatmove:
lodsb
stosb
loop .loopfatmove
mov di, 0
mov ax, word [fatsize]
stosw
%endif
          mov si, msgCRLF
          call Print
          push WORD 0x0050
          push WORD 0x0000
          retf
          
     FAILURE:
     
          mov si, msgFailure
          call Print
          mov ah, 0x00
          int 0x16 ; await keypress
          int 0x19 ; warm boot computer
     fatsize dw 0x0000
     datasector dw 0x0000
     cluster dw 0x0000
     ImageName db "MYOS BIN"
     msgLoading db 0x0D, 0x0A, "Loading Boot Image ", 0x00
     msgCRLF db 0x0D, 0x0A, 0x00
     msgProgress db ".", 0x00
     msgFailure db 0x0D, 0x0A, "MISSING OS. Hit Any Key to Reboot", 0x0D, 0x0A, 0x00
     
          TIMES 510-($-$$) DB 0
          DW 0xAA55

沒有留言:

張貼留言