Compare commits
38 Commits
main
...
7d6c823d79
Author | SHA1 | Date | |
---|---|---|---|
7d6c823d79 | |||
bbfea39c23 | |||
3b3e2597a1 | |||
0b0e37b762 | |||
388ac8e7f9 | |||
9172da075a | |||
23c68d9863 | |||
b4cff3e667 | |||
7330b81a10 | |||
97606dbf71 | |||
7496299761 | |||
0d8ef065e0 | |||
88cc1d75bb | |||
23ede25ed6 | |||
ba043ef31b | |||
88c5196586 | |||
3a87b74224 | |||
32909aaed9 | |||
5fb55367ca | |||
d79fc6e8e2 | |||
bdcf9e66f8 | |||
c9b789ed7b | |||
b4b615ae97 | |||
092c5d520d | |||
643f2d708b | |||
f2c8b8ac5c | |||
f48f8072c0 | |||
7409e579c8 | |||
04f941a625 | |||
24a855bb3b | |||
83d220019c | |||
48b65b2276 | |||
e0dfa69df8 | |||
394882ca2e | |||
592db0ebcf | |||
28ac6a05af | |||
0d0c06ab09 | |||
5e668f5e67 |
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -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
7
.gitignore
vendored
@ -1 +1,8 @@
|
|||||||
build
|
build
|
||||||
|
CON
|
||||||
|
.vscode
|
||||||
|
isodir/
|
||||||
|
root/
|
||||||
|
*.iso
|
||||||
|
*.img
|
||||||
|
|
||||||
|
73
Makefile
73
Makefile
@ -3,9 +3,9 @@ EMULATOR = qemu-system-i386
|
|||||||
AS = ${HOME}/opt/cross/bin/i686-elf-as
|
AS = ${HOME}/opt/cross/bin/i686-elf-as
|
||||||
CC = ${HOME}/opt/cross/bin/i686-elf-gcc
|
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 -Og -ggdb -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)/memory.o $(BUILD_DIR)/paging.o $(BUILD_DIR)/pit.o $(BUILD_DIR)/time.o $(BUILD_DIR)/keyboard.o $(BUILD_DIR)/io.o $(BUILD_DIR)/gdtc.o $(BUILD_DIR)/idt.o $(BUILD_DIR)/pic.o $(BUILD_DIR)/sv-terminal.o $(BUILD_DIR)/string.o
|
||||||
|
|
||||||
SRC_DIR = src
|
SRC_DIR = src
|
||||||
BUILD_DIR = build
|
BUILD_DIR = build
|
||||||
@ -21,15 +21,27 @@ INTERNAL_OBJS = $(CRTI_OBJ) $(OFILES) $(CRTN_OBJ)
|
|||||||
|
|
||||||
all: clean build
|
all: clean build
|
||||||
|
|
||||||
build: build_kernel run
|
build: build_kernel iso
|
||||||
|
|
||||||
run:
|
clean_iso:
|
||||||
$(EMULATOR) -kernel $(BUILD_DIR)/myos.bin -serial stdio
|
if [[ -a isodir/boot ]] ; then rm root/boot -rd ; fi
|
||||||
|
if [ -f build/barinkOS.iso ] ; then rm build/barinkOS.iso ; fi
|
||||||
|
|
||||||
|
iso: clean_iso clean build
|
||||||
|
mkdir -p root/boot/grub
|
||||||
|
cp build/myos.bin root/boot/myos.bin
|
||||||
|
cp src/grub.cfg root/boot/grub/grub.cfg
|
||||||
|
grub-mkrescue -o build/barinkOS.iso root
|
||||||
|
|
||||||
|
run: all
|
||||||
|
$(EMULATOR) -cdrom build/barinkOS.iso -serial stdio -vga std -display gtk -m 2G -cpu core2duo
|
||||||
|
|
||||||
|
debug: all
|
||||||
|
$(EMULATOR) -cdrom build/barinkOS.iso -serial stdio -vga std -display gtk -m 2G -cpu core2duo -s -d int
|
||||||
|
|
||||||
build_kernel: $(OBJ_LINK_LIST)
|
build_kernel: $(OBJ_LINK_LIST)
|
||||||
|
$(CC) -T $(SRC_DIR)/kernel//linker.ld -o $(BUILD_DIR)/myos.bin \
|
||||||
$(CC) -T $(SRC_DIR)/kernel/arch/i386/linker.ld -o $(BUILD_DIR)/myos.bin \
|
-ffreestanding -ggdb -Og -nostdlib $(OBJ_LINK_LIST) -lgcc
|
||||||
-ffreestanding -O2 -nostdlib $(OBJ_LINK_LIST) -lgcc
|
|
||||||
|
|
||||||
build_x86_64:
|
build_x86_64:
|
||||||
$(AS) $(SRC_DIR)/cgc/x86_64/crti.s -o $(BUILD_DIR)/crti_64.o
|
$(AS) $(SRC_DIR)/cgc/x86_64/crti.s -o $(BUILD_DIR)/crti_64.o
|
||||||
@ -42,18 +54,51 @@ $(BUILD_DIR)/kernel.o:
|
|||||||
$(CPP) -c $(SRC_DIR)/kernel/kernel.cpp -o $(BUILD_DIR)/kernel.o $(CFLAGS) -fno-exceptions -fno-rtti
|
$(CPP) -c $(SRC_DIR)/kernel/kernel.cpp -o $(BUILD_DIR)/kernel.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||||
|
|
||||||
$(BUILD_DIR)/kterm.o:
|
$(BUILD_DIR)/kterm.o:
|
||||||
$(CC) -c $(SRC_DIR)/kernel/arch/i386/tty/kterm.c -o $(BUILD_DIR)/kterm.o $(CFLAGS) -std=gnu99
|
$(CPP) -c $(SRC_DIR)/kernel/Terminal/kterm.cpp -o $(BUILD_DIR)/kterm.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||||
|
|
||||||
$(BUILD_DIR)/boot.o:
|
$(BUILD_DIR)/boot.o:
|
||||||
$(AS) $(SRC_DIR)/kernel/arch/i386/boot.s -o $(BUILD_DIR)/boot.o
|
$(AS) $(SRC_DIR)/kernel/KernelLauncher/boot.s -o $(BUILD_DIR)/boot.o
|
||||||
|
|
||||||
$(BUILD_DIR)/crti.o:
|
$(BUILD_DIR)/crti.o:
|
||||||
$(AS) $(SRC_DIR)/kernel/arch/i386/crti.s -o $(BUILD_DIR)/crti.o
|
$(AS) $(SRC_DIR)/kernel/KernelLauncher/crti.s -o $(BUILD_DIR)/crti.o
|
||||||
|
|
||||||
$(BUILD_DIR)/crtn.o:
|
$(BUILD_DIR)/crtn.o:
|
||||||
$(AS) $(SRC_DIR)/kernel/arch/i386/crtn.s -o $(BUILD_DIR)/crtn.o
|
$(AS) $(SRC_DIR)/kernel/KernelLauncher/crtn.s -o $(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)/idt.o:
|
||||||
|
$(CPP) -c $(SRC_DIR)/kernel/Interrupts/idt/idt.cpp -o $(BUILD_DIR)/idt.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||||
|
|
||||||
|
$(BUILD_DIR)/gdtc.o:
|
||||||
|
$(CPP) -c $(SRC_DIR)/kernel/Memory/GDT/gdtc.cpp -o $(BUILD_DIR)/gdtc.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||||
|
|
||||||
|
|
||||||
|
$(BUILD_DIR)/pic.o:
|
||||||
|
$(CPP) -c $(SRC_DIR)/kernel/Drivers/PIC/pic.cpp -o $(BUILD_DIR)/pic.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||||
|
|
||||||
|
$(BUILD_DIR)/string.o:
|
||||||
|
$(CC) -c $(SRC_DIR)/kernel/Lib/string.c -o $(BUILD_DIR)/string.o $(CFLAGS) -std=gnu99
|
||||||
|
|
||||||
|
|
||||||
|
$(BUILD_DIR)/pit.o:
|
||||||
|
$(CPP) -c $(SRC_DIR)/kernel/Drivers/PIT/pit.cpp -o $(BUILD_DIR)/pit.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||||
|
|
||||||
|
|
||||||
|
$(BUILD_DIR)/keyboard.o:
|
||||||
|
$(CPP) -c $(SRC_DIR)/kernel/Drivers/PS-2/keyboard.cpp -o $(BUILD_DIR)/keyboard.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||||
|
|
||||||
|
|
||||||
|
$(BUILD_DIR)/time.o:
|
||||||
|
$(CPP) -c $(SRC_DIR)/kernel/time.cpp -o $(BUILD_DIR)/time.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||||
|
|
||||||
|
$(BUILD_DIR)/sv-terminal.o:
|
||||||
|
$(CPP) -c $(SRC_DIR)/kernel/SuperVisorTerminal/superVisorTerminal.cpp -o $(BUILD_DIR)/sv-terminal.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||||
|
|
||||||
|
$(BUILD_DIR)/memory.o:
|
||||||
|
$(CPP) -c $(SRC_DIR)/kernel/Memory/memory.cpp -o $(BUILD_DIR)/memory.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||||
|
|
||||||
|
$(BUILD_DIR)/paging.o:
|
||||||
|
$(CPP) -c $(SRC_DIR)/kernel/Memory/paging.cpp -o $(BUILD_DIR)/paging.o $(CFLAGS) -fno-exceptions -fno-rtti
|
17
README.md
17
README.md
@ -10,14 +10,17 @@ ________________________
|
|||||||
The first scrolling boot screen. 😲
|
The first scrolling boot screen. 😲
|
||||||
|
|
||||||
|
|
||||||
|
 \
|
||||||
|
W.I.P - Working on interrupt handling
|
||||||
|
|
||||||
|
|
||||||
|
 \
