mirror of
https://github.com/gbowne1/ClassicOS.git
synced 2024-11-24 22:56:52 -08:00
Trying to fix the boot2.asm second stage bootloader
This commit is contained in:
parent
19b61da1af
commit
8e7cdce87d
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.
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@ -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}",
|
||||
|
@ -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
|
||||
|
||||
; 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
|
168
src/cpu/cpu.c
168
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");
|
||||
}
|
||||
#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");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user