Compare commits

..

18 Commits

Author SHA1 Message Date
bdcf9e66f8 Small adjustment in directory structure of memory and bootloader files in kernel 2021-11-02 21:15:00 +01:00
c9b789ed7b Added a bunch of new stuff no time to figure out what's what, No longer any compiler warnings 2021-11-02 21:03:11 +01:00
b4b615ae97 Checked off some todo's 2021-10-23 12:27:13 +01:00
092c5d520d Added option to create an iso 2021-10-23 12:26:15 +01:00
643f2d708b Added emulator options, Added header for VBE driver, Added CPUID function, Added demodisk.img as drive 2021-07-22 22:14:58 +01:00
f2c8b8ac5c Improved multiboot compliance 2021-07-22 20:02:47 +01:00
f48f8072c0 Merge InterruptHandling into MemoryManagement 2021-07-22 19:11:01 +01:00
7409e579c8 Basic keyboard input 2021-07-21 21:31:57 +01:00
04f941a625 Kernel now responding to keyboard interrupts 2021-05-28 22:20:13 +01:00
24a855bb3b Fix up wrong interrupt handler numbers in boot.s 2021-05-28 22:18:50 +01:00
83d220019c Nicer time print 2021-05-22 19:24:29 +01:00
48b65b2276 Kernel now enter continuous time telling mode 2021-05-18 21:14:26 +01:00
e0dfa69df8 Removed itoa and printf from idt 2021-05-18 21:13:14 +01:00
394882ca2e Added CMOS time read function, Added cariage return support to kterm 2021-05-18 21:11:48 +01:00
592db0ebcf More work on interrupt handling, Started timer interrupt implementation, PIC remapped hopefully successfull 2021-05-16 15:53:14 +01:00
nigel
28ac6a05af Interrupts are working.. processor no longer resets 2021-05-12 20:43:15 -04:00
0d0c06ab09 Working on PIC 2021-05-12 23:48:06 +01:00
5e668f5e67 Basics for an proper GDT and IDT 2021-05-12 23:03:00 +01:00
43 changed files with 2419 additions and 202 deletions

1
.gitattributes vendored
View File

@ -1,3 +1,4 @@
*.pdf filter=lfs diff=lfs merge=lfs -text *.pdf filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text *.png filter=lfs diff=lfs merge=lfs -text
*.svg filter=lfs diff=lfs merge=lfs -text *.svg filter=lfs diff=lfs merge=lfs -text
demodisk.img filter=lfs diff=lfs merge=lfs -text

7
.gitignore vendored
View File

@ -1 +1,8 @@
build build
CON
.vscode
isodir/
root/
*.iso
*.img

View File

