diff --git a/.vscode/browse.vc.db b/.vscode/browse.vc.db index 4a5b325..221bf55 100644 Binary files a/.vscode/browse.vc.db and b/.vscode/browse.vc.db differ diff --git a/.vscode/browse.vc.db-shm b/.vscode/browse.vc.db-shm index abbb87c..243fb84 100644 Binary files a/.vscode/browse.vc.db-shm and b/.vscode/browse.vc.db-shm differ diff --git a/.vscode/launch.json b/.vscode/launch.json index 4ea0cec..deac87e 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,7 +8,7 @@ "name": "gcc-8 - Build and debug active file Level 1", "type": "cppdbg", "request": "launch", - "program": "${fileDirname}/${fileBasenameNoExtension}", + "program": "/home/gbowne1/Documents/ClassicOS/build/ClassicOS", "args": [], "stopAtEntry": false, "cwd": "${workspaceFolder}", diff --git a/src/boot/boot2.asm b/src/boot/boot2.asm index 4dc5e76..9a610e3 100644 --- a/src/boot/boot2.asm +++ b/src/boot/boot2.asm @@ -1,43 +1,124 @@ -[BITS 16] -[ORG 0x0000] +[BITS 16] +[ORG 0x0000] start: - MOV AX, CS - MOV DS, AX + ; Initialize stack + MOV AX, 0x0000 ; Set up a segment for the stack MOV SS, AX - MOV SP, 0xFFFF + MOV SP, 0xFFFF ; Stack grows downwards from the top of the segment - MOV SI, msg - JMP println + ; Copy boot sector data to a safe location + mCopyBootSector - JMP $ + ; Load the kernel + CALL load_kernel - RET + switch_to_protected_mode: + CLI ; Disable interrupts + LGDT [gdt_descriptor] ; Load the global descriptor table + MOV EAX, CR0 + OR EAX, 0x1 ; Set the PE (Protection Enable) bit + MOV CR0, EAX + ; Far jump to flush CPU queue after changing to protected mode + JMP CODE_SEG:init_pm ; CODE_SEG is the segment selector for code segment in GDT + init_pm: + ; Update segment registers here + ; ... + RET -println: - .next_char: - LODSB - OR AL, AL - JZ .stop - MOV AH, 0x0E - MOV BH, 0x00 - MOV BL, 0x07 - INT 0x10 + enable_a20: + ; Enable A20 gate + cli ; Disable interrupts to prevent interference + call a20wait ; Wait for the keyboard controller to be ready + mov al, 0xAD ; Command to disable keyboard + out 0x64, al ; Send command to keyboard controller command port + call a20wait ; Wait for the keyboard controller to be ready + mov al, 0xD0 ; Command to read output port + out 0x64, al ; Send command to keyboard controller command port + call a20wait ; Wait for the keyboard controller to be ready + in al, 0x60 ; Read current state of output port + or al, 0x02 ; Set A20 bit + call a20wait ; Wait for the keyboard controller to be ready + mov al, 0xD1 ; Command to write output port + out 0x64, al ; Send command to keyboard controller command port + call a20wait ; Wait for the keyboard controller to be ready + mov al, 0x02 ; New output port data with A20 enabled + out 0x60, al ; Write new output port data + call a20wait ; Wait for the keyboard controller to be ready + sti ; Re-enable interrupts + ret - JMP .next_char + ; Wait for keyboard controller to be ready + a20wait: + in al, 0x64 ; Read keyboard controller status port + test al, 0x02 ; Check if input buffer is full + jnz a20wait ; Wait until it's not full + ret - .stop: - MOV AH, 0x03 ; AH = 0x03 (Get Cursor Position and Shape) - XOR BH, BH ; BH = 0x00 (Video Page Number) - INT 0x10 ; Call video interrupt + ; Enter kernel space and jump to the kernel entry point + JMP 0x1000:0x0000 - INC DH + ; Code to set up flat memory model for protected mode + ; This involves setting up the segment registers with selectors + ; that point to descriptors in the GDT that define a flat memory model + ; ... - MOV AH, 0x02 ; Set cursor position - XOR BH, BH ; Page number - XOR DL, DL ; Column (start from 0) - INT 0x10 ; Call video interrupt - RET + ; Jump to the kernel entry point + JMP 0x1000:0x0000 ; Assuming the kernel is loaded at 0x1000:0x0000 -msg db "Second stage loaded, and Gbowne1 stinks.", 0 \ No newline at end of file + +; Macro to copy boot sector data to a safe location +mCopyBootSector: + pusha ; Save all general-purpose registers + mov si, 0x7C00 ; Source address: where BIOS loads the boot sector + mov di, 0x6000 ; Destination address: safe memory area + mov cx, 512 ; Number of bytes to copy (size of boot sector) + cld ; Clear direction flag to increment SI and DI +copy_loop: + lodsb ; Load byte at address DS:SI into AL, increment SI + stosb ; Store byte from AL to address ES:DI, increment DI + loop copy_loop ; Decrement CX; if CX != 0, repeat loop + popa ; Restore all general-purpose registers + ret + +; Subroutine to load the kernel +load_kernel: + ; Disable interrupts + cli + + ; Setup disk parameters + ; ... (set CH, CL, DH, DL for LBA, set DX for drive number) + + ; Calculate load address for kernel + ; ... (set ES:BX to the target memory address) + + ; Read sectors from disk into memory + mov ah, 0x02 ; Read sectors function + mov al, 1 ; Number of sectors to read + int 0x13 ; BIOS disk services + + ; Check for read error + jc .disk_error ; Carry flag set means an error occurred + + ; Enable A20 line if necessary + ; ... (implementation depends on your system) + + ; Jump to the kernel's entry point + jmp 0x1000:0x0000 ; Assuming the kernel is loaded at 0x1000:0x0000 + +.disk_error: + ; Handle disk read error + ; ... (display error message or halt) + + hlt ; Halt the system + +; Function or Subroutine to switch to protected mode +switch_to_protected_mode: + CLI ; Disable interrupts + LGDT [gdt_descriptor] ; Load the global descriptor table + MOV EAX, CR0 + OR EAX, 0x1 ; Set the PE (Protection Enable) bit + MOV CR0, EAX + ; Far jump to flush CPU queue after changing to protected mode + JMP CODE_SEG:init_pm ; CODE_SEG is the segment selector for code segment in GDT \ No newline at end of file diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index fc11e28..40b9a8e 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -1,85 +1,83 @@ -#include "cpu.h" - -// Function to read a 32-bit value from a CPU register -uint32_t read_register(uint8_t reg) -{ - uint32_t value; - __asm__ volatile("mov %0, %%" + reg : "=r"(value)); - return value; -} - -// Function to write a 32-bit value to a CPU register -void write_register(uint8_t reg, uint32_t value) -{ - __asm__ volatile("mov %0, %%" + reg : : "r"(value)); -} - -// Function to read the value of the CR0 register -uint32_t read_cr0() -{ - uint32_t value; - __asm__ volatile("mov %%cr0, %0" : "=r"(value)); - return value; -} - -// Function to write a value to the CR0 register -void write_cr0(uint32_t value) -{ - __asm__ volatile("mov %0, %%cr0" : : "r"(value)); -} - -// Function to switch from real mode to protected mode -void switch_to_protected_mode() -{ - uint32_t cr0 = read_cr0(); - cr0 |= 0x1; // Set the PE bit to switch to protected mode - write_cr0(cr0); -} - -// Write a byte to a port -void outb(uint16_t port, uint8_t value) -{ - __asm__ volatile ("outb %0, %1" : : "a"(value), "Nd"(port)); -} - -// Read a byte from a port -uint8_t inb(uint16_t port) -{ - uint8_t value; - __asm__ volatile ("inb %1, %0" : "=a"(value) : "Nd"(port)); - return value; -} - -// Write a word to a port -void outw(uint16_t port, uint16_t value) -{ - __asm__ volatile ("outw %0, %1" : : "a"(value), "Nd"(port)); -} - -// Read a word from a port -uint16_t inw(uint16_t port) -{ - uint16_t value; - __asm__ volatile ("inw %1, %0" : "=a"(value) : "Nd"(port)); - return value; -} - -// Write a double word to a port -void outl(uint16_t port, uint32_t value) -{ - __asm__ volatile ("outl %0, %1" : : "a"(value), "Nd"(port)); -} - -// Read a double word from a port -uint32_t inl(uint16_t port) -{ - uint32_t value; - __asm__ volatile ("inl %1, %0" : "=a"(value) : "Nd"(port)); - return value; -} - -// Execute the CPUID instruction -void cpuid(uint32_t code, uint32_t *a, uint32_t *d) -{ - __asm__ volatile ("cpuid" : "=a"(*a), "=d"(*d) : "a"(code) : "ecx", "ebx"); -} \ No newline at end of file +#include "cpu.h" + +// Function to read a 32-bit value from a CPU register +uint32_t read_register(uint8_t reg) { + uint32_t value; + __asm__ volatile("mov %0, %%" : "+r"(value) : "c"(reg)); + return value; +} + +// Function to write a 32-bit value to a CPU register +void write_register(uint8_t reg, uint32_t value) { + __asm__ volatile("mov %0, %%" : : "c"(reg), "r"(value)); +} + +// Function to read the value of the CR0 register +uint32_t read_cr0() +{ + uint32_t value; + __asm__ volatile("mov %%cr0, %0" : "=r"(value)); + return value; +} + +// Function to write a value to the CR0 register +void write_cr0(uint32_t value) +{ + __asm__ volatile("mov %0, %%cr0" : : "r"(value)); +} + +// Function to switch from real mode to protected mode +void switch_to_protected_mode() +{ + uint32_t cr0 = read_cr0(); + cr0 |= 0x1; // Set the PE bit to switch to protected mode + write_cr0(cr0); +} + +// Write a byte to a port +void outb(uint16_t port, uint8_t value) +{ + __asm__ volatile ("outb %0, %1" : : "a"(value), "Nd"(port)); +} + +// Read a byte from a port +uint8_t inb(uint16_t port) +{ + uint8_t value; + __asm__ volatile ("inb %1, %0" : "=a"(value) : "Nd"(port)); + return value; +} + +// Write a word to a port +void outw(uint16_t port, uint16_t value) +{ + __asm__ volatile ("outw %0, %1" : : "a"(value), "Nd"(port)); +} + +// Read a word from a port +uint16_t inw(uint16_t port) +{ + uint16_t value; + __asm__ volatile ("inw %1, %0" : "=a"(value) : "Nd"(port)); + return value; +} + +// Write a double word to a port +void outl(uint16_t port, uint32_t value) +{ + __asm__ volatile ("outl %0, %1" : : "a"(value), "Nd"(port)); +} + +// Read a double word from a port +uint32_t inl(uint16_t port) +{ + uint32_t value; + __asm__ volatile ("inl %1, %0" : "=a"(value) : "Nd"(port)); + return value; +} + +// Execute the CPUID instruction +void cpuid(uint32_t code, uint32_t *a, uint32_t *d) +{ + __asm__ volatile ("cpuid" : "=a"(*a), "=d"(*d) : "a"(code) : "ecx", "ebx"); +}