This commit is contained in:
2021-09-14 18:34:14 +03:00
parent 7cb940e485
commit 4e5c38d0ff
152 changed files with 5042 additions and 2585 deletions

16
SysBoot/makeall.bat Normal file
View File

@@ -0,0 +1,16 @@
@echo off
set nasm_path=C:\nasm
set djgpp_path=C:\DJGPP\bin
@echo ***************** CTA Bootloader *****************
@echo.
:Stage1
cd stage1
call make.bat
cd..
:Stage2
cd stage2
call make.bat
cd..

BIN
SysBoot/stage1/BOOTLOAD.BIN Normal file

Binary file not shown.

314
SysBoot/stage1/bootload.asm Normal file
View File

@@ -0,0 +1,314 @@
;*********************************************
; Boot1.asm
; - A Simple Bootloader
;
; Operating Systems Development Series
;*********************************************
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 "CTA OS " ; OEM identifier (Cannot exceed 8 bytes!)
bpbBytesPerSector: DW 512
bpbSectorsPerCluster: DB 1
bpbReservedSectors: DW 1
bpbNumberOfFATs: DB 2
bpbRootEntries: DW 224
bpbTotalSectors: DW 2880
bpbMedia: DB 0xf8 ;; 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 "CTA 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
;************************************************;
; 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
;************************************************;
; 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
;*********************************************
; 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
div WORD [bpbBytesPerSector] ; sectors used by directory
xchg ax, cx
; compute location of root directory and store in "ax"
mov al, BYTE [bpbNumberOfFATs] ; number of FATs
mul WORD [bpbSectorsPerFAT] ; sectors used by FATs
add ax, WORD [bpbReservedSectors] ; adjust for bootsector
mov WORD [datasector], ax ; base of root directory
add WORD [datasector], cx
; 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's 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
; 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:
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
absoluteSector db 0x00
absoluteHead db 0x00
absoluteTrack db 0x00
datasector dw 0x0000
cluster dw 0x0000
ImageName db "STAGE2 CTA"
msgLoading db 0x0D, "CTA OS v0.1", 0x0A, 0x0D, "(c) CTA 2010", 0x0A, 0x0D, "Loading", 0x00
msgProgress db ".", 0x00
msgFailure db 0x0D, 0x0A, "Error: Could not find stage2.bin. Press any key to reboot.", 0x0A, 0x00
TIMES 510-($-$$) db 0
DW 0xAA55

23
SysBoot/stage1/make.bat Normal file
View File

@@ -0,0 +1,23 @@
@echo off
set nasm_path=C:\nasm
set djgpp_path=C:\DJGPP\bin
goto build
:error
@echo.
@echo There have been build errors. Building halted.
@pause
exit
:build
@echo Compiling stage 1...
del bootload.bin
%nasm_path%\nasm.exe -f bin bootload.asm -o bootload.bin
:check
if not exist bootload.bin goto error
:copy
@echo Writing stage 1 to floppy boot sector...
debug bootload.bin <..\..\scripts\stage1d >nul

24
SysBoot/stage2/MAKE.BAT Normal file
View File

@@ -0,0 +1,24 @@
@echo off
set nasm_path=C:\nasm
set djgpp_path=C:\DJGPP\bin
goto build
:error
@echo.
@echo There have been build errors. Building halted.
@pause
exit
:build
@echo Compiling stage 2...
del stage2.cta
%nasm_path%\nasm.exe -f bin stage2.asm -o stage2.cta
:test
if not exist stage2.cta goto error
:copy
@echo Copying stage 2 to floppy...
copy stage2.cta A:\stage2.cta >nul

BIN
SysBoot/stage2/STAGE2.CTA Normal file

Binary file not shown.

55
SysBoot/stage2/a20.inc Normal file
View File

@@ -0,0 +1,55 @@
;********************************************
; Enable A20 address line
;
; OS Development Series
;********************************************
bits 16 ; real mode 16 bit code
_EnableA20:
cli
call a20wait
mov al,0xAD
out 0x64,al
call a20wait
mov al,0xD0
out 0x64,al
call a20wait2
in al,0x60
push eax
call a20wait
mov al,0xD1
out 0x64,al
call a20wait
pop eax
or al,2
out 0x60,al
call a20wait
mov al,0xAE
out 0x64,al
call a20wait
sti
ret
a20wait:
in al,0x64
test al,2
jnz a20wait
ret
a20wait2:
in al,0x64
test al,1
jz a20wait2
ret

