; GazOS Operating System
; Copyright (C) 1999 Gareth Owen <gaz@athene.co.uk>
;
; This program is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version 2
; of the License, or (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program; if not, write to the Free Software
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
%include "gdtnasm.inc"
; GazOS bootsector by Gareth Owen <gaz@athene.co.uk>
%define ONE_MEG 0x100000
%define MEM_INCR ONE_MEG
%define LOAD_ADDR ONE_MEG
%define RDSK_ADDR (ONE_MEG * 2)
%define BUFFER_ADDR 0x8000
%define KERNEL_SIZE (kernel_end - kernel_start)
%define RDSK_SIZE (ramdisk_end - kernel_end)
[ORG 0x7c00]
jmp start
nop
;START BOOTSECTOR HEADER
;id db 'GazFS' ; Filing System ID
;version dd 1h ; Filing System Version
;fs_start dd 52 ; LBA address for start of root dir
BytesPerSector dw 512
SectorsPerTrack dw 18
TotalHeads dw 2
TotalSectors dd 2880 ; 1474560/512 for a 1.44meg disk
;END BOOTSECTOR HEADER
;BOOTSECTOR DATA
file_entry_nextdata equ 273 ; Offset in file_entry structure to the nextdata LBA pointer
data_entry_data equ 9 ; Offset in data_entry structure to the data
bootdrv db 0
;END BOOTSECTOR DATA
start:
xor ax, ax
mov ds, ax
mov si, msg
call print
mov [bootdrv], dl
; First get into protected mode
cli ;{0}
n5: in al, 0x64 ;Enable A20 {4A} {5}
test al, 2
jnz n5
mov al, 0xD1
out 0x64, al
n6: in al, 0x64
test al, 2
jnz n6
mov al, 0xDF
out 0x60, al
lgdt [gdtinfo] ;Load GDT
mov ecx, CR0 ;Switch to protected mode
inc cx
mov CR0, ecx
mov ax, flat_data-gdt_table ; Selector for 4Gb data seg
mov ds, ax ; {2} Extend limit for ds
mov es, ax ; Extend limit for es
mov fs, ax ; fs and...
mov gs, ax ; gs
dec cx ; switch back to real mode
mov CR0, ecx
sti
xor eax, eax
mov ds, ax
mov dl, [bootdrv] ; Store the boot drive
mov ax, 1 ; sector number
mov si, msg2
call print
mov cx, KERNEL_SIZE / 512; total sectors
mov ebx, LOAD_ADDR ; destination in memory
call load
mov si, msg3
call print
mov cx, RDSK_SIZE / 512
mov ebx, RDSK_ADDR
call load
jmp count_memory
;**************************************
;* in:
;* eax: start sector
;* ebx: start of destination buffer
;* cx: number of sectors
;* dl: disk drive
;* out:
;* ax: end sector
;* ebx: end of destination buffer
;* modifies:
;* bx, es, edi, esi, ecx, bp
;**************************************
load:
mov si, BUFFER_ADDR >> 4
mov es, si
mov di, 1
xor bp, bp
mov [sectors_total], cx
load_loop:
push ebx
call read_sectors
pop ebx
push cx
push di
push es
xor cx, cx
mov es, cx
movzx ecx, word [BytesPerSector]
mov edi, ebx
add ebx, ecx
mov esi, BUFFER_ADDR
a32 rep movsb
pop es
pop di
pop cx
;mov bx, es
;add bx, 32
;mov es, bx
inc ax
inc bp
push ax
push bx
mov ax, [sectors_total]
mov bx, 80
div bx
xor ah, ah
cmp bp, ax
jle .1
xor bp, bp
push bp
mov ax, 0efeh
xor bx, bx
int 10h
pop bp
.1:
pop bx
pop ax
loop load_loop
ret
count_memory:
; Turn off the floppy motor, its annoying leaving it on !
mov edx,0x3f2
mov al,0x0c
out dx,al
; set, restore and test a byte at each 1 Mb boundary
; the end is reached when byte read != byte written
mov edi,0
.start:
mov al,byte [es:edi]
mov byte [es:edi],0aah
mov ah,byte [es:edi]
mov byte [es:edi],al
cmp ah,0aah
jne .finish
add edi,MEM_INCR
jmp .start
.finish:
mov [memory_top],edi
; Re-enter protected mode ! A20 is already enabled
cli ; No interrupts please at all
lgdt [gdtinfo]
mov ecx, cr0
inc cx
mov cr0, ecx
mov ax, flat_data-gdt_table
mov fs, ax
mov gs, ax
mov ax, kernel_data-gdt_table
mov ds, ax
mov es, ax
mov ss, ax
jmp dword (flat_code-gdt_table):pmode1
read_sectors:
; Input:
; EAX = LBN
; DI = sector count
; ES = segment
; Output:
; BL = low byte of ES
; EBX high half cleared
; DL = 0x80
; EDX high half cleared
; ESI = 0
pusha
cdq ;edx = 0
movzx ebx, byte [SectorsPerTrack]
div ebx ;EAX=track ;EDX=sector-1
mov cx, dx ;CL=sector-1 ;CH=0
inc cx ; CL=Sector number
xor dx, dx
mov bl, [TotalHeads]
div ebx
mov dh, dl ;Head
mov dl, [bootdrv] ;Drive 0
xchg ch, al ;CH=Low 8 bits of cylinder number; AL=0
shr ax, 2 ;AL[6:7]=High two bits of cylinder; AH=0
or cl, al ;CX = Cylinder and sector
mov ax, di ;AX = Maximum sectors to xfer
retry:
mov ah, 2 ;Read
xor bx, bx
int 13h
jc retry
popa
ret
;**************************************
;* in:
;* si: address of message (NUL-terminated)
;* modifies:
;* nothing
;**************************************
print:
push ax
push bx
mov ah, 0eh
xor bx, bx
.1:
mov al, [si]
test al, al
jz .2
int 10h
inc si
jmp .1
.2:
pop bx
pop ax
ret
[BITS 32]
pmode1:
push dword 2
popfd
mov eax, dword[fs:memory_top]
mov ebx, KERNEL_SIZE
mov ecx, LOAD_ADDR
mov edx, RDSK_SIZE
mov esi, RDSK_ADDR
;jmp $
jmp (kernel_code-gdt_table):0
gdtinfo:
dw gdtlength
dd gdt_table
gdt_table:
null_desc desc 0,0,0
flat_code desc 0, 0xFFFFF, D_CODE + D_READ + D_BIG + D_BIG_LIM
flat_data desc 0, 0xFFFFF, D_DATA + D_WRITE + D_BIG + D_BIG_LIM
kernel_code desc LOAD_ADDR, 0xFFFFF, D_CODE + D_READ + D_BIG + D_BIG_LIM
kernel_data desc LOAD_ADDR, 0xFFFFF, D_DATA + D_WRITE + D_BIG + D_BIG_LIM
gdtlength equ $ - gdt_table - 1
sectors_total:
dw 0
msg: db "Starting The M”bius", 13, 10, 0
msg2: db "kernel", 13, 10, 0
msg3: db 13, 10, "ramdisk", 13, 10, 0
memory_top: dd 0
times 510-($-$$) nop
dw 0xAA55
kernel_start:
incbin "kernel.bin"
kernel_end:
incbin "ramdisk.bin"
ramdisk_end: