Compare commits

26 Commits

Author SHA1 Message Date
13e9beea79 KERNEL: Implementing VMM & cleaning up
Folders now are alll lower case

Started working on the implementation of the Virtual memory manager. Implemented allocate and free page funtionality for as far as I can atm.

Implemented the
2022-09-01 20:16:16 +02:00
9893a0bd17 KERNEL: Cleanup
Removing quite a few unnecessary parts.
2022-09-01 17:02:04 +02:00
a70ae5ca31 KERNEL: Mapping the bios region ( below 1Mib)
Keyboard.h: remove the incorrect use of typedef

PhysicalMemoryManager.cpp:
Map the Bios region as used. This prevents us from allocation the area used by the bios
2022-09-01 16:42:56 +02:00
15443601a6 Adding dev-scripts (Without much content) .. this can later help setting up the projects on other pc's. 2022-09-01 16:15:24 +02:00
c90e90bd84 Moving the images from the repo into the disk folder 2022-09-01 16:15:24 +02:00
a5e7fdd07e KERNEL: Physical Page Frame allocation
Rewriting the setup to allow for physical memory allocation again to work.
2022-09-01 16:15:10 +02:00
59ba41f3d2 Multiboot Memory Map get copied to a "safe" place 2022-08-23 21:35:19 +02:00
5051b8903c Divided the kernel into seperate distinct phases
The first stage after GRUB will be Pre-Kernel. This stage will organize the
information we receive from the bootloader. (in our case that will be grub)

The second stage is for now called early_main. The program will at this
point already be running in virtual higher-half / higher-quarter address space.
The goal of the second stage is to set up the kernel in such a way that we are
ready to jump in to usermode.

The third stage is for now called kernel_main. This stage will jump us into
usermode and load the startup programs.

- Added a GRUB entry for tests
- Started writing the pre-kernel stage
- Removed knowledge of multiboot from early_main
- Edited the linkerscript to link variables in pre-kernel to
	lower address space. ( from 1MB and up)
2022-08-22 21:16:34 +02:00
0f0fc9f252 Adding a skeleton for the memory management code
Moved the PMM away from being object orientated as it is just plain annoying
renamed src folder to source
Set timeout to 5 seconds in the grub config
2022-08-21 21:18:53 +02:00
e70f56a005 Improving the memory mapping boot code
Removed the need to map the extra MBI structure in as a seperate pagetable
Renaming / Restructuring the memory folder
2022-08-21 21:15:15 +02:00
560dd64e64 Kernel is working in its full former glory as a higher half kernel 2022-08-19 23:44:38 +02:00
9436e6e033 End of the day cleanup.
* Added symbol files to .gitignore
* Improved text in #PG and #GP handlers
* Added the printing of the multiboot structure address and the magic value
* Added page fault screenshot to readme
2022-08-19 01:05:10 +02:00
d280aa0584 Page faults and protetion faults will now hang with a helpful message
to explain what is going on.

I removed previously set barriers from the code to load
the kernel further.
2022-08-19 00:44:52 +02:00
7d6c823d79 Basic Launch of Higher half kernel
We now can launch the kernel at 0xC0000000 (or 3 GiB mark) with paging enabled.
A lot of early main is currently not executed to keep debugging as simple as possible
during the initial testing of higher half kernel loading.

A lot of the implementation is straight from wiki.osdev.org/Higher_Half_x86_Bare_Bones. Thanks to all the folks
who keep that wiki updated, its really resourceful.
2022-08-18 01:26:49 +02:00
bbfea39c23 Fixing include paths for new structure
Removed non-sensical libc folder from project
2022-08-17 14:57:50 +02:00
3b3e2597a1 Restructering Kernel folder before moving to higher half kernel
The boot up process will be changed somewhat dramatically, therefor a
restructering of the kernel seems as a good starting point.
2022-08-17 14:29:26 +02:00
0b0e37b762 Paging cleanup, more cpu testing and psuedo code for higher half kernel 2022-08-17 14:17:58 +02:00
388ac8e7f9 Added checks to be sure paging is actually enabled on the cpu.
- Made a special assembly file to put CPU check function in. E.G. functions to get the state of
	specific registers

In this case I have created a simple assembly function to get the contents of the CR0 register.
With the help of the c++ preprocessor the value can then be used to check if certains bits are set.
For example to check if the PG (paging) bit is set, indicating that paging is enabled for the
processor.
2022-08-16 19:06:16 +02:00
9172da075a Added identity paging basics
Followed wiki.osdev.org/Setting_Up_Paging
2022-08-15 19:51:22 +02:00
23c68d9863 Setup paging function signatures... Ready to be implemented. 2022-03-18 22:09:04 +01:00
b4cff3e667 Basic block allocation for physical memory allocation.
- 1 block = 4096 bytes : because this will make page fault handling possibly
somewhat easier

- 1 byte in the bitmap = 8 blocks of physical memory

unsure if the allocation is perfect ... guess i'll find out some day if this is actually correct.

The bitmap needs 16kb to keep track of 2gb of physical memory. Seems a decent percentage to me.
2022-02-26 20:55:34 +01:00
7330b81a10 Started definition file for a CMOS driver 2021-12-29 16:28:55 +01:00
97606dbf71 Clean up of debugging logs and new commands.
As this project grows it becomes important to keep things properly organised.
In this commit I've put some effort into making the kernel.cpp file more consise and thus improve its
readability.
Certain parts of the code have gotten their own definition file where before it
was only a header file.

- Moving the Supervisor Terminal into its own definition file.
- Subtracting debugging messages with preprocessor ifdef's
- Time and Date is now not just a header but has its own proper definition file
- Banner is displayed when booting up
- Terminal has a couple new commands

	Commmand		Description
	=================|||||===================================================
	DATE (was TIME)		Displays the curren time, date and ticks
	VERSION			Displays system version information
	MEMORY			Displays memory information
2021-12-29 16:15:18 +01:00
7496299761 Basic Intel Exceptions
Any interrupt thrown for any Intel defined Exception is not only being caught but
displays an appropriate message to the screen.

Changes made in src/kernel/idt/idt.cpp
2021-12-28 19:54:10 +01:00
0d8ef065e0 Interactive supervisor mode
To ease the pain of debuggin I can now interact with the system through a
very simplistic terminal. Hopefully things can be tested more easily by activating
the piece through a simple command. The max characters for a command is 10.

To achieve this I have had to make the following changes.
- Changed IRQ to update a global status variable
- Added a standalone keyboard driver with getKey functions
- Changed the main kernel loop to display a prompt
- Added a strncmp function to the clib/string file
2021-12-28 19:52:48 +01:00
88cc1d75bb Re-enabled interrupts from keyboard, Enabled and configured the PIT to throw interrupts at a regular interval 2021-12-20 21:53:57 +01:00
90 changed files with 1855 additions and 979 deletions

2
.gitignore vendored
View File

@ -5,4 +5,6 @@ isodir/
root/ root/
*.iso *.iso
*.img *.img
*.sym

View File

@ -3,11 +3,11 @@ 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)/PhysicalMemoryManager.o $(BUILD_DIR)/io.o $(BUILD_DIR)/PageDirectory.o $(BUILD_DIR)/gdtc.o $(BUILD_DIR)/idt.o $(BUILD_DIR)/pic.o $(BUILD_DIR)/string.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 $(BUILD_DIR)/prekernel.o $(BUILD_DIR)/cpu.o
SRC_DIR = src SRC_DIR = source
BUILD_DIR = build BUILD_DIR = build
CRTBEGIN_OBJ = $(shell $(CC) $(CFLAGS) -print-file-name=crtbegin.o) CRTBEGIN_OBJ = $(shell $(CC) $(CFLAGS) -print-file-name=crtbegin.o)
@ -23,8 +23,6 @@ all: clean build
build: build_kernel iso build: build_kernel iso
clean_iso: clean_iso:
if [[ -a isodir/boot ]] ; then rm root/boot -rd ; fi if [[ -a isodir/boot ]] ; then rm root/boot -rd ; fi
if [ -f build/barinkOS.iso ] ; then rm build/barinkOS.iso ; fi if [ -f build/barinkOS.iso ] ; then rm build/barinkOS.iso ; fi
@ -32,15 +30,19 @@ clean_iso:
iso: clean_iso clean build iso: clean_iso clean build
mkdir -p root/boot/grub mkdir -p root/boot/grub
cp build/myos.bin root/boot/myos.bin cp build/myos.bin root/boot/myos.bin
cp src/grub.cfg root/boot/grub/grub.cfg cp source/grub.cfg root/boot/grub/grub.cfg
grub-mkrescue -o build/barinkOS.iso root grub-mkrescue -o build/barinkOS.iso root
test: run: all
$(EMULATOR) -kernel $(BUILD_DIR)/myos.bin -serial stdio -vga std -monitor stdio -display gtk -m 2G -cpu core2duo $(EMULATOR) -cdrom build/barinkOS.iso -serial stdio -vga std -display gtk -m 2G -cpu core2duo
debug: all
objcopy --only-keep-debug build/myos.bin kernel.sym
$(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//linker.ld -o $(BUILD_DIR)/myos.bin \
-ffreestanding -O2 -nostdlib $(OBJ_LINK_LIST) -lgcc -ffreestanding -ggdb -Og -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
@ -53,10 +55,10 @@ $(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:
$(CPP) -c $(SRC_DIR)/kernel/tty/kterm.cpp -o $(BUILD_DIR)/kterm.o $(CFLAGS) -fno-exceptions -fno-rtti $(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//boot.S -o $(BUILD_DIR)/boot.o $(AS) $(SRC_DIR)/kernel/boot/boot.s -o $(BUILD_DIR)/boot.o
$(BUILD_DIR)/crti.o: $(BUILD_DIR)/crti.o:
$(AS) $(SRC_DIR)/kernel/crti.s -o $(BUILD_DIR)/crti.o $(AS) $(SRC_DIR)/kernel/crti.s -o $(BUILD_DIR)/crti.o
@ -67,21 +69,43 @@ $(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)/PageDirectory.o:
$(CPP) -c $(SRC_DIR)/kernel/memory/PageDirectory.cpp -o $(BUILD_DIR)/PageDirectory.o $(CFLAGS) -fno-exceptions -fno-rtti
$(BUILD_DIR)/idt.o: $(BUILD_DIR)/idt.o:
$(CPP) -c $(SRC_DIR)/kernel/idt/idt.cpp -o $(BUILD_DIR)/idt.o $(CFLAGS) -fno-exceptions -fno-rtti $(CPP) -c $(SRC_DIR)/kernel/interrupts/idt/idt.cpp -o $(BUILD_DIR)/idt.o $(CFLAGS) -fno-exceptions -fno-rtti
$(BUILD_DIR)/gdtc.o: $(BUILD_DIR)/gdtc.o:
$(CPP) -c $(SRC_DIR)/kernel/gdt/gdtc.cpp -o $(BUILD_DIR)/gdtc.o $(CFLAGS) -fno-exceptions -fno-rtti $(CPP) -c $(SRC_DIR)/kernel/memory/gdt/gdtc.cpp -o $(BUILD_DIR)/gdtc.o $(CFLAGS) -fno-exceptions -fno-rtti
$(BUILD_DIR)/pic.o: $(BUILD_DIR)/pic.o:
$(CPP) -c $(SRC_DIR)/kernel/pic/pic.cpp -o $(BUILD_DIR)/pic.o $(CFLAGS) -fno-exceptions -fno-rtti $(CPP) -c $(SRC_DIR)/kernel/drivers/pic/pic.cpp -o $(BUILD_DIR)/pic.o $(CFLAGS) -fno-exceptions -fno-rtti
$(BUILD_DIR)/string.o: $(BUILD_DIR)/string.o:
$(CC) -c $(SRC_DIR)/libc/include/string.c -o $(BUILD_DIR)/string.o $(CFLAGS) -std=gnu99 $(CC) -c $(SRC_DIR)/kernel/lib/string.c -o $(BUILD_DIR)/string.o $(CFLAGS) -std=gnu99
$(BUILD_DIR)/PhysicalMemoryManager.o:
$(CPP) -c $(SRC_DIR)/kernel/memory/PhysicalMemoryManager.cpp -o $(BUILD_DIR)/PhysicalMemoryManager.o $(CFLAGS) -fno-exceptions -fno-rtti $(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/PhysicalMemoryManager.cpp -o $(BUILD_DIR)/memory.o $(CFLAGS) -fno-exceptions -fno-rtti
$(BUILD_DIR)/paging.o:
$(CPP) -c $(SRC_DIR)/kernel/memory/VirtualMemoryManager.cpp -o $(BUILD_DIR)/paging.o $(CFLAGS) -fno-exceptions -fno-rtti
$(BUILD_DIR)/prekernel.o:
$(CPP) -c $(SRC_DIR)/kernel/prekernel/prekernel.cpp -o $(BUILD_DIR)/prekernel.o $(CFLAGS) -fno-exceptions -fno-rtti
$(BUILD_DIR)/cpu.o:
$(CPP) -c $(SRC_DIR)/kernel/cpu.cpp -o $(BUILD_DIR)/cpu.o $(CFLAGS) -fno-exceptions -fno-rtti

View File

@ -16,10 +16,16 @@ W.I.P - Working on interrupt handling
![Multiboot integration](screenshots/multiboot.png) \ ![Multiboot integration](screenshots/multiboot.png) \
Multiboot information can be read by the kernel. Multiboot information can be read by the kernel.
![Page faulting](screenshots/PageFault.png) \
Enabled paging and am getting page faults!
________________________ ________________________
### 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

View File

@ -1,29 +1,30 @@
# TODO list # TODO list
## Start planning ## Basics
<input type="checkbox" checked/> Setup Cross-Compiler \ <input type="checkbox" checked/> Setup Cross-Compiler \
<input type="checkbox" checked/> Multiboot to kernel \ <input type="checkbox" checked/> Multiboot to kernel \
<input type="checkbox" checked/> Printing string to the screen \ <input type="checkbox" checked/> Printing string to the screen \
<input type="checkbox" checked/> Printing values/numbers to the screen (a.k.k itoa) \ <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/> Extend Multiboot implementation \
<input type="checkbox" checked/> Output to serial port \ <input type="checkbox" checked/> Output to serial port \
<input type="checkbox" checked/> Move to protected mode \ <input type="checkbox" checked/> Move to protected mode \
<input type="checkbox" checked/> Enabel CMOS clock \ <input type="checkbox" checked/> Enabel CMOS clock \
<input type="checkbox" /> Time measurement (PIC &| PIT) \ <input type="checkbox" checked/> Time measurement (PIC &| PIT) \
<input type="checkbox" /> Detect CPU speed \ <input type="checkbox" /> Detect CPU speed \
<input type="checkbox" checked/> Interrupt / exception system (API) \ <input type="checkbox" checked/> Interrupt / exception system (API) \
<input type="checkbox" checked/> PCI support \
<input type="checkbox" checked/> Plan your memory map (virtual, and physical) : decide where you want the data to be. \ <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" /> 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" /> Enable SIMD Extensions (SSE)
## Other features I am thinking of: <input type="checkbox" /> Hardware Management system
<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" checked/> Memory Management (MMU)
<input type="checkbox" /> Preemptive multi tasking \ <input type="checkbox" /> Preemptive multi tasking \
<input type="checkbox" /> Processes \ <input type="checkbox" /> Processes \
<input type="checkbox" /> Threads <input type="checkbox" /> Threads
@ -32,9 +33,11 @@
<input type="checkbox" /> POSIX compliance (partially) \ <input type="checkbox" /> POSIX compliance (partially) \
<input type="checkbox" /> RPC - for interprocess communication \ <input type="checkbox" /> RPC - for interprocess communication \
<input type="checkbox" /> Sync primitives - Semaphores, Mutexes, spinlocks et al. \ <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" /> ACPI support \
<input type="checkbox" /> ATAPI support \
## Optional
<input type="checkbox" /> Basic Window server/client \ <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 <input type="checkbox" /> EXT2 Filesystem
<input type="checkbox" /> USTAR Filesystem \

BIN
images/BarinkOS.png (Stored with Git LFS)

Binary file not shown.

BIN
images/BarinkOS_logo(standard).svg (Stored with Git LFS)

Binary file not shown.

BIN
images/BarinkOS_logo.svg (Stored with Git LFS)

Binary file not shown.

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

Binary file not shown.

BIN
screenshots/must frustrating bug ever.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,3 @@
#!/bin/bash
cmake -DLLVM_ENABLE_PROJECTS="clang-tools-extra" -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles" ../llvm

View File

@ -0,0 +1,5 @@
#!/bin/bash
# Run clang-tidy

9
source/grub.cfg Normal file
View File

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

40
source/kernel/bitmap.h Normal file
View 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;
}

112
source/kernel/boot/boot.s Normal file
View File

@ -0,0 +1,112 @@
.include "./source/kernel/boot/multiboot.s"
/*
* 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
.globl boot_page_directory
boot_page_directory:
.skip 4096
.globl boot_page_table
boot_page_table:
.skip 4096
.globl multiboot_page_table
multiboot_page_table:
.skip 4096
# More page tables may be required
# Entry point
.section .multiboot.text, "a"
.global _start
.type _start, @function
_start:
/* push the pointer to the Multiboot information structure*/
pushl %ebx
/* push the magic value */
pushl %eax
call prekernelSetup
# Get physical address of the boot_page_table
movl $(boot_page_table - 0xC0000000), %edi
# Map address 0
movl $0, %esi
1:
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
# 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
call early_main
cli
1: hlt
jmp 1b
.include "./source/kernel/memory/gdt/gdt.s"
.include "./source/kernel/irs_table.s"
.include "./source/kernel/irq_table.s"
.include "./source/kernel/interrupts/idt/idt.s"

View File

@ -0,0 +1,15 @@
/*
* 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

39
source/kernel/cpu.cpp Normal file
View File

@ -0,0 +1,39 @@
#include "cpu.h"
uint32_t GetEFLAGS()
{
uint32_t EFLAGS = 0;
asm volatile ("pushfl;" "movl 4(%%esp), %%edx" : "=d"(EFLAGS));
return EFLAGS;
}
uint32_t GetCR0()
{
uint32_t cr0_value;
asm volatile ("movl %%cr0, %%edx" : "=d"(cr0_value));
return cr0_value;
}
uint32_t GetCR2(){
uint32_t cr2_value;
__asm__ volatile("movl %%cr2, %%edx": "=d"(cr2_value));
return cr2_value;
}
uint32_t GetCR3(){
uint32_t cr3_value;
__asm__ volatile("movl %%cr3, %%edx": "=d"(cr3_value));
return cr3_value;
}
uint32_t GetCR4(){
uint32_t cr4_value;
__asm__ volatile("movl %%cr4, %%edx": "=d"(cr4_value));
return cr4_value;
}

74
source/kernel/cpu.h Normal file
View File

@ -0,0 +1,74 @@
#pragma once
#include <stdint.h>
/*
Based on Intel specifications.
C++ interface for the cpu.s assembly file.
©Nigel Barink - 2022
*/
/*
* EFLAGS FUNCTIONS
*/
uint32_t GetEFLAGS();
/*
* CONTROL_REGISTER_0 FUNCTIONS
*/
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
*/
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)
/*
* CONTROL_REGISTER_2 FUNCTIONS
*/
uint32_t GetCR2();
/*
* CONTROL_REGISTER_3 FUNCTIONS
*/
uint32_t GetCR3();

View File

@ -0,0 +1,9 @@
#pragma once
/**
* Kernel definitions
*/
#define __DEBUG__ false
#define KERNEL_VERSION 0
#define ARCHITECTURE "I386"

View 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
}
}