View File

@@ -0,0 +1,40 @@
;*******************************************************
;
; bootinfo.inc
; multiboot information structure
;
; OS Development Series
;*******************************************************
%ifndef __BOOTINFO_INC_67343546FDCC56AAB872_INCLUDED__
%define __BOOTINFO_INC_67343546FDCC56AAB872_INCLUDED__
struc multiboot_info
.flags resd 1
.memoryLo resd 1
.memoryHi resd 1
.bootDevice resd 1
.cmdLine resd 1
.mods_count resd 1
.mods_addr resd 1
.syms0 resd 1
.syms1 resd 1
.syms2 resd 1
.mmap_length resd 1
.mmap_addr resd 1
.drives_length resd 1
.drives_addr resd 1
.config_table resd 1
.bootloader_name resd 1
.apm_table resd 1
.vbe_control_info resd 1
.vbe_mode_info resd 1
.vbe_mode resw 1
.vbe_interface_seg resw 1
.vbe_interface_off resw 1
.vbe_interface_len resw 1
endstruc
%endif

17
SysBoot/stage2/common.inc Normal file
View File

@@ -0,0 +1,17 @@
%ifndef _COMMON_INC_INCLUDED
%define _COMMON_INC_INCLUDED
; where the kernel is to be loaded to in protected mode
%define IMAGE_PMODE_BASE 0x100000
; where the kernel is to be loaded to in real mode
%define IMAGE_RMODE_BASE 0x3000
; kernel name (Must be 11 bytes)
ImageName db "KERNEL CTA"
; size of kernel image in bytes
ImageSize db 0
%endif

246
SysBoot/stage2/fat12.inc Normal file
View File