@ -5,7 +5,7 @@ CC = ${HOME}/opt/cross/bin/i686-elf-gcc
CPP = ${HOME}/opt/cross/bin/i686-elf-g++ CPP = ${HOME}/opt/cross/bin/i686-elf-g++
CFLAGS = -ffreestanding -O2 -Wall -Wextra CFLAGS = -ffreestanding -O2 -Wall -Wextra
OFILES = $(BUILD_DIR)/boot.o $(BUILD_DIR)/kterm.o $(BUILD_DIR)/kernel.o $(BUILD_DIR)/io.o $(BUILD_DIR)/MMU.o OFILES = $(BUILD_DIR)/boot.o $(BUILD_DIR)/kterm.o $(BUILD_DIR)/kernel.o $(BUILD_DIR)/io.o $(BUILD_DIR)/PageDirectory.o $(BUILD_DIR)/idt.o $(BUILD_DIR)/pic.o $(BUILD_DIR)/string.o
SRC_DIR = src SRC_DIR = src
BUILD_DIR = build BUILD_DIR = build
@ -19,12 +19,27 @@ OBJ_LINK_LIST = $(CRTI_OBJ) $(CRTBEGIN_OBJ) $(OFILES) $(CRTEND_OBJ) $(CRTN_OBJ)
INTERNAL_OBJS = $(CRTI_OBJ) $(OFILES) $(CRTN_OBJ) INTERNAL_OBJS = $(CRTI_OBJ) $(OFILES) $(CRTN_OBJ)
all: clean build all: clean build clean_up
build: build_kernel run build: build_kernel
run:
$(EMULATOR) -kernel $(BUILD_DIR)/myos.bin -serial stdio
clean_iso:
if [[ -a isodir/* ]] ; then rm isodir/* -d ; fi
if [ -f barinkOS.iso ] ; then rm barinkOS.iso ; fi
iso: clean_iso build
mkdir -p isodir/boot/grub
cp build/myos.bin isodir/boot/myos.bin
cp src/grub.cfg isodir/boot/grub/grub.cfg
grub-mkrescue -o barinkOS.iso isodir
clean_up:
rm build/*.o
test:
$(EMULATOR) -kernel $(BUILD_DIR)/myos.bin -serial file:CON -vga std -monitor stdio -display gtk -m 2G -cpu core2duo
build_kernel: $(OBJ_LINK_LIST) build_kernel: $(OBJ_LINK_LIST)
@ -55,5 +70,15 @@ $(BUILD_DIR)/crtn.o:
$(BUILD_DIR)/io.o: $(BUILD_DIR)/io.o:
$(CPP) -c $(SRC_DIR)/kernel/io.cpp -o $(BUILD_DIR)/io.o $(CFLAGS) -fno-exceptions -fno-rtti $(CPP) -c $(SRC_DIR)/kernel/io.cpp -o $(BUILD_DIR)/io.o $(CFLAGS) -fno-exceptions -fno-rtti
$(BUILD_DIR)/MMU.o:
$(CPP) -c $(SRC_DIR)/kernel/MMU.cpp -o $(BUILD_DIR)/MMU.o $(CFLAGS) -fno-exceptions -fno-rtti $(BUILD_DIR)/PageDirectory.o:
$(CPP) -c $(SRC_DIR)/kernel/memory/PageDirectory.cpp -o $(BUILD_DIR)/PageDirectory.o $(CFLAGS) -fno-exceptions -fno-rtti
$(BUILD_DIR)/idt.o:
$(CPP) -c $(SRC_DIR)/kernel/arch/i386/idt/idt.cpp -o $(BUILD_DIR)/idt.o $(CFLAGS) -fno-exceptions -fno-rtti
$(BUILD_DIR)/pic.o:
$(CPP) -c $(SRC_DIR)/kernel/arch/i386/pic/pic.cpp -o $(BUILD_DIR)/pic.o $(CFLAGS) -fno-exceptions -fno-rtti
$(BUILD_DIR)/string.o:
$(CC) -c $(SRC_DIR)/libc/include/string.c -o $(BUILD_DIR)/string.o $(CFLAGS) -std=gnu99

View File

@ -10,15 +10,17 @@ ________________________
The first scrolling boot screen. 😲 The first scrolling boot screen. 😲
![Interrupt handeling](screenshots/WIP_interruptHandling.png) \
W.I.P - Working on interrupt handling
![Multiboot integration](screenshots/multiboot.png) \
Multiboot information can be read by the kernel.
________________________ ________________________
### The goal ### The goal
Writing a hobby operating system to better understand the basic building blocks of any operating system. Writing a hobby operating system to better understand the basic building blocks of any operating system.
________________________ ________________________
### Operating System Technical specs/details ### Operating System Technical specs/details
The operating system can print strings to the The operating system can print strings to the

10
TODO.md
View File

@ -3,14 +3,14 @@
<input type="checkbox" checked/> Setup Cross-Compiler \ <input type="checkbox" checked/> Setup Cross-Compiler \
<input type="checkbox" checked/> Multiboot to kernel \ <input type="checkbox" checked/> Multiboot to kernel \
<input type="checkbox" checked/> Printing string to the screen \ <input type="checkbox" checked/> Printing string to the screen \
<input type="checkbox" /> Printing values/numbers to the screen (a.k.k itoa) \ <input type="checkbox" checked/> Printing values/numbers to the screen (a.k.k itoa) \
<input type="checkbox" /> Extend Multiboot implementation \ <input type="checkbox" checked/> Extend Multiboot implementation \
<input type="checkbox" checked/> Output to serial port \ <input type="checkbox" checked/> Output to serial port \
<input type="checkbox" /> Move to protected mode \ <input type="checkbox" checked/> Move to protected mode \
<input type="checkbox" /> Enabel CMOS clock \ <input type="checkbox" checked/> Enabel CMOS clock \
<input type="checkbox" /> Time measurement (PIC &| PIT) \ <input type="checkbox" /> Time measurement (PIC &| PIT) \
<input type="checkbox" /> Detect CPU speed \ <input type="checkbox" /> Detect CPU speed \
<input type="checkbox" /> Interrupt / exception system (API) \ <input type="checkbox" checked/> Interrupt / exception system (API) \
<input type="checkbox" /> Plan your memory map (virtual, and physical) : decide where you want the data to be. \ <input type="checkbox" /> Plan your memory map (virtual, and physical) : decide where you want the data to be. \
<input type="checkbox" /> The heap: allocating memory at runtime (malloc and free) is almost impossible to go without. \ <input type="checkbox" /> The heap: allocating memory at runtime (malloc and free) is almost impossible to go without. \

View File

BIN
screenshots/Screenshot from 2021-06-21 14-26-39.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
screenshots/WIP_interruptHandling.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
screenshots/multiboot.png (Stored with Git LFS) Normal file

Binary file not shown.

3
src/grub.cfg Normal file
View File

@ -0,0 +1,3 @@
menuentry "BarinkOS"{
multiboot /boot/myos.bin
}

View File

@ -1,14 +0,0 @@
#pragma once
#include <stdint.h>
extern "C" void loadPageDirectory (long unsigned int* addr );
extern "C" void enablePaging();
class MMU {
public:
void enable ();
private:
uint32_t page_directory[1024] __attribute__((aligned(4096)));
uint32_t first_page_table[1024] __attribute__((aligned(4096)));
};

View File

@ -20,10 +20,429 @@ stack_bottom:
.skip 16384 # 16 KiB .skip 16384 # 16 KiB
stack_top: stack_top:
.section .text
/*
* Interupt handlers
*/
# NOTE: I have no clue how I should use these macros.
# Have tried to use them in a myriad of ways, none would actually work
.macro irs_NoErrCode code:req
.globl irs\code
irs\code:
cli
pushb $0
pushb \code
jmp irs_common
.endm
.macro irs_ErrCode code
.globl irs\code
irs\code:
cli
pushb \code
jmp irs_common
.endm
.globl irs0
irs0:
cli
push $0
push $0
jmp irs_common
.globl irs1
irs1:
cli
push $0
push $1
jmp irs_common
.globl irs2
irs2:
cli
push $0
push $2
jmp irs_common
.globl irs3
irs3:
cli
push $0
push $3
jmp irs_common
.globl irs4
irs4:
cli
push $0
push $4
jmp irs_common
.globl irs5
irs5:
cli
push $0
push $5
jmp irs_common
.globl irs6
irs6:
cli
push $0
push $6
jmp irs_common
.globl irs7
irs7:
cli
push $0
push $7
jmp irs_common
.globl irs8
irs8:
cli
push $0
push $8
jmp irs_common
.globl irs9
irs9:
cli
push $0
push $9
jmp irs_common
.globl irs10
irs10:
cli
push $0
push $10
jmp irs_common
.globl irs11
irs11:
cli
push $0
push $11
jmp irs_common
.globl irs12
irs12:
cli
push $0
push $12
jmp irs_common
.globl irs13
irs13:
cli
push $13
jmp irs_common
.globl irs14
irs14:
cli
push $0
push $14
jmp irs_common
.globl irs15
irs15:
cli
push $0
push $15
jmp irs_common
.globl irs16
irs16:
cli
push $0
push $16
jmp irs_common
.globl irs17
irs17:
cli
push $0
push $17
jmp irs_common
.globl irs18
irs18:
cli
push $0
push $18
jmp irs_common
.globl irs19
irs19:
cli
push $0
push $19
jmp irs_common
.globl irs20
irs20:
cli
push $0
push $20
jmp irs_common
.globl irs21
irs21:
cli
push $0
push $21
jmp irs_common
.globl irs22
irs22:
cli
push $0
push $22
jmp irs_common
.globl irs23
irs23:
cli
push $0
push $23
jmp irs_common
.globl irs24
irs24:
cli
push $0
push $24
jmp irs_common
.globl irs25
irs25:
cli
push $0
push $25
jmp irs_common
.globl irs26
irs26:
cli
push $0
push $26
jmp irs_common
.globl irs27
irs27:
cli
push $0
push $27
jmp irs_common
.globl irs28
irs28:
cli
push $0
push $28
jmp irs_common
.globl irs29
irs29:
cli
push $0
push $29
jmp irs_common
.globl irs30
irs30:
cli
push $0
push $30
jmp irs_common
.globl irs31
irs31:
cli
push $0
push $31
jmp irs_common
.text .globl irq0
irq0:
cli
push $0
push $0
jmp irq_common
.globl irq1
irq1:
cli
push $0
push $1
jmp irq_common
.globl irq2
irq2:
cli
push $0
push $2
jmp irq_common
.globl irq3
irq3:
cli
push $0
push $3
jmp irq_common
.globl irq4
irq4:
cli
push $0
push $4
jmp irq_common
.globl irq5
irq5:
cli
push $0
push $5
jmp irq_common
.globl irq6
irq6:
cli
push $0
push $6
jmp irq_common
.globl irq7
irq7:
cli
push $0
push $7
jmp irq_common
.globl irq8
irq8:
cli
push $0
push $8
jmp irq_common
.globl irq9
irq9:
cli
push $0
push $9
jmp irq_common
.globl irq10
irq10:
cli
push $0
push $10
jmp irq_common
.globl irq11
irq11:
cli
push $0
push $11
jmp irq_common
.globl irq12
irq12:
cli
push $0
push $12
jmp irq_common
.globl irq13
irq13:
cli
push $0
push $13
jmp irq_common
.globl irq14
irq14:
cli
push $0
push $14
jmp irq_common
.globl irq15
irq15:
cli
push $0
push $15
jmp irq_common
irq_common:
pusha
mov %ds, %ax
push %eax
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
call irq_handler
pop %eax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
popa
add $8, %esp # cleans push error and irs code
sti
iret # pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
irs_common:
pusha # Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax
mov %ds, %ax
push %eax
/* load the kernel data segment descriptor*/
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
call irs_handler
pop %eax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
popa
add $8, %esp # cleans push error and irs code
sti
iret # pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
.globl idt_flush
idt_flush:
mov 4(%esp), %eax
lidt (%eax)
ret
.globl enablePaging .globl enablePaging
enablePaging: enablePaging:
push %ebp push %ebp
@ -35,7 +454,6 @@ enablePaging:
pop %ebp pop %ebp
ret ret
.text
.globl loadPageDirectory .globl loadPageDirectory
loadPageDirectory: loadPageDirectory:
push %ebp push %ebp
@ -46,19 +464,57 @@ loadPageDirectory:
pop %ebp pop %ebp
ret ret
.section .text
.global _start .global _start
.type _start, @function .type _start, @function
_start: _start:
/*Setup the stack pointer to point to the beginning of our stack */
/* I believe its a high address growing down to lower adress for the stack on x86*/
mov $stack_top, %esp mov $stack_top, %esp
/*Reset EFLAGS*/
pushl $0
popf
/* push the pointer to the Multiboot information structure*/
pushl %ebx
/* push the magic value */
pushl %eax
call early_main
cli
load_gdt:
lgdt gdt
# set the segment selecters
movw $0x10, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss
ljmp $0x08, $flush
flush:
#load idt
call init_idt
sti
# Try enable A20
# mov $0x2401, %ax
# int $0x15
# enable protected mode
mov %cr0, %eax
or $1, %eax
mov %eax, %cr0
call _init
call kernel_main call kernel_main
@ -67,4 +523,44 @@ _start:
jmp 1b jmp 1b
/* Tell processor to use our gdt*/
gdt:
.word (gdt_end - gdt_start -1) # Size of the GDT in bytes minus 1 for math reasons
.int gdt_start # linear address of our GDT
.att_syntax
.size _start, . - _start .size _start, . - _start
/*
* Create the GDT
*/
.section .data
gdt_start:
gdt_null:
.long 0x0
.long 0x0
gdt_kcode:
.word 0xFFFF # limit
.word 0x0 # base
.byte 0x0 # base
.byte 0b10011010 # 1st flags | type flags
.byte 0b11001111 # 2nd flags | limit
.byte 0x0 # base
gdt_kdata:
.word 0xFFFF # limit
.word 0x0 # base
.byte 0x0 # base
.byte 0b10010010 # 1st flags | type flags
.byte 0b11001111 # 2nd flags | limit
.byte 0x0 # base
gdt_end:

View File

@ -0,0 +1,31 @@
#include "gdtc.h"
#include "../tty/kterm.h"
gdtEntry_t gdt[3];
void gdtSetGate(int num, uint64_t base, uint64_t limit, uint8_t access,
uint8_t gran){
gdt[num].lBase = (base & 0xFFFF);
gdt[num].mBase = (base >> 16) & 0xFF;
gdt[num].hBase = (base >> 24) & 0xFF;
gdt[num].lLimit = (limit & 0xFFFF);
gdt[num].granularity = ((limit >> 16) & 0x0F);
gdt[num].granularity |= (gran & 0xF0);
gdt[num].access = access;
}
void setupGdt(){
printf("setupGdt is called!");
gdtPointer.limit = (sizeof(gdtEntry_t) * 3) - 1;
gdtPointer.base = &gdt;
gdtSetGate(0, 0, 0, 0, 0);
gdtSetGate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
gdtSetGate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
loadGdt();
}

View File

@ -0,0 +1,20 @@
#include <stdint.h>
extern "C"{
typedef struct {
uint16_t lLimit;
uint16_t lBase;
uint8_t mBase;
uint8_t access;
uint8_t granularity;
uint8_t hBase;
} gdtEntry_t;
struct {
uint16_t limit;
uint32_t base;
} gdtPointer;
extern void loadGdt();
void setupGdt();
}

View File

@ -0,0 +1,149 @@
#include "idt.h"
//#include "scancodes/set1.h"
IDT_entry idt_table[256];
IDT_ptr idt_ptr;
void set_id_entry (uint8_t num , uint32_t base, uint16_t sel, uint8_t flags){
idt_table[num].offset_1 = base & 0xFFFF;
idt_table[num].selector = sel;
idt_table[num].zero = 0;
idt_table[num].type_attr = flags;
idt_table[num].offset_2 = (base >> 16) & 0xFFFF;
};
void irs_handler (registers regs) {
kterm_writestring("received interrupt!\n");
printf("(IRS) Interrupt number: %d \n", regs.int_no);
if( regs.int_no == 13){
printf(" Error code: %d \n", regs.err_code);
}
}
void irq_handler (registers regs) {
if ( regs.int_no != 0) {
kterm_writestring("received interrupt!\n");
printf("(IRQ) Interrupt number: %d \n", regs.int_no);
}
if ( regs.int_no == 1 ){
// Keyboard interrupt !!
int scan;
/*register*/int i;
// Read scancode
scan = inb(0x60);
// Send ack message!
i = inb(0x61);
outb(0x61, i|0x80);
outb(0x61, i);
kterm_writestring("A key was pressed/released\n");
printf( "Scancode: %x\n", scan);
}
outb(0x20, 0x20); // send end of interrupt to master
if ( regs.int_no > 8 && regs.int_no <= 15) {
outb(0xA0, 0x20); // send end of interrupt to slave
}
if( regs.int_no == 13){
printf(" Error code: %d \n", regs.err_code);
}
}
void init_idt(){
// Initialise the IDT pointer
idt_ptr.length = sizeof(IDT_entry) * 255;
idt_ptr.base = (uint32_t)&idt_table;
// TODO: Set everything to zero first
set_id_entry(0, (uint32_t) irs0 , 0x08, 0x8F);
set_id_entry(1, (uint32_t) irs1 , 0x08, 0x8E);
set_id_entry(2, (uint32_t) irs2 , 0x08, 0x8E);
set_id_entry(3, (uint32_t) irs3 , 0x08, 0x8E);
set_id_entry(4, (uint32_t) irs4 , 0x08, 0x8E);
set_id_entry(5, (uint32_t) irs5 , 0x08, 0x8E);
set_id_entry(6, (uint32_t) irs6 , 0x08, 0x8E);
set_id_entry(7, (uint32_t) irs7 , 0x08, 0x8E);
set_id_entry(8, (uint32_t) irs8 , 0x08, 0x8E);
set_id_entry(9, (uint32_t) irs9 , 0x08, 0x8E);
set_id_entry(10, (uint32_t) irs10 , 0x08, 0x8E);
set_id_entry(11, (uint32_t) irs11 , 0x08, 0x8E);
set_id_entry(12, (uint32_t) irs12 , 0x08, 0x8E);
set_id_entry(13, (uint32_t) irs13 , 0x08, 0x8E);
set_id_entry(14, (uint32_t) irs14 , 0x08, 0x8E);
set_id_entry(15, (uint32_t) irs15 , 0x08, 0x8E);
set_id_entry(16, (uint32_t) irs16 , 0x08, 0x8E);
set_id_entry(17, (uint32_t) irs17 , 0x08, 0x8E);
set_id_entry(18, (uint32_t) irs18 , 0x08, 0x8E);
set_id_entry(19, (uint32_t) irs19 , 0x08, 0x8E);
set_id_entry(20, (uint32_t) irs20 , 0x08, 0x8E);
set_id_entry(21, (uint32_t) irs21 , 0x08, 0x8E);
set_id_entry(22, (uint32_t) irs22 , 0x08, 0x8E);
set_id_entry(23, (uint32_t) irs23 , 0x08, 0x8E);
set_id_entry(24, (uint32_t) irs24 , 0x08, 0x8E);
set_id_entry(25, (uint32_t) irs25 , 0x08, 0x8E);
set_id_entry(26, (uint32_t) irs26 , 0x08, 0x8E);
set_id_entry(27, (uint32_t) irs27 , 0x08, 0x8E);
set_id_entry(28, (uint32_t) irs28 , 0x08, 0x8E);
set_id_entry(29, (uint32_t) irs29 , 0x08, 0x8E);
set_id_entry(30, (uint32_t) irs30 , 0x08, 0x8E);
set_id_entry(31, (uint32_t) irs31 , 0x08, 0x8E);
//print_serial("Remapping PIC\n");
PIC_remap(0x20, 0x28);
// pic IRQ Table
set_id_entry(32, (uint32_t)irq0, 0x08, 0x8E);
set_id_entry(33, (uint32_t)irq1, 0x08, 0x8E);
set_id_entry(34, (uint32_t)irq2, 0x08, 0x8E);
set_id_entry(35, (uint32_t)irq3, 0x08, 0x8E);
set_id_entry(36, (uint32_t)irq4, 0x08, 0x8E);
set_id_entry(37, (uint32_t)irq5, 0x08, 0x8E);
set_id_entry(38, (uint32_t)irq6, 0x08, 0x8E);
set_id_entry(39, (uint32_t)irq7, 0x08, 0x8E);
set_id_entry(40, (uint32_t)irq8, 0x08, 0x8E);
set_id_entry(41, (uint32_t)irq9, 0x08, 0x8E);
set_id_entry(42, (uint32_t)irq10, 0x08, 0x8E);
set_id_entry(43, (uint32_t)irq11, 0x08, 0x8E);
set_id_entry(44, (uint32_t)irq12, 0x08, 0x8E);
set_id_entry(45, (uint32_t)irq13, 0x08, 0x8E);
set_id_entry(46, (uint32_t)irq14, 0x08, 0x8E);
set_id_entry(47, (uint32_t)irq15, 0x08, 0x8E);
idt_flush((uint32_t)&idt_ptr);
}

View File

@ -0,0 +1,79 @@
#pragma once
#include "stdint.h"
#include "stddef.h"
#include "../vga/colors.h"
#include "../pic/pic.h"
extern "C"{
#include "../tty/kterm.h"
}
extern "C" {
struct __attribute__((__packed__)) IDT_entry {
uint16_t offset_1;
uint16_t selector;
uint8_t zero;
uint8_t type_attr;
uint16_t offset_2;
};
struct __attribute__((__packed__)) IDT_ptr {
unsigned short length;
unsigned long base;
};
struct registers {
uint32_t ds; // Data segment selector
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed by pusha.
uint32_t int_no, err_code; // Interrupt number and error code (if applicable)
uint32_t eip, cs, eflags, useresp, ss;
};
extern void idt_flush(uint32_t);
void set_id_entry (uint8_t num , uint32_t base, uint16_t sel, uint8_t flags);
void init_idt();
void irq_handler (registers regs);
void irs_handler (registers regs);
extern void irs0 ();
extern void irs1 ();
extern void irs2 ();
extern void irs3 ();
extern void irs4 ();
extern void irs5 ();
extern void irs6 ();
extern void irs7 ();
extern void irs8 ();
extern void irs9 ();
extern void irs10 ();
extern void irs11 ();
extern void irs12 ();
extern void irs13 ();
extern void irs14 ();
extern void irs15 ();
extern void irs16 ();
extern void irs17 ();
extern void irs18 ();
extern void irs19 ();
extern void irs20 ();
extern void irs21 ();
extern void irs22 ();
extern void irs23 ();
extern void irs24 ();
extern void irs25 ();
extern void irs26 ();
extern void irs27 ();
extern void irs28 ();
extern void irs29 ();
extern void irs30 ();
extern void irs31 ();
}

View File

@ -0,0 +1,184 @@
#pragma once
// ScanCode set 1
int ScanCodeToKeyCode [0xD8];
/* key pressed scancode */
ScanCodeToKeyCode[0x01] = 4017; // escape pressed
ScanCodeToKeyCode[0x02] = 4018; // 1 pressed
ScanCodeToKeyCode[0x03] = 4019; // 2 pressed
ScanCodeToKeyCode[0x04] = 4020; // 3 pressed
ScanCodeToKeyCode[0x05] ="" // 4 pressed
ScanCodeToKeyCode[0x06] ="" // 5 pressed
ScanCodeToKeyCode[0x07] ="" // 6 pressed
ScanCodeToKeyCode[0x08] ="" // 7 pressed
ScanCodeToKeyCode[0x09] ="" // 8 pressed
ScanCodeToKeyCode[0x0A] ="" // 9 pressed
ScanCodeToKeyCode[0x0B] ="" // 0 (zero) pressed
ScanCodeToKeyCode[0x0C] ="" // - pressed
ScanCodeToKeyCode[0x0D] ="" // = pressed
ScanCodeToKeyCode[0x0E] ="" // backspace pressed
ScanCodeToKeyCode[0x0F] ="" // tab pressed
ScanCodeToKeyCode[0x10] ="" // Q pressed
ScanCodeToKeyCode[0x11] ="" // W pressed
ScanCodeToKeyCode[0x12] ="" // E pressed
ScanCodeToKeyCode[0x13] ="" // R pressed
ScanCodeToKeyCode[0x14] ="" // T pressed
ScanCodeToKeyCode[0x15] ="" // Y pressed
ScanCodeToKeyCode[0x16] ="" // U pressed
ScanCodeToKeyCode[0x17] ="" // I pressed
ScanCodeToKeyCode[0x18] ="" // O pressed
ScanCodeToKeyCode[0x19] ="" // P pressed
ScanCodeToKeyCode[0x1A] ="" // [ pressed
ScanCodeToKeyCode[0x1B] ="" // ] pressed
ScanCodeToKeyCode[0x1C] ="" // enter pressed
ScanCodeToKeyCode[0x1D] ="" // left control pressed
ScanCodeToKeyCode[0x1E] ="" // A pressed
ScanCodeToKeyCode[0x1F] ="" // S pressed
ScanCodeToKeyCode[0x20] ="" // D pressed
ScanCodeToKeyCode[0x21] ="" // F pressed
ScanCodeToKeyCode[0x22] ="" // G pressed
ScanCodeToKeyCode[0x23] ="" // H pressed
ScanCodeToKeyCode[0x24] ="" // J pressed
ScanCodeToKeyCode[0x25] ="" // K pressed
ScanCodeToKeyCode[0x26] ="" // L pressed
ScanCodeToKeyCode[0x27] ="" // ; pressed
ScanCodeToKeyCode[0x28] ="" // ' (single quote) pressed
ScanCodeToKeyCode[0x29] ="" // ` (back tick) pressed
ScanCodeToKeyCode[0x2A] ="" // left shift pressed
ScanCodeToKeyCode[0x2B] ="" // \ pressed
ScanCodeToKeyCode[0x2C] ="" // Z pressed
ScanCodeToKeyCode[0x2D] ="" // X pressed
ScanCodeToKeyCode[0x2E] ="" // C pressed
ScanCodeToKeyCode[0x2F] ="" // V pressed
ScanCodeToKeyCode[0x30] ="" // B pressed
ScanCodeToKeyCode[0x31] ="" // N pressed
ScanCodeToKeyCode[0x32] ="" // M pressed
ScanCodeToKeyCode[0x33] ="" // , pressed
ScanCodeToKeyCode[0x34] ="" // . pressed
ScanCodeToKeyCode[0x35] ="" // / pressed
ScanCodeToKeyCode[0x36] ="" // right shift pressed
ScanCodeToKeyCode[0x37] ="" // (keypad) * pressed
ScanCodeToKeyCode[0x38] ="" // left alt pressed
ScanCodeToKeyCode[0x39] ="" // space pressed
ScanCodeToKeyCode[0x3A] ="" // CapsLock pressed
ScanCodeToKeyCode[0x3B] ="" // F1 pressed
ScanCodeToKeyCode[0x3C] ="" // F2 pressed
ScanCodeToKeyCode[0x3D] ="" // F3 pressed
ScanCodeToKeyCode[0x3E] ="" // F4 pressed
ScanCodeToKeyCode[0x3F] ="" // F5 pressed
ScanCodeToKeyCode[0x40] ="" // F6 pressed
ScanCodeToKeyCode[0x41] ="" // F7 pressed
ScanCodeToKeyCode[0x42] ="" // F8 pressed
ScanCodeToKeyCode[0x43] ="" // F9 pressed
ScanCodeToKeyCode[0x44] ="" // F10 pressed
ScanCodeToKeyCode[0x45] ="" // NumberLock pressed
ScanCodeToKeyCode[0x46] ="" // ScrollLock pressed
ScanCodeToKeyCode[0x47] ="" // (keypad) 7 pressed
ScanCodeToKeyCode[0x48] ="" // (keypad) 8 pressed
ScanCodeToKeyCode[0x49] ="" // (keypad) 9 pressed
ScanCodeToKeyCode[0x4A] ="" // (keypad) - pressed
ScanCodeToKeyCode[0x4B] ="" // (keypad) 4 pressed
ScanCodeToKeyCode[0x4C] ="" // (keypad) 5 pressed
ScanCodeToKeyCode[0x4D] ="" // (keypad) 6 pressed
ScanCodeToKeyCode[0x4E] ="" // (keypad) + pressed
ScanCodeToKeyCode[0x4F] ="" // (keypad) 1 pressed
ScanCodeToKeyCode[0x50] ="" // (keypad) 2 pressed
ScanCodeToKeyCode[0x51] ="" // (keypad) 3 pressed
ScanCodeToKeyCode[0x52] ="" // (keypad) 0 pressed
ScanCodeToKeyCode[0x53] ="" // (keypad) . pressed
ScanCodeToKeyCode[0x57] ="" // F11 pressed
ScanCodeToKeyCode[0x58] ="" // F12 pressed
/* key released scanCode.""*/
ScanCodeToKeyCode[0x81] ="" // escape released
ScanCodeToKeyCode[0x82] ="" // 1 released
ScanCodeToKeyCode[0x83] ="" // 2 released
ScanCodeToKeyCode[0x84] ="" // 3 released
ScanCodeToKeyCode[0x85] ="" // 4 released
ScanCodeToKeyCode[0x86] ="" // 5 released
ScanCodeToKeyCode[0x87] ="" // 6 released
ScanCodeToKeyCode[0x88] ="" // 7 released
ScanCodeToKeyCode[0x89] ="" // 8 released
ScanCodeToKeyCode[0x8A] ="" // 9 released
ScanCodeToKeyCode[0x8B] ="" // 0 (zero) released
ScanCodeToKeyCode[0x8C] ="" // - released
ScanCodeToKeyCode[0x8D] ="" // = released
ScanCodeToKeyCode[0x8E] ="" // backspace released
ScanCodeToKeyCode[0x8F] ="" // tab released
ScanCodeToKeyCode[0x90] ="" // Q released
ScanCodeToKeyCode[0x91] ="" // W released
ScanCodeToKeyCode[0x92] ="" // E released
ScanCodeToKeyCode[0x93] ="" // R released
ScanCodeToKeyCode[0x94] ="" // T released
ScanCodeToKeyCode[0x95] ="" // Y released
ScanCodeToKeyCode[0x96] ="" // U released
ScanCodeToKeyCode[0x97] ="" // I released
ScanCodeToKeyCode[0x98] ="" // O released
ScanCodeToKeyCode[0x99] ="" // P released
ScanCodeToKeyCode[0x9A] ="" // [ released
ScanCodeToKeyCode[0x9B] ="" // ] released
ScanCodeToKeyCode[0x9C] ="" // enter released
ScanCodeToKeyCode[0x9D] ="" // left control released
ScanCodeToKeyCode[0x9E] ="" // A released
ScanCodeToKeyCode[0x9F] ="" // S released
ScanCodeToKeyCode[0xA0] ="" // D released
ScanCodeToKeyCode[0xA1] ="" // F released
ScanCodeToKeyCode[0xA2] ="" // G released
ScanCodeToKeyCode[0xA3] ="" // H released
ScanCodeToKeyCode[0xA4] ="" // J released
ScanCodeToKeyCode[0xA5] ="" // K released
ScanCodeToKeyCode[0xA6] ="" // L released
ScanCodeToKeyCode[0xA7] ="" // ; released
ScanCodeToKeyCode[0xA8] ="" // ' (single quote) released
ScanCodeToKeyCode[0xA9] ="" // ` (back tick) released
ScanCodeToKeyCode[0xAA] ="" // left shift released
ScanCodeToKeyCode[0xAB] ="" // \ released
ScanCodeToKeyCode[0xAC] ="" // Z released
ScanCodeToKeyCode[0xAD] ="" // X released
ScanCodeToKeyCode[0xAE] ="" // C released
ScanCodeToKeyCode[0xAF] ="" // V released
ScanCodeToKeyCode[0xB0] ="" // B released
ScanCodeToKeyCode[0xB1] ="" // N released
ScanCodeToKeyCode[0xB2] ="" // M released
ScanCodeToKeyCode[0xB3] ="" // , released
ScanCodeToKeyCode[0xB4] ="" // . released
ScanCodeToKeyCode[0xB5] ="" // / released
ScanCodeToKeyCode[0xB6] ="" // right shift released
ScanCodeToKeyCode[0xB7] ="" // (keypad) * released
ScanCodeToKeyCode[0xB8] ="" // left alt released
ScanCodeToKeyCode[0xB9] ="" // space released
ScanCodeToKeyCode[0xBA] ="" // CapsLock released
ScanCodeToKeyCode[0xBB] ="" // F1 released
ScanCodeToKeyCode[0xBC] ="" // F2 released
ScanCodeToKeyCode[0xBD] ="" // F3 released
ScanCodeToKeyCode[0xBE] ="" // F4 released
ScanCodeToKeyCode[0xBF] ="" // F5 released
ScanCodeToKeyCode[0xC0] ="" // F6 released
ScanCodeToKeyCode[0xC1] ="" // F7 released
ScanCodeToKeyCode[0xC2] ="" // F8 released
ScanCodeToKeyCode[0xC3] ="" // F9 released
ScanCodeToKeyCode[0xC4] ="" // F10 released
ScanCodeToKeyCode[0xC5] ="" // NumberLock released
ScanCodeToKeyCode[0xC6] ="" // ScrollLock released
ScanCodeToKeyCode[0xC7] ="" // (keypad) 7 released
ScanCodeToKeyCode[0xC8] ="" // (keypad) 8 released
ScanCodeToKeyCode[0xC9] ="" // (keypad) 9 released
ScanCodeToKeyCode[0xCA] ="" // (keypad) - released
ScanCodeToKeyCode[0xCB] ="" // (keypad) 4 released
ScanCodeToKeyCode[0xCC] ="" // (keypad) 5 released
ScanCodeToKeyCode[0xCD] ="" // (keypad) 6 released
ScanCodeToKeyCode[0xCE] ="" // (keypad) + released
ScanCodeToKeyCode[0xCF] ="" // (keypad) 1 released
ScanCodeToKeyCode[0xD0] ="" // (keypad) 2 released
ScanCodeToKeyCode[0xD1] ="" // (keypad) 3 released
ScanCodeToKeyCode[0xD2] ="" // (keypad) 0 released
ScanCodeToKeyCode[0xD3] ="" // (keypad) . released
ScanCodeToKeyCode[0xD7] ="" // F11 released
ScanCodeToKeyCode[0xD8] ="" // F12 released

View File

@ -6,10 +6,11 @@ ENTRY(_start)
kernel image. */ kernel image. */
SECTIONS SECTIONS
{ {
/* Begin putting sections at 1 MiB, a conventional place for kernels to be /* Begin putting sections at 1 MiB, a conventional place for kernels to be
loaded at by the bootloader. */ loaded at by the bootloader. */
. = 1M; . = 1M;
kernel_begin = .;
/* First put the multiboot header, as it is required to be put very early /* First put the multiboot header, as it is required to be put very early
early in the image or the bootloader won't recognize the file format. early in the image or the bootloader won't recognize the file format.
Next we'll put the .text section. */ Next we'll put the .text section. */
@ -40,4 +41,7 @@ SECTIONS
/* The compiler may produce other sections, by default it will put them in /* The compiler may produce other sections, by default it will put them in
a segment with the same name. Simply add stuff here as needed. */ a segment with the same name. Simply add stuff here as needed. */
kernel_end = .;
} }

View File

@ -0,0 +1,62 @@
#include "pic.h"
extern "C" void PIC_sendEOI (unsigned char irq){
if(irq >= 8)
outb(PIC2_COMMAND, PIC_EOI);
outb(PIC1_COMMAND, PIC_EOI);
}
/* Helper func */
static uint16_t __pic_get_irq_reg(int ocw3)
{
/* OCW3 to PIC CMD to get the register values. PIC2 is chained, and
* represents IRQs 8-15. PIC1 is IRQs 0-7, with 2 being the chain */
outb(PIC1_COMMAND, ocw3);
outb(PIC2_COMMAND, ocw3);
return (inb(PIC2_COMMAND) << 8) | inb(PIC1_COMMAND);
}
/* Returns the combined value of the cascaded PICs irq request register */
uint16_t pic_get_irr(void)
{
return __pic_get_irq_reg(PIC_READ_IRR);
}
/* Returns the combined value of the cascaded PICs in-service register */
uint16_t pic_get_isr(void)
{
return __pic_get_irq_reg(PIC_READ_ISR);
}
void PIC_remap (int offset1, int offset2 ){
unsigned char a1, a2;
a1 = inb(PIC1_DATA);
a2 = inb(PIC2_DATA);
// Start initialization
outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4);
io_wait();
outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4);
io_wait();
outb(PIC1_DATA, offset1);
io_wait();
outb(PIC2_DATA, offset2);
io_wait();
outb(PIC1_DATA, 4);
io_wait();
outb(PIC2_DATA, 2);
io_wait();
outb(PIC1_DATA, ICW4_8086);
io_wait();
outb(PIC2_DATA, ICW4_8086);
io_wait();
outb(PIC1_DATA, a1);
outb(PIC2_DATA, a2);
}

