Merge branch 'master' of https://git.coredoes.dev/c0repwn3r/shadeos
This commit is contained in:
commit
10dc3aeeac
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,56 @@
|
|||
# $@ = target file
|
||||
# $< = first dependency
|
||||
# $^ = all dependencies
|
||||
|
||||
GDB = gdb
|
||||
|
||||
C_FILES = $(shell find src/ -type f -name '*.c')
|
||||
CO_FILES = $(patsubst src/%.c, obj/%.o, $(C_FILES))
|
||||
ASM_FILES = $(shell find src/kernel/ -type f -name '*.asm')
|
||||
AO_FILES = $(patsubst src/kernel/%.asm, obj/kernel/%.o, $(ASM_FILES))
|
||||
ABIN_FILES = $(patsubst src/%.asm, bin/%.bin, $(ASM_FILES))
|
||||
|
||||
os-image.bin: bin/boot.bin bin/kernel.bin
|
||||
cat $^ > $@
|
||||
|
||||
bin/boot.bin: src/boot/boot.asm bin/kernel.bin .FORCE
|
||||
sed -i.orig "s@CH_REPLACE_BOOTSECTORCOUNT@$(shell ./getinblocks.py $(shell du -b "bin/kernel.bin" | cut -f 1))@g" src/boot/kernel.asm
|
||||
nasm -Isrc/boot/ $< -f bin -o $@
|
||||
mv src/boot/kernel.asm.orig src/boot/kernel.asm
|
||||
|
||||
.FORCE:
|
||||
|
||||
bin/kernel.bin: obj/kernel/entry.o ${CO_FILES} ${AO_FILES}
|
||||
i386-elf-ld -o $@ -Ttext 0x1000 $^ --oformat binary
|
||||
|
||||
kernel.elf: obj/kernel/entry.o ${CO_FILES} ${AO_FILES}
|
||||
i386-elf-ld -o $@ -Ttext 0x1000 $^
|
||||
|
||||
run: clean os-image.bin
|
||||
qemu-system-x86_64 -hdd os-image.bin -d int
|
||||
|
||||
debug: clean os-image.bin kernel.elf
|
||||
qemu-system-x86_64 -s -S -hdd os-image.bin &
|
||||
${GDB} os-image.bin -ex "symbol-file kernel.elf" -ex "target remote localhost:1234"
|
||||
|
||||
|
||||
|
||||
obj/%.o: src/%.c
|
||||
mkdir -p "$(@D)"
|
||||
i386-elf-gcc -g -ffreestanding -c $< -o $@
|
||||
|
||||
obj/%.o: src/%.asm
|
||||
mkdir -p "$(@D)"
|
||||
nasm -f elf $< -o $@
|
||||
|
||||
bin/%.bin: src/%.asm
|
||||
mkdir -p "$(@D)"
|
||||
nasm -f bin $< -o $@
|
||||
|
||||
clean:
|
||||
find obj -type f -name '*.o' -exec rm {} +
|
||||
find obj -type f -name '*.bin' -exec rm {} +
|
||||
find bin -type f -name '*.o' -exec rm {} +
|
||||
find bin -type f -name '*.bin' -exec rm {} +
|
||||
find . -type f -name '*.dis' -exec rm {} +
|
||||
rm -f kernel.elf
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/python3
|
||||
import sys, math
|
||||
intg = int(sys.argv[1])
|
||||
print(int(math.ceil(intg/512)), end='')
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,39 @@
|
|||
[org 0x7c00]
|
||||
KERNEL_OFFSET equ 0x1000 ; Same one used while linking!
|
||||
|
||||
mov [BOOT_DRIVE], dl ; BIOS sets boot drive to 'dl' for us
|
||||
mov bp, 0x9000
|
||||
mov sp, bp
|
||||
|
||||
mov bx, MSG_REAL_MODE
|
||||
call print
|
||||
call print_nl
|
||||
|
||||
call load_kernel
|
||||
call enable_protected
|
||||
|
||||
jmp $ ; never executed
|
||||
|
||||
%include "output/print.asm"
|
||||
%include "output/print_hex.asm"
|
||||
%include "disk/disk.asm"
|
||||
%include "protected/gdt.asm"
|
||||
%include "output/vga-print.asm"
|
||||
%include "protected/protected-switch.asm"
|
||||
%include "kernel.asm"
|
||||
|
||||
[bits 32]
|
||||
BEGIN_PROTECTED:
|
||||
mov ebx, MSG_PROT_MODE
|
||||
call print_string_pm
|
||||
|
||||
call KERNEL_OFFSET ; give control to kernel
|
||||
jmp $ ; infinite loop if kernel returns control to us
|
||||
|
||||
BOOT_DRIVE db 0
|
||||
MSG_REAL_MODE db "llb: started, preparing protected mode initialization", 0
|
||||
MSG_PROT_MODE db "llb: loaded protected mode successfully, jumping to llb2", 0
|
||||
MSG_LOAD_KERNEL db "llb: loading kernel into memory at 0x1000", 0
|
||||
|
||||
times 510 - ($-$$) db 0
|
||||
dw 0xaa55
|
|
@ -0,0 +1,40 @@
|
|||
; load 'dh' sectors from drive 'dl' into ES:BX
|
||||
disk_load:
|
||||
pusha
|
||||
push dx ; save dx to stack for later use, as it needs to be overwritten
|
||||
|
||||
mov ah, 0x02 ; ah: int 0x13 function. 0x02 = 'read'
|
||||
mov al, dh ; al: number of sectors to read (0x01 .. 0x80)
|
||||
mov cl, 0x02 ; cl: sector (0x01 .. 0x11). 0x01 is boot sector, 0x02 is first 'avaliable' sector
|
||||
mov ch, 0x00 ; ch: cylinder (0x0 .. 0x3FF, upper 2 bits in 'cl')
|
||||
; dl: drive number. caller sets it as param and gets it from bios
|
||||
; 0 = floppy, 1 = floppy2, 0x80 = hdd, 0x81 = hdd2
|
||||
mov dh, 0x00 ; dh: head number (0x0 .. 0xF)
|
||||
|
||||
; [es:bx] pointer to buf where data is stored
|
||||
; caller sets it up, and is standard location for int 13h
|
||||
int 13h
|
||||
jc disk_error ; if error (in carry)
|
||||
|
||||
pop dx
|
||||
cmp al, dh ; al is # of sectors read. compare it
|
||||
jne sectors_error
|
||||
popa
|
||||
ret
|
||||
|
||||
disk_error:
|
||||
mov bx, DISK_ERROR
|
||||
call print
|
||||
call print_nl
|
||||
mov dh, ah ; ah = error code, dl = disk drive that caused error
|
||||
call print_hex
|
||||
|
||||
sectors_error:
|
||||
mov bx, SECTORS_ERROR
|
||||
call print
|
||||
|
||||
disk_loop:
|
||||
jmp $
|
||||
|
||||
DISK_ERROR: db "Disk read error", 0
|
||||
SECTORS_ERROR: db "Incorrect number of sectors read", 0
|
|
@ -0,0 +1,11 @@
|
|||
[bits 16]
|
||||
load_kernel:
|
||||
mov bx, MSG_LOAD_KERNEL
|
||||
call print
|
||||
call print_nl
|
||||
|
||||
mov bx, KERNEL_OFFSET ; Read from disk and store at 0x1000
|
||||
mov dh, CH_REPLACE_BOOTSECTORCOUNT ; Populated with kernel sector count at build (see makefile)
|
||||
mov dl, [BOOT_DRIVE]
|
||||
call disk_load
|
||||
ret
|
|
@ -0,0 +1,33 @@
|
|||
print:
|
||||
pusha
|
||||
|
||||
; logic being implemented here:
|
||||
; while ( string[i] != 0 ) { print string[i]; i++ }
|
||||
|
||||
start:
|
||||
mov al, [bx]
|
||||
cmp al, 0 ; check if al (byte we are printing) is a 0 (null byte)
|
||||
je done ; if so, jump to done
|
||||
|
||||
; print with BIOS help
|
||||
mov ah, 0x0e
|
||||
int 0x10 ; char already in al
|
||||
|
||||
add bx, 1 ; increment pointer
|
||||
jmp start ; repeat
|
||||
|
||||
done:
|
||||
popa
|
||||
ret
|
||||
|
||||
print_nl:
|
||||
pusha
|
||||
|
||||
mov ah, 0x0e
|
||||
mov al, 0x0a ; newline char
|
||||
int 0x10
|
||||
mov al, 0x0d ; carriage return
|
||||
int 0x10
|
||||
|
||||
popa
|
||||
ret
|
|
@ -0,0 +1,38 @@
|
|||
; data in dx
|
||||
print_hex:
|
||||
pusha
|
||||
|
||||
mov cx, 0 ; index var
|
||||
|
||||
hex_loop:
|
||||
cmp cx, 4 ; loop 4 times
|
||||
je end
|
||||
|
||||
; 1) convert last char of 'dx' to ascii
|
||||
mov ax, dx ; ax is working register
|
||||
and ax, 0x000f ; 0x1234 -> 0x0004
|
||||
add al, 0x30 ; add 0x30 to N to convert it to ascii "n"
|
||||
cmp al, 0x39 ; if > 9, add extra 8 to represent a-f
|
||||
jle step2
|
||||
add al, 7 ; A is ascii 64 instead of 58, 65-58 = 7
|
||||
|
||||
step2:
|
||||
; 2) get correct pos of string to place char
|
||||
; bx <- base address + string length - index
|
||||
mov bx, HEX_OUT + 5
|
||||
sub bx, cx ; cx: index
|
||||
mov [bx], al ; copy ascii char on al to pos pointed by bx
|
||||
ror dx, 4 ; 1234 - 4123 - 3412 - 2341 - 1234
|
||||
|
||||
add cx, 1
|
||||
jmp hex_loop
|
||||
|
||||
end:
|
||||
mov bx, HEX_OUT
|
||||
call print
|
||||
|
||||
popa
|
||||
ret
|
||||
|
||||
HEX_OUT:
|
||||
db '0x0000', 0 ; reserve memory for string
|
|
@ -0,0 +1,26 @@
|
|||
[bits 32]
|
||||
|
||||
; defining constants
|
||||
VIDEO_MEMORY equ 0xb8000
|
||||
WHITE_ON_BLACK equ 0x0f ; color byte
|
||||
|
||||
print_string_pm:
|
||||
pusha
|
||||
mov edx, VIDEO_MEMORY
|
||||
|
||||
print_string_pm_loop:
|
||||
mov al, [ebx] ; [ebx] is address of char
|
||||
mov ah, WHITE_ON_BLACK
|
||||
|
||||
cmp al, 0 ; is end of string?
|
||||
je print_string_pm_done
|
||||
|
||||
mov [edx], ax ; store char + attribute in video memory
|
||||
add ebx, 1 ; next char
|
||||
add edx, 2 ; next video memory position
|
||||
|
||||
jmp print_string_pm_loop
|
||||
|
||||
print_string_pm_done:
|
||||
popa
|
||||
ret
|
|
@ -0,0 +1,32 @@
|
|||
|
||||
gdt_start: ; use labels to compute sizes and jumps
|
||||
; gdt starts with 8 byte null
|
||||
dd 0x0
|
||||
dd 0x0
|
||||
|
||||
; GDT for code segment, base = 0x00000000, length = 0xfffff
|
||||
gdt_code:
|
||||
dw 0xffff ; segment length
|
||||
dw 0x0 ; segment base
|
||||
db 0x0 ; segment base
|
||||
db 10011010b ; flags
|
||||
db 11001111b ; flags + segment length
|
||||
db 0x0 ; segment base
|
||||
|
||||
; GDT for data segment
|
||||
gdt_data:
|
||||
dw 0xffff ; segment length
|
||||
dw 0x0 ; segment base
|
||||
db 0x0 ; segment base
|
||||
db 10010010b ; flags
|
||||
db 11001111b ; flags + segment length
|
||||
db 0x0 ; segment base
|
||||
|
||||
gdt_end:
|
||||
|
||||
gdt_descriptor:
|
||||
dw gdt_end - gdt_start - 1 ; size, always 1 less than what it actually is
|
||||
dd gdt_start ; address
|
||||
|
||||
CODE_SEG equ gdt_code - gdt_start
|
||||
DATA_SEG equ gdt_data - gdt_start
|
|
@ -0,0 +1,24 @@
|
|||
[bits 16]
|
||||
enable_protected:
|
||||
cli ; Disable interrupts
|
||||
lgdt [gdt_descriptor] ; load the GDT
|
||||
mov eax, cr0
|
||||
or eax, 0x1 ; set 32-bit mode bit
|
||||
mov cr0, eax
|
||||
jmp CODE_SEG:init_protected ; far jump into a different segment
|
||||
|
||||
[bits 32]
|
||||
init_protected: ; now in 32bit
|
||||
mov ax, DATA_SEG ; update segment registers
|
||||
mov ds, ax
|
||||
mov ss, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
|
||||
; wipe registers clean
|
||||
|
||||
mov ebp, 0x90000 ; update stack to top of free space
|
||||
mov esp, ebp
|
||||
|
||||
call BEGIN_PROTECTED ; call known label with useful code
|
|
@ -0,0 +1,4 @@
|
|||
[bits 32]
|
||||
[extern main] ; define callpoint, must have same name as kernel.c entrypoint
|
||||
call main ; jump to fun, linker will figure out where it is
|
||||
jmp $
|
|
@ -0,0 +1,54 @@
|
|||
#include "./platform/drivers/ports.h"
|
||||
#include "print.h"
|
||||
#include "./platform/types.h"
|
||||
#include "./platform/interrupts/int.h"
|
||||
|
||||
void dummy_test_entrypoint() {}
|
||||
|
||||
void kernel_welcome() {
|
||||
print_str("Welcome to ");
|
||||
print_set_color(PRINT_COLOR_CYAN, PRINT_COLOR_BLACK);
|
||||
print_str("Shade");
|
||||
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK);
|
||||
print_str("!\n");
|
||||
|
||||
print_str("shadeOS kernel version ");
|
||||
|
||||
print_set_color(PRINT_COLOR_YELLOW, PRINT_COLOR_BLACK);
|
||||
print_str("0.2.2");
|
||||
|
||||
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK);
|
||||
print_newline();
|
||||
|
||||
print_str("Running on ");
|
||||
|
||||
print_set_color(PRINT_COLOR_YELLOW, PRINT_COLOR_BLACK);
|
||||
print_str("shade-development");
|
||||
|
||||
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK);
|
||||
|
||||
print_newline();
|
||||
}
|
||||
|
||||
// kMain
|
||||
void main() {
|
||||
// Initialize screen buffer
|
||||
struct Char* buffer = (struct Char*) 0xb8000;
|
||||
|
||||
clear_all(); // Clear screen
|
||||
set_cursor_pos(0, 0); // Set cursor position
|
||||
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK); // Set print color
|
||||
|
||||
// welcome messages
|
||||
kernel_msg_ok("Initialized display successfully\n");
|
||||
kernel_welcome();
|
||||
|
||||
print_str("Copyright (c) e3team 2022. All rights reserved.\n");
|
||||
print_str("This program is provided \"as-is\" and no express or implied warranty is provided.\n");
|
||||
print_str("The full license can be found at /sys/LICENCE on this system or ./LICENCE in the source tree.\n");
|
||||
|
||||
idt_init();
|
||||
kernel_msg_ok("Interrupts initialized");
|
||||
|
||||
__asm__ __volatile__("int $2");
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Read 1 byte from specified port
|
||||
*/
|
||||
unsigned char port_byte_in(unsigned short port) {
|
||||
unsigned char result;
|
||||
// source and dest are backwards.
|
||||
// "=a (result)" set the C variable to the value of register e'a'x
|
||||
// '"d" (port) map the C variable port into e'd'x register
|
||||
__asm__("in %%dx, %%al" : "=a" (result) : "d" (port));
|
||||
}
|
||||
|
||||
void port_byte_out(unsigned short port, unsigned char data) {
|
||||
// both regs are C vars, nothing is returned, so no '=' in asm syntax
|
||||
// comma because two vars in input area and none in return area
|
||||
__asm__("out %%al, %%dx" : : "a" (data), "d" (port));
|
||||
}
|
||||
|
||||
unsigned short port_word_in(unsigned short port) {
|
||||
unsigned short result;
|
||||
__asm__("in %%dx, %%ax" : "=a" (result) : "d" (port));
|
||||
return result;
|
||||
}
|
||||
|
||||
void port_word_out(unsigned short port, unsigned short data) {
|
||||
__asm__("out %%ax, %%dx" : : "a" (data), "d" (port));
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
unsigned char port_byte_in(unsigned short port);
|
||||
void port_byte_out(unsigned short port, unsigned char data);
|
||||
unsigned short port_word_in(unsigned short port);
|
||||
void port_word_out(unsigned short port, unsigned short data);
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef GDT_H
|
||||
#define GDT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// the GDT descriptor format makes literally no sense, who came up with this
|
||||
typedef struct {
|
||||
uint16_t limit_low16; // Low 16 bits of limit
|
||||
uint16_t base_low16; // Low 16 bits of base
|
||||
uint8_t base_mid8; // Middle 8 bits of base
|
||||
uint8_t access; // 7: present, 6-5: priv level, 4: type, 3: executable, 2: dc, 1: rw, 0: accessed (zero)
|
||||
uint8_t limit_flags; // High 4 bits of limit AND flags (?? why). flags: 3: granularity, 2: size, 1: long, 0: reserved
|
||||
uint8_t base_high8; // High 8 bits of base
|
||||
} __attribute__((packed)) gdt_entry_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t size; // GDT size (bytes) - 1
|
||||
uint32_t offset; // Address of element 0 of the GDT
|
||||
} __attribute__((packed)) gdt_ptr_t;
|
||||
|
||||
static gdt_entry_t gdt[8192];
|
||||
static gdt_ptr_t gdtr;
|
||||
|
||||
void init_gdt();
|
||||
void gdt_set_segment(int limit, int base, int access);
|
||||
void load_gdt();
|
||||
|
||||
#endif
|
|
@ -0,0 +1,35 @@
|
|||
#include "int.h"
|
||||
#include "../../print.h"
|
||||
|
||||
int count = 0;
|
||||
|
||||
void exception_handler(registers_t r) {
|
||||
print_str("I");
|
||||
count++;
|
||||
if (count > 4) {
|
||||
__asm__ __volatile__("cli; hlt");
|
||||
}
|
||||
}
|
||||
|
||||
void idt_set_descriptor(u8 vector, void* isr, u8 flags) {
|
||||
idt_entry_t* descriptor = &idt[vector];
|
||||
|
||||
descriptor->isr_low = (u32)isr & 0xFFFF;
|
||||
descriptor->kernel_cs = 0x08; // this value can be whatever offset your kernel code selector is in your GDT
|
||||
descriptor->attributes = flags;
|
||||
descriptor->isr_high = (u32)isr >> 16;
|
||||
descriptor->reserved = 0;
|
||||
}
|
||||
|
||||
void idt_init() {
|
||||
idtr.base = (u32)&idt[0];
|
||||
idtr.limit = (u16)sizeof(idt_entry_t) * 256 - 1;
|
||||
|
||||
for (u8 vector = 0; vector < 32; vector++) {
|
||||
idt_set_descriptor(vector, isr_stub_table[vector], 0x8E);
|
||||
isr_stub_table[vector] = TRUE;
|
||||
}
|
||||
|
||||
__asm__ volatile ("lidt %0" : : "m"(idtr)); // load the new IDT
|
||||
__asm__ volatile ("sti"); // set the interrupt flag
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef INT_H
|
||||
#define INT_H
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
typedef struct {
|
||||
u16 isr_low; // The lower 16 bits of the ISR's address
|
||||
u16 kernel_cs; // The GDT segment selector that the CPU will load into CS before calling the ISR
|
||||
u8 reserved; // Set to zero
|
||||
u8 attributes; // Type and attributes; see the IDT page
|
||||
u16 isr_high; // The higher 16 bits of the ISR's address
|
||||
} __attribute__((packed)) idt_entry_t;
|
||||
|
||||
__attribute__((aligned(0x10)))
|
||||
static idt_entry_t idt[256]; // Create an array of IDT entries; aligned for performance
|
||||
|
||||
typedef struct {
|
||||
u16 limit;
|
||||
u32 base;
|
||||
} __attribute__((packed)) idtr_t;
|
||||
|
||||
static idtr_t idtr;
|
||||
|
||||
typedef struct {
|
||||
u32 ds; /* Data segment selector */
|
||||
u32 edi, esi, ebp, esp, ebx, edx, ecx, eax; /* Pushed by pusha. */
|
||||
u32 int_no, err_code; /* Interrupt number and error code (if applicable) */
|
||||
u32 eip, cs, eflags, useresp, ss; /* Pushed by the processor automatically */
|
||||
} registers_t;
|
||||
|
||||
__attribute__((noreturn))
|
||||
void exception_handler(registers_t r);
|
||||
|
||||
void idt_set_descriptor(u8 vector, void* isr, u8 flags);
|
||||
|
||||
extern void* isr_stub_table[];
|
||||
|
||||
void idt_init(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,102 @@
|
|||
%macro isr_err_stub 1
|
||||
isr_stub_%+%1:
|
||||
push byte %1 ; Push interrupt no to stack
|
||||
|
||||
; 1. Save CPU state
|
||||
pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax
|
||||
mov ax, ds ; Lower 16-bits of eax = ds.
|
||||
push eax ; save the data segment descriptor
|
||||
mov ax, 0x10 ; kernel data segment descriptor
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
|
||||
; 2. Call C handler
|
||||
call exception_handler
|
||||
|
||||
; 3. Restore state
|
||||
pop eax
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
popa
|
||||
add esp, 8 ; Cleans up the pushed error code and pushed ISR number
|
||||
sti
|
||||
iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
|
||||
%endmacro
|
||||
; if writing for 64-bit, use iretq instead
|
||||
%macro isr_no_err_stub 1
|
||||
isr_stub_%+%1:
|
||||
push byte 0 ; No error occured
|
||||
push byte %1 ; Push interrupt no to stack
|
||||
|
||||
; 1. Save CPU state
|
||||
pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax
|
||||
mov ax, ds ; Lower 16-bits of eax = ds.
|
||||
push eax ; save the data segment descriptor
|
||||
mov ax, 0x10 ; kernel data segment descriptor
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
|
||||
; 2. Call C handler
|
||||
call exception_handler
|
||||
|
||||
; 3. Restore state
|
||||
pop eax
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
popa
|
||||
add esp, 8 ; Cleans up the pushed error code and pushed ISR number
|
||||
sti
|
||||
iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
|
||||
%endmacro
|
||||
|
||||
extern exception_handler
|
||||
|
||||
isr_no_err_stub 0
|
||||
isr_no_err_stub 1
|
||||
isr_no_err_stub 2
|
||||
isr_no_err_stub 3
|
||||
isr_no_err_stub 4
|
||||
isr_no_err_stub 5
|
||||
isr_no_err_stub 6
|
||||
isr_no_err_stub 7
|
||||
isr_err_stub 8
|
||||
isr_no_err_stub 9
|
||||
isr_err_stub 10
|
||||
isr_err_stub 11
|
||||
isr_err_stub 12
|
||||
isr_err_stub 13
|
||||
isr_err_stub 14
|
||||
isr_no_err_stub 15
|
||||
isr_no_err_stub 16
|
||||
isr_err_stub 17
|
||||
isr_no_err_stub 18
|
||||
isr_no_err_stub 19
|
||||
isr_no_err_stub 20
|
||||
isr_no_err_stub 21
|
||||
isr_no_err_stub 22
|
||||
isr_no_err_stub 23
|
||||
isr_no_err_stub 24
|
||||
isr_no_err_stub 25
|
||||
isr_no_err_stub 26
|
||||
isr_no_err_stub 27
|
||||
isr_no_err_stub 28
|
||||
isr_no_err_stub 29
|
||||
isr_err_stub 30
|
||||
isr_no_err_stub 31
|
||||
|
||||
global isr_stub_table
|
||||
isr_stub_table:
|
||||
%assign i 0
|
||||
%rep 32
|
||||
dd isr_stub_%+i ; use DQ instead if targeting 64-bit
|
||||
%assign i i+1
|
||||
%endrep
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef TYPES_H
|
||||
#define TYPES_H
|
||||
|
||||
typedef unsigned int u32;
|
||||
typedef int i32;
|
||||
typedef unsigned short u16;
|
||||
typedef short i16;
|
||||
typedef unsigned char u8;
|
||||
typedef char i8;
|
||||
|
||||
#define high16(i32) (i32 & 0xffff)
|
||||
#define low16(i32) ((i32>>16) & 0xffff)
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define NULL 0
|
||||
|
||||
#endif
|
|
@ -0,0 +1,110 @@
|
|||
#include "print.h"
|
||||
#include "./platform/drivers/ports.h"
|
||||
|
||||
int row = 0;
|
||||
int col = 0;
|
||||
char color = PRINT_COLOR_WHITE | PRINT_COLOR_BLACK << 4;
|
||||
|
||||
void clear_row(int row) {
|
||||
struct Char* buffer = (struct Char*) 0xb8000;
|
||||
|
||||
struct Char empty = (struct Char) {
|
||||
character: ' ',
|
||||
color: color,
|
||||
};
|
||||
|
||||
for (int x = 0; x < NUM_COLS; x++) {
|
||||
buffer[x + NUM_COLS * row] = empty;
|
||||
}
|
||||
set_cursor_pos(col, row);
|
||||
}
|
||||
|
||||
void clear_all() {
|
||||
for (int i = 0; i < NUM_ROWS; i++) {
|
||||
clear_row(i);
|
||||
}
|
||||
set_cursor_pos(col, row);
|
||||
}
|
||||
|
||||
void print_newline() {
|
||||
struct Char* buffer = (struct Char*) 0xb8000;
|
||||
|
||||
col = 0;
|
||||
|
||||
if (row < NUM_ROWS - 1) {
|
||||
row++;
|
||||
return;
|
||||
}
|
||||
|
||||
for (int row = 1; row < NUM_ROWS; row++) {
|
||||
for (int col = 0; col < NUM_COLS; col++) {
|
||||
struct Char character = buffer[col + NUM_COLS * row];
|
||||
buffer[col + NUM_COLS * (row - 1)] = character;
|
||||
}
|
||||
}
|
||||
|
||||
clear_row(NUM_COLS - 1);
|
||||
set_cursor_pos(col, row);
|
||||
}
|
||||
|
||||
void print_char(char character) {
|
||||
struct Char* buffer = (struct Char*) 0xb8000;
|
||||
|
||||
if (character == '\n') {
|
||||
print_newline();
|
||||
return;
|
||||
}
|
||||
|
||||
if (col > NUM_COLS) {
|
||||
print_newline();
|
||||
}
|
||||
|
||||
struct Char cr = (struct Char) {
|
||||
character: character,
|
||||
color: color,
|
||||
};
|
||||
buffer[col + NUM_COLS * row] = cr;
|
||||
|
||||
col++;
|
||||
set_cursor_pos(col, row);
|
||||
}
|
||||
|
||||
void print_str(char* str) {
|
||||
for (int i = 0; 1; i++) {
|
||||
char character = (char) str[i];
|
||||
|
||||
if (character == '\0') {
|
||||
return;
|
||||
}
|
||||
|
||||
print_char(character);
|
||||
}
|
||||
}
|
||||
|
||||
void print_set_color(char foreground, char background) {
|
||||
color = foreground + (background << 4);
|
||||
}
|
||||
|
||||
void set_cursor_pos(int col, int row) {
|
||||
int offset = col + NUM_COLS * row;
|
||||
port_byte_out(REG_SCREEN_CTRL, 14);
|
||||
port_byte_out(REG_SCREEN_DATA, (unsigned char)(offset >> 8));
|
||||
port_byte_out(REG_SCREEN_CTRL, 15);
|
||||
port_byte_out(REG_SCREEN_DATA, (unsigned char)(offset & 0xff));
|
||||
}
|
||||
|
||||
void kernel_msg_ok(char* msg) {
|
||||
char ok_p1[] = "[ ";
|
||||
char ok_p2[] = "OK ";
|
||||
char ok_p3[] = "] ";
|
||||
|
||||
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK);
|
||||
print_str(ok_p1);
|
||||
|
||||
print_set_color(PRINT_COLOR_GREEN, PRINT_COLOR_BLACK);
|
||||
print_str(ok_p2);
|
||||
|
||||
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK);
|
||||
print_str(ok_p3);
|
||||
print_str(msg);
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
#ifndef PRINT_H
|
||||
#define PRINT_H
|
||||
#define REG_SCREEN_CTRL 0x3d4
|
||||
#define REG_SCREEN_DATA 0x3d5
|
||||
|
||||
enum {
|
||||
PRINT_COLOR_BLACK = 0,
|
||||
PRINT_COLOR_BLUE = 1,
|
||||
PRINT_COLOR_GREEN = 2,
|
||||
PRINT_COLOR_CYAN = 3,
|
||||
PRINT_COLOR_RED = 4,
|
||||
PRINT_COLOR_MAGENTA = 5,
|
||||
PRINT_COLOR_BROWN = 6,
|
||||
PRINT_COLOR_LIGHT_GRAY = 7,
|
||||
PRINT_COLOR_DARK_GRAY = 8,
|
||||
PRINT_COLOR_LIGHT_BLUE = 9,
|
||||
PRINT_COLOR_LIGHT_GREEN = 10,
|
||||
PRINT_COLOR_LIGHT_CYAN = 11,
|
||||
PRINT_COLOR_LIGHT_RED = 12,
|
||||
PRINT_COLOR_PINK = 13,
|
||||
PRINT_COLOR_YELLOW = 14,
|
||||
PRINT_COLOR_WHITE = 15,
|
||||
};
|
||||
|
||||
const static int NUM_COLS = 80;
|
||||
const static int NUM_ROWS = 25;
|
||||
|
||||
struct Char {
|
||||
char character;
|
||||
char color;
|
||||
};
|
||||
|
||||
void clear_row(int row);
|
||||
void clear_all();
|
||||
|
||||
void print_newline();
|
||||
void print_char(char character);
|
||||
void print_set_color(char foreground, char background);
|
||||
void print_str(char* str);
|
||||
|
||||
void set_cursor_pos(int col, int row);
|
||||
|
||||
void kernel_msg_ok(char* msg);
|
||||
#endif
|
|
@ -0,0 +1,48 @@
|
|||
#include <strings.h>
|
||||
#include <stddef.h>
|
||||
|
||||
void itoa(int n, char str[]) {
|
||||
int i, sign;
|
||||
if ((sign = n) < 0) n = -n;
|
||||
i = 0;
|
||||
do {
|
||||
str[i++] = n % 10 + '0';
|
||||
} while ((n /= 10) > 0);
|
||||
|
||||
if (sign < 0) str[i++] = '-';
|
||||
str[i] = '\0';
|
||||
|
||||
strrev(str);
|
||||
}
|
||||
|
||||
/* K&R */
|
||||
void strrev(char s[]) {
|
||||
int c, i, j;
|
||||
for (i = 0, j = strlen(s)-1; i < j; i++, j--) {
|
||||
c = s[i];
|
||||
s[i] = s[j];
|
||||
s[j] = c;
|
||||
}
|
||||
}
|
||||
|
||||
/* K&R */
|
||||
int strlen(char s[]) {
|
||||
int i = 0;
|
||||
while (s[i] != '\0') ++i;
|
||||
return i;
|
||||
}
|
||||
|
||||
char* strcpy(char* strDest, const char* strSrc) {
|
||||
if ( (strDest == NULL) || (strSrc == NULL) ) {
|
||||
return NULL;
|
||||
}
|
||||
char* strDestCopy = strDest;
|
||||
while ((*strDest++=*strSrc++)!='\0');
|
||||
return strDestCopy;
|
||||
}
|
||||
|
||||
char* strcnc(char* str1, char* str2) {
|
||||
char* str_dest;
|
||||
strcpy(str_dest, str1);
|
||||
strcpy(str_dest, str2);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef STRINGS_H
|
||||
#define STRINGS_H
|
||||
|
||||
void itoa(int n, char str[]);
|
||||
void strrev(char s[]);
|
||||
int strlen(char s[]);
|
||||
char* strcpy(char* strDest, const char* strSrc);
|
||||
char* strcnc(char* str1, char* str2);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,25 @@
|
|||
#include "util.h"
|
||||
|
||||
void memcpy(char *source, char *dest, int nbytes) {
|
||||
int i;
|
||||
for (i = 0; i < nbytes; i++) {
|
||||
*(dest + i) = *(source + i);
|
||||
}
|
||||
}
|
||||
|
||||
void memset(char *dest, char val, int len) {
|
||||
char *temp = (char *)dest;
|
||||
for(; len !=0; len--) *temp++ = val;
|
||||
}
|
||||
|
||||
void int_to_ascii(int n, char str[]) {
|
||||
int i, sign;
|
||||
if ((sign = n) < 0) n = -n;
|
||||
i = 0;
|
||||
do {
|
||||
str[i++] = n % 10 + '0';
|
||||
} while ((n /= 10) > 0);
|
||||
|
||||
if (sign < 0) str[i++] = '-';
|
||||
str[i] = '\0';
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef UTIL_H
|
||||
#define UTIL_H
|
||||
|
||||
void memcpy(char *source, char *dest, int nbytes);
|
||||
void memset(char *dest, char val, int len);
|
||||
void int_to_ascii(int n, char str[]);
|
||||
|
||||
#endif
|
|
@ -48,10 +48,17 @@ check_cpuid:
|
|||
jmp error
|
||||
|
||||
check_x64_supported:
|
||||
<<<<<<< HEAD
|
||||
mov eax, 0x80000000
|
||||
cpuid
|
||||
cmp eax, 0x80000001
|
||||
jb .x64_unsupported ; CPUID extended feature set isnt even supported, def no x64
|
||||
=======
|
||||
mov eax, 0x80000000 ; Magic code that i dont understand
|
||||
cpuid ; Magic code that i dont understand
|
||||
cmp eax, 0x80000001 ; Magic code that i dont undetstand
|
||||
jb .x64_unsupported ; Something went wrong so x64 isnt supported
|
||||
>>>>>>> a6f98cddb6e41c517b2f8129624d0ad8965ee0f9
|
||||
|
||||
mov eax, 0x80000001 ; Set magic value 0x80000001 into EAX for cpuid
|
||||
cpuid ; Get "extended features list" from CPU info
|
||||
|
@ -131,6 +138,7 @@ stack_bottom:
|
|||
stack_top:
|
||||
|
||||
section .rodata
|
||||
<<<<<<< HEAD
|
||||
; Access bits
|
||||
PRESENT equ 1 << 7
|
||||
NOT_SYS equ 1 << 4
|
||||
|
@ -176,6 +184,13 @@ gdt64:
|
|||
db PRESENT | RING3 | NOT_SYS | RW ; access: 0b11110010
|
||||
db GRAN_4K | SZ_32 | 0xf ; flags and limit (high, bits 16-19)
|
||||
db 0 ; base (high, bits 24-31)
|
||||
=======
|
||||
gdt64:
|
||||
dd 0 ; zero entry
|
||||
dd 0
|
||||
.code_segment: equ $ - gdt64
|
||||
dq (1 << 43) | (1 << 44) | (1 << 47) | (1 << 53) ; code segment
|
||||
>>>>>>> a6f98cddb6e41c517b2f8129624d0ad8965ee0f9
|
||||
.pointer:
|
||||
dw $ - gdt64 - 1 ; length
|
||||
dq gdt64 ; address
|
Loading…
Reference in New Issue