@@ -0,0 +1,246 @@
;*******************************************************
;
; Fat12.inc
; FAT12 filesystem for 3-1/2 floppies
;
; OS Development Series
;*******************************************************
%ifndef __FAT12_INC_67343546FDCC56AAB872_INCLUDED__
%define __FAT12_INC_67343546FDCC56AAB872_INCLUDED__
bits 16
%include "Floppy16.inc" ; the erm.. floppy driver
%define ROOT_OFFSET 0x2e00
%define FAT_SEG 0x2c0
%define ROOT_SEG 0x2e0
;*******************************************
; LoadRoot ()
; - Load Root Directory Table to 0x7e00
;*******************************************
LoadRoot:
pusha ; store registers
push es
; compute size of root directory and store in "cx"
xor cx, cx ; clear registers
xor dx, dx
mov ax, 32 ; 32 byte directory entry
mul WORD [bpbRootEntries] ; total size of directory
div WORD [bpbBytesPerSector] ; sectors used by directory
xchg ax, cx ; move into AX
; compute location of root directory and store in "ax"
mov al, BYTE [bpbNumberOfFATs] ; number of FATs
mul WORD [bpbSectorsPerFAT] ; sectors used by FATs
add ax, WORD [bpbReservedSectors]
mov WORD [datasector], ax ; base of root directory
add WORD [datasector], cx
; read root directory into 0x7e00
push word ROOT_SEG
pop es
mov bx, 0 ; copy root dir
call ReadSectors ; read in directory table
pop es
popa ; restore registers and return
ret
;*******************************************
; LoadFAT ()
; - Loads FAT table to 0x7c00
;
; Parm/ ES:DI => Root Directory Table
;*******************************************
LoadFAT:
pusha ; store registers
push es
; 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
; compute location of FAT and store in "ax"
mov ax, WORD [bpbReservedSectors]
; read FAT into memory (Overwrite our bootloader at 0x7c00)
push word FAT_SEG
pop es
xor bx, bx
call ReadSectors
pop es
popa ; restore registers and return
ret
;*******************************************
; FindFile ()
; - Search for filename in root table
;
; parm/ DS:SI => File name
; ret/ AX => File index number in directory table. -1 if error
;*******************************************
FindFile:
push cx ; store registers
push dx
push bx
mov bx, si ; copy filename for later
; browse root directory for binary image
mov cx, WORD [bpbRootEntries] ; load loop counter
mov di, ROOT_OFFSET ; locate first root entry at 1 MB mark
cld ; clear direction flag
.LOOP:
push cx
mov cx, 11 ; eleven character name. Image name is in SI
mov si, bx ; image name is in BX
push di
rep cmpsb ; test for entry match
pop di
je .Found
pop cx
add di, 32 ; queue next directory entry
loop .LOOP
.NotFound:
pop bx ; restore registers and return
pop dx
pop cx
mov ax, -1 ; set error code
ret
.Found:
pop ax ; return value into AX contains entry of file
pop bx ; restore registers and return
pop dx
pop cx
ret
;*******************************************
; LoadFile ()
; - Load file
; parm/ ES:SI => File to load
; parm/ EBX:BP => Buffer to load file to
; ret/ AX => -1 on error, 0 on success
;*******************************************
LoadFile:
xor ecx, ecx ; size of file in sectors
push ecx
.FIND_FILE:
push bx ; BX=>BP points to buffer to write to; store it for later
push bp
call FindFile ; find our file. ES:SI contains our filename
cmp ax, -1
jne .LOAD_IMAGE_PRE
pop bp
pop bx
pop ecx
mov ax, -1
ret
.LOAD_IMAGE_PRE:
sub edi, ROOT_OFFSET
sub eax, ROOT_OFFSET
; get starting cluster
push word ROOT_SEG ;root segment loc
pop es
mov dx, WORD [es:di + 0x001A] ; DI points to file entry in root directory table. Refrence the table...
mov WORD [cluster], dx ; file's first cluster
pop bx ; get location to write to so we dont screw up the stack
pop es
push bx ; store location for later again
push es
call LoadFAT
.LOAD_IMAGE:
; load the cluster
mov ax, WORD [cluster] ; cluster to read
pop es ; bx:bp=es:bx
pop bx
call ClusterLBA
xor cx, cx
mov cl, BYTE [bpbSectorsPerCluster]
call ReadSectors
pop ecx
inc ecx
push ecx
push bx
push es
mov ax, FAT_SEG ;start reading from fat
mov es, ax
xor bx, bx
; get 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, 0 ;location of fat in memory
add bx, cx
mov dx, WORD [es:bx]
test ax, 0x0001 ; test for odd or even cluster
jnz .ODD_CLUSTER
.EVEN_CLUSTER:
and dx, 0000111111111111b ; take low 12 bits
jmp .DONE
.ODD_CLUSTER:
shr dx, 0x0004 ; take high 12 bits
.DONE:
mov WORD [cluster], dx
cmp dx, 0x0ff0 ; test for end of file marker
jb .LOAD_IMAGE
.SUCCESS:
pop es
pop bx
pop ecx
xor ax, ax
ret
%endif ;__FAT12_INC_67343546FDCC56AAB872_INCLUDED__

121
SysBoot/stage2/floppy16.inc Normal file
View File

@@ -0,0 +1,121 @@
;*******************************************************
;
; Floppy16.inc
; Floppy drive interface routines
;
; OS Development Series
;*******************************************************
%ifndef __FLOPPY16_INC_67343546FDCC56AAB872_INCLUDED__
%define __FLOPPY16_INC_67343546FDCC56AAB872_INCLUDED__
bits 16
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 "MOS FLOPPY "
bsFileSystem: DB "FAT12 "
datasector dw 0x0000
cluster dw 0x0000
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:EBX=>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:
pop cx
pop bx
pop ax
add bx, WORD [bpbBytesPerSector] ; queue next buffer
inc ax ; queue next sector
loop .MAIN ; read next sector
ret
%endif ;__FLOPPY16_INC_67343546FDCC56AAB872_INCLUDED__

68
SysBoot/stage2/gdt.inc Normal file
View File