|
||||||
|
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.Initially I'd like for my
|
||||||
|
operating system to be able to run bash.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
________________________
|
________________________
|
||||||
### Operating System Technical specs/details
|
### Operating System Technical specs/details
|
||||||
@ -26,8 +29,8 @@ screen. The terminal/screen has scrolling so the latest messages are visible on
|
|||||||
|
|
||||||
________________________
|
________________________
|
||||||
### Planning
|
### Planning
|
||||||
[See TODO](TODO.md)
|
[See TODO](todo.md) \
|
||||||
|
[See Features](features.md)
|
||||||
________________________
|
________________________
|
||||||
### Docs
|
### Docs
|
||||||
[Intro](docs/Intro.md) \
|
[Intro](docs/Intro.md) \
|
||||||
|
40
TODO.md
40
TODO.md
@ -1,40 +0,0 @@
|
|||||||
# TODO list
|
|
||||||
## Start planning
|
|
||||||
<input type="checkbox" checked/> Setup Cross-Compiler \
|
|
||||||
<input type="checkbox" checked/> Multiboot to kernel \
|
|
||||||
<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" /> Extend Multiboot implementation \
|
|
||||||
<input type="checkbox" checked/> Output to serial port \
|
|
||||||
<input type="checkbox" /> Move to protected mode \
|
|
||||||
<input type="checkbox" /> Enabel CMOS clock \
|
|
||||||
<input type="checkbox" /> Time measurement (PIC &| PIT) \
|
|
||||||
<input type="checkbox" /> Detect CPU speed \
|
|
||||||
<input type="checkbox" /> 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" /> The heap: allocating memory at runtime (malloc and free) is almost impossible to go without. \
|
|
||||||
<input type="checkbox" /> Enable SIMD Extensions (SSE)
|
|
||||||
|
|
||||||
## Other features I am thinking of:
|
|
||||||
<input type="checkbox" /> PCI support \
|
|
||||||
<input type="checkbox" /> ATA PIO Mode support \
|
|
||||||
<input type="checkbox" /> USTAR Filesystem ( For its simplicity this is very likely the first filesystem the OS is going to support) \
|
|
||||||
<input type="checkbox" /> ACPI support ( Or some other basic way to support shutdown, reboot and possibly hibernation ) \
|
|
||||||
<input type="checkbox" /> ATAPI support \
|
|
||||||
<input type="checkbox" /> Keyboard support ( P/S2 Keyboard) \
|
|
||||||
<input type="checkbox" /> Memory Management (MMU)\
|
|
||||||
<input type="checkbox" /> Preemptive multi tasking
|
|
||||||
<input type="checkbox" /> Processes
|
|
||||||
<input type="checkbox" /> Threads
|
|
||||||
<input type="checkbox" /> Scheduling (SRV2 Unix OR Priority Based Round Robin) \
|
|
||||||
<input type="checkbox" /> System V ABI compliance (partially)
|
|
||||||
<input type="checkbox" /> POSIX compliance (partially)
|
|
||||||
<input type="checkbox" /> RPC - for interprocess communication \
|
|
||||||
<input type="checkbox" /> Sync primitives - Semaphores, Mutexes, spinlocks et al. \
|
|
||||||
<input type="checkbox" /> Basic Terminal \
|
|
||||||
<input type="checkbox" /> Extend hardware recognition ( CPU codename, memory, ATA harddisk, RAW diskSpace, CPU speed through SMBIOS et al. ) \
|
|
||||||
<input type="checkbox" /> Basic Window server/client \
|
|
||||||
## Support for more filesystems if I like the challenge in writing these ...
|
|
||||||
<input type="checkbox" /> FAT Filesystem \
|
|
||||||
<input type="checkbox" /> EXT2 Filesystem \
|
|
43
features.md
Normal file
43
features.md
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# TODO list
|
||||||
|
## Basics
|
||||||
|
<input type="checkbox" checked/> Setup Cross-Compiler \
|
||||||
|
<input type="checkbox" checked/> Multiboot to kernel \
|
||||||
|
<input type="checkbox" checked/> Printing string to the screen \
|
||||||
|
<input type="checkbox" checked/> Printing values/numbers to the screen \
|
||||||
|
<input type="checkbox" checked/> Basic Terminal \
|
||||||
|
<input type="checkbox" checked/> Extend Multiboot implementation \
|
||||||
|
<input type="checkbox" checked/> Output to serial port \
|
||||||
|
<input type="checkbox" checked/> Move to protected mode \
|
||||||
|
<input type="checkbox" checked/> Enabel CMOS clock \
|
||||||
|
<input type="checkbox" checked/> Time measurement (PIC &| PIT) \
|
||||||
|
<input type="checkbox" /> Detect CPU speed \
|
||||||
|
<input type="checkbox" checked/> Interrupt / exception system (API) \
|
||||||
|
<input type="checkbox" checked/> PCI support \
|
||||||
|
<input type="checkbox" checked/> ATA PIO Mode support \
|
||||||
|
<input type="checkbox" checked/> FAT Filesystem \
|
||||||
|
<input type="checkbox" /> Virtual filesystem \
|
||||||
|
<input type="checkbox" checked/> Keyboard support ( P/S2 Keyboard) \
|
||||||
|
<input type="checkbox" checked/> Physical memory management \
|
||||||
|
<input type="checkbox" /> Paging \
|
||||||
|
<input type="checkbox" /> Virtual memory management \
|
||||||
|
<input type="checkbox" /> The heap: allocating memory at runtime (malloc and free) is almost impossible to go without. \
|
||||||
|
<input type="checkbox" /> Enable SIMD Extensions (SSE)
|
||||||
|
|
||||||
|
<input type="checkbox" /> Hardware Management system
|
||||||
|
|
||||||
|
<input type="checkbox" /> Preemptive multi tasking \
|
||||||
|
<input type="checkbox" /> Processes \
|
||||||
|
<input type="checkbox" /> Threads
|
||||||
|
<input type="checkbox" /> Scheduling (SRV2 Unix OR Priority Based Round Robin) \
|
||||||
|
<input type="checkbox" /> System V ABI compliance (partially) \
|
||||||
|
<input type="checkbox" /> POSIX compliance (partially) \
|
||||||
|
<input type="checkbox" /> RPC - for interprocess communication \
|
||||||
|
<input type="checkbox" /> Sync primitives - Semaphores, Mutexes, spinlocks et al. \
|
||||||
|
|
||||||
|
<input type="checkbox" /> ACPI support \
|
||||||
|
<input type="checkbox" /> ATAPI support \
|
||||||
|
|
||||||
|
## Optional
|
||||||
|
<input type="checkbox" /> Basic Window server/client \
|
||||||
|
<input type="checkbox" /> EXT2 Filesystem
|
||||||
|
<input type="checkbox" /> USTAR Filesystem \
|
BIN
screenshots/Screenshot from 2021-06-21 14-26-39.png
(Stored with Git LFS)
Normal 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
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
BIN
screenshots/multiboot.png
(Stored with Git LFS)
Normal file
Binary file not shown.
8
src/grub.cfg
Normal file
8
src/grub.cfg
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
GRUB_DEFAULT=0
|
||||||
|
GRUB_TIMEOUT=-1
|
||||||
|
GRUB_HIDDEN_TIMEOUT=0
|
||||||
|
GRUB_HIDDEN_TIMEOUT_QUITE=true
|
||||||
|
|
||||||
|
menuentry "BarinkOS" {
|
||||||
|
multiboot /boot/myos.bin
|
||||||
|
}
|
108
src/kernel/Drivers/PCI/pci.cpp
Normal file
108
src/kernel/Drivers/PCI/pci.cpp
Normal 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/Drivers/PCI/pci.h
Normal file
58
src/kernel/Drivers/PCI/pci.h
Normal 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 );
|
62
src/kernel/Drivers/PIC/pic.cpp
Normal file
62
src/kernel/Drivers/PIC/pic.cpp
Normal 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);
|
||||||
|
|
||||||
|
}
|
57
src/kernel/Drivers/PIC/pic.h
Normal file
57
src/kernel/Drivers/PIC/pic.h
Normal 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 );
|
54
src/kernel/Drivers/PIT/pit.cpp
Normal file
54
src/kernel/Drivers/PIT/pit.cpp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#include "pit.h"
|
||||||
|
#include "../../Terminal/kterm.h"
|
||||||
|
uint32_t pit_tick = 0;
|
||||||
|
|
||||||
|
|
||||||
|
void pit_initialise()
|
||||||
|
{
|
||||||
|
asm volatile("CLI");
|
||||||
|
|
||||||
|
#ifdef __VERBOSE__
|
||||||
|
printf("Init PIT!\n");
|
||||||
|
#endif
|
||||||
|
// clear mask for IRQ 0
|
||||||
|
uint8_t value = inb(0x21) & ~(1<< 0);
|
||||||
|
outb(0x21, value);
|
||||||
|
|
||||||
|
io_wait();
|
||||||
|
|
||||||
|
const int freq = 500;
|
||||||
|
|
||||||
|
uint32_t divisor = 1193180 / freq;
|
||||||
|
|
||||||
|
outb(PIT_COMMAND, 0x36);
|
||||||
|
|
||||||
|
uint8_t l = (uint8_t) (divisor & 0xFF);
|
||||||
|
uint8_t h = (uint8_t) ( (divisor>>8) & 0xff);
|
||||||
|
|
||||||
|
outb(PIT_DATA_0, l);
|
||||||
|
outb(PIT_DATA_0,h);
|
||||||
|
|
||||||
|
|
||||||
|
asm volatile("STI");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void get_pit_count()
|
||||||
|
{
|
||||||
|
asm volatile ("CLI");
|
||||||
|
|
||||||
|
outb(PIT_COMMAND, 0);
|
||||||
|
uint16_t count = inb(PIT_DATA_0);
|
||||||
|
count |= inb(PIT_DATA_0) << 8;
|
||||||
|
|
||||||
|
printf("PIT count: 0x%x\n", count);
|
||||||
|
|
||||||
|
asm volatile("STI");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_pit_count()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
18
src/kernel/Drivers/PIT/pit.h
Normal file
18
src/kernel/Drivers/PIT/pit.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "../../io.h"
|
||||||
|
#define PIT_DATA_0 0x40
|
||||||
|
#define PIT_DATA_1 0x41
|
||||||
|
#define PIT_DATA_2 0x42
|
||||||
|
#define PIT_COMMAND 0x43
|
||||||
|
|
||||||
|
|
||||||
|
extern uint32_t pit_tick;
|
||||||
|
|
||||||
|
|
||||||
|
void pit_initialise();
|
||||||
|
|
||||||
|
|
||||||
|
void get_pit_count();
|
||||||
|
|
||||||
|
void set_pit_count();
|
51
src/kernel/Drivers/PS-2/keyboard.cpp
Normal file
51
src/kernel/Drivers/PS-2/keyboard.cpp
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#include "keyboard.h"
|
||||||
|
|
||||||
|
KeyPressInfo keyPress {};
|
||||||
|
|
||||||
|
void KeyHandled(){
|
||||||
|
keyPress.ScanCode= 0x00;
|
||||||
|
keyPress.PressedModifiers = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char getASCIIKey(){
|
||||||
|
char keyPressed;
|
||||||
|
// Wait until a key is pressed
|
||||||
|
while(keyPress.ScanCode == 0x00) {
|
||||||
|
asm volatile ("NOP");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Translate keycode to ascii
|
||||||
|
// Probably a lookup table might be handy
|
||||||
|
// Until 0x37
|
||||||
|
const char* ASCIILookUp =
|
||||||
|
"\01234567890-=\0\0QWERTYUIOP[]\0\0ASDFGHJKL;\'`\0\\ZXCVBNM,./\0";
|
||||||
|
|
||||||
|
uint8_t ASCII_Index = keyPress.ScanCode - 3 ;
|
||||||
|
//printf("ASCII_INDEX: %x\n", ASCII_Index);
|
||||||
|
keyPressed = ASCIILookUp[ASCII_Index];
|
||||||
|
|
||||||
|
KeyHandled();
|
||||||
|
|
||||||
|
return keyPressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t getKey(){
|
||||||
|
// Wait until a key is pressed
|
||||||
|
while(keyPress.ScanCode == 0x00){
|
||||||
|
asm volatile ("NOP");
|
||||||
|
}
|
||||||
|
|
||||||
|
if( keyPress.ScanCode > 0x37){
|
||||||
|
keyPress.ScanCode = 0x00;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ScanCode = keyPress.ScanCode;
|
||||||
|
// KeyHandled();
|
||||||
|
|
||||||
|
return ScanCode ;
|
||||||
|
}
|
34
src/kernel/Drivers/PS-2/keyboard.h
Normal file
34
src/kernel/Drivers/PS-2/keyboard.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "../../Terminal/kterm.h"
|
||||||
|
typedef enum ScanCodeSet{
|
||||||
|
None = 0,
|
||||||
|
ScanCodeSet1 = 1,
|
||||||
|
ScanCodeSet2 = 2,
|
||||||
|
ScanCodeSet3 = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum Modifiers{
|
||||||
|
LSHIFT = 1,
|
||||||
|
RSHIFT = 2,
|
||||||
|
|
||||||
|
LCTRL = 3,
|
||||||
|
RCTRL = 4,
|
||||||
|
|
||||||
|
LALT = 5,
|
||||||
|
RALT = 6
|
||||||
|
};
|
||||||
|
|
||||||
|
struct KeyPressInfo{
|
||||||
|
uint8_t PressedModifiers;
|
||||||
|
uint8_t ScanCode;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
extern KeyPressInfo keyPress;
|
||||||
|
|
||||||
|
void KeyHandled();
|
||||||
|
|
||||||
|
char getASCIIKey();
|
||||||
|
uint8_t getKey();
|
41
src/kernel/Drivers/VGA/VBE.h
Normal file
41
src/kernel/Drivers/VGA/VBE.h
Normal 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);
|
||||||
|
}*/
|
38
src/kernel/Drivers/cmos/cmos.cpp
Normal file
38
src/kernel/Drivers/cmos/cmos.cpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
8
src/kernel/FileSystem/FAT/FAT16.h
Normal file
8
src/kernel/FileSystem/FAT/FAT16.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../../vfs/File.h"
|
||||||
|
|
||||||
|
|
||||||
|
class FAT16 : File {
|
||||||
|
public:
|
||||||
|
|
||||||
|
};
|
341
src/kernel/Interrupts/idt/idt.cpp
Normal file
341
src/kernel/Interrupts/idt/idt.cpp
Normal file
@ -0,0 +1,341 @@
|
|||||||
|
#include "idt.h"
|
||||||
|
#include "../../Drivers/PIT/pit.h"
|
||||||
|
#include "../../Drivers/PS-2/keyboard.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) {
|
||||||
|
|
||||||
|
//printf("(IRS) Interrupt number: %d \r", regs.int_no);
|
||||||
|
switch (regs.int_no)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
// Divide Error #DE
|
||||||
|
printf("#DE\n");
|
||||||
|
printf("EIP: 0x%x\n", regs.eip);
|
||||||
|
printf("EAX: 0x%x\n", regs.eax);
|
||||||
|
printf("EBP: 0x%x\n", regs.ebp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
// Debug Exception #DB
|
||||||
|
printf("#DB\n");
|
||||||
|
printf("EIP: 0x%x\n", regs.eip);
|
||||||
|
printf("EAX: 0x%x\n", regs.eax);
|
||||||
|
printf("EBP: 0x%x\n", regs.ebp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
// NMI Interrupt
|
||||||
|
printf("#NMI\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
// Breakpoint Exception #BP
|
||||||
|
printf("#BP\n");
|
||||||
|
printf("EIP: 0x%x\n", regs.eip);
|
||||||
|
printf("EAX: 0x%x\n", regs.eax);
|
||||||
|
printf("EBP: 0x%x\n", regs.ebp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
// Overflow Exception #OF
|
||||||
|
printf("#OF\n");
|
||||||
|
printf("EIP: 0x%x\n", regs.eip);
|
||||||
|
printf("EAX: 0x%x\n", regs.eax);
|
||||||
|
printf("EBP: 0x%x\n", regs.ebp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
// BOUND Range Exceeded Exception #BR
|
||||||
|
printf("#BR\n");
|
||||||
|
printf("EIP: 0x%x\n", regs.eip);
|
||||||
|
printf("EAX: 0x%x\n", regs.eax);
|
||||||
|
printf("EBP: 0x%x\n", regs.ebp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
// Invalid OpCode Exception #UD
|
||||||
|
printf("#UD\n");
|
||||||
|
printf("EIP: 0x%x\n", regs.eip);
|
||||||
|
printf("EAX: 0x%x\n", regs.eax);
|
||||||
|
printf("EBP: 0x%x\n", regs.ebp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7:
|
||||||
|
// Device Not Available Exception #NM
|
||||||
|
printf("#NM\n");
|
||||||
|
printf("EIP: 0x%x\n", regs.eip);
|
||||||
|
printf("EAX: 0x%x\n", regs.eax);
|
||||||
|
printf("EBP: 0x%x\n", regs.ebp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
// Double Fault Exception #DF
|
||||||
|
printf("#DF\n");
|
||||||
|
printf("EIP: 0x%x\n", regs.eip);
|
||||||
|
printf("EAX: 0x%x\n", regs.eax);
|
||||||
|
printf("EBP: 0x%x\n", regs.ebp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 9:
|
||||||
|
// Coprocessor Segment Overrun
|
||||||
|
printf("Coprocessor Segment overrun!\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 10:
|
||||||
|
// Invalid TSS Exception #TS
|
||||||
|
printf("#TS\n");
|
||||||
|
printf("EIP: 0x%x\n", regs.eip);
|
||||||
|
printf("EAX: 0x%x\n", regs.eax);
|
||||||
|
printf("EBP: 0x%x\n", regs.ebp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 11:
|
||||||
|
// Segment Not Present #NP
|
||||||
|
printf("#NP\n");
|
||||||
|
printf("EIP: 0x%x\n", regs.eip);
|
||||||
|
printf("EAX: 0x%x\n", regs.eax);
|
||||||
|
printf("EBP: 0x%x\n", regs.ebp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 12:
|
||||||
|
// Stack Fault Exception #SS
|
||||||
|
printf("#SS\n");
|
||||||
|
printf("EIP: 0x%x\n", regs.eip);
|
||||||
|
printf("EAX: 0x%x\n", regs.eax);
|
||||||
|
printf("EBP: 0x%x\n", regs.ebp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 13:
|
||||||
|
// General Protection Exception #GP
|
||||||
|
printf("#GP\n");
|
||||||
|
printf("EIP: 0x%x\n", regs.eip);
|
||||||
|
printf("EAX: 0x%x\n", regs.eax);
|
||||||
|
printf("EBP: 0x%x\n", regs.ebp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 14:
|
||||||
|
// Page Fault Exception #PF
|
||||||
|
printf("#PF\n");
|
||||||
|
|
||||||
|
printf("EIP: 0x%x\n", regs.eip); // Points to faulting instruction ???
|
||||||
|
printf("EAX: 0x%x\n", regs.eax);
|
||||||
|
printf("EBP: 0x%x\n", regs.ebp); // Base pointer pointing to the bottom of the stack
|
||||||
|
|
||||||
|
|
||||||
|
// Error code of 32 bits are on the stack
|
||||||
|
// CR2 register contains the 32-bit linear address that generated the exception
|
||||||
|
// See Intel Software Developers manual Volume 3A Part 1 page 236 for more info
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check the error code to figure out what happened here
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 16:
|
||||||
|
// x87 FPU Floating-point Error #MF
|
||||||
|
printf("#MF\n");
|
||||||
|
printf("EIP: 0x%x\n", regs.eip);
|
||||||
|
printf("EAX: 0x%x\n", regs.eax);
|
||||||
|
printf("EBP: 0x%x\n", regs.ebp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 17:
|
||||||
|
// Alignment Check Exception #AC
|
||||||
|
printf("#AC\n");
|
||||||
|
printf("EIP: 0x%x\n", regs.eip);
|
||||||
|
printf("EAX: 0x%x\n", regs.eax);
|
||||||
|
printf("EBP: 0x%x\n", regs.ebp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 18:
|
||||||
|
// Machine-Check Exception #MC
|
||||||
|
printf("#MC\n");
|
||||||
|
printf("EIP: 0x%x\n", regs.eip);
|
||||||
|
printf("EAX: 0x%x\n", regs.eax);
|
||||||
|
printf("EBP: 0x%x\n", regs.ebp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 19:
|
||||||
|
// SIMD Floating-point Exception #XM
|
||||||
|
printf("#XM\n");
|
||||||
|
printf("EIP: 0x%x\n", regs.eip);
|
||||||
|
printf("EAX: 0x%x\n", regs.eax);
|
||||||
|
printf("EBP: 0x%x\n", regs.ebp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 20:
|
||||||
|
// Virtualization Exception #VE
|
||||||
|
printf("#VE\n");
|
||||||
|
printf("EIP: 0x%x\n", regs.eip);
|
||||||
|
printf("EAX: 0x%x\n", regs.eax);
|
||||||
|
printf("EBP: 0x%x\n", regs.ebp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 21:
|
||||||
|
// Control Protection Exception #CP
|
||||||
|
printf("#CP\n");
|
||||||
|
printf("EIP: 0x%x\n", regs.eip);
|
||||||
|
printf("EAX: 0x%x\n", regs.eax);
|
||||||
|
printf("EBP: 0x%x\n", regs.ebp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// PANIC!!!
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void irq_handler (registers regs) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
switch (regs.int_no) {
|
||||||
|
case 0:
|
||||||
|
pit_tick++;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
// Keyboard interrupt !!
|
||||||
|
|
||||||
|
int scan;
|
||||||
|
int i;/*register*/
|
||||||
|
|
||||||
|
// Read scancode
|
||||||
|
scan = inb(0x60);
|
||||||
|
|
||||||
|
// Send ack message!
|
||||||
|
i = inb(0x61);
|
||||||
|
outb(0x61, i|0x80);
|
||||||
|
outb(0x61, i);
|
||||||
|
|
||||||
|
// NOTE: check for special scan codes
|
||||||
|
// e.g. modifiers etc..
|
||||||
|
if( scan < 0x37){
|
||||||
|
//printf("Read from IO: 0x%x\n", scan);
|
||||||
|
keyPress.ScanCode = scan ;
|
||||||
|
//printf( "[From Interrupt] Scancode: %x\n", keyPress.ScanCode);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
// PS2 Mouse interrupt
|
||||||
|
printf("Mouse event triggered!");
|
||||||
|
//int event = inb(0x60);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("Interrupt happened!");
|
||||||
|
printf("Received INT: 0x%x\n", regs.int_no);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
#ifdef __VERBOSE__
|
||||||
|
printf("Init IDT\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// clear mask for IRQ 12
|
||||||
|
uint8_t value = inb(0x21) & ~(1<< 12);
|
||||||
|
outb(0x21, value);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// pic IRQ Table
|
||||||
|
set_id_entry(32, (uint32_t)irq0, 0x08, 0x8E);
|
||||||
|
set_id_entry(33, (uint32_t)irq1, 0x08, 0x8E); // PS2 Keyboard
|
||||||
|
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); // PS2 Mouse
|
||||||
|
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);
|
||||||
|
}
|
77
src/kernel/Interrupts/idt/idt.h
Normal file
77
src/kernel/Interrupts/idt/idt.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "stdint.h"
|
||||||
|
#include "stddef.h"
|
||||||
|
#include "../../Drivers/VGA/colors.h"
|
||||||
|
#include "../../Drivers/PIC/pic.h"
|
||||||
|
|
||||||
|
#include "../../Terminal/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 ();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
6
src/kernel/Interrupts/idt/idt.s
Normal file
6
src/kernel/Interrupts/idt/idt.s
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
.globl idt_flush
|
||||||
|
idt_flush:
|
||||||
|
mov 4(%esp), %eax
|
||||||
|
lidt (%eax)
|
||||||
|
ret
|
184
src/kernel/Interrupts/idt/scancodes/set1.h
Normal file
184
src/kernel/Interrupts/idt/scancodes/set1.h
Normal 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
|
144
src/kernel/KernelLauncher/boot.s
Normal file
144
src/kernel/KernelLauncher/boot.s
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* Multiboot
|
||||||
|
*/
|
||||||
|
.set ALIGN, 1<<0 /* align loaded modules on page boundaries */
|
||||||
|
.set MEMINFO, 1<<1 /* provide memory map */
|
||||||
|
.set FLAGS, ALIGN | MEMINFO /* this is the Multiboot 'flag' field */
|
||||||
|
.set MAGIC, 0x1BADB002 /* 'magic number' lets bootloader find the header */
|
||||||
|
.set CHECKSUM, -(MAGIC + FLAGS) /* checksum of above, to prove we are multiboot */
|
||||||
|
|
||||||
|
.section .multiboot.data, "aw"
|
||||||
|
.align 4
|
||||||
|
.long MAGIC
|
||||||
|
.long FLAGS
|
||||||
|
.long CHECKSUM
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate initial stack
|
||||||
|
*/
|
||||||
|
.section .bootstrap_stack, "aw", @nobits
|
||||||
|
stack_bottom:
|
||||||
|
.skip 16384 # 16 KiB
|
||||||
|
stack_top:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Preallocate a couple pages to get us bootstrapped
|
||||||
|
* Being carefull to not use any address the bootloader might
|
||||||
|
* be using for its multiboot structures
|
||||||
|
*/
|
||||||
|
.section .bss, "aw", @nobits
|
||||||
|
.align 4096
|
||||||
|
boot_page_directory:
|
||||||
|
.skip 4096
|
||||||
|
boot_page_table:
|
||||||
|
.skip 4096
|
||||||
|
# More page tables may be required
|
||||||
|
|
||||||
|
# Entry point
|
||||||
|
.section .multiboot.text, "a"
|
||||||
|
.global _start
|
||||||
|
.type _start, @function
|
||||||
|
_start:
|
||||||
|
# Get physical address of the boot_page_table
|
||||||
|
movl $(boot_page_table - 0xC0000000), %edi
|
||||||
|
# Map address 0
|
||||||
|
movl $0, %esi
|
||||||
|
# Map 1023 pages the 1024th being the VGA text buffer
|
||||||
|
movl $1023, %ecx
|
||||||
|
|
||||||
|
1: # Map the kernel
|
||||||
|
cmpl $_kernel_start, %esi
|
||||||
|
jl 2f
|
||||||
|
cmpl $(_kernel_end - 0xC0000000), %esi
|
||||||
|
jge 3f
|
||||||
|
|
||||||
|
# Map physical address as "present and writable"
|
||||||
|
movl %esi, %edx
|
||||||
|
orl $0x003, %edx
|
||||||
|
movl %edx, (%edi)
|
||||||
|
|
||||||
|
2: # Size of page is 4096 bytes
|
||||||
|
addl $4096, %esi
|
||||||
|
# Size of entries in boot_page_table is 4 bytes
|
||||||
|
addl $4, %edi
|
||||||
|
# Loop to the next entry if we haven't finished.
|
||||||
|
loop 1b
|
||||||
|
|
||||||
|
3: # Map VGA video memory to 0xC03FF00 as "present, writable"
|
||||||
|
movl $(0x000B8000 | 0x003), boot_page_table - 0xC0000000 + 1023 * 4
|
||||||
|
|
||||||
|
|
||||||
|
# IMPORTANT NOTE FROM WIKI.OSDEV.ORG/HIGHER_HALF_X86_BARE_BONES
|
||||||
|
|
||||||
|
# The page table is used at both page directory entry 0 (virtually from 0x0
|
||||||
|
# to 0x3FFFFF) (thus identity mapping the kernel) and page directory entry
|
||||||
|
# 768 (virtually from 0xC0000000 to 0xC03FFFFF) (thus mapping it in the
|
||||||
|
# higher half). The kernel is identity mapped because enabling paging does
|
||||||
|
# not change the next instruction, which continues to be physical. The CPU
|
||||||
|
# would instead page fault if there was no identity mapping.\
|
||||||
|
|
||||||
|
# Map the page table to both virtual addresss 0x00000000 and 0xC0000000
|
||||||
|
movl $(boot_page_table - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 0
|
||||||
|
movl $(boot_page_table - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 768 * 4
|
||||||
|
|
||||||
|
# Set cr3 to the address of the boot_page_directory
|
||||||
|
movl $(boot_page_directory - 0xC0000000), %ecx
|
||||||
|
movl %ecx, %cr3
|
||||||
|
|
||||||
|
# Enable paging and the write-protect bit
|
||||||
|
movl %cr0, %ecx
|
||||||
|
orl $0x80010000, %ecx
|
||||||
|
movl %ecx, %cr0
|
||||||
|
|
||||||
|
# Jump to higher half with an absolute jump
|
||||||
|
lea 4f, %ecx
|
||||||
|
jmp *%ecx
|
||||||
|
|
||||||
|
.section .text
|
||||||
|
4:
|
||||||
|
# At this point, paging is fully set up and enabled
|
||||||
|
isPaging:
|
||||||
|
# Unmap the identity mapping as it is now unnecessary
|
||||||
|
movl $0, boot_page_directory + 0
|
||||||
|
|
||||||
|
# Reload cr3 to force tlb flush
|
||||||
|
movl %cr3, %ecx
|
||||||
|
movl %ecx, %cr3
|
||||||
|
|
||||||
|
/*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
|
||||||
|
|
||||||
|
/*Reset EFLAGS*/
|
||||||
|
pushl $0
|
||||||
|
popf
|
||||||
|
|
||||||
|
/* push the pointer to the Multiboot information structure*/
|
||||||
|
pushl %ebx
|
||||||
|
|
||||||
|
/* push the magic value */
|
||||||
|
pushl %eax
|
||||||
|
|
||||||
|
call early_main
|
||||||
|
|
||||||
|
mov %cr0, %eax
|
||||||
|
or $1, %eax
|
||||||
|
mov %eax, %cr0
|
||||||
|
|
||||||
|
|
||||||
|
//call kernel_main
|
||||||
|
|
||||||
|
|
||||||
|
cli
|
||||||
|
1: hlt
|
||||||
|
jmp 1b
|
||||||
|
|
||||||
|
|
||||||
|
.include "./src/kernel/Memory/GDT/gdt.s"
|
||||||
|
.include "./src/kernel/irs_table.s"
|
||||||
|
.include "./src/kernel/irq_table.s"
|
||||||
|
.include "./src/kernel/Interrupts/idt/idt.s"
|
||||||
|
.include "./src/kernel/Memory/paging.s"
|
||||||
|
.include "./src/kernel/cpu.s"
|
||||||
|
|
||||||
|
|
91
src/kernel/KernelLauncher/bootcheck.h
Normal file
91
src/kernel/KernelLauncher/bootcheck.h
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../multiboot.h"
|
||||||
|
#define CHECK_FLAG(flags, bit) ((flags) & (1 <<(bit)))
|
||||||
|
|
||||||
|
#include "../Terminal/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;
|
||||||
|
|
||||||
|
#ifdef __VERBOSE__
|
||||||
|
/* Print out the flags */
|
||||||
|
printf("flags = 0x%x\n", (unsigned) mbi->flags);
|
||||||
|
#endif
|
||||||
|
/* Are mem_* valid? */
|
||||||
|
if ( CHECK_FLAG(mbi->flags,0)){
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
/* is boot device valid ? */
|
||||||
|
if (CHECK_FLAG (mbi->flags, 1))
|
||||||
|
{
|
||||||
|
#ifdef __VERBOSE__
|
||||||
|
printf("boot_device = 0x0%x\n", (unsigned) mbi->boot_device);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* is the command line passed? */
|
||||||
|
if (CHECK_FLAG ( mbi->flags,2))
|
||||||
|
{
|
||||||
|
#ifdef __VERBOSE__
|
||||||
|
printf("cmdline = %s\n", (char *) mbi->cmdline);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Are mods_* valid? */
|
||||||
|
if(CHECK_FLAG ( mbi->flags, 3)){
|
||||||
|
multiboot_module_t *mod;
|
||||||
|
uint32_t i;
|
||||||
|
#ifdef __VERBOSE__
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bits 4 and 5 are mutually exclusive! */
|
||||||
|
if (CHECK_FLAG (mbi->flags, 4) && CHECK_FLAG(mbi->flags, 5))
|
||||||
|
{
|
||||||
|
#ifdef __VERBOSE__
|
||||||
|
printf("Both bits 4 and 5 are set.\n");
|
||||||
|
#endif
|
||||||
|
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);
|
||||||
|
#ifdef __VERBOSE__
|
||||||
|
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);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
#ifdef __VERBOSE__
|
||||||
|
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);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw diagonal blue line */
|
||||||
|
if (CHECK_FLAG (mbt->flags, 12)){
|
||||||
|
#ifdef __VERBOSE__
|
||||||
|
printf("Can draw!\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
8
src/kernel/Lib/mem.h
Normal file
8
src/kernel/Lib/mem.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
inline void* memset (void* ptr, int value, size_t num){
|
||||||
|
for( int i = 0; i < num; i++ )
|
||||||
|
{
|
||||||
|
unsigned char* data = (unsigned char*)ptr+ i;
|
||||||
|
*data = (unsigned char)value;
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
28
src/kernel/Lib/string.c
Normal file
28
src/kernel/Lib/string.c
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include "string.h"
|
||||||
|
|
||||||
|
size_t strlen(const char* str) {
|
||||||
|
size_t len = 0;
|
||||||
|
while(str[len]){
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int strncmp ( const char* str1, const char* str2, size_t num ){
|
||||||
|
for( int i = 0; i < num ; i++){
|
||||||
|
|
||||||
|
if( str1[i] < str2[i]){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( str1[i] > str2[i] ){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
6
src/kernel/Lib/string.h
Normal file
6
src/kernel/Lib/string.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stddef.h>
|
||||||
|
size_t strlen(const char* str);
|
||||||
|
|
||||||
|
|
||||||
|
int strncmp ( const char* str1, const char* str2, size_t num );
|
@ -1,35 +0,0 @@
|
|||||||
#include "MMU.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void MMU::enable(){
|
|
||||||
|
|
||||||
//set each entry to not present
|
|
||||||
int i;
|
|
||||||
for(i = 0; i < 1024; i++)
|
|
||||||
{
|
|
||||||
// This sets the following flags to the pages:
|
|
||||||
// Supervisor: Only kernel-mode can access them
|
|
||||||
// Write Enabled: It can be both read from and written to
|
|
||||||
// Not Present: The page table is not present
|
|
||||||
this->page_directory[i] = 0x00000002;
|
|
||||||
}
|
|
||||||
|
|
||||||
// holds the physical address where we want to start mapping these pages to.
|
|
||||||
// in this case, we want to map these pages to the very beginning of memory.
|
|
||||||
|
|
||||||
//we will fill all 1024 entries in the table, mapping 4 megabytes
|
|
||||||
for(unsigned int i = 0; i < 1024; i++)
|
|
||||||
{
|
|
||||||
// As the address is page aligned, it will always leave 12 bits zeroed.
|
|
||||||
// Those bits are used by the attributes ;)
|
|
||||||
first_page_table[i] = (i * 0x1000) | 3; // attributes: supervisor level, read/write, present.
|
|
||||||
}
|
|
||||||
|
|
||||||
// attributes: supervisor level, read/write, present
|
|
||||||
this->page_directory[0] = ((unsigned int)first_page_table) | 3;
|
|
||||||
|
|
||||||
|
|
||||||
loadPageDirectory(this->page_directory);
|
|
||||||
enablePaging();
|
|
||||||
}
|
|
@ -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)));
|
|
||||||
};
|
|
19
src/kernel/Memory/GDT/gdt.s
Normal file
19
src/kernel/Memory/GDT/gdt.s
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
.global LoadGlobalDescriptorTable
|
||||||
|
|
||||||
|
LoadGlobalDescriptorTable:
|
||||||
|
lgdt gdtDescriptor
|
||||||
|
|
||||||
|
movw $16, %ax
|
||||||
|
movw %ax, %ds
|
||||||
|
movw %ax, %es
|
||||||
|
movw %ax, %fs
|
||||||
|
movw %ax, %gs
|
||||||
|
movw %ax, %ss
|
||||||
|
|
||||||
|
jmp $8,$flush
|
||||||
|
|
||||||
|
flush:
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
58
src/kernel/Memory/GDT/gdtc.cpp
Normal file
58
src/kernel/Memory/GDT/gdtc.cpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#include "gdtc.h"
|
||||||
|
#include "../../Terminal/kterm.h"
|
||||||
|
|
||||||
|
#define NULL_SEGMENT 0
|
||||||
|
#define KERNEL_CODE_SEGMENT 1
|
||||||
|
#define KERNEL_DATA_SEGMENT 2
|
||||||
|
#define USER_CODE_SEGMENT 3
|
||||||
|
#define USER_DATA_SEGMENT 4
|
||||||
|
|
||||||
|
SegmentDescriptor GlobalDescriptorTable[5];
|
||||||
|
GlobalDescriptorTableDescriptor gdtDescriptor;
|
||||||
|
|
||||||
|
void add_descriptor(int which , unsigned long base, unsigned long limit, unsigned char access, unsigned char granularity ){
|
||||||
|
GlobalDescriptorTable[which].base_low = (base & 0xFFFF );
|
||||||
|
GlobalDescriptorTable[which].base_middle = (base >> 6) & 0xFF;
|
||||||
|
GlobalDescriptorTable[which].base_high = (base >> 24) & 0xFF;
|
||||||
|
|
||||||
|
GlobalDescriptorTable[which].limit_low = (limit & 0xFFFF);
|
||||||
|
GlobalDescriptorTable[which].granularity = ((limit >> 16) & 0x0F);
|
||||||
|
|
||||||
|
GlobalDescriptorTable[which].granularity |= (granularity & 0xF0);
|
||||||
|
GlobalDescriptorTable[which].access = access;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void initGDT(){
|
||||||
|
|
||||||
|
#ifdef __VERBOSE__
|
||||||
|
printf("Init GDT!\n");
|
||||||
|
#endif
|
||||||
|
// NULL segment
|
||||||
|
add_descriptor(NULL_SEGMENT, 0,0,0,0);
|
||||||
|
|
||||||
|
// Kernel Code Segment
|
||||||
|
add_descriptor(KERNEL_CODE_SEGMENT, 0, 0xFFFFFFFF, 0x9A, 0xCF);
|
||||||
|
|
||||||
|
// Kernel Data Segment
|
||||||
|
add_descriptor(KERNEL_DATA_SEGMENT, 0, 0xFFFFFFFF, 0x92, 0xCF);
|
||||||
|
|
||||||
|
// User Code Segment
|
||||||
|
// TODO:
|
||||||
|
|
||||||
|
// User Data Segement
|
||||||
|
// TODO:
|
||||||
|
|
||||||
|
// init Gdt Descriptor
|
||||||
|
gdtDescriptor.limit = ((sizeof(SegmentDescriptor ) * 5 ) - 1);
|
||||||
|
gdtDescriptor.base = (unsigned int) &GlobalDescriptorTable;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
LoadGlobalDescriptorTable();
|
||||||
|
|
||||||
|
}
|
27
src/kernel/Memory/GDT/gdtc.h
Normal file
27
src/kernel/Memory/GDT/gdtc.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct SegmentDescriptor {
|
||||||
|
unsigned short limit_low;
|
||||||
|
unsigned short base_low;
|
||||||
|
unsigned char base_middle;
|
||||||
|
unsigned char access;
|
||||||
|
unsigned char granularity;
|
||||||
|
unsigned char base_high;
|
||||||
|
}__attribute__((packed));
|
||||||
|
|
||||||
|
|
||||||
|
struct GlobalDescriptorTableDescriptor{
|
||||||
|
unsigned short limit;
|
||||||
|
unsigned int base;
|
||||||
|
}__attribute__((packed));
|
||||||
|
|
||||||
|
extern SegmentDescriptor GlobalDescriptorTable[];
|
||||||
|
extern GlobalDescriptorTableDescriptor gdtDescriptor;
|
||||||
|
|
||||||
|
|
||||||
|
void add_descriptor(int which , unsigned long base, unsigned long limit, unsigned char access, unsigned char granularity );
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" void LoadGlobalDescriptorTable();
|
||||||
|
void initGDT();
|
142
src/kernel/Memory/memory.cpp
Normal file
142
src/kernel/Memory/memory.cpp
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
#include "./memory.h"
|
||||||
|
uint32_t* memoryBitMap;
|
||||||
|
/*
|
||||||
|
|
||||||
|
*/
|
||||||
|
void PhysicalMemory::setup( MemoryInfo* memory) {
|
||||||
|
|
||||||
|
// calculate the maximum number of blocks
|
||||||
|
max_blocks = KB_TO_BLOCKS(memory->TotalMemory);
|
||||||
|
|
||||||
|
used_blocks = 0;
|
||||||
|
|
||||||
|
memoryBitMap = (uint32_t*) 0x00a00000;
|
||||||
|
|
||||||
|
|
||||||
|
printf("Maximum Number of blocks: 0x%x, Number of bytes for memMap: 0x%x\n", max_blocks , (max_blocks/8));
|
||||||
|
|
||||||
|
//Size of memory map
|
||||||
|
uint32_t memMap_size = (max_blocks / 8 ) ;
|
||||||
|
|
||||||
|
printf("Memory Map size: 0x%x\n", memMap_size );
|
||||||
|
printf("size of int in bytes: 0x%x \n" , sizeof(int));
|
||||||
|
|
||||||
|
// Set all places in memory as free
|
||||||
|
memset(memoryBitMap, 0xFF, memMap_size );
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: this can only give blocks of 4kb at a time!
|
||||||
|
void* PhysicalMemory::allocate_block() {
|
||||||
|
uint8_t blocks_available = max_blocks - used_blocks;
|
||||||
|
// Are there any blocks available?
|
||||||
|
if( blocks_available <= 0)
|
||||||
|
{
|
||||||
|
printf("No blocks available. Blocks Delta: 0x%x\n", blocks_available);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find 1 free block somewhere
|
||||||
|
int free_block_index = bitmap_first_unset(memoryBitMap, (max_blocks /8) /*memMap Size*/ );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(free_block_index == -1)
|
||||||
|
{
|
||||||
|
printf("Could not find a good block!\n");
|
||||||
|
// Could not find a block
|
||||||
|
return (void*)0xFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(free_block_index == 0)
|
||||||
|
printf("Somethings wrong!!!\n");
|
||||||
|
|
||||||
|
// Set the block to be used!
|
||||||
|
bitmap_unset(memoryBitMap, free_block_index);
|
||||||
|
// Increase the used_block count!
|
||||||
|
used_blocks++;
|
||||||
|
printf("used blocks: 0x%x\n", used_blocks);
|
||||||
|
// return the pointer to the physical address
|
||||||
|
return (void*) (BLOCK_SIZE * free_block_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PhysicalMemory::free_block(void* p) {
|
||||||
|
// If it is a null pointer we don't need to do anything.
|
||||||
|
if(p==0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// calculate the index into the bitmap
|
||||||
|
int index = ((uint32_t) p) / BLOCK_SIZE;
|
||||||
|
|
||||||
|
// set the block to be free
|
||||||
|
bitmap_set(memoryBitMap, index);
|
||||||
|
used_blocks--;
|
||||||
|
printf("used blocks: 0x%x, after free\n", used_blocks);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void PhysicalMemory::allocate_region(uint32_t startAddress, uint32_t size) {
|
||||||
|
// every bit should be 4KiB
|
||||||
|
// every byte is 8*4KiB = 32KiB
|
||||||
|
|
||||||
|
int NumberOfBlocksToAllocate = ( size / 1024) / 4 / 8 + 1;
|
||||||
|
int startBlock = (startAddress / 1024) / 4 / 8 ;
|
||||||
|
|
||||||
|
// printf("NumberOfBlocksToAllocate: 0x%x\n", NumberOfBlocksToAllocate);
|
||||||
|
//printf( "start block: 0x%x\n" , startBlock);
|
||||||
|
for( int i = 0; i < NumberOfBlocksToAllocate; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
//printf("ALLOCATE BLOCK: 0x%x\n" , startBlock + i );
|
||||||
|
bitmap_unset(memoryBitMap, startBlock+ i);
|
||||||
|
used_blocks++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
void PhysicalMemory::deallocate_region(uint32_t StartAddress , uint32_t size ) {
|
||||||
|
// NOT IMPLEMENTED YET
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mapMultibootMemoryMap( MemoryInfo* memInfo , multiboot_info_t *mbt) {
|
||||||
|
printf("mmap_addr = 0x%x, mmap_length = 0x%x\n",
|
||||||
|
(unsigned) mbt->mmap_addr, (unsigned) mbt->mmap_length);
|
||||||
|
multiboot_memory_map_t *mmap = (multiboot_memory_map_t*) mbt->mmap_addr;
|
||||||
|
|
||||||
|
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){
|
||||||
|
|
||||||
|
memInfo->TotalMemory += mmap->len;
|
||||||
|
} else {
|
||||||
|
memInfo->ReservedMemory += mmap->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
print_Multiboot_memory_Map(mmap);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Debug Verbose functions
|
||||||
|
*
|
||||||
|
* @param mmap
|
||||||
|
*/
|
||||||
|
|
||||||
|
void print_Multiboot_memory_Map(multiboot_memory_map_t* mmap) {
|
||||||
|
printf(
|
||||||
|
"size = 0x%x, base_addr = 0x%x%08x, length = 0x%x%08x, type = 0x%x\n",
|
||||||
|
(unsigned) mmap->size,
|
||||||
|
(unsigned) (mmap->addr >> 32),
|
||||||
|
(unsigned) (mmap->addr & 0xffffffff),
|
||||||
|
(unsigned) (mmap->len >> 32),
|
||||||
|
(unsigned) (mmap->len & 0xffffffff),
|
||||||
|
(unsigned) mmap->type
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
48
src/kernel/Memory/memory.h
Normal file
48
src/kernel/Memory/memory.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "memoryinfo.h"
|
||||||
|
#include "../multiboot.h"
|
||||||
|
#include "../Terminal/kterm.h"
|
||||||
|
#include "../Lib/mem.h"
|
||||||
|
#include "../bitmap.h"
|
||||||
|
|
||||||
|
#define BLOCK_SIZE 4092
|
||||||
|
#define BLOCKS_PER_WORD 32 // A word is 16 bit in x86 machines according to my google search results!
|
||||||
|
|
||||||
|
#define KB_TO_BLOCKS(x) (x / BLOCK_SIZE)
|
||||||
|
#define IS_ALIGNED(addr, align) !((addr) & ~((align) - 1))
|
||||||
|
#define ALIGN(addr, align) (((addr) & ~((align) - 1 )) + (align))
|
||||||
|
|
||||||
|
extern uint32_t kernel_begin;
|
||||||
|
extern uint32_t kernel_end;
|
||||||
|
|
||||||
|
void initialise_available_regions(uint32_t memoryMapAddr, uint32_t memoryMapLastAddr, uint32_t* memoryBitMap, int* used_blocks);
|
||||||
|
|
||||||
|
extern uint32_t* memoryBitMap;
|
||||||
|
|
||||||
|
class PhysicalMemory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void setup(MemoryInfo* memory);
|
||||||
|
void destroy();
|
||||||
|
void free_block(void* ptr);
|
||||||
|
void* allocate_block();
|
||||||
|
void allocate_region(uint32_t, uint32_t);
|
||||||
|
void deallocate_region(uint32_t , uint32_t );
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t pmmap_size;
|
||||||
|
size_t max_blocks;
|
||||||
|
int used_blocks;
|
||||||
|
};
|
||||||
|
|
||||||
|
void mapMultibootMemoryMap( MemoryInfo* memInfo , multiboot_info_t *mbt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Debug Verbose Functions
|
||||||
|
*
|
||||||
|
* @param mmap
|
||||||
|
*/
|
||||||
|
void print_Multiboot_memory_Map(multiboot_memory_map_t* mmap);
|
20
src/kernel/Memory/memoryinfo.h
Normal file
20
src/kernel/Memory/memoryinfo.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
struct MemoryArea{
|
||||||
|
void* StartAddress;
|
||||||
|
size_t Size;
|
||||||
|
unsigned int type;
|
||||||
|
MemoryArea* Next;
|
||||||
|
|
||||||
|
}__attribute__((packed));
|
||||||
|
|
||||||
|
struct MemoryInfo {
|
||||||
|
uint32_t TotalMemory;
|
||||||
|
uint32_t ReservedMemory;
|
||||||
|
MemoryArea* MemoryRegionList;
|
||||||
|
}__attribute__((packed));
|
||||||
|
|
||||||
|
|
||||||
|
|
170
src/kernel/Memory/paging.cpp
Normal file
170
src/kernel/Memory/paging.cpp
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
#include "paging.h"
|
||||||
|
PageDirectoryEntry kernel_directory[MAX_DIRECTORY_ENTRIES]__attribute__((aligned(4096)));
|
||||||
|
|
||||||
|
PageTableEntry first_page_table[MAX_PAGE_TABLE_ENTRIES]__attribute__((aligned(4096)));
|
||||||
|
|
||||||
|
void IdentityMap (){
|
||||||
|
printf("\nInit paging\n");
|
||||||
|
// The basics as explained by wiki.osdev.org
|
||||||
|
|
||||||
|
// Set all page_directories to not present
|
||||||
|
int i = 0;
|
||||||
|
while ( i < 1024)
|
||||||
|
{
|
||||||
|
kernel_directory[i] = 0x2;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// map 4 megabytes
|
||||||
|
unsigned int j ;
|
||||||
|
for( j = 0; j < 1024; j++ )
|
||||||
|
{
|
||||||
|
first_page_table[j] = (j * 0x1000) | 3 ;
|
||||||
|
|
||||||
|
//Attributes:
|
||||||
|
//Supervisor Level ,
|
||||||
|
//read/write,
|
||||||
|
//present,
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put the page table in the page directory
|
||||||
|
// attributes: supervisor level, read/write, present;
|
||||||
|
kernel_directory[0] = ((unsigned int)first_page_table) | 3;
|
||||||
|
|
||||||
|
printf("Init paging DONE\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitializePaging()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Initial kernel page directory
|
||||||
|
set all page tables to not present
|
||||||
|
*/
|
||||||
|
for (int i = 0; i < MAX_DIRECTORY_ENTRIES; i++)
|
||||||
|
{
|
||||||
|
kernel_directory[i] = 0x2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BIOS Address Identity mapping
|
||||||
|
// Identity map the first 8MiB ... Physical addresses 0x00000000 to 0x007A1200
|
||||||
|
PHYSICAL_ADDRESS BIOSAddr = 0x00000000;
|
||||||
|
PHYSICAL_ADDRESS BIOSAddr_Max = 0x800000;
|
||||||
|
|
||||||
|
// How many PDE's do we need
|
||||||
|
uint8_t NUM_PDE = BIOSAddr_Max / (4 * 1024 * 1024);
|
||||||
|
|
||||||
|
printf("The first 8MiB require %d Page Directory Entries\n", NUM_PDE);
|
||||||
|
/*
|
||||||
|
for( int i = 0; i < NUM_PDE; i++)
|
||||||
|
{
|
||||||
|
// setup a page table
|
||||||
|
PageTableEntry pagetable[MAX_PAGE_TABLE_ENTRIES] = PhysicalMemory::allocate_block(); // TODO :: Physical memory manager functions should be available here.
|
||||||
|
|
||||||
|
for(int j = 0; j < MAX_PAGE_TABLE_ENTRIES; j++)
|
||||||
|
{
|
||||||
|
pagetable[j] = ( j * 4096 ) | 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add page table as page directory entry
|
||||||
|
kernel_directory[i] = ( (unsigned int) pagetable ) | 3;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
// map the kernel space
|
||||||
|
VIRTUAL_ADDRESS Vaddr = KERNEL_VRT_MEMORY_BEGIN;
|
||||||
|
PHYSICAL_ADDRESS KernelAddr = kernel_begin;
|
||||||
|
PHYSICAL_ADDRESS KernelEndAddr = kernel_end;
|
||||||
|
|
||||||
|
uint32_t KernelSizeInBytes = (KernelEndAddr - KernelAddr);
|
||||||
|
printf("Kernel is 0x%x bytes\n", KernelSizeInBytes);
|
||||||
|
NUM_PDE = KernelSizeInBytes / (4 * 1024* 1024);
|
||||||
|
printf("Kernel requires %d Page Directory Entries\n", NUM_PDE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
for(int i = 0; i < NUM_PDE; i++)
|
||||||
|
{
|
||||||
|
PageTableEntry pageTable [MAX_PAGE_TABLE_ENTRIES] = PhysicalMemory::allocate_block();
|
||||||
|
|
||||||
|
for(int j = 0; j < MAX_PAGE_TABLE_ENTRIES; j++)
|
||||||
|
{
|
||||||
|
pageTable[j] = ( j * 4096) | 3; // NOTE: Check if page is actually supposed to be present
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Calculate Page Directory index
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Identity map VGA memory
|
||||||
|
// Calc which PDE adn
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AllocatePage(VIRTUAL_ADDRESS vaddr, PageDirectoryEntry& page_directory)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreePage(VIRTUAL_ADDRESS vaddr , PageDirectoryEntry& page_directory)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Map ( PHYSICAL_ADDRESS paddr, VIRTUAL_ADDRESS vaddr, PageDirectoryEntry& page_directory)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Unmap(VIRTUAL_ADDRESS vaddr, PageDirectoryEntry& page_directory)
|
||||||
|
{
|
||||||
|
// NOTE: I will implement lazy unmapping for now
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Enable()
|
||||||
|
{
|
||||||
|
|
||||||
|
//TODO: Write protect will not be turned on
|
||||||
|
// for the moment altough according to the intel
|
||||||
|
// developer manual this should happen.
|
||||||
|
|
||||||
|
uint32_t CR0;
|
||||||
|
|
||||||
|
CR0 = GetCR0();
|
||||||
|
printf("PG bit = %d \n" , GET_PG_BIT(CR0));
|
||||||
|
|
||||||
|
printf("Load into CR3 address: 0x%x\n", (uint32_t)(&kernel_directory[0]));
|
||||||
|
loadPageDirectory(&kernel_directory[0]);
|
||||||
|
enablePaging();
|
||||||
|
|
||||||
|
printf("Paging enabled!\n");
|
||||||
|
|
||||||
|
|
||||||
|
CR0 = GetCR0();
|
||||||
|
uint32_t CR4 = GetCR4();
|
||||||
|
printf("PG bit = %d\n" , GET_PG_BIT(CR0) );
|
||||||
|
printf("PAE bit = %d\n", GET_PAE_BIT(CR4));
|
||||||
|
|
||||||
|
if(GET_PAE_BIT(CR4) == 0){
|
||||||
|
printf("Using 32bit paging\n");
|
||||||
|
|
||||||
|
if(GET_PSE_BIT(CR4) == 0 ){
|
||||||
|
printf("Page size is 4KiB\n");
|
||||||
|
} else {
|
||||||
|
printf("Page size is 4MiB\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("Using some extended version for paging\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
56
src/kernel/Memory/paging.definitions.h
Normal file
56
src/kernel/Memory/paging.definitions.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
/*
|
||||||
|
This file contains some handy definitions for different types
|
||||||
|
that have to do with paging in atleast 32 bit and maybe sometime in the future
|
||||||
|
also 64 bit mode.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MAX_DIRECTORY_ENTRIES 1024
|
||||||
|
#define MAX_PAGE_TABLE_ENTRIES 1024
|
||||||
|
#define MAX_PAGES 1024
|
||||||
|
|
||||||
|
#define PHYSICAL_ADDRESS uint32_t
|
||||||
|
#define VIRTUAL_ADDRESS uint32_t
|
||||||
|
|
||||||
|
#define PageDirectoryEntry uint32_t
|
||||||
|
#define PageTableEntry uint32_t
|
||||||
|
|
||||||
|
|
||||||
|
#define KERNEL_VRT_MEMORY_BEGIN 0xC0000000
|
||||||
|
#define KERNEL_VRT_MEMORY_END 0xCFFFFFFF
|
||||||
|
#define PAGE_SIZE 4096;
|
||||||
|
|
||||||
|
|
||||||
|
// NOTE: FIXME: I am fairly certain these masks are off by one!
|
||||||
|
|
||||||
|
#define PD32_PRESENT_MASK (0x1 << 0)
|
||||||
|
#define PD32_READ_WRITE_MASK (0x1 << 1)
|
||||||
|
#define PD32_SUPERVISOR_MASK (0x1 << 2)
|
||||||
|
#define PD32_WRITE_THROUGH_MASK (0x1 << 3)
|
||||||
|
#define PD32_CACHE_DISABLE_MASK (0x1 << 4)
|
||||||
|
#define PD32_ACCESSED_MASK (0x1 << 5)
|
||||||
|
#define PD32_AVAILABLE_1_4KB_MASK (0x1 << 6)
|
||||||
|
#define PD32_DISABLE_4MB_MASK (0x1 << 6)
|
||||||
|
#define PD32_PAGE_SIZE_MASK (0x1 << 7)
|
||||||
|
#define PD32_GLOBAL_4MB_MASK (0x1 << 8)
|
||||||
|
#define PD32_AVAILABLE_2_4MB_MASK ( 14 << 9)
|
||||||
|
#define PD32_AVAILABLE_2_4KB_MASK ( 15 << 8)
|
||||||
|
#define PD32_ADDRESS_4KB_MASK (0x8FFFF << 12)
|
||||||
|
#define PD32_PAGE_ATTRIBUTE_TABLE_4MB_MASK (0x1 << 12)
|
||||||
|
#define PD32_HIGH_HALF_ADDRESS_4MB_MASK (0x7F<< 13)
|
||||||
|
#define PD32_RESERVED_4MB_MASK (0x1 << 21)
|
||||||
|
#define PD32_LOWER_HALF_ADDRESS_4MB_MASK (0x1FF << 22)
|
||||||
|
|
||||||
|
#define PT32_PRESENT_MASK (0x1 << 0)
|
||||||
|
#define PT32_READ_WRITE_MASK (0x1 << 1)
|
||||||
|
#define PT32_SUPERVISOR_MASK (0x1 << 2)
|
||||||
|
#define PT32_WRITE_THROUGH_MASK (0x1 << 3)
|
||||||
|
#define PT32_CACHE_DISABLE_MASK (0x1 << 4)
|
||||||
|
#define PT32_ACCESSED_MASK (0x1 << 5)
|
||||||
|
#define PT32_DIRTY_MASK (0x1 << 6)
|
||||||
|
#define PT32_PAGE_ATTRIBUTE_TABLE_MASK (0x1 << 7)
|
||||||
|
#define PT32_GLOBAL_MASK (0x1 << 8)
|
||||||
|
#define PT32_AVAILABLE_MASK (0x7 << 9)
|
||||||
|
#define PT32_CACHE_DISABLE_MASK (0x7FFFF << 12)
|
||||||
|
|
22
src/kernel/Memory/paging.h
Normal file
22
src/kernel/Memory/paging.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "memory.h"
|
||||||
|
#include "paging.definitions.h"
|
||||||
|
#include "../Terminal/kterm.h"
|
||||||
|
#include "../cpu.h"
|
||||||
|
|
||||||
|
extern "C" void loadPageDirectory (uint32_t* addr );
|
||||||
|
extern "C" void enablePaging();
|
||||||
|
|
||||||
|
|
||||||
|
void IdentityMap();
|
||||||
|
void InitializePaging();
|
||||||
|
|
||||||
|
void Enable();
|
||||||
|
|
||||||
|
void AllocatePage(VIRTUAL_ADDRESS, PageDirectoryEntry&);
|
||||||
|
void FreePage(VIRTUAL_ADDRESS, PageDirectoryEntry&);
|
||||||
|
|
||||||
|
void Map(PHYSICAL_ADDRESS, VIRTUAL_ADDRESS, PageDirectoryEntry&);
|
||||||
|
void Unmap (VIRTUAL_ADDRESS, PageDirectoryEntry&);
|
||||||
|
|
||||||
|
|
44
src/kernel/Memory/paging.s
Normal file
44
src/kernel/Memory/paging.s
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# NOTE: I wish this wasn't AT&T Syntax its horrible
|
||||||
|
# REMINDER: INSTRUCTION FROM_REGISTER, TO_REGISTER
|
||||||
|
.globl enablePaging
|
||||||
|
enablePaging:
|
||||||
|
# Create a new call frame
|
||||||
|
push %ebp
|
||||||
|
mov %esp, %ebp
|
||||||
|
|
||||||
|
# Set the PG bit of CR0
|
||||||
|
mov %cr0, %eax
|
||||||
|
or $0x80000000, %eax
|
||||||
|
mov %eax, %cr0
|
||||||
|
|
||||||
|
# Restore to the previous call frame
|
||||||
|
mov %ebp, %esp
|
||||||
|
pop %ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
.globl loadPageDirectory
|
||||||
|
loadPageDirectory:
|
||||||
|
push %ebp
|
||||||
|
mov %esp, %ebp
|
||||||
|
|
||||||
|
/* NOTE: We should probably check if paging is already enabled.
|
||||||
|
Changing the CR3 register whilst paging is enabled might
|
||||||
|
result in unwanted behaviour (in the worst case) or cause a
|
||||||
|
fault (in the best case).
|
||||||
|
*/
|
||||||
|
|
||||||
|
mov 8(%esp), %eax # Move the first argument in the eax register
|
||||||
|
|
||||||
|
mov %eax, %cr3 # Move the value of eax into the CR3 register
|
||||||
|
|
||||||
|
/*
|
||||||
|
Moving the value of the argument passed to this function
|
||||||
|
into the CR3 register will allow the MMU to access the paging
|
||||||
|
structure we setup in memory once we enable paging
|
||||||
|
*/
|
||||||
|
|
||||||
|
mov %ebp, %esp
|
||||||
|
pop %ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
83
src/kernel/SuperVisorTerminal/superVisorTerminal.cpp
Normal file
83
src/kernel/SuperVisorTerminal/superVisorTerminal.cpp
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#include "superVisorTerminal.h"
|
||||||
|
|
||||||
|
void startSuperVisorTerminal(BootInfo* bootinfo){
|
||||||
|
while (true){
|
||||||
|
|
||||||
|
printf("SUPERVISOR:>$ " );
|
||||||
|
int characterCount = 0;
|
||||||
|
char command[10] = "";
|
||||||
|
|
||||||
|
// NOTE: lets just show a kernel prompt
|
||||||
|
uint8_t ScanCode = getKey();
|
||||||
|
while( ScanCode != 0x1C )
|
||||||
|
{
|
||||||
|
char character = getASCIIKey();
|
||||||
|
kterm_put(character );
|
||||||
|
// wHAT THE HELL
|
||||||
|
|
||||||
|
if( characterCount < 10 ){
|
||||||
|
command[characterCount] = character;
|
||||||
|
characterCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScanCode = getKey();
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
KeyHandled();
|
||||||
|
|
||||||
|
|
||||||
|
if ( strncmp("DATE", command , characterCount ) == 0 )
|
||||||
|
{
|
||||||
|
read_rtc();
|
||||||
|
printf("======= Time & Date ==========\n");
|
||||||
|
printf(" - Date: %02d-%02d-%02d\n",day, month, year);
|
||||||
|
printf(" - Time: %02d:%02d:%02d\n" , hour, minute, second);
|
||||||
|
printf(" - Ticks: %09d\n", pit_tick);
|
||||||
|
}
|
||||||
|
else if( strncmp ("MEMORY" , command , characterCount) == 0 )
|
||||||
|
{
|
||||||
|
// Show memory layout
|
||||||
|
printf("========= Memory ==========\n");
|
||||||
|
printf("Kernel MemoryMap:\n");
|
||||||
|
printf("kernel: 0x%x - 0x%x\n", &kernel_begin , &kernel_end);
|
||||||
|
printf("Frames used: 0x%x blocks of 4 KiB\n", 0);
|
||||||
|
const int bytesInGiB = 1073741824;
|
||||||
|
int64_t bytesLeft = (bootinfo->memory->TotalMemory % bytesInGiB) / bytesInGiB;
|
||||||
|
int64_t effectiveNumberOfGib = bootinfo->memory->TotalMemory / bytesInGiB;
|
||||||
|
|
||||||
|
int64_t GiBs = effectiveNumberOfGib + bytesLeft;
|
||||||
|
|
||||||
|
printf("Available Memory: %d bytes, %d GiB\n", bootinfo->memory->TotalMemory, GiBs );
|
||||||
|
printf("Reserved Memory: %d bytes\n", bootinfo->memory->ReservedMemory);
|
||||||
|
|
||||||
|
//printf("\n\n");
|
||||||
|
//PrintPhysicalMemoryAllocation( );
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(strncmp("TEST", command, characterCount) == 0)
|
||||||
|
{
|
||||||
|
// TEST #DE exception
|
||||||
|
asm volatile ("MOV $4, %AX ; MOV $0, %BX ; DIV %BX"); // IRS 0
|
||||||
|
}
|
||||||
|
else if (strncmp("VERSION", command , characterCount) == 0)
|
||||||
|
{
|
||||||
|
// Show version information
|
||||||
|
printf("========= Version ========\n");
|
||||||
|
printf("Kernel v%d\n", 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(strncmp("CLEAR", command, characterCount) == 0)
|
||||||
|
{
|
||||||
|
kterm_init();
|
||||||
|
printf("|=== BarinkOS ===|\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Unknown command\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
delay(1000);
|
||||||
|
}
|
||||||
|
}
|
9
src/kernel/SuperVisorTerminal/superVisorTerminal.h
Normal file
9
src/kernel/SuperVisorTerminal/superVisorTerminal.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../Terminal/kterm.h"
|
||||||
|
#include "../time.h"
|
||||||
|
#include "../Drivers/PIT/pit.h"
|
||||||
|
#include "../Drivers/PS-2/keyboard.h"
|
||||||
|
#include "../Memory/memory.h"
|
||||||
|
#include "../bootinfo.h"
|
||||||
|
|
||||||
|
void startSuperVisorTerminal(BootInfo * );
|
234
src/kernel/Terminal/kterm.cpp
Normal file
234
src/kernel/Terminal/kterm.cpp
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
#include "kterm.h"
|
||||||
|
|
||||||
|
static const size_t VGA_WIDTH = 80;
|
||||||
|
static const size_t VGA_HEIGHT = 25;
|
||||||
|
|
||||||
|
size_t kterm_row;
|
||||||
|
size_t kterm_column;
|
||||||
|
uint8_t kterm_color;
|
||||||
|
uint16_t* kterm_buffer;
|
||||||
|
|
||||||
|
|
||||||
|
static inline uint8_t vga_entry_color( enum vga_color fg, enum vga_color bg) {
|
||||||
|
return fg | bg << 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t vga_entry (unsigned char uc, uint8_t color) {
|
||||||
|
return (uint16_t) uc | (uint16_t) color << 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
void kterm_init () {
|
||||||
|
kterm_row = 0;
|
||||||
|
kterm_column = 0;
|
||||||
|
kterm_color = vga_entry_color ( VGA_COLOR_LIGHT_GREY , VGA_COLOR_BLACK);
|
||||||
|
kterm_buffer = (uint16_t*) 0xC03FF000;
|
||||||
|
for (size_t y = 0; y < VGA_HEIGHT; y++ ){
|
||||||
|
for( size_t x = 0; x < VGA_WIDTH; x++){
|
||||||
|
const size_t index = y * VGA_WIDTH + x;
|
||||||
|
kterm_buffer[index] = vga_entry(' ', kterm_color);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void kterm_resetcolor(){
|
||||||
|
kterm_color = vga_entry_color ( VGA_COLOR_LIGHT_GREY , VGA_COLOR_BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kterm_setcolor(uint8_t color){
|
||||||
|
kterm_color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void kterm_putat (char c, uint8_t color, size_t x, size_t y ) {
|
||||||
|
const size_t index = y * VGA_WIDTH + x;
|
||||||
|
|
||||||
|
kterm_buffer[index] = vga_entry(c, color);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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:
|
||||||
|
* https://whiteheadsoftware.dev/operating-systems-development-for-dummies/
|
||||||
|
**/
|
||||||
|
void kterm_scrollup(){
|
||||||
|
size_t i ;
|
||||||
|
for(i=0; i < (VGA_WIDTH * VGA_HEIGHT - VGA_WIDTH); i++)
|
||||||
|
kterm_buffer[i] = kterm_buffer[i+VGA_WIDTH];
|
||||||
|
|
||||||
|
for( i=0; i< VGA_WIDTH; i++)
|
||||||
|
kterm_buffer[(VGA_HEIGHT -1) * VGA_WIDTH + i ] = vga_entry(' ', kterm_color);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void kterm_put (char c) {
|
||||||
|
if(++kterm_column == VGA_WIDTH || c == '\n' ) {
|
||||||
|
update_cursor(kterm_column , kterm_row);
|
||||||
|
kterm_column = 0;
|
||||||
|
if(kterm_row == VGA_HEIGHT-1 ) {
|
||||||
|
kterm_scrollup();
|
||||||
|
} else {
|
||||||
|
kterm_row ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( c == '\r'){
|
||||||
|
kterm_column = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(c == '\n') return;
|
||||||
|
kterm_putat ( c, kterm_color, kterm_column, kterm_row);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void kterm_write(const char* data, size_t size) {
|
||||||
|
for(size_t i = 0; i < size; i++){
|
||||||
|
kterm_put(data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void kterm_writestring(const char* data ){
|
||||||
|
// AS_KERNEL();
|
||||||
|
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':
|
||||||
|
|
||||||
|
case 'u':
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
46
src/kernel/Terminal/kterm.h
Normal file
46
src/kernel/Terminal/kterm.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "../Drivers/VGA/colors.h"
|
||||||
|
#include "../io.h"
|
||||||
|
|
||||||
|
extern "C"{
|
||||||
|
#include "../Lib/string.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
void kterm_init();
|
||||||
|
|
||||||
|
/* Kernel terminal - Colour functions*/
|
||||||
|
void kterm_resetcolor();
|
||||||
|
void kterm_setcolor(uint8_t);
|
||||||
|
|
||||||
|
/* Kernel terminal - Printing function */
|
||||||
|
void kterm_putat(char, uint8_t, size_t, size_t);
|
||||||
|
void kterm_put(char);
|
||||||
|
void kterm_write(const char*, size_t);
|
||||||
|
void kterm_writestring(const char*);
|
||||||
|
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 AS_KERNEL() ( kterm_setcolor(VGA_COLOR_LIGHT_BLUE),\
|
||||||
|
kterm_write(KernelTag, 10 ), \
|
||||||
|
kterm_resetcolor())
|
||||||
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
* Multiboot
|
|
||||||
*/
|
|
||||||
.set ALIGN, 1<<0 /* align loaded modules on page boundaries */
|
|
||||||
.set MEMINFO, 1<<1 /* provide memory map */
|
|
||||||
.set FLAGS, ALIGN | MEMINFO /* this is the Multiboot 'flag' field */
|
|
||||||
.set MAGIC, 0x1BADB002 /* 'magic number' lets bootloader find the header */
|
|
||||||
.set CHECKSUM, -(MAGIC + FLAGS) /* checksum of above, to prove we are multiboot */
|
|
||||||
|
|
||||||
.section .multiboot
|
|
||||||
.align 4
|
|
||||||
.long MAGIC
|
|
||||||
.long FLAGS
|
|
||||||
.long CHECKSUM
|
|
||||||
|
|
||||||
|
|
||||||
.section .bss
|
|
||||||
.align 16
|
|
||||||
stack_bottom:
|
|
||||||
.skip 16384 # 16 KiB
|
|
||||||
stack_top:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.text
|
|
||||||
.globl enablePaging
|
|
||||||
enablePaging:
|
|
||||||
push %ebp
|
|
||||||
mov %esp, %ebp
|
|
||||||
mov %cr0, %eax
|
|
||||||
or $0x80000000, %eax
|
|
||||||
mov %eax, %cr0
|
|
||||||
mov %ebp, %esp
|
|
||||||
pop %ebp
|
|
||||||
ret
|
|
||||||
|
|
||||||
.text
|
|
||||||
.globl loadPageDirectory
|
|
||||||
loadPageDirectory:
|
|
||||||
push %ebp
|
|
||||||
mov %esp, %ebp
|
|
||||||
mov 8(%esp), %eax
|
|
||||||
mov %eax, %cr3
|
|
||||||
mov %ebp, %esp
|
|
||||||
pop %ebp
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
.section .text
|
|
||||||
.global _start
|
|
||||||
.type _start, @function
|
|
||||||
_start:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
mov $stack_top, %esp
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
call _init
|
|
||||||
call kernel_main
|
|
||||||
|
|
||||||
|
|
||||||
cli
|
|
||||||
1: hlt
|
|
||||||
jmp 1b
|
|
||||||
|
|
||||||
|
|
||||||
.size _start, . - _start
|
|
@ -1,43 +0,0 @@
|
|||||||
/* The bootloader will look at this image and start execution at the symbol
|
|
||||||
designated as the entry point. */
|
|
||||||
ENTRY(_start)
|
|
||||||
|
|
||||||
/* Tell where the various sections of the object files will be put in the final
|
|
||||||
kernel image. */
|
|
||||||
SECTIONS
|
|
||||||
{
|
|
||||||
/* Begin putting sections at 1 MiB, a conventional place for kernels to be
|
|
||||||
loaded at by the bootloader. */
|
|
||||||
. = 1M;
|
|
||||||
|
|
||||||
/* 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.
|
|
||||||
Next we'll put the .text section. */
|
|
||||||
.text BLOCK(4K) : ALIGN(4K)
|
|
||||||
{
|
|
||||||
*(.multiboot)
|
|
||||||
*(.text)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read-only data. */
|
|
||||||
.rodata BLOCK(4K) : ALIGN(4K)
|
|
||||||
{
|
|
||||||
*(.rodata)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read-write data (initialized) */
|
|
||||||
.data BLOCK(4K) : ALIGN(4K)
|
|
||||||
{
|
|
||||||
*(.data)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read-write data (uninitialized) and stack */
|
|
||||||
.bss BLOCK(4K) : ALIGN(4K)
|
|
||||||
{
|
|
||||||
*(COMMON)
|
|
||||||
*(.bss)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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. */
|
|
||||||
}
|
|
@ -1,92 +0,0 @@
|
|||||||
#include "kterm.h"
|
|
||||||
static const size_t VGA_WIDTH = 80;
|
|
||||||
static const size_t VGA_HEIGHT = 25;
|
|
||||||
|
|
||||||
size_t kterm_row;
|
|
||||||
size_t kterm_column;
|
|
||||||
uint8_t kterm_color;
|
|
||||||
uint16_t* kterm_buffer;
|
|
||||||
|
|
||||||
|
|
||||||
static inline uint8_t vga_entry_color( enum vga_color fg, enum vga_color bg) {
|
|
||||||
return fg | bg << 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint16_t vga_entry (unsigned char uc, uint8_t color) {
|
|
||||||
return (uint16_t) uc | (uint16_t) color << 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
void kterm_init () {
|
|
||||||
kterm_row = 0;
|
|
||||||
kterm_column = 0;
|
|
||||||
kterm_color = vga_entry_color ( VGA_COLOR_LIGHT_GREY , VGA_COLOR_BLACK);
|
|
||||||
kterm_buffer = (uint16_t*) 0xB8000;
|
|
||||||
for (size_t y = 0; y < VGA_HEIGHT; y++ ){
|
|
||||||
for( size_t x = 0; x < VGA_WIDTH; x++){
|
|
||||||
const size_t index = y * VGA_WIDTH + x;
|
|
||||||
kterm_buffer[index] = vga_entry(' ', kterm_color);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void kterm_resetcolor(){
|
|
||||||
kterm_color = vga_entry_color ( VGA_COLOR_LIGHT_GREY , VGA_COLOR_BLACK);
|
|
||||||
}
|
|
||||||
|
|
||||||
void kterm_setcolor(uint8_t color){
|
|
||||||
kterm_color = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
void kterm_putat (char c, uint8_t color, size_t x, size_t y ) {
|
|
||||||
const size_t index = y * VGA_WIDTH + x;
|
|
||||||
|
|
||||||
kterm_buffer[index] = vga_entry(c, color);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* With the help from:
|
|
||||||
* https://whiteheadsoftware.dev/operating-systems-development-for-dummies/
|
|
||||||
**/
|
|
||||||
void kterm_scrollup(){
|
|
||||||
size_t i ;
|
|
||||||
for(i=0; i < (VGA_WIDTH * VGA_HEIGHT - VGA_WIDTH); i++)
|
|
||||||
kterm_buffer[i] = kterm_buffer[i+VGA_WIDTH];
|
|
||||||
|
|
||||||
for( i=0; i< VGA_WIDTH; i++)
|
|
||||||
kterm_buffer[(VGA_HEIGHT -1) * VGA_WIDTH + i ] = vga_entry(' ', kterm_color);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void kterm_put (char c) {
|
|
||||||
|
|
||||||
if(++kterm_column == VGA_WIDTH || c == '\n' ) {
|
|
||||||
kterm_column = 0;
|
|
||||||
if(kterm_row == VGA_HEIGHT-1) {
|
|
||||||
kterm_scrollup();
|
|
||||||
} else {
|
|
||||||
kterm_row ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if(c == '\n') return;
|
|
||||||
kterm_putat ( c, kterm_color, kterm_column, kterm_row);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void kterm_write(const char* data, size_t size) {
|
|
||||||
for(size_t i = 0; i < size; i++){
|
|
||||||
kterm_put(data[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void kterm_writestring(const char* data ){
|
|
||||||
AS_KERNEL();
|
|
||||||
kterm_write(data, strlen(data));
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include "../vga/colors.h"
|
|
||||||
|
|
||||||
void kterm_init();
|
|
||||||
|
|
||||||
void kterm_resetcolor();
|
|
||||||
void kterm_setcolor(uint8_t);
|
|
||||||
|
|
||||||
void kterm_putat(char, uint8_t, size_t, size_t);
|
|
||||||
void kterm_put(char);
|
|
||||||
void kterm_write(const char*, size_t);
|
|
||||||
void kterm_writestring(const char*);
|
|
||||||
void kterm_scrollup();
|
|
||||||
|
|
||||||
#define KernelTag "[Kernel]: "
|
|
||||||
#define AS_KERNEL() ( kterm_setcolor(VGA_COLOR_LIGHT_BLUE),\
|
|
||||||
kterm_write(KernelTag, 10 ), \
|
|
||||||
kterm_resetcolor())
|
|
40
src/kernel/bitmap.h
Normal file
40
src/kernel/bitmap.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
inline void bitmap_set( uint32_t* map , int index )
|
||||||
|
{
|
||||||
|
map[index/32] |= (1 << (index % 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void bitmap_unset(uint32_t* map , int index)
|
||||||
|
{
|
||||||
|
map[index/32] &= ~(1 << (index % 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32_t bitmap_first_unset( uint32_t* map , int map_size)
|
||||||
|
{
|
||||||
|
for ( int i = 0 ; i < map_size ; i ++ )
|
||||||
|
{
|
||||||
|
// a bit or more is set within this byte!
|
||||||
|
if( (map[i] & 0xFFFFFFFF) > 0 ){
|
||||||
|
|
||||||
|
// which bit is set?
|
||||||
|
for(int j = 0 ; j < 32 ; j++){
|
||||||
|
if ( (map[i] & (0x00000001 << j)) > 0)
|
||||||
|
{
|
||||||
|
printf("Found bit: byte 0x%x , bit 0x%x\n", i , j);
|
||||||
|
return (i*32)+j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
8
src/kernel/bootinfo.h
Normal file
8
src/kernel/bootinfo.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Memory/memoryinfo.h"
|
||||||
|
|
||||||
|
struct BootInfo{
|
||||||
|
const char* BootStructureID = "BarinkOS";
|
||||||
|
MemoryInfo* memory;
|
||||||
|
|
||||||
|
};
|
62
src/kernel/cpu.h
Normal file
62
src/kernel/cpu.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/*
|
||||||
|
Based on Intel specifications.
|
||||||
|
|
||||||
|
C++ interface for the cpu.s assembly file.
|
||||||
|
|
||||||
|
©Nigel Barink - 2022
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EFLAGS FUNCTIONS
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern "C" uint32_t GetEFLAGS();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CONTROL_REGISTER_0 FUNCTIONS
|
||||||
|
*/
|
||||||
|
extern "C" uint32_t GetCR0();
|
||||||
|
|
||||||
|
/*
|
||||||
|
struct CR0_Register {
|
||||||
|
uint8_t PE :1; // Protection Mode Enabled 0
|
||||||
|
uint8_t MP :1; // Monitor co-processor 1
|
||||||
|
uint8_t EM :1; // Emulation 2
|
||||||
|
uint8_t TS :1; // Task switched 3
|
||||||
|
uint8_t ET :1; // Extension Type 4
|
||||||
|
uint8_t NE :1; // Numeric error 5
|
||||||
|
uint16_t Reserved :10; // 6,7,8,9,10,11,12,13,14,15
|
||||||
|
uint8_t WP :1; // Write Protect 16
|
||||||
|
uint8_t Reserved :1; // 17
|
||||||
|
uint8_t AM :1; // Alligment Task 18
|
||||||
|
uint16_t Reserved :10; // 19,20,21,22,23,24,25,26,27,28
|
||||||
|
uint8_t NW :1; // Not-write through 29
|
||||||
|
uint8_t CD :1; // Cache disable 30
|
||||||
|
uint8_t PG :1; // Paging 31
|
||||||
|
};*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define GET_PE_BIT(CONTROL_REGISTER_0) (CONTROL_REGISTER_0&0x1)
|
||||||
|
#define GET_MP_BIT(CONTROL_REGISTER_0) (CONTROL_REGISTER_0&0x2)
|
||||||
|
#define GET_EM_BIT(CONTROL_REGISTER_0) (CONTROL_REGISTER_0&0x3)
|
||||||
|
#define GET_TS_BIT(CONTROL_REGISTER_0) (CONTROL_REGISTER_0&0x4)
|
||||||
|
#define GET_ET_BIT(CONTROL_REGISTER_0) (CONTROL_REGISTER_0&0x5)
|
||||||
|
#define GET_NE_BIT(CONTROL_REGISTER_0) (CONTROL_REGISTER_0&0x6)
|
||||||
|
|
||||||
|
|
||||||
|
#define GET_PG_BIT(CONTROL_REGISTER_0) (CONTROL_REGISTER_0>>31)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CONTROL_REGISTER_4 FUNCTIONS
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern "C" uint32_t GetCR4();
|
||||||
|
|
||||||
|
#define GET_PSE_BIT(CONTROL_REGISTER_4) (CONTROL_REGISTER_4&0x4)
|
||||||
|
#define GET_PAE_BIT(CONTROL_REGISTER_4) (CONTROL_REGISTER_4&0x5)
|
39
src/kernel/cpu.s
Normal file
39
src/kernel/cpu.s
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# Basic cpu functions
|
||||||
|
.globl GetCR0
|
||||||
|
GetCR0:
|
||||||
|
push %ebp # save the base pointer on the stack
|
||||||
|
mov %esp, %ebp # Set the base pointer to the current stack pointer
|
||||||
|
|
||||||
|
xor %eax, %eax # Clear EAX to make sure no weird stuff is going on
|
||||||
|
mov %cr0, %eax # Copy the value of the CR0 register into EAX
|
||||||
|
|
||||||
|
mov %ebp, %esp # restore the base pointer
|
||||||
|
pop %ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
.globl GetCR4
|
||||||
|
GetCR4:
|
||||||
|
push %ebp
|
||||||
|
mov %esp, %ebp
|
||||||
|
|
||||||
|
xor %eax, %eax
|
||||||
|
mov %cr4, %eax
|
||||||
|
|
||||||
|
mov %ebp, %esp
|
||||||
|
pop %ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.globl GetEFLAGS
|
||||||
|
GetEFLAGS:
|
||||||
|
push %ebp
|
||||||
|
mov %esp, %ebp
|
||||||
|
|
||||||
|
xor %eax, %eax
|
||||||
|
pushfl # Push the EFLAGS register content onto the stack, should be pushfd but GAS apparently doesn't agree
|
||||||
|
mov 4(%esp) , %eax
|
||||||
|
|
||||||
|
mov %ebp, %esp
|
||||||
|
pop %ebp
|
||||||
|
ret
|
9
src/kernel/definitions.h
Normal file
9
src/kernel/definitions.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
/**
|
||||||
|
* Kernel definitions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define __DEBUG__ false
|
||||||
|
#define KERNEL_VERSION 0
|
||||||
|
|
||||||
|
#define ARCHITECTURE "I386"
|
@ -1,23 +1,28 @@
|
|||||||
#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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void outb_p(unsigned char , unsigned short ){
|
void b_p(unsigned char , unsigned short ){
|
||||||
|
|
||||||
}
|
}
|
||||||
void outw(unsigned short , unsigned short ){
|
void outw(unsigned short , unsigned short ){
|
||||||
@ -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:" );
|
||||||
|
}
|
@ -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();
|
138
src/kernel/irq_table.s
Normal file
138
src/kernel/irq_table.s
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
.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
|
256
src/kernel/irs_table.s
Normal file
256
src/kernel/irs_table.s
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
/*
|
||||||
|
* Interupt handlers
|
||||||
|
*/
|
||||||
|
|
||||||
|
.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
|
||||||
|
|
||||||
|
|
||||||
|
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
|
@ -1,136 +1,128 @@
|
|||||||
#include "kernel.h"
|
#include "kernel.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(){
|
extern "C" void kernel_main (BootInfo* bootinfo) {
|
||||||
kterm_writestring("Create a test object\n");
|
init_serial();
|
||||||
};
|
//pit_initialise();
|
||||||
|
|
||||||
void Test::printMe(){
|
startSuperVisorTerminal(bootinfo);
|
||||||
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() {
|
extern "C" void early_main(unsigned long magic, unsigned long addr){
|
||||||
return inb(PORT + 5) & 0x20;
|
/**
|
||||||
}
|
* Initialize terminal interface
|
||||||
|
* NOTE: This should be done later on , the magic value should be checked first.
|
||||||
|
*/
|
||||||
|
initGDT();
|
||||||
|
kterm_init();
|
||||||
|
init_serial();
|
||||||
|
print_serial("Hello Higher half kernel!");
|
||||||
|
printf("DDDDDDDDDDDDDDDD");
|
||||||
|
return;
|
||||||
|
/**
|
||||||
|
* Check Multiboot magic number
|
||||||
|
* NOTE: Printf call should not be a thing this early on ...
|
||||||
|
*/
|
||||||
|
if (magic != MULTIBOOT_BOOTLOADER_MAGIC){
|
||||||
|
printf("Invalid magic number: 0x%x\n", magic);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
void write_serial(char a) {
|
/**
|
||||||
while (is_transmit_empty() == 0);
|
* Show a little banner for cuteness
|
||||||
|
*/
|
||||||
|
printf("|=== BarinkOS ===|\n");
|
||||||
|
printf("Kernel Begin AT(0x%x)", kernel_begin);
|
||||||
|
|
||||||
outb(PORT,a);
|
/**
|
||||||
}
|
* Use the address given as an argument as the pointer
|
||||||
|
* to a Multiboot information structure.
|
||||||
|
*/
|
||||||
|
multiboot_info_t* mbt = (multiboot_info_t*) addr;
|
||||||
|
|
||||||
int serial_received() {
|
/**
|
||||||
return inb(PORT + 5) & 1;
|
* Construct our own bootInfo structure
|
||||||
}
|
*/
|
||||||
|
BootInfo bootinfo = {};
|
||||||
char read_serial() {
|
|
||||||
while (serial_received() == 0);
|
|
||||||
|
|
||||||
return inb(PORT);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void test_serial(){
|
/*
|
||||||
/** Serial test **/
|
If we got a memory map from our bootloader we
|
||||||
kterm_writestring("Writing to COM1 serial port:");
|
should be parsing it to find out the memory regions available.
|
||||||
init_serial();
|
*/
|
||||||
write_serial('A');
|
if (CHECK_FLAG(mbt->flags, 6))
|
||||||
write_serial('B');
|
{
|
||||||
write_serial('C');
|
|
||||||
write_serial('D');
|
|
||||||
write_serial('E');
|
|
||||||
|
|
||||||
char Character_received = read_serial();
|
/*
|
||||||
kterm_writestring("\n");
|
Setup Physical memory managment
|
||||||
kterm_writestring("received from COM 1: \n");
|
*/
|
||||||
kterm_put(Character_received);
|
MemoryInfo meminfo = {};
|
||||||
|
bootinfo.memory = &meminfo;
|
||||||
|
|
||||||
kterm_writestring("\n");
|
mapMultibootMemoryMap(bootinfo.memory , mbt);
|
||||||
}
|
printf("Memory size: 0x%x bytes\n", bootinfo.memory->TotalMemory );
|
||||||
|
|
||||||
|
PhysicalMemory memAlloc = PhysicalMemory{};
|
||||||
|
memAlloc.setup(bootinfo.memory );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Mark already in use sections
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Mark kernel memory as used
|
||||||
|
printf("Kernel Begin Pointer: 0x%x, Kernel end pointer: 0x%x\n", kernel_begin , kernel_end );
|
||||||
|
|
||||||
|
multiboot_memory_map_t *mmap = (multiboot_memory_map_t*) mbt->mmap_addr;
|
||||||
|
|
||||||
|
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){
|
||||||
|
|
||||||
|
} else{
|
||||||
|
printf("allocate region: 0x%x, size : 0x%x bytes\n", (unsigned) mmap->addr,(unsigned) mmap->len );
|
||||||
|
memAlloc.allocate_region((unsigned)mmap->addr , (unsigned)mmap->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
void kernel_main (void) {
|
|
||||||
/** initialize terminal interface */
|
|
||||||
kterm_init();
|
|
||||||
|
|
||||||
/** Wrtite stuff to the screen to test the terminal**/
|
|
||||||
kterm_writestring("Hello world!\n");
|
|
||||||
kterm_writestring("We got newline support!\n");
|
|
||||||
|
|
||||||
/** Test scrolling **/
|
|
||||||
for(int i=0; i < 5; i++){
|
|
||||||
delay(500);
|
|
||||||
kterm_writestring("We have implemented terminal scrolling!\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Test objective cpp **/
|
printf("allocate region: 0x%x, size : 0x%x bytes\n", kernel_begin, kernel_end - kernel_begin );
|
||||||
kterm_writestring("Testing C++ object support\n");
|
memAlloc.allocate_region(kernel_end, kernel_end - kernel_begin);
|
||||||
auto testObject = Test();
|
|
||||||
testObject.printMe();
|
|
||||||
|
|
||||||
/** Setup the MMU **/
|
// test alloc_block
|
||||||
kterm_writestring("Starting MMU...\n");
|
/*
|
||||||
auto mmu = MMU();
|
uint8_t* memory = (uint8_t*) memAlloc.allocate_block();
|
||||||
mmu.enable();
|
printf("Got a new pointer: 0x%x\n", memory);
|
||||||
kterm_writestring("MMU enabled!\n");
|
|
||||||
|
uint8_t* memory2 = (uint8_t*) memAlloc.allocate_block();
|
||||||
|
printf("Got a new pointer: 0x%x\n", memory2);
|
||||||
|
|
||||||
|
|
||||||
|
memAlloc.free_block((void*) memory);
|
||||||
|
|
||||||
|
uint8_t* newBlockPlse = (uint8_t*) memAlloc.allocate_block();
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//memAlloc.free_block((void*) memory);
|
||||||
/** Lets start using the serial port for debugging .. **/
|
//InitializePaging();
|
||||||
// Hopefully once we go into realmode or do something that
|
//IdentityMap();
|
||||||
// cause the screen to go black.. this serial comms part will give
|
//Enable();
|
||||||
// some situational awareness
|
|
||||||
//Serial serialbus = Serial::init();
|
|
||||||
|
|
||||||
test_serial();
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//initGDT();
|
||||||
|
//init_idt();
|
||||||
|
// Enable interrupts
|
||||||
|
//asm volatile("STI");
|
||||||
|
|
||||||
|
|
||||||
|
//CheckMBT( (multiboot_info_t *) addr);
|
||||||
|
|
||||||
|
|
||||||
|
kernel_main(&bootinfo);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,34 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
extern "C" {
|
extern "C"
|
||||||
#include "../libc/include/string.h"
|
{
|
||||||
#include "arch/i386/tty/kterm.h"
|
#include "Lib/string.h"
|
||||||
}
|
}
|
||||||
#include "MMU.h"
|
|
||||||
|
#include "definitions.h"
|
||||||
|
|
||||||
|
#include "Drivers/VGA/VBE.h"
|
||||||
|
#include "Terminal/kterm.h"
|
||||||
|
|
||||||
|
#include "multiboot.h"
|
||||||
|
#include "bootinfo.h"
|
||||||
|
|
||||||
|
#include "Memory/memory.h"
|
||||||
|
#include "Memory/memoryinfo.h"
|
||||||
|
#include "Memory/paging.h"
|
||||||
|
#include "KernelLauncher/bootcheck.h"
|
||||||
|
|
||||||
|
#include "Memory/GDT/gdtc.h"
|
||||||
|
#include "Interrupts/idt/idt.h"
|
||||||
|
|
||||||
|
#include "Drivers/PIT/pit.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
#include "serial.h"
|
||||||
|
|
||||||
|
#include "time.h"
|
||||||
|
#include "SuperVisorTerminal/superVisorTerminal.h"
|
||||||
|
|
||||||
|
#define CHECK_FLAG(flags, bit) ((flags) & (1 <<(bit)))
|
||||||
|
#define PANIC(message) {return;}
|
||||||
|
|
||||||
|
|
||||||
|
45
src/kernel/linker.ld
Normal file
45
src/kernel/linker.ld
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
/* Tell where the various sections of the object files will be put in the final
|
||||||
|
kernel image. */
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 0x00100000; /* place code at 1MB mark*/
|
||||||
|
|
||||||
|
_kernel_start = .;
|
||||||
|
kernel_begin = .; /* For legacy reasons */
|
||||||
|
|
||||||
|
|
||||||
|
.multiboot.data : {
|
||||||
|
*(.multiboot.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
.multiboot.text : {
|
||||||
|
*(multiboot.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
. += 0xC0000000; /* Addresses in the following code need to be above the 3Gb mark */
|
||||||
|
|
||||||
|
|
||||||
|
.text ALIGN (4K) : AT (ADDR (.text) - 0xC0000000)
|
||||||
|
{
|
||||||
|
*(.text)
|
||||||
|
}
|
||||||
|
.rodata ALIGN (4K) : AT (ADDR (.rodata) - 0xC0000000)
|
||||||
|
{
|
||||||
|
*(.rodata)
|
||||||
|
}
|
||||||
|
.data ALIGN (4K) : AT (ADDR (.data) - 0xC0000000)
|
||||||
|
{
|
||||||
|
*(.data)
|
||||||
|
}
|
||||||
|
.bss ALIGN (4K) : AT (ADDR (.bss) - 0xC0000000)
|
||||||
|
{
|
||||||
|
*(COMMON)
|
||||||
|
*(.bss)
|
||||||
|
*(.bootstrap_stack)
|
||||||
|
}
|
||||||
|
_kernel_end = .;
|
||||||
|
kernel_end = .; /* For legacy reasons */
|
||||||
|
}
|
||||||
|
|
274
src/kernel/multiboot.h
Normal file
274
src/kernel/multiboot.h
Normal 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 */
|
75
src/kernel/serial.h
Normal file
75
src/kernel/serial.h
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Terminal/kterm.h"
|
||||||
|
#include "io.h"
|
||||||
|
#define PORT 0x3f8
|
||||||
|
static int init_serial() {
|
||||||
|
|
||||||
|
#ifdef __VERBOSE__
|
||||||
|
printf("Init Serial\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
111
src/kernel/time.cpp
Normal file
111
src/kernel/time.cpp
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
#include "time.h"
|
||||||
|
|
||||||
|
// Set by ACPI table parsing code if possible
|
||||||
|
int century_register = 0x00;
|
||||||
|
unsigned char second;
|
||||||
|
unsigned char minute;
|
||||||
|
unsigned char hour;
|
||||||
|
unsigned char day;
|
||||||
|
unsigned char month;
|
||||||
|
unsigned int year;
|
||||||
|
|
||||||
|
|
||||||
|
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 delay(int t){
|
||||||
|
volatile int i,j;
|
||||||
|
for(i=0;i<t;i++)
|
||||||
|
for(j=0;j<25000;j++)
|
||||||
|
asm("NOP");
|
||||||
|
}
|
23
src/kernel/time.h
Normal file
23
src/kernel/time.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "io.h"
|
||||||
|
#define CURRENT_YEAR 2021
|
||||||
|
|
||||||
|
|
||||||
|
extern int century_register;
|
||||||
|
extern unsigned char second;
|
||||||
|
extern unsigned char minute;
|
||||||
|
extern unsigned char hour;
|
||||||
|
extern unsigned char day;
|
||||||
|
extern unsigned char month;
|
||||||
|
extern unsigned int year;
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
cmos_address = 0x70,
|
||||||
|
cmos_data = 0x71
|
||||||
|
};
|
||||||
|
|
||||||
|
int get_update_in_progress_flag();
|
||||||
|
unsigned char get_RTC_register();
|
||||||
|
void read_rtc();
|
||||||
|
void delay(int t);
|
27
src/kernel/timer.cpp
Normal file
27
src/kernel/timer.cpp
Normal 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
6
src/kernel/timer.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void init_timer (uint32_t frequency);
|
@ -1,8 +0,0 @@
|
|||||||
#include <stddef.h>
|
|
||||||
size_t strlen(const char* str){
|
|
||||||
size_t len = 0;
|
|
||||||
while(str[len]){
|
|
||||||
len++;
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
|
21
todo.md
Normal file
21
todo.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# TODO list
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
This list keeps me focused and organised so I don't forget what
|
||||||
|
needs to be done. It is a expansion on the features markdown file which describes the features. Here I put things I need to remember
|
||||||
|
to do on a more in depth level.
|
||||||
|
|
||||||
|
## --
|
||||||
|
[ ] Setup paging \
|
||||||
|
[ ] HELP command
|
||||||
|
[ ] Setup a proper HEAP \
|
||||||
|
[ ] Setup a proper Stack \
|
||||||
|
[ ] Setup KMalloc and KFree \
|
||||||
|
[ ] Merge Functioning Feature branches into sandboxKernelDev \
|
||||||
|
[ ] Remove merged feature branches \
|
||||||
|
[ ] Merge sandboxKernelDev with dev \
|
||||||
|
[ ] Remove sandboxKernelDev branch \
|
||||||
|
[ ] Implement proper virtual filesystem
|
||||||
|
|
Reference in New Issue
Block a user