View File

@ -0,0 +1,57 @@
#pragma once
#include "../../../io.h"
#define PIC1 0x20 /* IO base address for master PIC */
#define PIC2 0xA0 /* IO base address for slave PIC */
#define PIC1_COMMAND PIC1
#define PIC1_DATA (PIC1+1)
#define PIC2_COMMAND PIC2
#define PIC2_DATA (PIC2+1)
#define ICW1_ICW4 0x01 /* ICW4 (not) needed */
#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
#define ICW1_INIT 0x10 /* Initialization - required! */
#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
#define PIC_EOI 0x20
#define PIC_READ_IRR 0x0a /* OCW3 irq ready next CMD read */
#define PIC_READ_ISR 0x0b /* OCW3 irq service next CMD read */
extern "C"{
extern void irq0 ();
extern void irq1 ();
extern void irq2 ();
extern void irq3 ();
extern void irq4 ();
extern void irq5 ();
extern void irq6 ();
extern void irq7 ();
extern void irq8 ();
extern void irq9 ();
extern void irq10 ();
extern void irq11 ();
extern void irq12 ();
extern void irq13 ();
extern void irq14 ();
extern void irq15 ();
void PIC_sendEOI (unsigned char irq);
}
//static uint16_t __pic_get_irq_reg(int ocw3);
uint16_t pic_get_irr(void);
uint16_t pic_get_isr(void);
void PIC_remap (int offset1, int offset2 );