@@ -0,0 +1,68 @@
;*************************************************
; Gdt.inc
; -GDT Routines
;
; OS Development Series
;*************************************************
%ifndef __GDT_INC_67343546FDCC56AAB872_INCLUDED__
%define __GDT_INC_67343546FDCC56AAB872_INCLUDED__
bits 16
;*******************************************
; InstallGDT()
; - Install our GDT
;*******************************************
InstallGDT:
cli ; clear interrupts
pusha ; save registers
lgdt [toc] ; load GDT into GDTR
sti ; enable interrupts
popa ; restore registers
ret ; All done!
;*******************************************
; Global Descriptor Table (GDT)
;*******************************************
gdt_data:
dd 0 ; null descriptor
dd 0
; gdt code: ; code descriptor
dw 0FFFFh ; limit low
dw 0 ; base low
db 0 ; base middle
db 10011010b ; access
db 11001111b ; granularity
db 0 ; base high
; gdt data: ; data descriptor
dw 0FFFFh ; limit low (Same as code)10:56 AM 7/8/2007
dw 0 ; base low
db 0 ; base middle
db 10010010b ; access
db 11001111b ; granularity
db 0 ; base high
end_of_gdt:
toc:
dw end_of_gdt - gdt_data - 1 ; limit (Size of GDT)
dd gdt_data ; base of GDT
; give the descriptor offsets names
%define NULL_DESC 0
%define CODE_DESC 0x8
%define DATA_DESC 0x10
%endif ;__GDT_INC_67343546FDCC56AAB872_INCLUDED__

175
SysBoot/stage2/memory.inc Normal file
View File

@@ -0,0 +1,175 @@
;*************************************************
; Memory.inc
; -Basic memory routines
;
; OS Development Series
;*************************************************
%ifndef __MEMORY_INC_67343546FDCC56AAB872_INCLUDED__
%define __MEMORY_INC_67343546FDCC56AAB872_INCLUDED__
bits 16
;--------------------------------------------
; Memory map entry structure
;--------------------------------------------
struc MemoryMapEntry
.baseAddress resq 1
.length resq 1
.type resd 1
.acpi_null resd 1
endstruc
;---------------------------------------------
; Get memory map from bios
; /in es:di->destination buffer for entries
; /ret bp=entry count
;---------------------------------------------
BiosGetMemoryMap:
pushad
xor ebx, ebx
xor bp, bp ; number of entries stored here
mov edx, 'PAMS' ; 'SMAP'
mov eax, 0xe820
mov ecx, 24 ; memory map entry struct is 24 bytes
int 0x15 ; get first entry
jc .error
cmp eax, 'PAMS' ; bios returns SMAP in eax
jne .error
test ebx, ebx ; if ebx=0 then list is one entry long; bail out
je .error
jmp .start
.next_entry:
mov edx, 'PAMS' ; some bios's trash this register
mov ecx, 24 ; entry is 24 bytes
mov eax, 0xe820
int 0x15 ; get next entry
.start:
jcxz .skip_entry ; if actual returned bytes is 0, skip entry
.notext:
mov ecx, [es:di + MemoryMapEntry.length] ; get length (low dword)
test ecx, ecx ; if length is 0 skip it
jne short .good_entry
mov ecx, [es:di + MemoryMapEntry.length + 4]; get length (upper dword)
jecxz .skip_entry ; if length is 0 skip it
.good_entry:
inc bp ; increment entry count
add di, 24 ; point di to next entry in buffer
.skip_entry:
cmp ebx, 0 ; if ebx return is 0, list is done
jne .next_entry ; get next entry
jmp .done
.error:
stc
.done:
popad
ret
;---------------------------------------------
; Get memory size for >64M configuations (32 bit)
; ret\ ax=KB between 1MB and 16MB
; ret\ bx=number of 64K blocks above 16MB
; ret\ bx=0 and ax= -1 on error
;---------------------------------------------
BiosGetMemorySize64MB_32Bit:
push ecx
push edx
xor ecx, ecx
xor edx, edx
mov ax, 0xe881
int 0x15
jc .error
cmp ah, 0x86 ;unsupported function
je .error
cmp ah, 0x80 ;invalid command
je .error
jcxz .use_ax ;bios may have stored it in ax,bx or cx,dx. test if cx is 0
mov ax, cx ;its not, so it should contain mem size; store it
mov bx, dx
.use_ax:
pop edx ;mem size is in ax and bx already, return it
pop ecx
ret
.error:
mov ax, -1
mov bx, 0
pop edx
pop ecx
ret
;---------------------------------------------
; Get memory size for >64M configuations
; ret\ ax=KB between 1MB and 16MB
; ret\ bx=number of 64K blocks above 16MB
; ret\ bx=0 and ax= -1 on error
;---------------------------------------------
BiosGetMemorySize64MB:
push ecx
push edx
xor ecx, ecx
xor edx, edx
mov ax, 0xe801
int 0x15
jc .error
cmp ah, 0x86 ;unsupported function
je .error
cmp ah, 0x80 ;invalid command
je .error
jcxz .use_ax ;bios may have stored it in ax,bx or cx,dx. test if cx is 0
mov ax, cx ;its not, so it should contain mem size; store it
mov bx, dx
.use_ax:
pop edx ;mem size is in ax and bx already, return it
pop ecx
ret
.error:
mov si, msgNotSupported
call Puts16
mov ax, -1
mov bx, 0
pop edx
pop ecx
ret
;---------------------------------------------
; Get amount of contiguous KB from addr 0
; ret\ ax=KB size from address 0
;---------------------------------------------
BiosGetMemorySize:
int 0x12
ret
;---------------------------------------------
; Get contiguous exetended memory size
; ret\ ax=KB size above 1MB; ax= -1 on error
;---------------------------------------------
BiosGetExtendedMemorySize:
mov ax, 0x88
int 0x15
jc .error
test ax, ax ; if size=0
je .error
cmp ah, 0x86 ;unsupported function
je .error
cmp ah, 0x80 ;invalid command
je .error
ret
.error:
mov ax, -1
ret
msgNotSupported db 0x0A, 0x0D, "BiosGetMemorySize64MB: function not supported.",0x0A, 0x0D, 0x00
%endif