View File

@ -1,5 +1,5 @@
#pragma once #pragma once
#include "../io.h" #include "../../io.h"
#define PIC1 0x20 /* IO base address for master PIC */ #define PIC1 0x20 /* IO base address for master PIC */
#define PIC2 0xA0 /* IO base address for slave PIC */ #define PIC2 0xA0 /* IO base address for slave PIC */

View File

@ -0,0 +1,54 @@
#include "pit.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()
{
}

View File

@ -0,0 +1,19 @@
#pragma once
#include <stdint.h>
#include "../../io.h"
#include "../../terminal/kterm.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();

View 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 ;
}

View File

@ -0,0 +1,34 @@
#pragma once
#include <stdint.h>
#include "../../terminal/kterm.h"
enum ScanCodeSet {
None = 0,
ScanCodeSet1 = 1,
ScanCodeSet2 = 2,
ScanCodeSet3 = 3,
};
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();

View File

View File

@ -0,0 +1,8 @@
#pragma once
#include "../../vfs/File.h"
class FAT16 : File {
public:
};

View File

@ -0,0 +1,395 @@
#include "idt.h"
#include "../../drivers/pit/pit.h"
#include "../../drivers/ps-2/keyboard.h"
#include "../../cpu.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) {
uint32_t FaultingAddress;
//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("Accessing memory caused a general protectuion exception.\n");
printf("Fault due to entry at index: %d", (regs.err_code >> 3 & 0xFFF ) );
if(regs.err_code & 0x3 >> 1 == 0 ){
printf("* Index references GDT");
}
if(regs.err_code & 0x3 >> 1 == 1 ){
printf("* Index references IDT");
}
if(regs.err_code & 0x3 >> 1 == 2 ){
printf("* Index references LDT");
}
if(regs.err_code & 0x3 >> 1 == 4 ){
printf("* Index references IDT");
}
if( regs.err_code & 0x1)
{
printf("* Originated externally!");
}
__asm__("cli;" "1: hlt;" "jmp 1b;");
break;
case 14:
// Page Fault Exception #PF
printf("#PF\n");
FaultingAddress = GetCR2();
printf("Accessing the linear address 0x%x resulted in a page fault!\n\n", FaultingAddress);
// Error code of 32 bits are on the stack
// CR2 register contains the 32-bit linear virtual address that generated the exception
// See Intel Software Developers manual Volume 3A Part 1 page 236 for more info
#define PF_ERR_PRESENT_BIT 0x1
#define PF_ERR_WRITE_BIT 0x2
#define PF_ERR_USER_BIT 0x3
#define PF_ERR_RESERVERD_WRITE_BIT 0x4
#define PF_ERR_INSTRUCTION_FETCH_BIT 0x5
#define PF_ERR_PROTECTION_KEY_BIT 0x6
#define PF_ERR_SHADOW_STACK_BIT 0x7
#define PF_ERR_SOFTWARE_GUARD_EXTENSION_BIT 0xE
printf("REASON: \n\n");
if (regs.err_code & PF_ERR_PRESENT_BIT ){
printf("* Page protection violation!\n");
} else{
printf("* Page not-present!\n");
}
if(regs.err_code & PF_ERR_WRITE_BIT){
printf("* Write access violation!\n");
} else{
printf("* Read access violation!\n");
}
if(regs.err_code & PF_ERR_USER_BIT){
printf("* Violation from user-space (CPL=3)\n");
}
if(regs.err_code & PF_ERR_INSTRUCTION_FETCH_BIT){
printf("* Caused by an instruction fetch. \n");
}
/*
Check the error code to figure out what happened here
*/
__asm__("cli;" "1: hlt;" "jmp 1b;");
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);
}

View File