View File

@ -1,4 +1,5 @@
#include "kterm.h" #include "kterm.h"
static const size_t VGA_WIDTH = 80; static const size_t VGA_WIDTH = 80;
static const size_t VGA_HEIGHT = 25; static const size_t VGA_HEIGHT = 25;
@ -46,6 +47,48 @@ void kterm_putat (char c, uint8_t color, size_t x, size_t y ) {
} }
void enable_cursor (uint8_t start_cursor , uint8_t end_cursor ){
outb(0x3D4, 0x0A);
outb(0x3D5, (inb(0x3D5) & 0xC0) | start_cursor);
outb(0x3D4, 0x0B);
outb(0x3D5, (inb(0x3D5) & 0xE0) | end_cursor);
}
void disable_cursor()
{
outb(0x3D4, 0x0A);
outb(0x3D5, 0x20);
}
void update_cursor(int x, int y){
uint16_t pos = y * VGA_WIDTH + x;
outb(0x3D4, 0x0F);
outb(0x3D5, (uint8_t) (pos & 0xFF));
outb(0x3D4, 0x0E);
outb(0x3D5, (uint8_t) ((pos >> 8) & 0xFF));
}
uint16_t get_cursor_position(){
uint16_t pos = 0;
outb(0x3D4, 0x0F);
pos |= inb(0x3D5);
outb(0x3D4, 0x0E);
pos |= ((uint16_t) inb(0x3D5)) << 8;
return pos;
}
int get_cursor_x (uint16_t cursor_pos) {
return cursor_pos % VGA_WIDTH;
}
int get_cursor_y (uint16_t cursor_pos ) {
return cursor_pos / VGA_WIDTH;
}
/** /**
* With the help from: * With the help from:
@ -62,15 +105,18 @@ void kterm_scrollup(){
} }
void kterm_put (char c) { void kterm_put (char c) {
if(++kterm_column == VGA_WIDTH || c == '\n' ) { if(++kterm_column == VGA_WIDTH || c == '\n' ) {
update_cursor(kterm_column , kterm_row);
kterm_column = 0; kterm_column = 0;
if(kterm_row == VGA_HEIGHT-1 ) { if(kterm_row == VGA_HEIGHT-1 ) {
kterm_scrollup(); kterm_scrollup();
} else { } else {
kterm_row ++; kterm_row ++;
} }
}
if ( c == '\r'){
kterm_column = 0;
return;
} }
if(c == '\n') return; if(c == '\n') return;
@ -86,7 +132,105 @@ void kterm_write(const char* data, size_t size) {
} }
void kterm_writestring(const char* data ){ void kterm_writestring(const char* data ){
AS_KERNEL(); // AS_KERNEL();
kterm_write(data, strlen(data)); kterm_write(data, strlen(data));
} }
static void itoa (char *buf, int base, int d) {
char *p = buf;
char *p1, *p2;
unsigned long ud = d;
int divisor = 10;
if ( base == 'd' && d < 0){
*p++ = '-';
buf++;
ud = -d;
} else if (base == 'x'){
divisor = 16;
}
do {
int remainder = ud % divisor;
*p++ = (remainder < 10 ) ? remainder + '0' : remainder + 'a' -10;
} while(ud /= divisor);
/*terminate buf*/
*p =0;
p1 = buf;
p2 = p -1;
while (p1 < p2)
{
char tmp = *p1;
*p1 = *p2;
*p2 = tmp;
p1++;
p2--;
}
}
void printf ( const char *format, ...) {
char **arg = (char **)&format;
int c;
char buf[20];
arg++;
while ((c = *format++) != 0){
if( c != '%')
kterm_put(c);
else{
char *p, *p2;
int pad0 = 0, pad = 0;
c = *format++;
if(c =='0'){
pad0 = 1;
c = *format++;
}
if ( c >= '0' && c <= '9'){
pad = c - '0';
c = *format++;
}
switch (c)
{
case 'd':
kterm_writestring("Not implemented!!");
break;
case 'u':
break;
case 'x':
itoa(buf, c, *((int *) arg++));
p = buf;
goto string;
break;
case 's':
p = *arg++;
if(!p)
p = "(null)";
string:
for (p2 = p; *p2; p2++);
for (; p2 < p + pad; p2++)
kterm_put(pad0 ? '0': ' ');
while (*p)
kterm_put(*p++);
break;
default:
kterm_put(*((int *)arg++));
break;
}
}
}
}