172
SysBoot/stage2/stage2.asm Normal file
View File

@@ -0,0 +1,172 @@
;*******************************************************
;
; Stage2.asm
; Stage2 Bootloader
;
; OS Development Series
;*******************************************************
bits 16
org 0x500
jmp main ; go to start
;*******************************************************
; Preprocessor directives
;*******************************************************
%include "stdio.inc" ; basic i/o routines
%include "gdt.inc" ; Gdt routines
%include "a20.inc" ; A20 enabling
%include "fat12.inc" ; FAT12 driver. Kinda :)
%include "common.inc"
;%include "bootinfo.inc"
%include "memory.inc"
;*******************************************************
; Data Section
;*******************************************************
msgFailure db 0x0D, 0x0A, "FATAL ERROR: Kernel file KERNEL.CTA missing or corrupt. Press Any Key to Reboot.", 0x0D, 0x0A, 0x0A, 0x00
boot_info:
multiboot_info_flags dd 0
multiboot_info_memoryLo dd 0
multiboot_info_memoryHi dd 0
multiboot_info_bootDevice dd 0
multiboot_info_cmdLine dd 0
multiboot_info_mods_count dd 0
multiboot_info_mods_addr dd 0
multiboot_info_syms0 dd 0
multiboot_info_syms1 dd 0
multiboot_info_syms2 dd 0
multiboot_info_mmap_length dd 0
multiboot_info_mmap_addr dd 0
multiboot_info_drives_length dd 0
multiboot_info_drives_addr dd 0
multiboot_info_config_table dd 0
multiboot_info_bootloader_name dd 0
multiboot_info_apm_table dd 0
multiboot_info_vbe_control_info dd 0
multiboot_info_vbe_mode_info dw 0
multiboot_info_vbe_interface_seg dw 0
multiboot_info_vbe_interface_off dw 0
multiboot_info_vbe_interface_len dw 0
main:
;-------------------------------;
; Setup segments and stack ;
;-------------------------------;
cli ; clear interrupts
xor ax, ax ; null segments
mov ds, ax
mov es, ax
mov ax, 0x0000 ; stack begins at 0x9000-0xffff
mov ss, ax
mov sp, 0xFFFF
sti ; enable interrupts
mov [multiboot_info_bootDevice], dl
call _EnableA20
call InstallGDT
sti
xor eax, eax
xor ebx, ebx
call BiosGetMemorySize64MB
mov word [multiboot_info_memoryHi], bx
mov word [multiboot_info_memoryLo], ax
mov eax, 0x0
mov ds, ax
mov di, 0x1000
call BiosGetMemoryMap
mov dword [multiboot_info_mmap_addr], 0x1000
xor eax, eax
mov ax, bp
mov dword [multiboot_info_mmap_length], eax
call LoadRoot
mov ebx, 0
mov ebp, IMAGE_RMODE_BASE
mov esi, ImageName
call LoadFile ; load our file
mov dword [ImageSize], ecx
cmp ax, 0
je EnterStage3
mov si, msgFailure
call Puts16
mov ah, 0
int 0x16 ; await keypress
int 0x19 ; warm boot computer
;-------------------------------;
; Go into pmode ;
;-------------------------------;
EnterStage3:
cli ; clear interrupts
mov eax, cr0 ; set bit 0 in cr0--enter pmode
or eax, 1
mov cr0, eax
jmp CODE_DESC:Stage3 ; far jump to fix CS. Remember that the code selector is 0x8!
; Note: Do NOT re-enable interrupts! Doing so will triple fault!
; We will fix this in Stage 3.
;******************************************************
; ENTRY POINT FOR STAGE 3
;******************************************************
bits 32
BadImage db "FATAL ERROR: Kernel file KERNEL.CTA missing or corrupt. Press Any Key to Reboot.", 0
Stage3:
;-------------------------------;
; Set registers ;
;-------------------------------;
mov ax, DATA_DESC ; set data segments to data selector (0x10)
mov ds, ax
mov ss, ax
mov es, ax
mov esp, 90000h ; stack begins from 90000h
CopyImage:
mov eax, dword [ImageSize]
movzx ebx, word [bpbBytesPerSector]
mul ebx
mov ebx, 4
div ebx
cld
mov esi, IMAGE_RMODE_BASE
mov edi, IMAGE_PMODE_BASE
mov ecx, eax
rep movsd ; copy image to its protected mode address
mov eax, 0x2badb002 ; multiboot specs say eax should be this
mov ebx, 0
;edx=8
push dword boot_info
push dword [ImageSize]
jmp CODE_DESC:IMAGE_PMODE_BASE ; Execute Kernel
add esp, 4
cli
hlt