@ -1,11 +1,11 @@
#pragma once #pragma once
#include "stdint.h" #include <stdint.h>
#include "stddef.h" #include <stddef.h>
#include "../vga/colors.h" #include "../../drivers/vga/colors.h"
#include "../pic/pic.h" #include "../../drivers/pic/pic.h"
#include "../tty/kterm.h" #include "../../terminal/kterm.h"
extern "C" { extern "C" {

View File

@ -22,7 +22,7 @@ unsigned int inl_p(unsigned short ){
} }
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 ){

122
source/kernel/kernel.cpp Normal file
View File

@ -0,0 +1,122 @@
#include "kernel.h"
extern "C" void early_main()
{
kterm_init();
initGDT();
init_serial();
print_serial("Hello Higher half kernel!\n");
init_idt();
// Enable interrupts
asm volatile("STI");
/*
* Show a little banner for cuteness
*/
printf("|=== BarinkOS ===|\n");
printf("Kernel End Addr: 0x%x\n" , &kernel_end );
uint32_t PageDirectoryEntryIndex = ((uint32_t)&kernel_end + KERNEL_BASE_ADDR ) >> 22 ;
uint32_t PageTableEntryIndex = (((uint32_t)&kernel_end + KERNEL_BASE_ADDR) >> 12) & 0x1FFF;
printf("Kernel End PDE: %d, PTE: %d\n" , PageDirectoryEntryIndex, PageTableEntryIndex);
uint32_t BootInfoStruct = BootInfoBlock_pptr + 0xC0000000;
printf("Addr BootInfostruct: 0x%x\n", BootInfoStruct);
uint32_t PageDirectoryEntryIndex2 = (BootInfoStruct ) >> 2 ;
uint32_t PageTableEntryIndex2 = (BootInfoStruct >> 12) & 0x1FFF;
printf("PDE: 0x%x, PTE: 0x%x\n", PageDirectoryEntryIndex2 , PageTableEntryIndex2 );
BootInfoBlock* BootInfo = (BootInfoBlock*) ( BootInfoBlock_pptr + 0xC0000000 );
printf("Size of BootInfoBlock: %d bytes\n", sizeof(BootInfoBlock));
printf("Bootloader information:\n");
if( BootInfo->ValidELFHeader )
{
printf("- Valid ELF Header is available!\n");
}
if(BootInfo->EnabledVBE)
{
printf("- VBE graphics mode is available!\n");
}
if(BootInfo->ValidSymbolTable)
{
printf("- Valid Symbol Table available at 0x%x.\n Tab Size: %d, str Size: %d\n", BootInfo->SymbolTableAddr, BootInfo->SymbolTabSize, BootInfo->SymbolStrSize);
}
if(BootInfo->PhysicalMemoryMapAvailable)
{
printf("- Physical Memory Map available!\n");
printf("MemoryInfoheap size : %d bytes\n", BootInfo->map_size);
// Print the memory regions
MemoryInfoBlock* currentBlock = (MemoryInfoBlock*) ((uint32_t)BootInfo->MemoryMap + KERNEL_BASE_ADDR) ;
printf( "Starting address: 0x%x\n", currentBlock);
while( (uint32_t)currentBlock->next != 0x0 )
{
printf("CurrentBlock: 0x%x \n", (uint32_t ) currentBlock );
if(IS_AVAILABLE_MEM(currentBlock->type)){
//printf("AVAILABLE RAM\n");
}
else if(IS_ACPI_MEM(currentBlock->type)){
//printf("ACPI MEMORY\n");
}
else if(IS_RESERVED_MEM(currentBlock->type)){
// printf("RESERVED MEMORY\n");
}
else if(IS_NVS_MEMORY(currentBlock->type)){
// printf("NVS MEMORY \n");
}
else if(IS_BADRAM_MEMORY(currentBlock->type)){
// printf("BADRAM MEMORY \n");
}
else {
// printf("(TYPE 0x%x )TYPE NOT SPECIFIED\n", currentBlock->type);
}
currentBlock = (MemoryInfoBlock*) ((uint32_t)currentBlock->next + KERNEL_BASE_ADDR );
}
printf("Starting physical memory management setup\n");
// Setup PhysicalMemoryManagement
SetupPhysicalMemoryManager(BootInfo);
}
printf("Enable Protected mode and jump to kernel main\n");
asm volatile("mov %cr0, %eax ");
asm volatile("or $1, %eax");
asm volatile("mov %eax, %cr0"); // re-enable protected mode ?
kernel_main();
}
void PhysicalMemoryAllocatorTest(){
#ifdef UNIT_TESTS
// Small test!
void* block = allocate_block();
void* block2 = allocate_block();
printf("Allocated addresss 1: 0x%x 2: 0x%x\n", (uint32_t)block ,(uint32_t)block2);
free_block(block);
free_block(block2);
void* block3 = allocate_block();
printf("Allocated addresss 3: 0x%x\n", (uint32_t)block3);
free_block(block3);
#endif
}
extern "C" void kernel_main () {
pit_initialise();
startSuperVisorTerminal();
}

38
source/kernel/kernel.h Normal file
View File

@ -0,0 +1,38 @@
#pragma once
extern "C"
{
#include "lib/string.h"
}
#include "definitions.h"
#include "drivers/vga/VBE.h"
#include "terminal/kterm.h"
#include "memory/PhysicalMemoryManager.h"
#include "memory/VirtualMemoryManager.h"
#include "memory/gdt/gdtc.h"
#include "interrupts/idt/idt.h"
#include "drivers/pit/pit.h"
#include "io.h"
#include "cpu.h"
#include "serial.h"
#include "time.h"
#include "supervisorterminal/superVisorTerminal.h"
#include "prekernel/bootstructure.h"
#define CHECK_FLAG(flag, bit) ( flag & (1 << bit ))
#define PANIC(message) {return;}
void map_multiboot_info_structure(unsigned long addr);
extern "C" void kernel_main ();
extern "C" uint32_t boot_page_directory;
extern "C" uint32_t multiboot_page_table;
const uint32_t KERNEL_BASE_ADDR = 0xC0000000;

View File

@ -1,8 +1,8 @@
inline void* memset (void* ptr, int value, size_t num){ inline void* memset (void* ptr, int value, size_t num){
for( int i = 0; i < num; i++ ) for( int i = 0; i < num; i++ )
{ {
int* data = (int*)ptr+ i; unsigned char* data = (unsigned char*)ptr+ i;
*data = value; *data = (unsigned char)value;
} }
return ptr; return ptr;
} }

View 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;
}

View File

@ -1,3 +1,6 @@
#pragma once #pragma once
#include <stddef.h> #include <stddef.h>
size_t strlen(const char* str); size_t strlen(const char* str);
int strncmp ( const char* str1, const char* str2, size_t num );

46
source/kernel/linker.ld Normal file
View File

@ -0,0 +1,46 @@
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)
*prekernel.o(.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 */
}

View File

@ -0,0 +1,52 @@
#include "KernelHeap.h"
// Size of heap meta data is 5 bytes
struct heap_block{
uint8_t Used;
uint32_t Size;
}
uint32_t heap_size;
heap_block* start ;
void* malloc(size_t size)
{
printf("Received request for %d bytes of memory", size);
heap_block* current = start;
// look for a free block
while(current < start + heap_size)
{
if(current->size >= size && current->Used == false )
{
// We found a spot
// Set the spot to in-use
current->Used = false;
// return the free address
// NOTE: added an offset from the initial address to accomodate for
// meta-data.
return current + sizeof(heap_block);
}
current += current->Size + sizeof(heap_block);
}
// If we are here we need more memory so we should
// probably ask the VMM for more
// TODO: ask for more memory | Extend kernel heap
}
void free(void* addr)
{
// clear the free boolean that corresponds to this adddress
// This should be fairly simple
heap_block* allocatedBlock = addr - sizeof(heap_block);
allocate_block->Used = false;
}
void initHeap()
{
}