View File

@ -5,19 +5,41 @@
#include <stdbool.h> #include <stdbool.h>
#include "../vga/colors.h" #include "../vga/colors.h"
#include "../../../io.h"
#include "./../../../../libc/include/string.h"
void kterm_init(); void kterm_init();
/* Kernel terminal - Colour functions*/
void kterm_resetcolor(); void kterm_resetcolor();
void kterm_setcolor(uint8_t); void kterm_setcolor(uint8_t);
/* Kernel terminal - Printing function */
void kterm_putat(char, uint8_t, size_t, size_t); void kterm_putat(char, uint8_t, size_t, size_t);
void kterm_put(char); void kterm_put(char);
void kterm_write(const char*, size_t); void kterm_write(const char*, size_t);
void kterm_writestring(const char*); void kterm_writestring(const char*);
void kterm_scrollup(); void kterm_scrollup();
/* Kernel terminal - Cursor functions */
void enable_cursor (uint8_t start_cursor , uint8_t end_cursor );
void disable_cursor();
void update_cursor(int x, int y);
uint16_t get_cursor_position();
int get_cursor_x (uint16_t cursor_pos);
int get_cursor_y (uint16_t cursor_pos);
void printf ( const char *format, ...);
//static void itoa (char *buf, int base, int d);
#define KernelTag "[Kernel]: " #define KernelTag "[Kernel]: "
#define AS_KERNEL() ( kterm_setcolor(VGA_COLOR_LIGHT_BLUE),\ #define AS_KERNEL() ( kterm_setcolor(VGA_COLOR_LIGHT_BLUE),\
kterm_write(KernelTag, 10 ), \ kterm_write(KernelTag, 10 ), \
kterm_resetcolor()) kterm_resetcolor())

View File

@ -0,0 +1,41 @@
#define VBE_DISPI_IOPORT_INDEX 0x01CE
#define VBE_DISPI_IOPORT_DATA 0x01CF
/* VBE index values*/
#define VBE_DISPI_INDEX_ID 0x0
#define VBE_DISPI_INDEX_XRES 0x1
#define VBE_DISPI_INDEX_YRES 0x2
#define VBE_DISPI_INDEX_BPP 0x3
#define VBE_DISPI_INDEX_ENABLE 0x4
#define VBE_DISPI_INDEX_BANK 0x5
#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
#define VBE_DISPI_INDEX_X_OFFSET 0x8
#define VBE_DISPI_INDEX_Y_OFFSET 0x9
/* BGA Version */
#define VBE_DISPI_ID5 0xB0C5
#define VBE_DISPI_ID4 0xB0C3
#define VBE_DISPI_ID3 0xB0C2
#define VBE_DISPI_ID2 0xB0C1
#define VBE_DISPI_ID1 0xB0C0
/* BGA BIT DEPTH */
#define VBE_DISPI_BPP_4 0x04
#define VBE_DISPI_BPP_8 0x08
#define VBE_DISPI_BPP_15 0x0F
#define VBE_DISPI_BPP_16 0x10
#define VBE_DISPI_BPP_24 0x18
#define VBE_DISPI_BPP_32 0x20
/*unsigned short BGAReadRegister(unsigned short IndexValue){
// outpw(VBE_DISPI_IOPORT_INDEX, IndexValue);
// return inpw (VBE_DISPI_IOPORT_DATA);
}
int BGAIsAvailable (){
return (BGAReadRegister(VBE_DISPI_INDEX_ID) == VBE_DISPI_ID5);
}*/

73
src/kernel/bootcheck.h Normal file
View File

@ -0,0 +1,73 @@
#pragma once
#include "bootloader/multiboot.h"
#define CHECK_FLAG(flags, bit) ((flags) & (1 <<(bit)))
extern "C" {
#include "arch/i386/tty/kterm.h"
}
void CheckMBT ( multiboot_info_t* mbt ){
/* Set MBI to the addresss of the multiboot information structure*/
multiboot_info_t * mbi = (multiboot_info_t *) mbt;
/* Print out the flags */
printf("flags = 0x%x\n", (unsigned) mbi->flags);
/* Are mem_* valid? */
if ( CHECK_FLAG(mbi->flags,0)){
printf("mem_lower = %uKB, mem_upper = %uKB\n");
}
/* is boot device valid ? */
if (CHECK_FLAG (mbi->flags, 1)){
printf("boot_device = 0x0%x\n", (unsigned) mbi->boot_device);
}
/* is the command line passed? */
if (CHECK_FLAG ( mbi->flags,2)){
printf("cmdline = %s\n", (char *) mbi->cmdline);
}
/* Are mods_* valid? */
if(CHECK_FLAG ( mbi->flags, 3)){
multiboot_module_t *mod;
uint32_t i;
printf("mods count = %d, mods_addr = 0x%x\n", (int) mbi->mods_count, (int) mbi->mods_addr);
for(i = 0, mod = (multiboot_module_t *) mbi->mods_addr; i < mbi->mods_count; i++ , mod++){
printf(" mod start = 0x%x, mod_end = 0x%x, cmdline = %s\n", (unsigned) mod->mod_start, (unsigned) mod->mod_end, (char*) mod->cmdline);
}
}
/* Bits 4 and 5 are mutually exclusive! */
if (CHECK_FLAG (mbi->flags, 4) && CHECK_FLAG(mbi->flags, 5)){
printf("Both bits 4 and 5 are set.\n");
return;
}
/* Is the symbol table of a.out valid? */
if (CHECK_FLAG(mbi->flags, 4)){
multiboot_aout_symbol_table_t *multiboot_aout_sym = &(mbi->u.aout_sym);
printf( "multiboot_aout_symbol_table: tabsize = 0x%0x, strsize = 0x%x, addr = 0x%x\n",
(unsigned) multiboot_aout_sym->tabsize,
(unsigned) multiboot_aout_sym->strsize,
(unsigned) multiboot_aout_sym->addr);
}
/* Is the section header table of ELF valid? */
if (CHECK_FLAG(mbi->flags, 5)){
multiboot_elf_section_header_table_t *multiboot_elf_sec = &(mbi->u.elf_sec);
printf("multiboot_elf_sec: num = %u, size = 0x%x, addr = 0x%x, shnd = 0x%x\n",
(unsigned) multiboot_elf_sec->num, (unsigned) multiboot_elf_sec->size,
(unsigned) multiboot_elf_sec->addr, (unsigned) multiboot_elf_sec->shndx);
}
}