295
SysBoot/stage2/stdio.inc Normal file
View File

@@ -0,0 +1,295 @@
;*************************************************
; stdio.inc
; -Input/Output routines
;
; OS Development Series
;*************************************************
%ifndef __STDIO_INC_67343546FDCC56AAB872_INCLUDED__
%define __STDIO_INC_67343546FDCC56AAB872_INCLUDED__
;==========================================================
;
; 16 Bit Real Mode Routines
;==========================================================
;************************************************;
; Puts16 ()
; -Prints a null terminated string
; DS=>SI: 0 terminated string
;************************************************;
tmpStr db " ", 0x0D, 0x0A, 0x00
bits 16
Puts16:
pusha ; save registers
.Loop1:
lodsb ; load next byte from string from SI to AL
or al, al ; Does AL=0?
jz Puts16Done ; Yep, null terminator found-bail out
mov ah, 0eh ; Nope-Print the character
int 10h ; invoke BIOS
jmp .Loop1 ; Repeat until null terminator found
Puts16Done:
popa ; restore registers
ret ; we are done, so return
PutINT:
pusha ; save registers
mov cx, 0
.init:
mov bx, cx
add bx, tmpStr
mov [bx], byte ' '
inc cx
cmp cx, 31
jne .init
mov cx, 31 ; initialize counter
.loop:
mov dx, 0
mov bx, 0x0A
div bx ; ax = ax/10, dx = ax%10
mov bx, cx
add bx, tmpStr
add dl, '0'
mov [bx], dl
sub cx, 1
cmp ax, 0 ; when done, ax = 0;
je .done
jmp .loop
.done:
mov si, tmpStr
call Puts16
popa
ret
;==========================================================
;
; 32 Bit Protected Mode Routines
;==========================================================
bits 32
%define VIDMEM 0xB8000 ; video memory
%define COLS 80 ; width and height of screen
%define LINES 25
%define CHAR_ATTRIB 14 ; character attribute (White text on black background)
_CurX db 0 ; current x/y location
_CurY db 0
;**************************************************;
; Putch32 ()
; - Prints a character to screen
; BL => Character to print
;**************************************************;
Putch32:
pusha
mov edi, VIDMEM
xor eax, eax ; clear eax
; y * screen width
mov ecx, COLS*2 ; Mode 7 has 2 bytes per char, so its COLS*2 bytes per line
mov al, byte [_CurY] ; get y pos
mul ecx ; multiply y*COLS
push eax ; save eax--the multiplication
; now add _CurX * 2
mov al, byte [_CurX] ; multiply _CurX by 2 because it is 2 bytes per char
mov cl, 2
mul cl
pop ecx ; pop y*COLS result
add eax, ecx
; add the position to draw to the base of vid memory
xor ecx, ecx
add edi, eax ; add it to the base address
; watch for new line
cmp bl, 0x0A ; is it a newline character?
je .Row ; yep--go to next row
; print the character
mov dl, bl ; Get character
mov dh, CHAR_ATTRIB ; the character attribute
mov word [edi], dx ; write to video display
; go to next location
inc byte [_CurX] ; go to next character
jmp .done ; nope, bail out
.Row:
mov byte [_CurX], 0 ; go back to col 0
inc byte [_CurY] ; go to next row
.done:
popa
ret
;**************************************************;
; Puts32 ()
; - Prints a null terminated string
; parm\ EBX = address of string to print
;**************************************************;
Puts32:
pusha
push ebx ; copy the string address
pop edi
.loop:
;-------------------------------;
; Get character ;
;-------------------------------;
mov bl, byte [edi] ; get next character
cmp bl, 0 ; is it 0 (Null terminator)?
je .done ; yep-bail out
;-------------------------------;
; Print the character ;
;-------------------------------;
call Putch32 ; Nope-print it out
;-------------------------------;
; Go to next character ;
;-------------------------------;
inc edi ; go to next character
jmp .loop
.done:
;-------------------------------;
; Update hardware cursor ;
;-------------------------------;
mov bh, byte [_CurY] ; get current position
mov bl, byte [_CurX]
call MovCur ; update cursor
popa ; restore registers, and return
ret
;**************************************************;
; MoveCur ()
; - Update hardware cursor
; parm/ bh = Y pos
; parm/ bl = x pos
;**************************************************;
bits 32
MovCur:
pusha
;-------------------------------;
; Get current position ;
;-------------------------------;
; location = _CurX + _CurY * COLS
xor eax, eax
mov ecx, COLS
mov al, bh ; get y pos
mul ecx ; multiply y*COLS
add al, bl ; Now add x
mov ebx, eax
;--------------------------------------;
; Set low byte index to VGA register ;
;--------------------------------------;
mov al, 0x0f
mov dx, 0x03D4
out dx, al
mov al, bl
mov dx, 0x03D5
out dx, al ; low byte
;---------------------------------------;
; Set high byte index to VGA register ;
;---------------------------------------;
xor eax, eax
mov al, 0x0e
mov dx, 0x03D4
out dx, al
mov al, bh
mov dx, 0x03D5
out dx, al ; high byte
popa
ret
;**************************************************;
; ClrScr32 ()
; - Clears screen
;**************************************************;
bits 32
ClrScr32:
pusha
cld
mov edi, VIDMEM
mov cx, 2000
mov ah, CHAR_ATTRIB
mov al, ' '
rep stosw
mov byte [_CurX], 0
mov byte [_CurY], 0
popa
ret
;**************************************************;
; GotoXY ()
; - Set current X/Y location
; parm\ AL=X position
; parm\ AH=Y position
;**************************************************;
bits 32
GotoXY:
pusha
mov [_CurX], al
mov [_CurY], ah
popa
ret
%endif ;__STDIO_INC_67343546FDCC56AAB872_INCLUDED__