View File

@ -0,0 +1,9 @@
#pragma once
#include <stdint.h>
void initHeap();
void* malloc (size_t size );
void free(void* addr);

View File

@ -0,0 +1,143 @@
#include "./PhysicalMemoryManager.h"
PhysicalMemoryManagerInfoBlock* PMMInfoBlock;
extern uint32_t* boot_page_directory;
extern uint32_t* boot_page_table;
const uint32_t KERNEL_OFFSET = 0xC0000000;
void SetupPhysicalMemoryManager( BootInfoBlock* Bootinfo) {
// NOTE: Physical memory map will override the boot info for now!
PMMInfoBlock = (PhysicalMemoryManagerInfoBlock*) (&BootInfoBlock_pptr + KERNEL_OFFSET );
printf("Setting up physical memory infoblock (0x%x) \n", (uint32_t)&PMMInfoBlock);
/*
Every byte contains 8 pages
A page is 4096 kib
Every block (1 bit) represent an page
*/
// Calculate the maximum number of blocks
printf("Maxblocks at address(0x%x)\n" , (uint32_t)&(PMMInfoBlock->max_blocks));
int maximum_blocks = (uint32_t)Bootinfo->MemorySize / BLOCK_SIZE / 8;
printf("Set bitmap block maximum: %d\n", maximum_blocks);
PMMInfoBlock->max_blocks = maximum_blocks;
printf("Set used blocks to zero\n");
PMMInfoBlock->used_blocks = 0;
printf("Determine memory bit map address");
// put the map after the gdt
PMMInfoBlock->memoryBitMap = (uint32_t*) ( 0xC010b100) ;
printf("Maximum num blocks: %d \n",PMMInfoBlock->max_blocks);
//Size of memory map
uint32_t memMap_size = PMMInfoBlock->max_blocks / 8;
printf("Memory map size: %d\n", memMap_size);
printf("Address of memory map 0x%x\n", PMMInfoBlock->memoryBitMap);
// Set all places in memory as free
memset(PMMInfoBlock->memoryBitMap, 0xFF, memMap_size );
// Loop over memory map and allocate physical locations
// that are already in use
MemoryInfoBlock* currentBlock = (MemoryInfoBlock*) ((uint32_t)Bootinfo->MemoryMap + KERNEL_OFFSET) ;
printf("Starting address: 0x%x\n", currentBlock);
while( (uint32_t) currentBlock->next != 0x0)
{
if(IS_AVAILABLE_MEM(currentBlock->type)){
printf("skip!\n");
} else {
printf("allocate region 0x%x of size 0x%x\n" , currentBlock->Base_addr, currentBlock->Memory_Size);
allocate_region((uint32_t) currentBlock->Base_addr, currentBlock->Memory_Size);
}
currentBlock = (MemoryInfoBlock*) ((uint32_t)currentBlock->next + KERNEL_OFFSET );
}
uint32_t kernel_size = ((uint32_t)&kernel_end - (uint32_t)&kernel_begin ) - KERNEL_OFFSET;
printf("kernel size in memory: 0x%x\n", kernel_size);
allocate_region((uint32_t)&kernel_begin, kernel_size);
printf("allocate BIOS region\n");
allocate_region (0x0000000, 0x00100000);
}
// NOTE: This can only give blocks of 4kb at a time!
// We might at some point want to allocate multiple blocks at once.
void* allocate_block() {
uint8_t blocks_available = PMMInfoBlock->max_blocks - PMMInfoBlock->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(PMMInfoBlock->memoryBitMap, PMMInfoBlock->max_blocks / 8 );
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(PMMInfoBlock->memoryBitMap, free_block_index);
// Increase the used_block count!
PMMInfoBlock->used_blocks++;
printf("used blocks: 0x%x\n", PMMInfoBlock->used_blocks);
// return the pointer to the physical address
return (void*) (BLOCK_SIZE * free_block_index);
}
void 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(PMMInfoBlock->memoryBitMap, index);
PMMInfoBlock->used_blocks--;
printf("used blocks: 0x%x, after free\n", PMMInfoBlock->used_blocks);
}
void 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 ;
for( int i = 0; i < NumberOfBlocksToAllocate; i++)
{
bitmap_unset(PMMInfoBlock->memoryBitMap, startBlock+ i);
PMMInfoBlock->used_blocks++;
}
}
void deallocate_region(uint32_t StartAddress , uint32_t size ) {
// reverse of what happened in allocate_region
int NumberOfBlocks = (size / 1024) / 4 / 8 + 1;
int startBlock = (StartAddress / 1024) / 4 / 8;
for(int i = 0; i < NumberOfBlocks; i++)
{
bitmap_set(PMMInfoBlock->memoryBitMap, startBlock + i);
PMMInfoBlock->used_blocks --;
}
}

View File

@ -0,0 +1,26 @@
#pragma once
#include <stddef.h>
#include "../prekernel/bootstructure.h"
#include "../terminal/kterm.h"
#include "../lib/mem.h"
#include "../bitmap.h"
// Asumming i386 for now!
#define BLOCK_SIZE 4092
#define IS_ALIGNED(addr, align) !((addr) & ~((align) - 1))
#define ALIGN(addr, align) (((addr) & ~((align) - 1 )) + (align))
struct PhysicalMemoryManagerInfoBlock
{
uint32_t* memoryBitMap;
uint32_t pmmap_size;
uint32_t max_blocks;
int used_blocks;
};
void SetupPhysicalMemoryManager(BootInfoBlock* memory);
void free_block(void* ptr);
void* allocate_block();
void allocate_region(uint32_t, uint32_t);
void deallocate_region(uint32_t , uint32_t );

View File

@ -0,0 +1,73 @@
#include "VirtualMemoryManager.h"
extern uint32_t boot_page_directory[1024] ;
extern uint32_t boot_page_table[1024];
void AllocatePage(uint32_t vaddr)
{
uint32_t page_aligned_address = ALIGN(vaddr, 4096);
// allocate a page at virtual address
int PageDirectoryEntryIndex = vaddr >> 22;
int PageTableEntryIndex = (vaddr >> 12) & 0x1FFF;
printf("Allocation happening at PDE: %d PTE: %d\n", PageDirectoryEntryIndex, PageTableEntryIndex);
// check if the page directory entry is marked as present
if (boot_page_directory[PageDirectoryEntryIndex] & 0x1 ) {
uint32_t* page_table = (uint32_t*)((boot_page_directory[PageDirectoryEntryIndex]) & 0xFFFFE000 + 0xC0000000);
// check if the page table entry is marked as present
if ( page_table[PageTableEntryIndex] & 0x1 )
{
// Map the entry to a physical page
page_table[PageTableEntryIndex] = (uint32_t)(allocate_block() + 0x3);
} else{
// mark page as present
page_table[PageTableEntryIndex] = 0x3;
}
} else {
// mark the page table as present and allocate a physical block for it
boot_page_directory[PageDirectoryEntryIndex] = (uint32_t)(allocate_block() + 0x3);
}
}
void FreePage(uint32_t vaddr )
{
uint32_t page_aligned_address = ALIGN(vaddr, 4096);
// allocate a page at virtual address
int PageDirectoryEntryIndex = vaddr >> 22;
int PageTableEntryIndex = (vaddr >> 12) & 0x1FFF;
uint32_t* pageTable = (uint32_t*)(boot_page_directory[PageDirectoryEntryIndex] & 0xFFFFE000 + 0xC0000000);
void* physicalAddressToFree = (void*)(pageTable[PageTableEntryIndex] & 0xFFFFE000 + 0xC0000000);
free_block(physicalAddressToFree);
pageTable[PageTableEntryIndex] = 0x0;
}
void Map ( uint32_t vaddr, uint32_t paddr)
{
uint32_t page_aligned_address = ALIGN(vaddr, 4096);
// allocate a page at virtual address
int PageDirectoryEntryIndex = vaddr >> 22;
int PageTableEntryIndex = (vaddr >> 12) & 0x1FFF;
}
void Unmap(uint32_t vaddr)
{
// NOTE: I will implement lazy unmapping for now
uint32_t page_aligned_address = ALIGN(vaddr, 4096);
// allocate a page at virtual address
int PageDirectoryEntryIndex = vaddr >> 22;
int PageTableEntryIndex = (vaddr >> 12) & 0x1FFF;
}

