mirror of
https://github.com/gbowne1/ClassicOS.git
synced 2024-11-23 14:26:52 -08:00
fixing up a bunch of files including the bootloader and kernel malloc kmalloc
This commit is contained in:
parent
79edf9eb6e
commit
3554f240a8
BIN
.vscode/browse.vc.db
vendored
BIN
.vscode/browse.vc.db
vendored
Binary file not shown.
BIN
.vscode/browse.vc.db-shm
vendored
BIN
.vscode/browse.vc.db-shm
vendored
Binary file not shown.
@ -1,165 +1,249 @@
|
|||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
[bits 16]
|
||||||
; Stage 1 bootloader for ClassicOS ;
|
[org 0x7c00]
|
||||||
; -------------------------------- ;
|
|
||||||
; Determines if it was loaded from ;
|
|
||||||
; a floppy disk or an hard disk ;
|
|
||||||
; drive, and then loads stage 2 ;
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
; Assembler directives ;
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
|
|
||||||
; tells the assembler that the program will be loaded at 0x7C00
|
|
||||||
; this is done by the BIOS
|
|
||||||
org 0x7C00
|
|
||||||
|
|
||||||
; we are targeting (x86) 16-bit real mode
|
|
||||||
bits 16
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;
|
|
||||||
; Jump to start ;
|
|
||||||
;;;;;;;;;;;;;;;;;
|
|
||||||
jmp start
|
|
||||||
|
|
||||||
;;;;;;;;
|
|
||||||
; Data ;
|
|
||||||
;;;;;;;;
|
|
||||||
; fdd geometry & options
|
|
||||||
fddsamt db 1 ; how many sectors to load
|
|
||||||
fddretr db 5 ; max retries for fdd operations
|
|
||||||
fddcretr db 0 ; current retries left
|
|
||||||
|
|
||||||
; misc strings
|
|
||||||
welcome1 db "Welcome to the ClassicOS Stage 1 bootloader.", 13, 10, 0
|
|
||||||
disktype db "Drive type: ", 0
|
|
||||||
diskfdd db "FDD", 13, 10, 0
|
|
||||||
diskhdd db "HDD", 13, 10, 0
|
|
||||||
loaded db "Data loaded!", 13, 10, 0
|
|
||||||
|
|
||||||
; errors
|
|
||||||
fdderes db "FDD reset failed.", 13, 10, 0
|
|
||||||
fddeload db "FDD read failed.", 13, 10, 0
|
|
||||||
|
|
||||||
; storage
|
|
||||||
disknum db 0
|
|
||||||
|
|
||||||
;;;;;;;;;;;
|
|
||||||
; Program ;
|
|
||||||
;;;;;;;;;;;
|
|
||||||
|
|
||||||
start:
|
start:
|
||||||
xor ax, ax ; set up segment registers to segment 0 since
|
;Set up segments correctly
|
||||||
mov ds, ax ; our addresses are already relative to 0x7C00
|
xor ax, ax
|
||||||
|
mov ds, ax
|
||||||
mov es, ax
|
mov es, ax
|
||||||
|
mov fs, ax
|
||||||
|
mov gs, ax
|
||||||
|
|
||||||
mov [disknum], dl ; save disk number to memory
|
;Set up stack
|
||||||
|
mov ss, ax
|
||||||
|
mov bp, 0x7c00
|
||||||
|
mov sp, bp
|
||||||
|
|
||||||
mov ah, 0x01 ; set cursor shape
|
;Save boot device number
|
||||||
mov cx, 0x0100 ; hide cursor by setting ch = 1 and cl = 0x00
|
mov [bootdev], dl
|
||||||
int 0x10 ; video interrupt
|
|
||||||
|
|
||||||
mov ah, 0x08 ; read page number into bh
|
;Enable A20 Gate
|
||||||
int 0x10
|
EnableA20Gate:
|
||||||
|
call TestA20
|
||||||
|
cmp ax, 1
|
||||||
|
je A20Enabled
|
||||||
|
|
||||||
mov si, welcome1 ; print welcome
|
tryUsingBIOS:
|
||||||
call printstr
|
mov ax, 0x2401
|
||||||
|
int 0x15
|
||||||
|
call TestA20
|
||||||
|
cmp ax, 1
|
||||||
|
je A20Enabled
|
||||||
|
|
||||||
mov si, disktype ; print first part of disk type
|
tryUsingKeyboardController:
|
||||||
call printstr
|
|
||||||
|
|
||||||
mov dl, [disknum] ; restore disk number - should not be
|
|
||||||
; strictly necessary but you never know
|
|
||||||
and dl, 0x80 ; sets zf if disk is floppy
|
|
||||||
jz fddload
|
|
||||||
|
|
||||||
hddload:
|
|
||||||
mov si, diskhdd ; print disk type
|
|
||||||
call printstr
|
|
||||||
jmp load_onto_reset
|
|
||||||
|
|
||||||
fddload:
|
|
||||||
mov si, diskfdd ; print disk type
|
|
||||||
call printstr
|
|
||||||
|
|
||||||
load_onto_reset:
|
|
||||||
mov ah, [fddretr] ; load max retries in memory
|
|
||||||
mov [fddcretr], ah
|
|
||||||
load_reset:
|
|
||||||
mov si, fdderes ; load error message pointer
|
|
||||||
dec byte [fddcretr] ; decrement the retries counter
|
|
||||||
jz load_err ; if it is 0, we stop trying
|
|
||||||
|
|
||||||
mov ah, 0x00 ; otherwise, reset function (int 0x13)
|
|
||||||
int 0x13
|
|
||||||
jc load_reset ; if jc (error), we try again
|
|
||||||
|
|
||||||
load_onto_load:
|
|
||||||
mov ah, [fddretr] ; reset retries counter
|
|
||||||
mov [fddcretr], ah
|
|
||||||
mov ax, 0x8000 ; need to stay within real mode limits
|
|
||||||
mov es, ax
|
|
||||||
load_load: ; loads 512*fddsamt bytes from sector 2 on.
|
|
||||||
mov si, fddeload
|
|
||||||
dec byte [fddcretr]
|
|
||||||
jz load_err
|
|
||||||
|
|
||||||
mov dh, 0 ; head 0
|
|
||||||
mov ch, 0 ; cyl/track 0
|
|
||||||
mov cl, 2 ; start sector
|
|
||||||
mov bx, 0x8000 ; memory location
|
|
||||||
mov al, [fddsamt] ; how many sectors to read
|
|
||||||
mov ah, 0x02 ; read function (int 0x13)
|
|
||||||
int 0x13
|
|
||||||
jc load_load ; if jc (error), we try again
|
|
||||||
cmp al, [fddsamt] ; also if al is not 1, we have a problem
|
|
||||||
jnz load_load
|
|
||||||
|
|
||||||
load_done:
|
|
||||||
mov si, loaded ; we have successfully loaded the data
|
|
||||||
call printstr
|
|
||||||
jmp 0x8000:0x0000 ; this will be jmp 0x1000:0x0000
|
|
||||||
|
|
||||||
load_err:
|
|
||||||
call printstr ; print
|
|
||||||
jmp halt ; and die
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
; printstr routine, prints the string pointed by si using int 0x10 ;
|
|
||||||
; sets the direction flag to 0 ;
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
printstr:
|
|
||||||
cld ; clear df flag - lodsb increments si
|
|
||||||
printstr_loop:
|
|
||||||
lodsb ; load next character into al, increment si
|
|
||||||
or al, al ; sets zf if al is 0x00
|
|
||||||
jz printstr_end
|
|
||||||
mov ah, 0x0E ; teletype output (int 0x10)
|
|
||||||
int 0x10 ; print character
|
|
||||||
jmp printstr_loop
|
|
||||||
printstr_end:
|
|
||||||
ret ; return to caller address
|
|
||||||
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
; halt routine - infinite loop ;
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
halt:
|
|
||||||
cli
|
cli
|
||||||
jmp halt
|
call WaitCommand
|
||||||
|
mov al, 0xAD ;Disable the keyboard
|
||||||
|
out 0x64, al
|
||||||
|
|
||||||
;;;;;;;;;;;
|
call WaitCommand
|
||||||
; Padding ;
|
mov al, 0xD0 ;Read from input
|
||||||
;;;;;;;;;;;
|
out 0x64, al
|
||||||
; $ is the address of the current line, $$ is the base address for
|
|
||||||
; this program.
|
|
||||||
; the expression is expanded to 510 - ($ - 0x7C00), or
|
|
||||||
; 510 + 0x7C00 - $, which is, in other words, the number of bytes
|
|
||||||
; before the address 510 + 0x7C00 (= 0x7DFD), where the 0xAA55
|
|
||||||
; signature shall be put.
|
|
||||||
times 510 - ($ - $$) db 0x00
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;
|
call WaitData
|
||||||
; BIOS signature ;
|
in al, 0x60 ;Read input from keyboard
|
||||||
;;;;;;;;;;;;;;;;;;
|
push ax ;Save it
|
||||||
dw 0xAA55
|
|
||||||
|
call WaitCommand
|
||||||
|
mov al, 0xD1 ;Write to output
|
||||||
|
out 0x64, al
|
||||||
|
|
||||||
|
call WaitCommand
|
||||||
|
pop ax ;Write to input back with bit #2 set
|
||||||
|
or al, 2
|
||||||
|
out 0x60, al
|
||||||
|
|
||||||
|
call WaitCommand
|
||||||
|
mov al, 0xAE ;Enable Keyboard
|
||||||
|
out 0x64, al
|
||||||
|
|
||||||
|
call WaitCommand
|
||||||
|
sti
|
||||||
|
jmp A20KeyboardCheck
|
||||||
|
|
||||||
|
WaitCommand:
|
||||||
|
in al, 0x64
|
||||||
|
test al, 2
|
||||||
|
jnz WaitCommand
|
||||||
|
ret
|
||||||
|
|
||||||
|
WaitData:
|
||||||
|
in al, 0x64
|
||||||
|
test al, 1
|
||||||
|
jz WaitData
|
||||||
|
ret
|
||||||
|
|
||||||
|
A20KeyboardCheck:
|
||||||
|
call TestA20
|
||||||
|
cmp ax, 1
|
||||||
|
je A20Enabled
|
||||||
|
|
||||||
|
UseFastA20Method:
|
||||||
|
in al, 0x92
|
||||||
|
or al, 2
|
||||||
|
out 0x92, al
|
||||||
|
call TestA20
|
||||||
|
cmp ax, 1
|
||||||
|
je A20Enabled
|
||||||
|
|
||||||
|
;Else bail out, A20 cannot be enabled, maybe :)
|
||||||
|
A20Error:
|
||||||
|
mov si, A20_error_msg
|
||||||
|
call print
|
||||||
|
xor ax, ax
|
||||||
|
int 16h
|
||||||
|
xor ax, ax
|
||||||
|
int 19h
|
||||||
|
|
||||||
|
jmp $
|
||||||
|
;If we ever get here, A20 is enabled!
|
||||||
|
A20Enabled:
|
||||||
|
LoadSecondStage:
|
||||||
|
push es
|
||||||
|
mov ax, 0x7e0
|
||||||
|
mov es, ax
|
||||||
|
|
||||||
|
stc
|
||||||
|
mov dh, 0
|
||||||
|
mov ah, 0x02
|
||||||
|
mov al, 2 ;load 2 sectors
|
||||||
|
mov ch, 0
|
||||||
|
mov cl, 2
|
||||||
|
|
||||||
|
mov dl, [bootdev]
|
||||||
|
|
||||||
|
xor bx, bx ; [es:bx] = 0x07e0:0x0000
|
||||||
|
int 13h
|
||||||
|
|
||||||
|
jnc load_success
|
||||||
|
|
||||||
|
disk_error:
|
||||||
|
mov si, disk_read_error_msg
|
||||||
|
call print
|
||||||
|
xor ax, ax
|
||||||
|
int 16h
|
||||||
|
xor ax, ax
|
||||||
|
int 19h
|
||||||
|
|
||||||
|
jmp $
|
||||||
|
|
||||||
|
load_success:
|
||||||
|
pop es
|
||||||
|
mov dl, [bootdev]
|
||||||
|
jmp 0x07e0:0x0000
|
||||||
|
|
||||||
|
jmp $
|
||||||
|
|
||||||
|
;Print string routine
|
||||||
|
print:
|
||||||
|
pusha
|
||||||
|
|
||||||
|
.loop:
|
||||||
|
lodsb
|
||||||
|
cmp al, 0
|
||||||
|
je .done
|
||||||
|
mov ah, 0x0e
|
||||||
|
int 10h
|
||||||
|
jmp .loop
|
||||||
|
|
||||||
|
.done:
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
;****************************
|
||||||
|
;Function to check if A20 Gate is enabled
|
||||||
|
;IN = nothing
|
||||||
|
;OUT : AX = status; 0 = Disabled, 1 = Enabled
|
||||||
|
TestA20:
|
||||||
|
cli
|
||||||
|
push es
|
||||||
|
push di
|
||||||
|
push ds
|
||||||
|
push si
|
||||||
|
|
||||||
|
push bx
|
||||||
|
push dx
|
||||||
|
|
||||||
|
xor dx, dx
|
||||||
|
xor bx, bx
|
||||||
|
|
||||||
|
mov es, bx
|
||||||
|
mov di, 0x0500
|
||||||
|
|
||||||
|
mov bx, 0xffff
|
||||||
|
mov ds, bx
|
||||||
|
mov si, 0x0510
|
||||||
|
|
||||||
|
mov al, byte [es:di]
|
||||||
|
push ax
|
||||||
|
|
||||||
|
mov al, byte [ds:si]
|
||||||
|
push ax
|
||||||
|
|
||||||
|
mov [es:di], byte 0x00
|
||||||
|
mov [ds:si], byte 0xff
|
||||||
|
|
||||||
|
mov bl, byte [es:di]
|
||||||
|
cmp bl, 0xff
|
||||||
|
je A20Exit
|
||||||
|
mov dx, 0x0001 ;A20 Enabled
|
||||||
|
|
||||||
|
A20Exit:
|
||||||
|
pop ax
|
||||||
|
mov [ds:si], al
|
||||||
|
pop ax
|
||||||
|
mov [es:di], al
|
||||||
|
|
||||||
|
mov ax, dx
|
||||||
|
pop dx
|
||||||
|
pop bx
|
||||||
|
pop si
|
||||||
|
pop ds
|
||||||
|
pop di
|
||||||
|
pop es
|
||||||
|
sti
|
||||||
|
ret
|
||||||
|
;;;;;;End of function;;;;;;;;;;;;
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
disk_read_error_msg db 'Error Reading disk. Press any key to reboot. Code : 0x01', 0
|
||||||
|
A20_error_msg db 'An Internal error occured. Press any key to reboot. Code: 0x02', 0
|
||||||
|
bootdev db 0
|
||||||
|
|
||||||
|
times 442 - ($-$$) db 0
|
||||||
|
dd 0x07112026 ;Boot signature: Unique for each boot disk this OS is installed on ;6:20 PM
|
||||||
|
|
||||||
|
;Written on 7th November, 2020 6:20 pm
|
||||||
|
;Partition tables
|
||||||
|
; #1
|
||||||
|
|
||||||
|
db 0x0
|
||||||
|
db 0
|
||||||
|
db 0
|
||||||
|
db 0
|
||||||
|
db 0x00 ;Reserved
|
||||||
|
db 0
|
||||||
|
db 0
|
||||||
|
db 0
|
||||||
|
dd 0x0
|
||||||
|
dd 20480
|
||||||
|
|
||||||
|
; #2
|
||||||
|
db 0x80
|
||||||
|
db 0
|
||||||
|
db 0
|
||||||
|
db 0
|
||||||
|
db 07h ;FAT 32 fs
|
||||||
|
db 0
|
||||||
|
db 0
|
||||||
|
db 0
|
||||||
|
dd 20480
|
||||||
|
dd 8388608
|
||||||
|
|
||||||
|
; #3
|
||||||
|
times 16 db 0
|
||||||
|
|
||||||
|
; #4
|
||||||
|
times 16 db 0
|
||||||
|
|
||||||
|
dw 0xaa55
|
Binary file not shown.
@ -1,133 +1,473 @@
|
|||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
[bits 16]
|
||||||
; Stage 2 bootloader for ClassicOS ;
|
[org 0x7e00]
|
||||||
; -------------------------------- ;
|
|
||||||
; Loads the kernel, sets up tables, ;
|
|
||||||
; and transitions to protected mode ;
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
; Assembler directives ;
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
|
|
||||||
; tells the assembler that the program will be loaded at 0x8000
|
|
||||||
; this is done by the first stage bootloader
|
|
||||||
org 0x8000
|
|
||||||
|
|
||||||
; we are targeting (x86) 16-bit real mode
|
|
||||||
bits 16
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;
|
|
||||||
; Jump to start ;
|
|
||||||
;;;;;;;;;;;;;;;;;
|
|
||||||
jmp start
|
|
||||||
|
|
||||||
;;;;;;;;
|
|
||||||
; Data ;
|
|
||||||
;;;;;;;;
|
|
||||||
; kernel file name
|
|
||||||
kername db "KERNEL.BIN", 0
|
|
||||||
|
|
||||||
;;;;;;;;;;;
|
|
||||||
; Program ;
|
|
||||||
;;;;;;;;;;;
|
|
||||||
|
|
||||||
start:
|
start:
|
||||||
xor ax, ax ; set up segment registers to segment 0 since
|
mov [bootdev], dl
|
||||||
mov ds, ax ; our addresses are already relative to 0x8000
|
|
||||||
|
GetVesaControllerInfo:
|
||||||
|
;Preset 1st 4 bytes of block with
|
||||||
|
; 'VBE2' to get VBE2 information
|
||||||
|
|
||||||
|
mov di, VESAControllerInfo
|
||||||
|
mov byte [di], 'V'
|
||||||
|
mov byte [di+1], 'B'
|
||||||
|
mov byte [di+2], 'E'
|
||||||
|
mov byte [di+3], '2'
|
||||||
|
|
||||||
|
;Function 00h: get VESA controller information
|
||||||
|
|
||||||
|
mov ax, 0x4f00
|
||||||
|
int 10h
|
||||||
|
|
||||||
|
;Get pointer to list of supported modes
|
||||||
|
mov ax, word [VESAControllerInfo+14]
|
||||||
|
|
||||||
|
push ax
|
||||||
|
shr ax, 4 ;Grab segment of pointer
|
||||||
|
mov bx, ax ;and save it
|
||||||
|
|
||||||
|
pop ax
|
||||||
|
and ax, 0x000f
|
||||||
|
|
||||||
|
mov dx, word [VESAControllerInfo+16] ;pointer's offset
|
||||||
|
add dx, ax
|
||||||
|
|
||||||
|
push es ;Save 'es' on stack
|
||||||
|
mov es, bx ;Segment
|
||||||
|
mov di, dx ;Offset
|
||||||
|
; mov si, VESAControllerInfo ;Print VESA
|
||||||
|
; call print
|
||||||
|
|
||||||
|
save_available_video_modes:
|
||||||
|
mov bx, VbeModeList
|
||||||
|
|
||||||
|
.save_modes_loop: ;Save all available modes
|
||||||
|
mov ax, word [es:di]
|
||||||
|
|
||||||
|
cmp ax, 0xffff ;End of list?
|
||||||
|
je finished_mode_save
|
||||||
|
|
||||||
|
mov [bx], ax ;Save mode number
|
||||||
|
|
||||||
|
add bx, 2
|
||||||
|
add di, 2
|
||||||
|
jmp .save_modes_loop
|
||||||
|
|
||||||
|
finished_mode_save:
|
||||||
|
mov [bx], ax
|
||||||
|
pop es
|
||||||
|
jmp short do_e820
|
||||||
|
|
||||||
|
mmap_ent equ mem_map_entries_count ; the number of entries will be stored at mem_map_entries_count
|
||||||
|
|
||||||
|
do_e820:
|
||||||
|
pusha
|
||||||
|
push es
|
||||||
|
push bp
|
||||||
|
|
||||||
|
mov ax, 0x3000
|
||||||
|
mov es, ax
|
||||||
|
mov di, 0
|
||||||
|
xor ebx, ebx ; ebx must be 0 to start
|
||||||
|
xor bp, bp ; keep an entry count in bp
|
||||||
|
mov edx, 0x0534D4150 ; Place "SMAP" into edx
|
||||||
|
mov eax, 0x0000e820
|
||||||
|
mov [es:di + 20], dword 1 ; force a valid ACPI 3.X entry
|
||||||
|
mov ecx, 24 ; ask for 24 bytes
|
||||||
|
int 0x15
|
||||||
|
jc short .failed ; carry set on first call means "unsupported function"
|
||||||
|
mov edx, 0x0534D4150 ; Some BIOSes apparently trash this register?
|
||||||
|
cmp eax, edx ; on success, eax must have been reset to "SMAP"
|
||||||
|
jne short .failed
|
||||||
|
test ebx, ebx ; ebx = 0 implies list is only 1 entry long (worthless)
|
||||||
|
je short .failed
|
||||||
|
jmp short .jmpin
|
||||||
|
|
||||||
|
.e820lp:
|
||||||
|
mov eax, 0xe820 ; eax, ecx get trashed on every int 0x15 call
|
||||||
|
mov [es:di + 20], dword 1 ; force a valid ACPI 3.X entry
|
||||||
|
mov ecx, 24 ; ask for 24 bytes again
|
||||||
|
int 0x15
|
||||||
|
jc short .e820f ; carry set means "end of list already reached"
|
||||||
|
mov edx, 0x0534D4150 ; repair potentially trashed register
|
||||||
|
|
||||||
|
.jmpin:
|
||||||
|
jcxz .skipent ; skip any 0 length entries
|
||||||
|
cmp cl, 20 ; got a 24 byte ACPI 3.X response?
|
||||||
|
jbe short .notext
|
||||||
|
test byte [es:di + 20], 1 ; if so: is the "ignore this data" bit clear?
|
||||||
|
je short .skipent
|
||||||
|
|
||||||
|
.notext:
|
||||||
|
mov ecx, [es:di + 8] ; get lower uint32_t of memory region length
|
||||||
|
or ecx, [es:di + 12] ; "or" it with upper uint32_t to test for zero
|
||||||
|
jz .skipent ; if length uint64_t is 0, skip entry
|
||||||
|
inc bp ; got a good entry: ++count, move to next storage spot
|
||||||
|
add di, 24
|
||||||
|
|
||||||
|
.skipent:
|
||||||
|
test ebx, ebx ; if ebx resets to 0, list is complete
|
||||||
|
jne short .e820lp
|
||||||
|
|
||||||
|
.e820f:
|
||||||
|
mov [mmap_ent], bp ; store the entry count
|
||||||
|
clc ; there is "jc" on end of list to this point, so the carry must be cleared
|
||||||
|
|
||||||
|
mov dword [mem_map], 0x30000 ; the memory map is stored at this address
|
||||||
|
|
||||||
|
pop bp
|
||||||
|
pop es
|
||||||
|
popa
|
||||||
|
jmp short load_kernel
|
||||||
|
|
||||||
|
.failed:
|
||||||
|
mov si, memory_error
|
||||||
|
call print
|
||||||
|
jmp $
|
||||||
|
|
||||||
|
load_kernel:
|
||||||
|
|
||||||
|
mov ah, 8
|
||||||
|
mov dl, [bootdev]
|
||||||
|
int 13h ;Get drive params
|
||||||
|
|
||||||
|
jc disk_error
|
||||||
|
|
||||||
|
and cx, 111111b
|
||||||
|
mov [sectorsPerTrack], cx
|
||||||
|
mov [numHeads], dh
|
||||||
|
inc word [numHeads]
|
||||||
|
|
||||||
|
push es
|
||||||
|
mov ax, 0x900
|
||||||
mov es, ax
|
mov es, ax
|
||||||
|
|
||||||
mov si, kername ; print kernel file name
|
stc
|
||||||
call printstr
|
mov dh, 0
|
||||||
|
mov ah, 0x02
|
||||||
|
mov al, 120 ;load 120 sectors
|
||||||
|
mov ch, 0
|
||||||
|
mov cl, 4 ;Kernel is at the fourth sector of the disk
|
||||||
|
|
||||||
; Load the kernel into memory
|
mov dl, [bootdev]
|
||||||
%include "kernel_loader.asm"
|
|
||||||
|
|
||||||
; Set up IVT (GTD and IDT not used in 16 bit real mode)
|
xor bx, bx ; [es:bx] = 0x0900:0x0000
|
||||||
; Define interrupt handlers (replace with your actual handler code)
|
int 13h
|
||||||
div_by_zero_handler:
|
|
||||||
cli
|
|
||||||
hlt
|
|
||||||
|
|
||||||
timer_handler:
|
jc disk_error
|
||||||
; Your timer interrupt handler code
|
|
||||||
hlt
|
mov ax, 0x1800
|
||||||
|
mov es, ax
|
||||||
|
stc
|
||||||
|
mov ax, 123
|
||||||
|
call getchs
|
||||||
|
mov dh, [head]
|
||||||
|
mov ah, 0x02
|
||||||
|
mov al, 120 ;load another 120 sectors making a total of 240 sectors
|
||||||
|
mov ch, [cyl]
|
||||||
|
mov cl, [sect]
|
||||||
|
|
||||||
|
mov dl, [bootdev]
|
||||||
|
xor bx, bx ;[es:bx] = 0x1800:0x0000
|
||||||
|
|
||||||
|
int 13h
|
||||||
|
|
||||||
|
jnc switch_video_mode
|
||||||
|
|
||||||
|
disk_error:
|
||||||
|
mov si, disk_read_error_msg
|
||||||
|
call print
|
||||||
|
xor ax, ax
|
||||||
|
int 16h
|
||||||
|
xor ax, ax
|
||||||
|
int 19h
|
||||||
|
|
||||||
|
switch_video_mode:
|
||||||
|
pop es
|
||||||
|
mov di, VbeModeList
|
||||||
|
|
||||||
|
.loop:
|
||||||
|
mov ax, word [es:di]
|
||||||
|
cmp ax, 0xFFFF
|
||||||
|
je next_mode
|
||||||
|
|
||||||
|
mov cx, ax ;Save mode number in cx
|
||||||
|
push di
|
||||||
|
mov di, VbeModeInfo
|
||||||
|
mov ax, 4f01h
|
||||||
|
int 10h
|
||||||
|
|
||||||
|
;This searches for 32bpp 1024*768 <Default OS Mode>
|
||||||
|
cmp byte [di+25], 0x20 ;Bits Per Pixel
|
||||||
|
jne .continue
|
||||||
|
cmp WORD [di+18], 1024
|
||||||
|
jne .continue
|
||||||
|
cmp WORD [di+20], 768
|
||||||
|
je found_mode
|
||||||
|
|
||||||
|
.continue:
|
||||||
|
pop di
|
||||||
|
add di, 2
|
||||||
|
jmp .loop
|
||||||
|
|
||||||
|
found_mode:
|
||||||
|
mov [CurrentMode], cx
|
||||||
|
|
||||||
|
mov di, VbeModeInfo
|
||||||
|
|
||||||
|
mov ax, 0x4f01
|
||||||
|
int 10h
|
||||||
|
|
||||||
|
mov bx, cx
|
||||||
|
mov ax, 0x4f02 ;Set vbe mode
|
||||||
|
|
||||||
|
; int 10h
|
||||||
|
|
||||||
|
jmp EnablePaging
|
||||||
|
|
||||||
|
jmp $
|
||||||
|
|
||||||
|
next_mode:
|
||||||
|
mov di, VbeModeList
|
||||||
|
|
||||||
|
.loop:
|
||||||
|
mov ax, word [es:di]
|
||||||
|
cmp ax, 0xFFFF
|
||||||
|
je no_mode_found
|
||||||
|
|
||||||
|
mov cx, ax ;Save mode number in cx
|
||||||
|
push di
|
||||||
|
mov di, VbeModeInfo
|
||||||
|
mov ax, 4f01h
|
||||||
|
int 10h
|
||||||
|
|
||||||
|
;This searches for 32bpp 1280 * 1024
|
||||||
|
|
||||||
|
cmp byte [di+25], 0x20 ;Bits Per Pixel
|
||||||
|
jne .continue
|
||||||
|
cmp WORD [di+18], 1280
|
||||||
|
jne .continue
|
||||||
|
cmp WORD [di+20], 1024
|
||||||
|
je found_mode
|
||||||
|
|
||||||
|
.continue:
|
||||||
|
pop di
|
||||||
|
add di, 2
|
||||||
|
jmp .loop
|
||||||
|
|
||||||
|
;For now, only two modes are supported in this OS
|
||||||
|
|
||||||
|
no_mode_found:
|
||||||
|
mov si, no_mode_msg
|
||||||
|
call print
|
||||||
|
jmp $
|
||||||
|
|
||||||
|
;Print string routine
|
||||||
|
print:
|
||||||
|
pusha
|
||||||
|
|
||||||
|
.loop:
|
||||||
|
lodsb
|
||||||
|
cmp al, 0
|
||||||
|
je .done
|
||||||
|
mov ah, 0x0e
|
||||||
|
int 10h
|
||||||
|
jmp .loop
|
||||||
|
|
||||||
|
.done:
|
||||||
|
popa
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; IVT entries (offset 0 for all handlers since segment 0)
|
;GETCHS Function
|
||||||
times 0x100 dw 0x0000 ; Initialize unused entries
|
;put lba value to convert in ax
|
||||||
dw offset div_by_zero_handler ; Interrupt 0 (Division by Zero)
|
;returns cyl, head, sect
|
||||||
times 0x7 dw 0x0000 ; Skip unused entries
|
|
||||||
dw offset timer_handler ; Interrupt 0x8 (Timer)
|
|
||||||
|
|
||||||
; Switch to protected mode
|
cyl db 0
|
||||||
; Enable Protected Mode
|
head db 0
|
||||||
switch_to_protected_mode:
|
sect db 0
|
||||||
cli ; Disable interrupts
|
sectorsPerTrack dw 0
|
||||||
mov eax, cr0 ; Get current CR0 value
|
numHeads dw 0
|
||||||
or eax, 0x01 ; Set PE bit (Protected Mode Enable)
|
|
||||||
mov cr0, eax ; Write modified CR0 value back
|
|
||||||
|
|
||||||
; Set up stack and start executing kernel's code
|
getchs:
|
||||||
; Define GDT structure (replace with your actual GDT definition)
|
xor dx,dx
|
||||||
gdt_start: ; Beginning of GDT
|
mov bx,[sectorsPerTrack]
|
||||||
times 5 dd 0 ; Null descriptor entries (optional)
|
div bx
|
||||||
gdt_code: ; Code segment descriptor
|
inc dx
|
||||||
dw 0xffff ; Segment size (limit)
|
mov byte [sect],dl
|
||||||
dw 0x0000 ; Segment base address (low)
|
xor dx,dx
|
||||||
db 0x0 ; Segment base address (high)
|
mov bx,[numHeads]
|
||||||
db 10011010b ; Access rights (present, readable, conforming, executable)
|
div bx
|
||||||
db 11001111b ; Access rights (long mode, 4-granularity, size)
|
mov byte [cyl],al
|
||||||
gdt_end: ; End of GDT
|
mov byte [head],dl
|
||||||
gdt_descriptor:
|
ret
|
||||||
equ gdt_end - gdt_start ; Size of GDT
|
|
||||||
dw gdt_descriptor ; Offset of GDT
|
|
||||||
dd gdt_start ; Base address of GDT
|
|
||||||
|
|
||||||
; Load the GDT
|
jmp $
|
||||||
lgdt [gdt_descriptor] ; Load GDT descriptor into GDTR
|
|
||||||
|
|
||||||
; Set up Stack (replace with your actual stack segment and address)
|
EnablePaging:
|
||||||
mov ss, data_segment ; Set stack segment selector
|
|
||||||
mov esp, 0x100000 ; Set stack pointer (top of stack)
|
|
||||||
|
|
||||||
; Start Kernel Execution
|
.fill_page_directory:
|
||||||
jmp farptr kernel_entry ; Jump to kernel entry point (replace with actual address)
|
push es
|
||||||
|
mov ax, 0x2900
|
||||||
|
mov es, ax
|
||||||
|
mov cx, 1024
|
||||||
|
mov di, 0
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
.paging_loop0: ;Fill the page directory with zeros
|
||||||
; printstr routine, prints the string pointed by si using int 0x10 ;
|
mov dword [es:di], 0x00000002
|
||||||
; sets the direction flag to 0 ;
|
add di, 4
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
loop .paging_loop0
|
||||||
printstr:
|
|
||||||
cld ; clear df flag - lodsb increments si
|
|
||||||
printstr_loop:
|
|
||||||
lodsb ; load next character into al, increment si
|
|
||||||
or al, al ; sets zf if al is 0x00
|
|
||||||
jz printstr_end
|
|
||||||
mov ah, 0x0E ; teletype output (int 0x10)
|
|
||||||
int 0x10 ; print character
|
|
||||||
jmp printstr_loop
|
|
||||||
printstr_end:
|
|
||||||
ret ; return to caller address
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;Fill the first two page table to map the first 8MB of memory.
|
||||||
; halt routine - infinite loop ;
|
; The remaining tables will be filled once the switch to protected mode is made and more memory
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
; can be accessed.
|
||||||
halt:
|
.fill_first_page_table:
|
||||||
|
mov ax, 0x2A00
|
||||||
|
mov es, ax
|
||||||
|
mov cx, 1024
|
||||||
|
mov di, 0x0000
|
||||||
|
mov esi, 0x00000003
|
||||||
|
|
||||||
|
.paging_loop1:
|
||||||
|
mov dword [es:di], esi
|
||||||
|
add di, 4
|
||||||
|
add esi, 0x1000
|
||||||
|
loop .paging_loop1
|
||||||
|
|
||||||
|
.fill_second_page_table:
|
||||||
|
mov ax, 0x2B00
|
||||||
|
mov es, ax
|
||||||
|
mov cx, 1024
|
||||||
|
mov di, 0
|
||||||
|
mov esi, 0x00400003
|
||||||
|
|
||||||
|
.paging_loop2:
|
||||||
|
mov dword [es:di], esi
|
||||||
|
add di, 4
|
||||||
|
add esi, 0x1000
|
||||||
|
loop .paging_loop2
|
||||||
|
|
||||||
|
loadPageTables: ;Map the first 8mb
|
||||||
|
mov ax, 0x2900
|
||||||
|
mov es, ax
|
||||||
|
mov di, 0x0000
|
||||||
|
|
||||||
|
mov dword [es:di], 0x2A003 ;Page directory entry 0 (0-3.99MB)
|
||||||
|
add di, 4
|
||||||
|
mov dword [es:di], 0x2B003 ;Page directory entry 1 (4-7.99MB)
|
||||||
|
|
||||||
|
loadGDT:
|
||||||
|
lgdt [gdt_descriptor] ;Load the Global Descriptor Table
|
||||||
|
|
||||||
|
loadPageDirectory:
|
||||||
|
pop es
|
||||||
|
mov dword [page_directory], 0x29000 ;Save the linear address of the page directory
|
||||||
|
|
||||||
|
mov eax, 0x29000 ;Load the page directory address to cr3
|
||||||
|
mov cr3, eax
|
||||||
|
|
||||||
|
switch_to_pmode:
|
||||||
cli
|
cli
|
||||||
jmp halt
|
|
||||||
|
|
||||||
;;;;;;;;;;;
|
mov eax, cr0
|
||||||
; Padding ;
|
or eax, 0x80000001 ;Turn on paging (bit 31) and protected mode enable (bit 0)
|
||||||
;;;;;;;;;;;
|
mov cr0, eax
|
||||||
; $ is the address of the current line, $$ is the base address for
|
|
||||||
; this program.
|
|
||||||
; the expression is expanded to 510 - ($ - 0x8000), or
|
|
||||||
; 510 + 0x8000 - $, which is, in other words, the number of bytes
|
|
||||||
; before the address 510 + 0x8000 (= 0x80FD), where the 0xAA55
|
|
||||||
; signature shall be put.
|
|
||||||
times 510 - ($ - $$) db 0x00
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;
|
jmp CODE_SEG:BEGIN_PM
|
||||||
; BIOS signature ;
|
|
||||||
;;;;;;;;;;;;;;;;;;
|
;Data
|
||||||
dw 0xAA55
|
|
||||||
|
;THE GLOBAL DESCRIPTOR TABLE
|
||||||
|
gdt_start:
|
||||||
|
dd 0x0
|
||||||
|
dd 0x0
|
||||||
|
gdt_code:
|
||||||
|
dw 0xffff
|
||||||
|
dw 0x0
|
||||||
|
db 0x0
|
||||||
|
db 0x9a
|
||||||
|
db 11001111b
|
||||||
|
db 0x0
|
||||||
|
gdt_data:
|
||||||
|
dw 0xffff
|
||||||
|
dw 0x0
|
||||||
|
db 0x0
|
||||||
|
db 0x92
|
||||||
|
db 11001111b
|
||||||
|
db 0x0
|
||||||
|
gdt_end:
|
||||||
|
|
||||||
|
gdt_descriptor:
|
||||||
|
dw gdt_end - gdt_start - 1
|
||||||
|
dd gdt_start
|
||||||
|
|
||||||
|
CODE_SEG equ gdt_code - gdt_start
|
||||||
|
DATA_SEG equ gdt_data - gdt_start
|
||||||
|
|
||||||
|
disk_read_error_msg: db "Error Loading OS Kernel. Press any key to reboot! Code: 0x01", 0
|
||||||
|
memory_error db "Memory test error! Reboot the PC to try again. Code: 0x03" ,0
|
||||||
|
no_mode_msg db 'No supported video mode found. Code: 0x04' , 0
|
||||||
|
bootdev db 0
|
||||||
|
|
||||||
|
[BITS 32]
|
||||||
|
BEGIN_PM:
|
||||||
|
;Set up segments
|
||||||
|
|
||||||
|
mov ax, DATA_SEG
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
mov fs, ax
|
||||||
|
mov gs, ax
|
||||||
|
|
||||||
|
mov ss, ax ;Set up stack segment
|
||||||
|
mov ebp, 0x1F0000 ;and pointer
|
||||||
|
mov esp, ebp
|
||||||
|
|
||||||
|
mov ecx, 512*240 ;We have 240 sectors loaded
|
||||||
|
mov esi, 0x9000 ;at address 0x9000
|
||||||
|
mov edi, 0x100000 ;we must copy them to 0x100000
|
||||||
|
|
||||||
|
rep movsb ;perform copy from EDI to ESI
|
||||||
|
|
||||||
|
; Map the whole 4Gb 0f memory
|
||||||
|
fillPageTables:
|
||||||
|
mov esi, 0x200000
|
||||||
|
mov ecx, 1048576 ;1024 page directory entries * 1024 entries per page table
|
||||||
|
mov eax, 0x00000003
|
||||||
|
|
||||||
|
.paging_loop3:
|
||||||
|
mov dword [esi], eax
|
||||||
|
add esi, 4
|
||||||
|
add eax, 0x1000
|
||||||
|
loop .paging_loop3
|
||||||
|
|
||||||
|
.loadAllPageTables:
|
||||||
|
mov ecx, 1024
|
||||||
|
mov eax, 0x200003
|
||||||
|
mov esi, 0x29000
|
||||||
|
|
||||||
|
.paging_loop4:
|
||||||
|
mov dword [esi] ,eax
|
||||||
|
add eax, 0x1000
|
||||||
|
add esi, 4
|
||||||
|
loop .paging_loop4
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
mov eax, kernel_info_block
|
||||||
|
call 0x100000 ;Jump to kernel's entry point
|
||||||
|
|
||||||
|
_stop:
|
||||||
|
hlt
|
||||||
|
jmp _stop
|
||||||
|
|
||||||
|
times 1024 - ($-$$) db 0
|
||||||
|
|
||||||
|
section .bss
|
||||||
|
kernel_info_block:
|
||||||
|
VESAControllerInfo: resb 512 ;0x8200
|
||||||
|
VbeModeList: resw 128 ;0x8400
|
||||||
|
CurrentMode: resw 1 ;0x8500
|
||||||
|
VbeModeInfo: resb 256 ;0x8502
|
||||||
|
mem_map_entries_count: resd 1 ;0x8602
|
||||||
|
mem_map: resd 1 ;0x8606
|
||||||
|
page_directory: resd 1; 0x860A
|
BIN
src/boot/boot2.bin
Normal file
BIN
src/boot/boot2.bin
Normal file
Binary file not shown.
@ -1,23 +0,0 @@
|
|||||||
; Define constants (adjust as needed)
|
|
||||||
boot_drive equ 0x00 ; Drive to load kernel from (usually 0 for primary)
|
|
||||||
kernel_sector equ 1 ; Sector containing the kernel (adjust for your kernel's location)
|
|
||||||
kernel_segments equ 4 ; Number of sectors to load (adjust for your kernel size)
|
|
||||||
kernel_load_address equ 0x1000 ; Memory address to load the kernel
|
|
||||||
|
|
||||||
void int_13h(unsigned int ah, unsigned int al, unsigned int dx, unsigned int ch, unsigned int cl, unsigned int bx);
|
|
||||||
|
|
||||||
void error_handler(const char *message)
|
|
||||||
; Main kernel loading code
|
|
||||||
mov bx, kernel_load_address ; Set load address
|
|
||||||
|
|
||||||
; Loop to load kernel sectors
|
|
||||||
mov cx, 0 ; Initialize counter
|
|
||||||
loop_load:
|
|
||||||
int_13h(0x02, kernel_segments, boot_drive * 256 + kernel_sector, ch, cl, bx) ; Read sectors
|
|
||||||
add bx, 512 * kernel_segments ; Update load address
|
|
||||||
inc cx ; Increment counter
|
|
||||||
cmp cx, kernel_segments ; Check if all sectors loaded
|
|
||||||
jne loop_load ; Jump back if not finished
|
|
||||||
|
|
||||||
; Success - kernel is now loaded into memory
|
|
||||||
ret ; Return to the main bootloader code
|
|
@ -1,31 +1,25 @@
|
|||||||
ENTRY(start)
|
ENTRY(start)
|
||||||
SECTIONS {
|
SECTIONS
|
||||||
. = 0x7c00;
|
{
|
||||||
|
.text :
|
||||||
.text : {
|
{
|
||||||
*(.text)
|
*(.text)
|
||||||
}
|
}
|
||||||
|
|
||||||
.data : {
|
.data :
|
||||||
|
{
|
||||||
*(.data)
|
*(.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
.bss : {
|
.bss :
|
||||||
|
{
|
||||||
*(.bss)
|
*(.bss)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Define the bootloader signature at the end of the bootloader */
|
.kernel :
|
||||||
bootloader_signature : {
|
{
|
||||||
*(.bootloader_signature)
|
/* Kernel code */
|
||||||
}
|
. = 0x9000; /* Start of kernel code section */
|
||||||
|
*(.kernel)
|
||||||
/* Define the bootloader magic number at the end of the bootloader */
|
|
||||||
bootloader_magic : {
|
|
||||||
*(.bootloader_magic)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Define the bootloader padding to fill up the remaining space */
|
|
||||||
bootloader_padding : {
|
|
||||||
*(.bootloader_padding)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,16 +3,30 @@
|
|||||||
global cpuid
|
global cpuid
|
||||||
|
|
||||||
cpuid:
|
cpuid:
|
||||||
|
; Save registers
|
||||||
|
push ebp
|
||||||
|
mov ebp, esp
|
||||||
|
push ebx
|
||||||
|
push edi
|
||||||
|
push esi
|
||||||
|
|
||||||
; Input parameter in EAX register
|
; Input parameter in EAX register
|
||||||
mov eax, %edi
|
mov eax, [ebp + 8] ; Assuming the input is passed on the stack
|
||||||
|
|
||||||
; Call CPUID instruction (clobbers EAX, EBX, ECX, EDX)
|
; Call CPUID instruction (clobbers EAX, EBX, ECX, EDX)
|
||||||
cpuid
|
cpuid
|
||||||
|
|
||||||
; Return values in output registers
|
; Move output values to the appropriate registers
|
||||||
mov %esi, [esp + 4] ; eax (output)
|
mov esi, eax ; Output EAX
|
||||||
mov %edx, [esp + 8] ; ebx (output)
|
mov edi, ebx ; Output EBX
|
||||||
mov %ecx, [esp + 12] ; ecx (output)
|
mov ecx, ecx ; Output ECX
|
||||||
mov %edi, [esp + 16] ; edx (output)
|
mov edx, edx ; Output EDX
|
||||||
|
|
||||||
|
; Restore registers and clean up the stack
|
||||||
|
pop esi
|
||||||
|
pop edi
|
||||||
|
pop ebx
|
||||||
|
mov esp, ebp
|
||||||
|
pop ebp
|
||||||
|
|
||||||
ret
|
ret
|
@ -51,9 +51,28 @@ void eisa_detect_devices()
|
|||||||
// This is my device, configure it
|
// This is my device, configure it
|
||||||
uint32_t config1 = eisa_read_config_dword(address, 4);
|
uint32_t config1 = eisa_read_config_dword(address, 4);
|
||||||
uint32_t config2 = eisa_read_config_dword(address, 8);
|
uint32_t config2 = eisa_read_config_dword(address, 8);
|
||||||
|
|
||||||
//printf("Config1: %u\n", config1);
|
//printf("Config1: %u\n", config1);
|
||||||
//printf("Config2: %u\n", config2);
|
//printf("Config2: %u\n", config2);
|
||||||
// Do something with the configuration data
|
// Do something with the configuration data
|
||||||
|
|
||||||
|
// Check for specific bits in config1
|
||||||
|
if (config1 & 0x00000001) {
|
||||||
|
// Enable feature 1 based on bit 0 of config1
|
||||||
|
eisa_write(0xspecific_port_1, 0xvalue_to_enable_feature_1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config1 & 0x00000010) {
|
||||||
|
// Set DMA channel based on bits 4-5 of config1
|
||||||
|
uint8_t dma_channel = (config1 >> 4) & 0x03;
|
||||||
|
eisa_write(0xspecific_port_2, dma_channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for specific bits in config2
|
||||||
|
if (config2 & 0x00000001) {
|
||||||
|
// Configure interrupt line based on bit 0 of config2
|
||||||
|
eisa_write(0xspecific_port_3, 0xinterrupt_line_number);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,27 @@
|
|||||||
#include "fat16.h"
|
#include "fat16.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "fat16_io.h"
|
#include "fat16_io.h"
|
||||||
|
#include "src/kernel/arch/x86/disk/ata.h"
|
||||||
// Implementation of read_sector and write_sector functions (replace with actual disk I/O)
|
// Implementation of read_sector and write_sector functions (replace with actual disk I/O)
|
||||||
int read_sector(uint32_t sector_number, void *buffer)
|
int read_sector(uint32_t sector_number, void *buffer)
|
||||||
{
|
{
|
||||||
// ... (Code to read a sector from disk) ...
|
// ... (Code to read a sector from disk) ...
|
||||||
|
// Calculate physical disk location based on sector number
|
||||||
|
uint32_t head, sector, cylinder;
|
||||||
|
translate_logical_to_physical(sector_number, &head, §or, &cylinder); // Replace with your driver's translation function
|
||||||
|
|
||||||
|
// Issue read command to disk controller
|
||||||
|
if (disk_read_sector(head, sector, cylinder, buffer) != 0) {
|
||||||
|
// Error handling: This could involve setting an error flag or returning a specific error code
|
||||||
|
return -1; // Example error code
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0; // Success
|
||||||
}
|
}
|
||||||
|
|
||||||
int write_sector(uint32_t sector_number, void *buffer)
|
int write_sector(uint32_t sector_number, void *buffer)
|
||||||
{
|
{
|
||||||
return read_sector_from_disk(sector_number, buffer);
|
return read_sector(sector_number, buffer); // Use the existing read_sector function
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to parse the boot sector (replace with actual parsing logic)
|
// Function to parse the boot sector (replace with actual parsing logic)
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
#define FAT16_H
|
#define FAT16_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "../../ata.h"
|
||||||
|
|
||||||
// Define constants for sector size, cluster size, etc. (replace with actual values)
|
// Define constants for sector size, cluster size, etc. (replace with actual values)
|
||||||
#define SECTOR_SIZE 512
|
#define SECTOR_SIZE 512
|
||||||
#define BYTES_PER_CLUSTER 4096 // Example: 8 sectors per cluster
|
#define BYTES_PER_CLUSTER 4096 // Example: 8 sectors per cluster
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "fat16_io.h"
|
#include "fat16_io.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "src/kernel/arch/x86/disk/ata.h"
|
||||||
|
#include "fat16.h"
|
||||||
// I/O port addresses for IDE controller (replace with actual values if needed)
|
// I/O port addresses for IDE controller (replace with actual values if needed)
|
||||||
#define PRIMARY_DATA_REGISTER 0x1F0
|
#define PRIMARY_DATA_REGISTER 0x1F0
|
||||||
#define PRIMARY_ERROR_REGISTER 0x1F1
|
#define PRIMARY_ERROR_REGISTER 0x1F1
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
#define FAT16_IO_H
|
#define FAT16_IO_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "fat16.h"
|
||||||
|
#include "src/kernel/arch/x86/disk/ata.h"
|
||||||
|
|
||||||
// I/O port addresses for IDE controller (replace with actual values if needed)
|
// I/O port addresses for IDE controller (replace with actual values if needed)
|
||||||
#define PRIMARY_DATA_REGISTER 0x1F0
|
#define PRIMARY_DATA_REGISTER 0x1F0
|
||||||
|
32
src/kernel/arch/x86/disk/ata.h
Normal file
32
src/kernel/arch/x86/disk/ata.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#ifndef ATA_H
|
||||||
|
#define ATA_H
|
||||||
|
|
||||||
|
#include "../include/types.h"
|
||||||
|
// I/O port addresses for IDE controllers (replace with actual values if needed)
|
||||||
|
#define PRIMARY_DATA_REGISTER 0x1F0
|
||||||
|
#define PRIMARY_ERROR_REGISTER 0x1F1
|
||||||
|
#define PRIMARY_COMMAND_REGISTER 0x1F2
|
||||||
|
#define PRIMARY_SELECT_REGISTER 0x1F6
|
||||||
|
#define SECONDARY_DATA_REGISTER 0x1F4
|
||||||
|
#define SECONDARY_ERROR_REGISTER 0x1F5
|
||||||
|
#define SECONDARY_COMMAND_REGISTER 0x1F6
|
||||||
|
#define SECONDARY_SELECT_REGISTER 0x1F7
|
||||||
|
|
||||||
|
// Define bit masks for IDE commands (replace with actual values if needed)
|
||||||
|
#define ATA_CMD_READ_SECTORS_WITHOUT_RETRIES 0x20
|
||||||
|
#define ATA_CMD_READ_SECTORS_WITH_RETRIES 0xC4
|
||||||
|
#define ATA_CMD_WRITE_SECTORS_WITHOUT_RETRIES 0x30
|
||||||
|
#define ATA_CMD_WRITE_SECTORS_WITH_RETRIES 0x34
|
||||||
|
|
||||||
|
// Define bit masks for IDE status register bits (replace with actual values if needed)
|
||||||
|
#define ATA_STATUS_BSY 0x02 // Busy bit
|
||||||
|
#define ATA_STATUS_DRQ 0x08 // Data Request bit
|
||||||
|
#define ATA_STATUS_ERR 0x01 // Error bit
|
||||||
|
|
||||||
|
// Function prototypes (replace with actual function implementations)
|
||||||
|
int read_sector(uint32_t sector_number, void *buffer, int drive); // Read a sector from disk (drive: 0 for primary, 1 for secondary)
|
||||||
|
int write_sector(uint32_t sector_number, void *buffer, int drive); // Write a sector to disk (drive: 0 for primary, 1 for secondary)
|
||||||
|
|
||||||
|
// Additional function prototypes specific to your IDE controller library can be added here
|
||||||
|
|
||||||
|
#endif
|
@ -1,4 +1,8 @@
|
|||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
|
#include "./arch/x86/gdt.h"
|
||||||
|
#include "../kernel/malloc/malloc.h"
|
||||||
|
#include "../kernel/malloc/kmalloc.h"
|
||||||
|
#include "./arch/x86/include/memory.h"
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -45,6 +49,13 @@ void init_devices() {
|
|||||||
// Placeholder for actual implementation
|
// Placeholder for actual implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void early_init() {
|
||||||
|
// ... other early initialization tasks
|
||||||
|
init_kernel_heap((void*)KERNEL_HEAP_START, (void*)KERNEL_HEAP_END);
|
||||||
|
// Initialize GDT
|
||||||
|
gdt_init();
|
||||||
|
}
|
||||||
|
|
||||||
void kernel_main() {
|
void kernel_main() {
|
||||||
clear_screen();
|
clear_screen();
|
||||||
print("Welcome to ClassicOS!");
|
print("Welcome to ClassicOS!");
|
||||||
@ -52,6 +63,16 @@ void kernel_main() {
|
|||||||
// Initialize memory management
|
// Initialize memory management
|
||||||
init_memory_management();
|
init_memory_management();
|
||||||
|
|
||||||
|
// Initialize user-space heap (example)
|
||||||
|
void* user_heap_start = /* address of user-space heap start */;
|
||||||
|
void* user_heap_end = /* address of user-space heap end */;
|
||||||
|
init_heap(user_heap_start, user_heap_end);
|
||||||
|
|
||||||
|
// Initialize kernel heap (example)
|
||||||
|
void* kernel_heap_start = /* address of kernel heap start */;
|
||||||
|
void* kernel_heap_end = /* address of kernel heap end */;
|
||||||
|
init_kernel_heap(kernel_heap_start, kernel_heap_end);
|
||||||
|
|
||||||
// Initialize devices
|
// Initialize devices
|
||||||
init_devices();
|
init_devices();
|
||||||
|
|
||||||
@ -70,4 +91,3 @@ void kernel_main() {
|
|||||||
handle_system_calls();
|
handle_system_calls();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
#ifndef KERNEL_H
|
#ifndef KERNEL_H
|
||||||
#define KERNEL_H
|
#define KERNEL_H
|
||||||
|
|
||||||
// Function to print a null-terminated string to the screen
|
|
||||||
void print_string(const char* str);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -1,12 +1,24 @@
|
|||||||
#ifndef KMALLOC_H_ // Corrected guard macro
|
#ifndef KMALLOC_H
|
||||||
#define KMALLOC_H_
|
#define KMALLOC_H
|
||||||
|
|
||||||
#include <stddef.h> // For size_t
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
void *kmalloc(size_t size);
|
// Structure to represent a memory block in the kernel heap
|
||||||
void kfree(void *ptr);
|
typedef struct {
|
||||||
|
void* base; // Starting address of the block
|
||||||
|
size_t size; // Size of the block in bytes
|
||||||
|
struct heap_block* next; // Pointer to the next block in the free list
|
||||||
|
} heap_block_t;
|
||||||
|
|
||||||
void mark_as_used_kernel(void *ptr, size_t size);
|
// Function prototypes
|
||||||
void mark_as_free_kernel(void *ptr);
|
void init_kernel_heap(void* start, void* end);
|
||||||
|
void init_user_heap(void* start, void* end);
|
||||||
|
void* kmalloc(size_t size);
|
||||||
|
void kfree(void* ptr);
|
||||||
|
|
||||||
#endif /* KMALLOC_H_ */
|
// Global variable to store the free list head
|
||||||
|
extern heap_block_t* kheap_free_list;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/* KMALLOC_H_ */
|
||||||
|
Loading…
Reference in New Issue
Block a user