View File

@ -0,0 +1,274 @@
/* multiboot.h - Multiboot header file. */
/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY
* DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef MULTIBOOT_HEADER
#define MULTIBOOT_HEADER 1
/* How many bytes from the start of the file we search for the header. */
#define MULTIBOOT_SEARCH 8192
#define MULTIBOOT_HEADER_ALIGN 4
/* The magic field should contain this. */
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
/* This should be in %eax. */
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
/* Alignment of multiboot modules. */
#define MULTIBOOT_MOD_ALIGN 0x00001000
/* Alignment of the multiboot info structure. */
#define MULTIBOOT_INFO_ALIGN 0x00000004
/* Flags set in the flags member of the multiboot header. */
/* Align all boot modules on i386 page (4KB) boundaries. */
#define MULTIBOOT_PAGE_ALIGN 0x00000001
/* Must pass memory information to OS. */
#define MULTIBOOT_MEMORY_INFO 0x00000002
/* Must pass video information to OS. */
#define MULTIBOOT_VIDEO_MODE 0x00000004
/* This flag indicates the use of the address fields in the header. */
#define MULTIBOOT_AOUT_KLUDGE 0x00010000
/* Flags to be set in the flags member of the multiboot info structure. */
/* is there basic lower/upper memory information? */
#define MULTIBOOT_INFO_MEMORY 0x00000001
/* is there a boot device set? */
#define MULTIBOOT_INFO_BOOTDEV 0x00000002
/* is the command-line defined? */
#define MULTIBOOT_INFO_CMDLINE 0x00000004
/* are there modules to do something with? */
#define MULTIBOOT_INFO_MODS 0x00000008
/* These next two are mutually exclusive */
/* is there a symbol table loaded? */
#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010
/* is there an ELF section header table? */
#define MULTIBOOT_INFO_ELF_SHDR 0X00000020
/* is there a full memory map? */
#define MULTIBOOT_INFO_MEM_MAP 0x00000040
/* Is there drive info? */
#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080
/* Is there a config table? */
#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100
/* Is there a boot loader name? */
#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200
/* Is there a APM table? */
#define MULTIBOOT_INFO_APM_TABLE 0x00000400
/* Is there video information? */
#define MULTIBOOT_INFO_VBE_INFO 0x00000800
#define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000
#ifndef ASM_FILE
typedef unsigned char multiboot_uint8_t;
typedef unsigned short multiboot_uint16_t;
typedef unsigned int multiboot_uint32_t;
typedef unsigned long long multiboot_uint64_t;
struct multiboot_header
{
/* Must be MULTIBOOT_MAGIC - see above. */
multiboot_uint32_t magic;
/* Feature flags. */
multiboot_uint32_t flags;
/* The above fields plus this one must equal 0 mod 2^32. */
multiboot_uint32_t checksum;
/* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */
multiboot_uint32_t header_addr;
multiboot_uint32_t load_addr;
multiboot_uint32_t load_end_addr;
multiboot_uint32_t bss_end_addr;
multiboot_uint32_t entry_addr;
/* These are only valid if MULTIBOOT_VIDEO_MODE is set. */
multiboot_uint32_t mode_type;
multiboot_uint32_t width;
multiboot_uint32_t height;
multiboot_uint32_t depth;
};
/* The symbol table for a.out. */
struct multiboot_aout_symbol_table
{
multiboot_uint32_t tabsize;
multiboot_uint32_t strsize;
multiboot_uint32_t addr;
multiboot_uint32_t reserved;
};
typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t;
/* The section header table for ELF. */
struct multiboot_elf_section_header_table
{
multiboot_uint32_t num;
multiboot_uint32_t size;
multiboot_uint32_t addr;
multiboot_uint32_t shndx;
};
typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t;
struct multiboot_info
{
/* Multiboot info version number */
multiboot_uint32_t flags;
/* Available memory from BIOS */
multiboot_uint32_t mem_lower;
multiboot_uint32_t mem_upper;
/* "root" partition */
multiboot_uint32_t boot_device;
/* Kernel command line */
multiboot_uint32_t cmdline;
/* Boot-Module list */
multiboot_uint32_t mods_count;
multiboot_uint32_t mods_addr;
union
{
multiboot_aout_symbol_table_t aout_sym;
multiboot_elf_section_header_table_t elf_sec;
} u;
/* Memory Mapping buffer */
multiboot_uint32_t mmap_length;
multiboot_uint32_t mmap_addr;
/* Drive Info buffer */
multiboot_uint32_t drives_length;
multiboot_uint32_t drives_addr;
/* ROM configuration table */
multiboot_uint32_t config_table;
/* Boot Loader Name */
multiboot_uint32_t boot_loader_name;
/* APM table */
multiboot_uint32_t apm_table;
/* Video */
multiboot_uint32_t vbe_control_info;
multiboot_uint32_t vbe_mode_info;
multiboot_uint16_t vbe_mode;
multiboot_uint16_t vbe_interface_seg;
multiboot_uint16_t vbe_interface_off;
multiboot_uint16_t vbe_interface_len;
multiboot_uint64_t framebuffer_addr;
multiboot_uint32_t framebuffer_pitch;
multiboot_uint32_t framebuffer_width;
multiboot_uint32_t framebuffer_height;
multiboot_uint8_t framebuffer_bpp;
#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
multiboot_uint8_t framebuffer_type;
union
{
struct
{
multiboot_uint32_t framebuffer_palette_addr;
multiboot_uint16_t framebuffer_palette_num_colors;
};
struct
{
multiboot_uint8_t framebuffer_red_field_position;
multiboot_uint8_t framebuffer_red_mask_size;
multiboot_uint8_t framebuffer_green_field_position;
multiboot_uint8_t framebuffer_green_mask_size;
multiboot_uint8_t framebuffer_blue_field_position;
multiboot_uint8_t framebuffer_blue_mask_size;
};
};
};
typedef struct multiboot_info multiboot_info_t;
struct multiboot_color
{
multiboot_uint8_t red;
multiboot_uint8_t green;
multiboot_uint8_t blue;
};
struct multiboot_mmap_entry
{
multiboot_uint32_t size;
multiboot_uint64_t addr;
multiboot_uint64_t len;
#define MULTIBOOT_MEMORY_AVAILABLE 1
#define MULTIBOOT_MEMORY_RESERVED 2
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
#define MULTIBOOT_MEMORY_NVS 4
#define MULTIBOOT_MEMORY_BADRAM 5
multiboot_uint32_t type;
} __attribute__((packed));
typedef struct multiboot_mmap_entry multiboot_memory_map_t;
struct multiboot_mod_list
{
/* the memory used goes from bytes mod_start to mod_end-1 inclusive */
multiboot_uint32_t mod_start;
multiboot_uint32_t mod_end;
/* Module command line */
multiboot_uint32_t cmdline;
/* padding to take it to 16 bytes (must be zero) */
multiboot_uint32_t pad;
};
typedef struct multiboot_mod_list multiboot_module_t;
/* APM BIOS info. */
struct multiboot_apm_info
{
multiboot_uint16_t version;
multiboot_uint16_t cseg;
multiboot_uint32_t offset;
multiboot_uint16_t cseg_16;
multiboot_uint16_t dseg;
multiboot_uint16_t flags;
multiboot_uint16_t cseg_len;
multiboot_uint16_t cseg_16_len;
multiboot_uint16_t dseg_len;
};
#endif /* ! ASM_FILE */
#endif /* ! MULTIBOOT_HEADER */

17
src/kernel/cpu.h Normal file
View File

@ -0,0 +1,17 @@
#include <cpuid.h> // NOTE: Only available in GCC
// NOT currently usefull!
/* static int get_model(){
int ebx, unused;
__cpuid(0, unused, ebx, unused, unused);
return ebx;
}
enum {
CPUID_FEAT_EDX_APIC = 1 << 9
};
static int check_apic (){
unsigned int eax, unused, edx;
__get_cpuid(1, &eax, &unused, &unused, &edx);
return edx & CPUID_FEAT_EDX_APIC;
}
*/

17
src/kernel/disk.h Normal file
View File

@ -0,0 +1,17 @@
#pragma once
// Let's write an ATA PIO | ATA driver for now. Mostly to show that I can in theory interact with a
// storage device
// PRIMARY_ATA_BUS
// 0x1F0 through 0x1F7
// SECONDARY_ATA_BUS
// 0x170 through 0x177
#define DEVICE_CONTROL_REGISTER 0x3F6
#define DEVICE_CONTROL_ALTERNATE 0x376
// IRQ14 Primary bus interrupt
// IRQ15 Secondary bus interrupt

View File

@ -1,19 +1,24 @@
#include "io.h" #include "io.h"
unsigned char inb_p(unsigned short ){ unsigned char inb_p(unsigned short ){
// TODO: implement me!
return 0;
} }
unsigned short inw(unsigned short ){ unsigned short inw(unsigned short ){
// TODO: implement me!
return 0;
} }
unsigned short inw_p(unsigned short ){ unsigned short inw_p(unsigned short ){
// TODO: implement me!
return 0;
} }
unsigned int inl(unsigned short ){ unsigned int inl(unsigned short ){
// TODO: implement me!
return 0;
} }
unsigned int inl_p(unsigned short ){ unsigned int inl_p(unsigned short ){
// TODO: implement me!
return 0;
} }
@ -57,3 +62,11 @@ void outsl(unsigned short , const void *,
unsigned long ){ unsigned long ){
} }
void io_wait(void)
{
/* TODO: This is probably fragile. */
asm volatile ( "jmp 1f\n\t"
"1:jmp 2f\n\t"
"2:" );
}

View File

@ -41,3 +41,4 @@ void outsw(unsigned short port, const void *addr,
unsigned long count); unsigned long count);
void outsl(unsigned short port, const void *addr, void outsl(unsigned short port, const void *addr,
unsigned long count); unsigned long count);
void io_wait();

View File