View File

@ -0,0 +1,10 @@
#pragma once
#include "PhysicalMemoryManager.h"
#include "../terminal/kterm.h"
#include "../cpu.h"
void AllocatePage(uint32_t v_addr );
void FreePage(uint32_t v_addr);
void Map(uint32_t p_addr, uint32_t v_addr);
void Unmap (uint32_t v_addr);

View File

@ -1,5 +1,5 @@
#include "gdtc.h" #include "gdtc.h"
#include "../tty/kterm.h" #include "../../terminal/kterm.h"
#define NULL_SEGMENT 0 #define NULL_SEGMENT 0
#define KERNEL_CODE_SEGMENT 1 #define KERNEL_CODE_SEGMENT 1
@ -29,6 +29,9 @@ void add_descriptor(int which , unsigned long base, unsigned long limit, unsigne
void initGDT(){ void initGDT(){
#ifdef __VERBOSE__
printf("Init GDT!\n");
#endif
// NULL segment // NULL segment
add_descriptor(NULL_SEGMENT, 0,0,0,0); add_descriptor(NULL_SEGMENT, 0,0,0,0);
@ -48,14 +51,8 @@ void initGDT(){
gdtDescriptor.limit = ((sizeof(SegmentDescriptor ) * 5 ) - 1); gdtDescriptor.limit = ((sizeof(SegmentDescriptor ) * 5 ) - 1);
gdtDescriptor.base = (unsigned int) &GlobalDescriptorTable; gdtDescriptor.base = (unsigned int) &GlobalDescriptorTable;
printf("GDT at address 0x%x, with an size of 0x%x bytes\n" , (unsigned int)GlobalDescriptorTable, sizeof(GlobalDescriptorTable));
LoadGlobalDescriptorTable(); LoadGlobalDescriptorTable();
while (true)
asm volatile("hlt");
} }

View File

@ -0,0 +1,45 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
extern "C" const uint32_t kernel_begin;
extern "C" const uint32_t kernel_end;
#define IS_AVAILABLE_MEM(MEM_TYPE) MEM_TYPE & 0x1
#define IS_ACPI_MEM(MEM_TYPE) MEM_TYPE & 0x2
#define IS_RESERVED_MEM(MEM_TYPE) MEM_TYPE & 0x4
#define IS_NVS_MEMORY(MEM_TYPE) MEM_TYPE & 0x8
#define IS_BADRAM_MEMORY(MEM_TYPE) MEM_TYPE & 0x10
struct MemoryInfoBlock {
uint32_t Base_addr ;
uint32_t Memory_Size;
MemoryInfoBlock* next;
uint8_t type;
};
struct BootInfoBlock {
bool MapIsInvalid;
uint32_t bootDeviceID ;
uint32_t GrubModuleCount;
bool ValidSymbolTable;
uint32_t SymbolTableAddr;
uint32_t SymbolTabSize;
uint32_t SymbolStrSize;
bool ValidELFHeader;
bool EnabledVBE;
bool PhysicalMemoryMapAvailable;
MemoryInfoBlock* MemoryMap;
uint32_t map_size;
uint32_t MemorySize ;
};
// TODO Put the BootInfoBlock 1MB above the kernel.
const uint32_t BootInfoBlock_pptr = (uint32_t)&kernel_end - 0xC0000000 + 0x1;
const uint32_t MemoryMapHeap_pptr = BootInfoBlock_pptr + sizeof(BootInfoBlock);

View File

@ -0,0 +1,120 @@
#include <stdint.h>
#include <stddef.h>
#include "multiboot.h"
#include "bootstructure.h"
#define CHECK_FLAG(flags, bit) ((flags) & (1 <<(bit)))
extern "C" void prekernelSetup ( unsigned long magic, multiboot_info_t* mbi) {
// Create the bootInfoBlock at its location
BootInfoBlock* BIB = (BootInfoBlock*) BootInfoBlock_pptr;
/*
* Check Multiboot magic number
*/
if (magic != MULTIBOOT_BOOTLOADER_MAGIC)
{
BIB->MapIsInvalid = true;
// crash
return;
} else{
BIB->MapIsInvalid = false;
}
/* is boot device valid ? */
if (CHECK_FLAG (mbi->flags, 1))
{
BIB->bootDeviceID = mbi->boot_device;
} else{
BIB->bootDeviceID = 0x11111111;
}
/* Are mods_* valid? */
if(CHECK_FLAG ( mbi->flags, 3)){
multiboot_module_t *mod;
uint32_t i;
BIB->GrubModuleCount = mbi->mods_count;
for(i = 0, mod = (multiboot_module_t *) mbi->mods_addr; i < mbi->mods_count; i++ , mod++){
}
}
/* Is the symbol table of a.out valid? */
if (CHECK_FLAG(mbi->flags, 4))
{
BIB->ValidSymbolTable = true;
multiboot_aout_symbol_table_t *multiboot_aout_sym = &(mbi->u.aout_sym);
} else{
BIB->ValidSymbolTable = false;
}
/* Is the section header table of ELF valid? */
if (CHECK_FLAG(mbi->flags, 5))
{
BIB->ValidELFHeader = true;
multiboot_elf_section_header_table_t *multiboot_elf_sec = &(mbi->u.elf_sec);
}else{
BIB->ValidELFHeader = false;
}
/*
If we got a memory map from our bootloader we
should be parsing it to find out the memory regions available.
*/
if (CHECK_FLAG(mbi->flags, 6))
{
BIB->PhysicalMemoryMapAvailable = true;
BIB->MemoryMap = (MemoryInfoBlock*) MemoryMapHeap_pptr;
multiboot_memory_map_t *mmap = (multiboot_memory_map_t*) (mbi->mmap_addr) ;
auto MemoryMapEnd = mbi->mmap_addr + mbi->mmap_length;
auto CurrentInfoBlock = BIB->MemoryMap;
uint32_t RAM_size = 0;
while((unsigned long) mmap < MemoryMapEnd){
BIB->map_size += sizeof(MemoryInfoBlock);
CurrentInfoBlock->Base_addr = mmap->addr;
CurrentInfoBlock->Memory_Size = mmap->len;
if(mmap->type == MULTIBOOT_MEMORY_AVAILABLE)
CurrentInfoBlock->type |= 0x1;
RAM_size += mmap->len;
if(mmap->type == MULTIBOOT_MEMORY_ACPI_RECLAIMABLE)
CurrentInfoBlock->type |= 0x2;
if(mmap->type == MULTIBOOT_MEMORY_RESERVED)
CurrentInfoBlock->type |= 0x4;
if(mmap->type == MULTIBOOT_MEMORY_NVS)
CurrentInfoBlock->type |= 0x8;
if(mmap->type == MULTIBOOT_MEMORY_BADRAM)
CurrentInfoBlock->type |= 0x10;
// continue to the next block
mmap = (multiboot_memory_map_t *) ((unsigned long) mmap + mmap->size + sizeof(mmap->size));
CurrentInfoBlock->next = (MemoryInfoBlock*) ((uint32_t)CurrentInfoBlock) + sizeof(MemoryInfoBlock);
CurrentInfoBlock = CurrentInfoBlock->next;
}
CurrentInfoBlock->next = (MemoryInfoBlock*) 0x0;
BIB->MemorySize = RAM_size;
} else
{
BIB->PhysicalMemoryMapAvailable = false;
}
/* Draw diagonal blue line */
if (CHECK_FLAG (mbi->flags, 12)){
BIB->EnabledVBE = true;
} else{
BIB->EnabledVBE;
}
}

View File

@ -1,9 +1,14 @@
#pragma once #pragma once
#include "tty/kterm.h" #include "terminal/kterm.h"
#include "io.h" #include "io.h"
#define PORT 0x3f8 #define PORT 0x3f8
static int init_serial() { static int init_serial() {
#ifdef __VERBOSE__
printf("Init Serial\n");
#endif
outb(PORT + 1, 0x00); // Disable all interrupts outb(PORT + 1, 0x00); // Disable all interrupts
outb(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor) outb(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
outb(PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud outb(PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud

View File

@ -0,0 +1,72 @@
#include "superVisorTerminal.h"
void startSuperVisorTerminal(){
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("Not Available!\n");
printf("Kernel MemoryMap:\n");
printf("Frames used: -- \n");
printf("Available Memory:-- \n");
printf("Reserved Memory: -- bytes\n");
}
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);
}
}

View File

@ -0,0 +1,8 @@
#pragma once
#include "../terminal/kterm.h"
#include "../time.h"
#include "../drivers/pit/pit.h"
#include "../drivers/ps-2/keyboard.h"
#include "../memory/PhysicalMemoryManager.h"
void startSuperVisorTerminal();

View File

@ -21,7 +21,8 @@ void kterm_init () {
kterm_row = 0; kterm_row = 0;
kterm_column = 0; kterm_column = 0;
kterm_color = vga_entry_color ( VGA_COLOR_LIGHT_GREY , VGA_COLOR_BLACK); kterm_color = vga_entry_color ( VGA_COLOR_LIGHT_GREY , VGA_COLOR_BLACK);
kterm_buffer = (uint16_t*) 0xB8000; kterm_buffer = (uint16_t*) 0xC03FF000;
for (size_t y = 0; y < VGA_HEIGHT; y++ ){ for (size_t y = 0; y < VGA_HEIGHT; y++ ){
for( size_t x = 0; x < VGA_WIDTH; x++){ for( size_t x = 0; x < VGA_WIDTH; x++){
const size_t index = y * VGA_WIDTH + x; const size_t index = y * VGA_WIDTH + x;
@ -31,7 +32,6 @@ void kterm_init () {
} }
} }
void kterm_resetcolor(){ void kterm_resetcolor(){
kterm_color = vga_entry_color ( VGA_COLOR_LIGHT_GREY , VGA_COLOR_BLACK); kterm_color = vga_entry_color ( VGA_COLOR_LIGHT_GREY , VGA_COLOR_BLACK);
} }
@ -42,9 +42,7 @@ void kterm_setcolor(uint8_t color){
void kterm_putat (char c, uint8_t color, size_t x, size_t y ) { void kterm_putat (char c, uint8_t color, size_t x, size_t y ) {
const size_t index = y * VGA_WIDTH + x; const size_t index = y * VGA_WIDTH + x;
kterm_buffer[index] = vga_entry(c, color); kterm_buffer[index] = vga_entry(c, color);
} }
void enable_cursor (uint8_t start_cursor , uint8_t end_cursor ){ void enable_cursor (uint8_t start_cursor , uint8_t end_cursor ){

View File

@ -1,14 +1,13 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "../vga/colors.h" #include "../drivers/vga/colors.h"
#include "../io.h" #include "../io.h"
extern "C"{ extern "C"{
#include "./../../libc/include/string.h" #include "../lib/string.h"
} }
void kterm_init(); void kterm_init();

View File

@ -1,7 +1,7 @@
#define CURRENT_YEAR 2021 // Change this each year! #include "time.h"
int century_register = 0x00; // Set by ACPI table parsing code if possible
// Set by ACPI table parsing code if possible
int century_register = 0x00;
unsigned char second; unsigned char second;
unsigned char minute; unsigned char minute;
unsigned char hour; unsigned char hour;
@ -10,12 +10,6 @@ unsigned char month;
unsigned int year; unsigned int year;
enum {
cmos_address = 0x70,
cmos_data = 0x71
};
int get_update_in_progress_flag() { int get_update_in_progress_flag() {
outb(cmos_address, 0x0A); outb(cmos_address, 0x0A);
return (inb(cmos_data) & 0x80); return (inb(cmos_data) & 0x80);
@ -109,45 +103,9 @@ void read_rtc() {
} }
/* void delay(int t){
void ReadFromCMOS(unsigned char array[]) volatile int i,j;
{ for(i=0;i<t;i++)
unsigned char tvalue, index; for(j=0;j<25000;j++)
asm("NOP");
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
}
}
*/

23
source/kernel/time.h Normal file
View 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);

View File

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

View File

@ -1,78 +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:
.section .text
.include "./src/kernel/irs_table.s"
.include "./src/kernel/irq_table.s"
.include "./src/kernel/idt/idt.s"
.include "./src/kernel/paging.s"
.global _start
.type _start, @function
_start:
/*Setup the stack pointer to point to the beginning of our stack */
/* I believe its a high address growing down to lower adress for the stack on x86*/
mov $stack_top, %esp
/*Reset EFLAGS*/
pushl $0
popf
/* push the pointer to the Multiboot information structure*/
pushl %ebx
/* push the magic value */
pushl %eax
call early_main
cli
.include "./src/kernel/gdt/gdt.s"
loadIDT:
#load idt
call init_idt
sti
# Try enable A20
# mov $0x2401, %ax
# int $0x15
# enable protected mode
mov %cr0, %eax
or $1, %eax
mov %eax, %cr0
call kernel_main
cli
1: hlt
jmp 1b
.size _start, . - _start

View File

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

View File

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

View File

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

View File

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

View File

@ -1,50 +0,0 @@
#include "kernel.h"
#define GB4 524288
#define GB2 262144
extern "C" void early_main(unsigned long magic, unsigned long addr){
/** initialize terminal interface */
kterm_init();
if (magic != MULTIBOOT_BOOTLOADER_MAGIC){
printf("Invalid magic number: 0x%x\n", magic);
return;
}
CheckMBT( (multiboot_info_t *) addr);
multiboot_info_t* mbt = (multiboot_info_t*) addr;
/* Are mmap_* valid? */
if (CHECK_FLAG(mbt->flags, 6)){
PhysicalMemoryManager_initialise( mbt->mmap_addr, GB2/* Seriously dangerous hardcoded memory value*/);
PhysicalMemoryManager_initialise_available_regions(mbt->mmap_addr, mbt->mmap_addr + mbt->mmap_length);
PhysicalMemoryManager_deinitialise_kernel();
extern uint8_t* kernel_begin;
extern uint8_t* kernel_end;
printf("Kernel MemoryMap:\n");
printf("kernel: 0x%x - 0x%x\n", &kernel_begin , &kernel_end);
}
initGDT();
}
extern "C" void kernel_main (void) {
printf("call to init serial\n");
init_serial();
while (true){
//Read time indefinetely
read_rtc();
printf( "UTC time: %02d-%02d-%02d %02d:%02d:%02d [ Formatted as YY-MM-DD h:mm:ss]\r" ,year, month, day, hour, minute, second);
delay(1000);
}
}

View File

@ -1,33 +0,0 @@
#pragma once
extern "C"{
#include "../libc/include/string.h"
}
#include "vga/VBE.h"
#include "tty/kterm.h"
#include "./bootloader/multiboot.h"
#include "bootcheck.h"
#include "memory/PhysicalMemoryManager.h"
#include "gdt/gdtc.h"
#include "idt/idt.h"
#include "io.h"
#include "time.h"
#include "cpu.h"
#include "serial.h"
#define CHECK_FLAG(flags, bit) ((flags) & (1 <<(bit)))
#define PANIC(message) { return; }
/* This needs to be moved! */
/**
* simple delay function
**/
void delay(int t){
volatile int i,j;
for(i=0;i<t;i++)
for(j=0;j<25000;j++)
asm("NOP");
}

View File

@ -1,40 +0,0 @@
#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 int bitmap_first_unset( uint32_t* map , int size)
{
uint32_t rem_bits = size % 32;
for(uint32_t i = 0; i < size/32; i++)
{
if(map[i] != 0xFFFFFFFF){
for(int j = 0; j < 32; j++){
if(!(map[i] & (1<< j))){
return (i*32) + j;
}
}
}
}
if(rem_bits){
for(uint32_t j = 0; j < rem_bits; j++){
if(!(map[size/32] & (1 << j ))){
return size + j; // Original author divided size by 32 and then multiplied it by 32 which is a net zero calculation ?!?
}
}
}
return -1;
}

View File

@ -1,47 +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;
kernel_begin = .;
/* 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. */
kernel_end = .;
}

View File

@ -1,47 +0,0 @@
#include "PageDirectory.h"
#include <stdint.h>
void PageDirectory::enable(){
// https://wiki.osdev.org/Setting_Up_Paging
//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();
}
/*
void IdentityPaging(uint32_t *first_pte, vaddr from, int size)
{
from = from & 0xFFFFF000; // Discard the bits we don't want
for (; size > 0; from += 4096, first_pte++)
{
*first_pte = from | 1; // makr page present.
}
}
*/

View File

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

View File

@ -1,38 +0,0 @@
#include "PageFrameAllocator.h"
MemoryInfo memInfo {};
void mapMultibootMemoryMap( 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.memorySizeInBytes += mmap->len;
} else {
memInfo.reservedMemoryInBytes += mmap->len;
}
print_Multiboot_memory_Map(mmap);
}
uint32_t memorySizeInGiB = memInfo.memorySizeInBytes / 1073741824;
printf("Available Memory: 0x%x bytes, 0x%x GiB\n", memInfo.memorySizeInBytes, memorySizeInGiB );
printf("Reserved Memory: 0x%x bytes\n", memInfo.reservedMemoryInBytes );
}
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
);
}

View File

@ -1,20 +0,0 @@
#pragma once
#include "../arch/i386/tty/kterm.h"
#include <stdint.h>
#include "../bootloader/multiboot.h"
struct MemoryInfo{
uint32_t memorySizeInBytes = 0;
uint32_t reservedMemoryInBytes = 0;
};
extern void *kernel_begin;
extern void *kernel_end;
void print_Multiboot_memory_Map(multiboot_memory_map_t*);
void mapMultibootMemoryMap(multiboot_info_t*);

View File

@ -1,118 +0,0 @@
#include "PhysicalMemoryManager.h"
size_t mem_size = 0;
int used_blocks = 0;
size_t max_blocks = 0;
uint32_t* pmmap = 0;
size_t pmmap_size = 0;
void PhysicalMemoryManager_initialise(uint32_t physicalmemorymap_address, size_t size )
{
mem_size = size;
max_blocks = KB_TO_BLOCKS(mem_size);
used_blocks = max_blocks;
pmmap = (uint32_t*) physicalmemorymap_address;
if(max_blocks % BLOCKS_PER_WORD)
pmmap_size++;
memset(pmmap, 0xFF, pmmap_size);
}
void PhysicalMemoryManager_region_initialise(uint32_t base, size_t size)
{
size_t blocks = size /BLOCK_SIZE;
uint32_t align = base / BLOCK_SIZE;
for(size_t i = 0 ; i < blocks; i ++)
{
bitmap_unset(pmmap, align++);
used_blocks--;
}
bitmap_set(pmmap, 0);
}
void PhysicalMemoryManager_region_deinitialise(uint32_t base, size_t size )
{
size_t blocks = size / BLOCK_SIZE;
uint32_t align = base / BLOCK_SIZE;
for(size_t i = 0 ; i < blocks; i++ )
{
bitmap_set(pmmap, align++);
used_blocks++;
}
}
void PhysicalMemoryManager_initialise_available_regions(uint32_t mmap_, uint32_t mmap_end_)
{
multiboot_memory_map_t *mmap = (multiboot_memory_map_t*)mmap_;
multiboot_memory_map_t *mmap_end= (multiboot_memory_map_t*) mmap_end_;
for(int i = 0; mmap < mmap_end ; mmap++, i++)
{
if(mmap->type == MULTIBOOT_MEMORY_AVAILABLE)
{
PhysicalMemoryManager_region_initialise((uint32_t) mmap->addr, (size_t) mmap->len);
}
}
}
void PhysicalMemoryManager_deinitialise_kernel()
{
extern uint8_t kernel_begin;
extern uint8_t kernel_end;
size_t kernel_size = (size_t) &kernel_end - (size_t) &kernel_begin;
uint32_t pmmap_size_aligned = pmmap_size;
if(!IS_ALIGNED(pmmap_size_aligned, BLOCK_SIZE))
{
pmmap_size_aligned = ALIGN(pmmap_size_aligned, BLOCK_SIZE);
}
PhysicalMemoryManager_region_deinitialise((uint32_t) &kernel_begin, kernel_size);
PhysicalMemoryManager_region_deinitialise((uint32_t) &kernel_end, pmmap_size_aligned);
}
void* PhysicalMemoryManager_allocate_block()
{
if(used_blocks - max_blocks <= 0)
{
return 0;
}
int p_index = bitmap_first_unset(pmmap, p_index );
if(p_index == -1){
return 0;
}
bitmap_set(pmmap, p_index);
used_blocks++;
return (void*) (BLOCK_SIZE * p_index);
}
void PhysicalMemoryManager_free_block(void* p){
if(p==0){
return ;
}
uint32_t p_addr = (uint32_t) p;
int index = p_addr / BLOCK_SIZE;
bitmap_unset(pmmap, index);
used_blocks--;
}

View File

@ -1,34 +0,0 @@
#pragma once
#include "../bootloader/multiboot.h"
#include <stdint.h>
#include <stddef.h>
#include "../../libc/include/mem.h"
#include "../kstructures/bitmap.h"
#define BLOCK_SIZE 4092
#define BLOCKS_PER_WORD 32
#define KB_TO_BLOCKS(x) (((x) * 1024 ) / BLOCK_SIZE)
#define IS_ALIGNED(addr, align) !((addr) & ~((align) - 1))
#define ALIGN(addr, align) (((addr) & ~((align) - 1 )) + (align))
extern void PhysicalMemoryManager_initialise(uint32_t, size_t);
extern void PhysicalMemoryManager_region_initialise(uint32_t, size_t);
extern void PhysicalMemoryManager_region_deinitialise(uint32_t,size_t);
extern void PhysicalMemoryManager_initialise_available_regions(uint32_t, uint32_t);
extern void PhysicalMemoryManager_deinitialise_kernel();
extern void* PhysicalMemoryManager_allocate_block();
extern void PhysicalMemoryManager_free_block(void* p);
extern size_t mem_size;
extern int used_blocks;
extern size_t max_blocks;
extern uint32_t* pmmap;
extern size_t pmmap_size ;

View File

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

View File

@ -1,20 +0,0 @@
.globl enablePaging
enablePaging:
push %ebp
mov %esp, %ebp
mov %cr0, %eax
or $0x80000000, %eax
mov %eax, %cr0
mov %ebp, %esp
pop %ebp
ret
.globl loadPageDirectory
loadPageDirectory:
push %ebp
mov %esp, %ebp
mov 8(%esp), %eax
mov %eax, %cr3
mov %ebp, %esp
pop %ebp
ret

View File

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

21
todo.md
View File

@ -0,0 +1,21 @@
# TODO list
![Todo image](https://camo.githubusercontent.com/c43d969d9d071c8342e9a69cdd6acb433c541f431127738974ce22290c46f2b8/68747470733a2f2f692e696d6775722e636f6d2f4f764d5a4273392e6a7067)
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