@ -1,136 +1,91 @@
#include "kernel.h" #include "kernel.h"
/** #include "arch/i386/gdt/gdtc.h"
* simple delay function
**/
void delay(int t){
volatile int i,j;
for(i=0;i<t;i++)
for(j=0;j<25000;j++)
asm("NOP");
}
class Test {
public:
Test();
void printMe();
~Test();
};
Test::Test(){
kterm_writestring("Create a test object\n");
};
void Test::printMe(){
kterm_writestring("testObject.printMe()\n");
}
Test::~Test(){
kterm_writestring("Destroy testObject! Bye bye\n");
}
#define PORT 0x3f8
static int init_serial() {
outb(PORT + 1, 0x00); // Disable all interrupts
outb(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
outb(PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
outb(PORT + 1, 0x00); // (hi byte)
outb(PORT + 3, 0x03); // 8 bits, no parity, one stop bit
outb(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
outb(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
outb(PORT + 4, 0x1E); // Set in loopback mode, test the serial chip
outb(PORT + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
// Check if serial is faulty (i.e: not same byte as sent)
if(inb(PORT + 0) != 0xAE) {
return 1;
}
// If serial is not faulty set it in normal operation mode
// (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
outb(PORT + 4, 0x0F);
return 0;
}
int is_transmit_empty() {
return inb(PORT + 5) & 0x20;
}
void write_serial(char a) {
while (is_transmit_empty() == 0);
outb(PORT,a);
}
int serial_received() {
return inb(PORT + 5) & 1;
}
char read_serial() {
while (serial_received() == 0);
return inb(PORT);
}
void test_serial(){
/** Serial test **/
kterm_writestring("Writing to COM1 serial port:");
init_serial();
write_serial('A');
write_serial('B');
write_serial('C');
write_serial('D');
write_serial('E');
char Character_received = read_serial();
kterm_writestring("\n");
kterm_writestring("received from COM 1: \n");
kterm_put(Character_received);
kterm_writestring("\n");
}
extern "C" { extern "C" {
void kernel_main (void) {
void early_main(unsigned long magic, unsigned long addr){
/** initialize terminal interface */ /** initialize terminal interface */
kterm_init(); kterm_init();
/** Wrtite stuff to the screen to test the terminal**/ if (magic != MULTIBOOT_BOOTLOADER_MAGIC){
kterm_writestring("Hello world!\n"); printf("Invalid magic number: 0x%x\n", magic);
kterm_writestring("We got newline support!\n"); return;
}
/** Test scrolling **/ CheckMBT( (multiboot_info_t *) addr);
for(int i=0; i < 5; i++){
delay(500);
kterm_writestring("We have implemented terminal scrolling!\n"); multiboot_info_t* mbt = (multiboot_info_t*) addr;
// Map the kernel
//initPhysicalMemoryManager();
// AAAAAH memory map, Yes please!
/* Are mmap_* valid? */
if (CHECK_FLAG(mbt->flags, 6)){
multiboot_memory_map_t *mmap = (multiboot_memory_map_t*) mbt->mmap_addr;
uint32_t memorySizeInBytes = 0;
uint32_t reservedMemoryInBytes = 0;
printf("mmap_addr = 0x%x, mmap_length = 0x%x\n",
(unsigned) mbt->mmap_addr, (unsigned) mbt->mmap_length);
for (; (unsigned long) mmap < mbt->mmap_addr + mbt->mmap_length; mmap = (multiboot_memory_map_t *) ((unsigned long) mmap + mmap->size + sizeof(mmap->size))){
if ( mmap->type == MULTIBOOT_MEMORY_AVAILABLE){
memorySizeInBytes += mmap->len;
} else {
reservedMemoryInBytes += mmap->len;
} }
/** Test objective cpp **/ printf(
kterm_writestring("Testing C++ object support\n"); "size = 0x%x, base_addr = 0x%x%08x, length = 0x%x%08x, type = 0x%x\n",
auto testObject = Test(); (unsigned) mmap->size,
testObject.printMe(); (unsigned) (mmap->addr >> 32),
(unsigned) (mmap->addr & 0xffffffff),
(unsigned) (mmap->len >> 32),
(unsigned) (mmap->len & 0xffffffff),
(unsigned) mmap->type);
/** Setup the MMU **/ }
kterm_writestring("Starting MMU...\n"); uint32_t memorySizeInGiB = memorySizeInBytes / 1073741824;
auto mmu = MMU();
mmu.enable(); printf("Available Memory: 0x%x bytes, 0x%x GiB\n", memorySizeInBytes, memorySizeInGiB );
kterm_writestring("MMU enabled!\n"); printf("Reserved Memory: 0x%x bytes\n", reservedMemoryInBytes );
}
//int cpu_model = get_model();
//int local_apic = check_apic();
//printf( "CPU Model: %x, Local APIC: %D\n", cpu_model, local_apic);
/** Lets start using the serial port for debugging .. **/
// Hopefully once we go into realmode or do something that
// cause the screen to go black.. this serial comms part will give
// some situational awareness
//Serial serialbus = Serial::init();
test_serial(); /* Setup Paging and memory Managment*/
//MMU MemoryManagementUnit = MMU();
//MemoryManagementUnit.enable(); // Warning: Causes triple page fault
//printf("Pages available: %9d\n", pmm_available());
/* Draw diagonal blue line */
if (CHECK_FLAG (mbt->flags, 12)){
printf("Can draw!");
}
//setupGdt();
} }
void kernel_main (void) {
init_serial();
while (false){
//Read time indefinetely
read_rtc();
printf( "UTC time: %02d-%02d-%02d %02d:%02d:%02d [ Formatted as YY-MM-DD h:mm:ss]\r" ,year, month, day, hour, minute, second);
delay(1000);
}
}
} }

View File

@ -1,7 +1,114 @@
#pragma once #pragma once
extern "C" { extern "C" {
#include "../libc/include/string.h"
#include "arch/i386/tty/kterm.h" #include "arch/i386/tty/kterm.h"
} }
#include "MMU.h"
#include "../libc/include/string.h"
#include "./bootloader/multiboot.h"
#include "bootcheck.h"
#include "arch/i386/idt/idt.h"
#include "io.h" #include "io.h"
#include "time.h"
#include "cpu.h"
#include "arch/i386/vga/VBE.h"
#define CHECK_FLAG(flags, bit) ((flags) & (1 <<(bit)))
/* This needs to be moved! */
/**
* simple delay function
**/
void delay(int t){
volatile int i,j;
for(i=0;i<t;i++)
for(j=0;j<25000;j++)
asm("NOP");
}
class Test {
public:
Test();
void printMe();
~Test();
};
Test::Test(){
kterm_writestring("Create a test object\n");
};
void Test::printMe(){
kterm_writestring("testObject.printMe()\n");
}
Test::~Test(){
kterm_writestring("Destroy testObject! Bye bye\n");
}
#define PORT 0x3f8
static int init_serial() {
outb(PORT + 1, 0x00); // Disable all interrupts
outb(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
outb(PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
outb(PORT + 1, 0x00); // (hi byte)
outb(PORT + 3, 0x03); // 8 bits, no parity, one stop bit
outb(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
outb(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
outb(PORT + 4, 0x1E); // Set in loopback mode, test the serial chip
outb(PORT + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
// Check if serial is faulty (i.e: not same byte as sent)
if(inb(PORT + 0) != 0xAE) {
return 1;
}
// If serial is not faulty set it in normal operation mode
// (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
outb(PORT + 4, 0x0F);
return 0;
}
int is_transmit_empty() {
return inb(PORT + 5) & 0x20;
}
void write_serial(char a) {
while (is_transmit_empty() == 0);
outb(PORT,a);
}
int serial_received() {
return inb(PORT + 5) & 1;
}
char read_serial() {
while (serial_received() == 0);
return inb(PORT);
}
void print_serial(const char* string ){
for(size_t i = 0; i < strlen(string); i ++){
write_serial(string[i]);
}
}
void test_serial(){
/** Serial test **/
kterm_writestring("Writing to COM1 serial port:");
init_serial();
write_serial('A');
write_serial('B');
write_serial('C');
write_serial('D');
write_serial('E');
char Character_received = read_serial();
kterm_writestring("\n");
kterm_writestring("received from COM 1: \n");
kterm_put(Character_received);
kterm_writestring("\n");
}

View File

@ -1,8 +1,9 @@
#include "MMU.h" #include "PageDirectory.h"
#include <stdint.h>
void MMU::enable(){ void PageDirectory::enable(){
//set each entry to not present //set each entry to not present
int i; int i;
@ -33,3 +34,14 @@ void MMU::enable(){
loadPageDirectory(this->page_directory); loadPageDirectory(this->page_directory);
enablePaging(); enablePaging();
} }
/*
void IdentityPaging(uint32_t *first_pte, vaddr from, int size)
{
from = from & 0xFFFFF000; // Discard the bits we don't want
for (; size > 0; from += 4096, first_pte++)
{
*first_pte = from | 1; // makr page present.
}
}
*/

View File

@ -0,0 +1,28 @@
#pragma once
#include <stdint.h>
extern "C" void loadPageDirectory (uint32_t* addr );
extern "C" void enablePaging();
typedef uintptr_t address_t;
#define KB 1024
static const int MAX_PAGES = 1024 * KB; // 4GB , 4kB/page
static volatile address_t pmem_stack[MAX_PAGES];
static volatile address_t pmem_stack_top = MAX_PAGES; // top down allocation
struct page_directory_entry {};
struct page_table_entry{};
class PageDirectory {
public:
void enable ();
private:
uint32_t page_directory[1024] __attribute__((aligned(4096)));
uint32_t first_page_table[1024] __attribute__((aligned(4096)));
};

View File

@ -0,0 +1 @@
#include "PageFrameAllocator.h"

View File

@ -0,0 +1,8 @@
#pragma once
#include <stdint.h>
extern void *kernel_begin;
extern void *kernel_end;

View File

@ -0,0 +1,33 @@
#pragma once
/**
* We'll need something to this effect to allocate memory in the kernel
* this will hopefully someday implement a full slab allocator
**/
enum SlabState {
empty,
partial,
full
};
class CacheSlab {
const int SlabSize = 4000;
void* start = 0x0;
};
class Allocator {
public:
Allocator();
~Allocator();
void* kmalloc( int size );
void kfree (void* address);
private:
CacheSlab** _cache;
};

108
src/kernel/pci.cpp Normal file
View File

@ -0,0 +1,108 @@
#include "pci.h"
uint16_t ConfigReadWord (uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset){
uint32_t address;
uint32_t lbus = (uint32_t) bus;
uint32_t lslot = (uint32_t) slot;
uint32_t lfunc = (uint32_t) func;
uint16_t tmp = 0;
/* Create configuration address as per Figure 1 */
address = (uint32_t) ((lbus << 16) | (lslot << 11) | (lfunc << 8) | (offset & 0xFC) |((uint32_t) 0x80000000) );
/*write out the address */
outl(CONFIG_ADDRESS, address);
/* read in the data */
/* (offset & 2 ) * 8 ) = o will choosse the first word of the 32 bits register*/
tmp = (uint16_t)((inl(CONFIG_DATA)) >> ((offset & 2) * 8) & 0xFFFF);
return (tmp);
}
uint16_t CheckVendor (uint8_t bus, uint8_t slot) {
uint16_t vendor, device;
/*
Try and read the first configuration register. Since there ar no
vendors that == 0xFFFF, it must be a non-existent device.
*/
if((vendor = ConfigReadWord(bus, slot, 0,0)) != 0xFFFF) {
device = ConfigReadWord(bus, slot, 0,2);
// Possible read more config values ...
} return (vendor);
}
void checkDevice (uint8_t bus, uint8_t device ) {
uint8_t function = 0;
uint16_t vendorID = CheckVendor(bus, device);
if (vendorID == 0xFFFF) {
return;
}
checkFunction (bus, device, function );
headerType = getHeaderType(bus, device, function );
if( (headerType & 0x80) != 0) {
/* It is a multi-function device, so check remaining functions */
for (function = 1; function < 8; function++){
if (CheckVendor(bus, device)!= 0xFFFF){
checkFunction(bus, device, function );
}
}
}
}
void checkFunction (uint8_t bus, uint8_t device, uint8_t function ){
uint8_t baseClass;
uint8_t subClass;
uint8_t secondaryBus;
baseClass = getBaseClass(bus, device, function);
subClass = getSubClass (bus, device, function );
if ( (baseClass == 0x06) && (subClass == 0x04)){
secondaryBus = getSecondaryBus(bus,device, function);
checkBus(secondaryBus);
}
}
// Brute-force scan
void checkAllBuses (){
uint16_t bus;
uint8_t device;
for(bus = 0; bus < 256; bus++){
for(device = 0; device < 32; device++){
checkDevice(bus,device);
}
}
}
// Recursive scan
void checkBus (uint8_t bus){
uint8_t device;
for(device = 0; device < 32; device ++){
checkDevice(bus,device);
}
}
void checkAllBuses(){
uint8_t function;
uint8_t bus;
headerType = getHeaderType(0,0,0);
if ( (headerType & 0x80) == 0 ){
/* Single PCI host controller */
checkBus(0);
} else{
/* Multiple PCI host controllers */
for (function = 0; function < 8; function++){
if( CheckVendor(0,0) != 0xFFFF) {
break;
}
bus = function;
checkBus(bus);
}
}
}

58
src/kernel/pci.h Normal file
View File

@ -0,0 +1,58 @@
#pragma once
#include <stdint.h>
#include "io.h"
// Configuration Space Access Mechanism #1
#define CONFIG_ADDRESS 0xCF8 // Configuration adress that is to be accessed
#define CONFIG_DATA 0xCFC // Will do the actual configuration operation
/*
CONFIG_ADDRESS
32 bit register
bit 31 Enable bit (Should CONFIG_DATA be translatedc to configuration cycles)
bit 30 - 24 Reserved
bit 23 - 16 Bus Number (Choose a specific PCI BUS)
bit 15 - 11 Device Number (Selects specific device one the pci bus)
bit 10 - 8 Function Number (Selects a specific function in a device)
bit 7 - 0 Register Offset (Offset in the configuration space of 256 Bytes ) NOTE: lowest two bits will always be zero
*/
/*
PCI Device structure
Register offset bits 31-24 bits 23-16 bits 15-8 bits 7-0
00 00 Device ID <---- Vendor ID <-------
01 04 Status <---- Command <-------
02 08 Class code Sub class Prog IF Revision ID
03 0C BIST Header Type Ltncy Timer Cache line Size
04 10 Base address #0 (BAR0)
05 14 Base address #1 (BAR1)
06 18 Base address #2 (BAR2)
07 1C Base address #3 (BAR3)
08 20 Base address #4 (BAR4)
09 24 Base address #5 (BAR5)
0A 28 Cardbus CIS Pointer
0B 2C Subsystem ID <------ Subsystem Vendor ID <-------
0C 30 Expansion ROM base address
0D 34 Reserved <------- Capabilities Pointer <------
0E 38 Reserved <------- <-------- <--------
0F 3C Max ltncy Min Grant Interrupt PIN Interrupt Line
*/
/*
The idea for now is to support the minimal things necessary to find ATA supported drives
*/
// Lets write some boiler plate configuration code
uint16_t ConfigReadWord (uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset);
uint16_t CheckVendor (uint8_t bus, uint8_t slot);
void checkDevice (uint8_t bus, uint8_t device );

153
src/kernel/time.h Normal file
View File

@ -0,0 +1,153 @@
#define CURRENT_YEAR 2021 // Change this each year!
int century_register = 0x00; // Set by ACPI table parsing code if possible
unsigned char second;
unsigned char minute;
unsigned char hour;
unsigned char day;
unsigned char month;
unsigned int year;
enum {
cmos_address = 0x70,
cmos_data = 0x71
};
int get_update_in_progress_flag() {
outb(cmos_address, 0x0A);
return (inb(cmos_data) & 0x80);
}
unsigned char get_RTC_register(int reg) {
outb(cmos_address, reg);
return inb(cmos_data);
}
void read_rtc() {
unsigned char century;
unsigned char last_second;
unsigned char last_minute;
unsigned char last_hour;
unsigned char last_day;
unsigned char last_month;
unsigned char last_year;
unsigned char last_century;
unsigned char registerB;
// Note: This uses the "read registers until you get the same values twice in a row" technique
// to avoid getting dodgy/inconsistent values due to RTC updates
while (get_update_in_progress_flag()); // Make sure an update isn't in progress
second = get_RTC_register(0x00);
minute = get_RTC_register(0x02);
hour = get_RTC_register(0x04);
day = get_RTC_register(0x07);
month = get_RTC_register(0x08);
year = get_RTC_register(0x09);
if(century_register != 0) {
century = get_RTC_register(century_register);
} else {
century = 21;
}
do {
last_second = second;
last_minute = minute;
last_hour = hour;
last_day = day;
last_month = month;
last_year = year;
last_century = century;
while (get_update_in_progress_flag()); // Make sure an update isn't in progress
second = get_RTC_register(0x00);
minute = get_RTC_register(0x02);
hour = get_RTC_register(0x04);
day = get_RTC_register(0x07);
month = get_RTC_register(0x08);
year = get_RTC_register(0x09);
if(century_register != 0) {
century = get_RTC_register(century_register);
}
} while( (last_second != second) || (last_minute != minute) || (last_hour != hour) ||
(last_day != day) || (last_month != month) || (last_year != year) ||
(last_century != century) );
registerB = get_RTC_register(0x0B);
// Convert BCD to binary values if necessary
if (!(registerB & 0x04)) {
second = (second & 0x0F) + ((second / 16) * 10);
minute = (minute & 0x0F) + ((minute / 16) * 10);
hour = ( (hour & 0x0F) + (((hour & 0x70) / 16) * 10) ) | (hour & 0x80);
day = (day & 0x0F) + ((day / 16) * 10);
month = (month & 0x0F) + ((month / 16) * 10);
year = (year & 0x0F) + ((year / 16) * 10);
if(century_register != 0) {
century = (century & 0x0F) + ((century / 16) * 10);
}
}
// Convert 12 hour clock to 24 hour clock if necessary
if (!(registerB & 0x02) && (hour & 0x80)) {
hour = ((hour & 0x7F) + 12) % 24;
}
// Calculate the full (4-digit) year
if(century_register != 0) {
year += century * 100;
} else {
year += (CURRENT_YEAR / 100) * 100;
if(year < CURRENT_YEAR) year += 100;
}
}
/*
void ReadFromCMOS(unsigned char array[])
{
unsigned char tvalue, index;
for (index = 0; index < 128; index++)
{
asm(
"cli\n\t" // Disable interrupts
"mov al, index\n\t" // Move index address
// since the 0x80 bit of al is not set, NMI is active
"out 0x70,al\n\t" // Copy address to CMOS register
// some kind of real delay here is probably best
"in al,0x71\n\t" // Fetch 1 byte to al
"sti\n\t" // Enable interrupts
"mov tvalue,al\n\t");
array[index] = tvalue;
}
}
*/
/*
void WriteTOCMOS(unsigned char array[])
{
unsigned char index;
for(index = 0; index < 128; index++)
{
unsigned char tvalue = array[index];
asm("cli\n\t" // Clear interrupts
"mov al,index\n\t" // move index address
"out 0x70,al\n\t" // copy address to CMOS register
// some kind of real delay here is probably best
"mov al,tvalue\n\t" // move value to al
"out 0x71,al\n\t" // write 1 byte to CMOS
"sti\n\\t" ); // Enable interrupts
}
}
*/

27
src/kernel/timer.cpp Normal file
View File

@ -0,0 +1,27 @@
#include "timer.h"
uint32_t tick = 0;
static void timer_callback (registers_t regs ){
tick ++ ;
kterm_writestring ("tick passed!");
}
void init_timer (uint32_t frequency){
// register timer callback
uint32_t divisor = 1193180 / frequency;
// Send the commmand byte
outb(0x43, 0x36);
// Divisor has to be sent byt-wise , so will send lower then upper bytes
uint8_t low = (uint8_t) (divisor & 0xFF);
uint8_t high = (uint8_t) ((divisor >> 8) & 0xFF);
outb(0x40, low);
outb(0x40, high);
}

6
src/kernel/timer.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
void init_timer (uint32_t frequency);

View File

@ -0,0 +1,9 @@
#include "string.h"
size_t strlen(const char* str) {
size_t len = 0;
while(str[len]){
len++;
}
return len;
}

View File

@ -1,8 +1,3 @@
#pragma once
#include <stddef.h> #include <stddef.h>
size_t strlen(const char* str){ size_t strlen(const char* str);
size_t len = 0;
while(str[len]){
len++;
}
return len;
}