Merge into main the new state of the operating system/kernel #1

Open
Nigel wants to merge 120 commits from dev into main
39 changed files with 1197 additions and 618 deletions
Showing only changes of commit 2e59e6593e - Show all commits

View File

@ -9,9 +9,8 @@ OFILES = \
$(BUILD_DIR)/boot.o \
$(BUILD_DIR)/kterm.o \
$(BUILD_DIR)/kernel.o \
$(BUILD_DIR)/PhysicalMemoryManager.o \
$(BUILD_DIR)/memory.o \
$(BUILD_DIR)/io.o \
$(BUILD_DIR)/PageDirectory.o \
$(BUILD_DIR)/gdtc.o \
$(BUILD_DIR)/idt.o \
$(BUILD_DIR)/pci.o \
@ -21,6 +20,11 @@ $(BUILD_DIR)/pcidevice.o \
$(BUILD_DIR)/atapiDevice.o \
$(BUILD_DIR)/ataDevice.o \
$(BUILD_DIR)/rsdp.o \
$(BUILD_DIR)/pit.o \
$(BUILD_DIR)/time.o \
$(BUILD_DIR)/keyboard.o \
$(BUILD_DIR)/sv-terminal.o \
SRC_DIR = src
@ -39,8 +43,6 @@ all: clean build
build: build_kernel iso
clean_iso:
if [[ -a isodir/boot ]] ; then rm root/boot -rd ; fi
if [ -f build/barinkOS.iso ] ; then rm build/barinkOS.iso ; fi
@ -77,7 +79,7 @@ $(BUILD_DIR)/kterm.o:
$(CPP) -c $(SRC_DIR)/kernel/tty/kterm.cpp -o $(BUILD_DIR)/kterm.o $(CFLAGS) -fno-exceptions -fno-rtti
$(BUILD_DIR)/boot.o:
$(AS) $(SRC_DIR)/kernel/boot.S -o $(BUILD_DIR)/boot.o
$(AS) $(SRC_DIR)/kernel/boot.s -o $(BUILD_DIR)/boot.o
$(BUILD_DIR)/crti.o:
$(AS) $(SRC_DIR)/kernel/crti.s -o $(BUILD_DIR)/crti.o
@ -88,8 +90,6 @@ $(BUILD_DIR)/crtn.o:
$(BUILD_DIR)/io.o:
$(CPP) -c $(SRC_DIR)/kernel/drivers/IO/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:
$(CPP) -c $(SRC_DIR)/kernel/idt/idt.cpp -o $(BUILD_DIR)/idt.o $(CFLAGS) -fno-exceptions -fno-rtti
@ -122,3 +122,20 @@ $(BUILD_DIR)/ataDevice.o:
$(BUILD_DIR)/rsdp.o:
$(CPP) -c $(SRC_DIR)/kernel/drivers/ACPI/rsdp.cpp -o $(BUILD_DIR)/rsdp.o $(CFLAGS) -fno-exceptions -fno-rtti
$(BUILD_DIR)/pit.o:
$(CPP) -c $(SRC_DIR)/kernel/pit.cpp -o $(BUILD_DIR)/pit.o $(CFLAGS) -fno-exceptions -fno-rtti
$(BUILD_DIR)/keyboard.o:
$(CPP) -c $(SRC_DIR)/kernel/keyboard/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/sv-terminal/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

View File

@ -26,7 +26,8 @@ Correctly identified our ATAPI device 🎉
________________________
### 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

View File

@ -1,18 +1,25 @@
# TODO list
## Start planning
## 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 (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/> Output to serial port \
<input type="checkbox" checked/> Move to protected mode \
<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" checked/> Interrupt / exception system (API) \
<input type="checkbox" checked/> Plan your memory map (virtual, and physical) : decide where you want the data to be. \
<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)
@ -24,6 +31,8 @@
<input type="checkbox" /> ATAPI support \
<input type="checkbox" /> Keyboard support ( P/S2 Keyboard) \
<input type="checkbox" checked/> Memory Management (MMU)
<input type="checkbox" /> Hardware Management system
<input type="checkbox" /> Preemptive multi tasking \
<input type="checkbox" /> Processes \
<input type="checkbox" /> Threads
@ -32,9 +41,11 @@
<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" /> ACPI support \
<input type="checkbox" /> ATAPI support \
## Optional
<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" /> USTAR Filesystem \

View File

@ -1,3 +1,8 @@
menuentry "BarinkOS"{
GRUB_DEFAULT=0
GRUB_TIMEOUT=-1
GRUB_HIDDEN_TIMEOUT=0
GRUB_HIDDEN_TIMEOUT_QUITE=true
menuentry "BarinkOS" {
multiboot /boot/myos.bin
}

View File

@ -21,6 +21,7 @@ stack_bottom:
stack_top:
.section .text
.include "./src/kernel/gdt/gdt.s"
.include "./src/kernel/irs_table.s"
.include "./src/kernel/irq_table.s"
.include "./src/kernel/idt/idt.s"
@ -45,34 +46,21 @@ _start:
pushl %eax
call early_main
mov %cr0, %eax
or $1, %eax
mov %eax, %cr0
call kernel_main
cli
.include "./src/kernel/gdt/gdt.s"
loadIDT:
#load idt
call init_idt
sti
# Try enable A20
# mov $0x2401, %ax
# int $0x15
1: hlt
jmp 1b
# enable protected mode
mov %cr0, %eax
or $1, %eax
mov %eax, %cr0
call kernel_main
.size _start, . - _start
cli
1: hlt
jmp 1b
.size _start, . - _start

View File

@ -10,66 +10,81 @@ 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)){
printf("mem_lower = %uKB, mem_upper = %uKB\n");
// Do nothing
}
/* is boot device valid ? */
if (CHECK_FLAG (mbi->flags, 1)){
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)){
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)){
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)){
printf("Can draw!");
#ifdef __VERBOSE__
printf("Can draw!\n");
#endif
}

9
src/kernel/bootinfo.h Normal file
View File

@ -0,0 +1,9 @@
#pragma once
#include "memory/memoryinfo.h"
struct BootInfo{
const char* BootStructureID = "BarinkOS";
MemoryInfo* memory;
};

11
src/kernel/definitions.h Normal file
View File

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

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

@ -23,7 +23,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 ){

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

@ -29,6 +29,9 @@ void add_descriptor(int which , unsigned long base, unsigned long limit, unsigne
void initGDT(){
#ifdef __VERBOSE__
printf("Init GDT!\n");
#endif
// NULL segment
add_descriptor(NULL_SEGMENT, 0,0,0,0);
@ -52,6 +55,4 @@ void initGDT(){
LoadGlobalDescriptorTable();
}

View File

@ -1,5 +1,6 @@
#include "idt.h"
//#include "scancodes/set1.h"
#include "../pit.h"
#include "../keyboard/keyboard.h"
IDT_entry idt_table[256];
IDT_ptr idt_ptr;
@ -13,78 +14,249 @@ void set_id_entry (uint8_t num , uint32_t base, uint16_t sel, uint8_t flags){
};
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);
}
//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);
printf("EAX: 0x%x\n", regs.eax);
printf("EBP: 0x%x\n", regs.ebp);
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) {
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);
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);
}
outb(0x20, 0x20); // send end of interrupt to master
break;
case 12:
// PS2 Mouse interrupt
printf("Mouse event triggered!");
//int event = inb(0x60);
break;
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);
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
@ -125,10 +297,15 @@ void init_idt(){
//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);
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);
@ -139,7 +316,7 @@ void init_idt(){
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(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);

View File

@ -167,11 +167,6 @@
}
wait_until_shutdown();
}
@ -179,35 +174,118 @@
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();
kernel_main();
extern "C" void early_main(unsigned long magic, unsigned long addr){
/**
* Initialize terminal interface
* NOTE: This should be done later on , the magic value should be checked first.
*/
kterm_init();
/**
* 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;
}
/**
* Use the address given as an argument as the pointer
* to a Multiboot information structure.
*/
multiboot_info_t* mbt = (multiboot_info_t*) addr;
/**
* Construct our own bootInfo structure
*/
BootInfo bootinfo = {};
/*
If we got a memory map from our bootloader we
should be parsing it to find out the memory regions available.
*/
if (CHECK_FLAG(mbt->flags, 6))
{
/*
Setup Physical memory managment
*/
MemoryInfo meminfo = {};
bootinfo.memory = &meminfo;
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);
}
}
printf("allocate region: 0x%x, size : 0x%x bytes\n", kernel_begin, kernel_end - kernel_begin );
memAlloc.allocate_region(kernel_end, kernel_end - kernel_begin);
// test alloc_block
uint8_t* memory = (uint8_t*) memAlloc.allocate_block();
printf("Got a new pointer: 0x%x\n", memory);
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);
}
initGDT();
init_idt();
// Enable interrupts
asm volatile("STI");
init_serial();
pit_initialise();
CheckMBT( (multiboot_info_t *) addr);
startSuperVisorTerminal(&bootinfo);
kernel_main();
}

View File

@ -1,5 +1,6 @@
#pragma once
extern "C"{
extern "C"
{
#include "../libc/include/string.h"
}
@ -8,14 +9,19 @@ extern "C"{
#include "tty/kterm.h"
#include "./bootloader/multiboot.h"
#include "bootinfo.h"
#include "memory/memory.h"
#include "memory/memoryinfo.h"
#include "bootcheck.h"
#include "memory/PhysicalMemoryManager.h"
#include "gdt/gdtc.h"
#include "idt/idt.h"
#include "drivers/IO/io.h"
#include "time.h"
#include "pit.h"
#include "cpu.h"
#include "serial.h"
#include "drivers/IO/PCI/pci.h"
@ -28,17 +34,10 @@ extern "C"{
#include "drivers/ACPI/rsdp.h"
#include "time.h"
#include "sv-terminal/superVisorTerminal.h"
#define CHECK_FLAG(flags, bit) ((flags) & (1 <<(bit)))
#define PANIC(message) { return; }
#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

@ -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 "../tty/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();

View File

@ -13,26 +13,26 @@ 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)
inline uint32_t bitmap_first_unset( uint32_t* map , int map_size)
{
uint32_t rem_bits = size % 32;
for(uint32_t i = 0; i < size/32; i++)
for ( int i = 0 ; i < map_size ; i ++ )
{
if(map[i] != 0xFFFFFFFF){
for(int j = 0; j < 32; j++){
if(!(map[i] & (1<< j))){
return (i*32) + j;
// 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;
}
}
}
}
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 +1,43 @@
#include "PageDirectory.h"
#include <stdint.h>
void PageDirectory::enable()
{
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;
}
// 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.
// // 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.
}
// //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;
// // attributes: supervisor level, read/write, present
// this->page_directory[0] = ((unsigned int)first_page_table) | 3;
printf("Enable Paging!\n");
loadPageDirectory(this->page_directory);
enablePaging();
}
/*
void IdentityPaging(uint32_t *first_pte, vaddr from, int size)
void PageDirectory::MapPhysicalToVirtualAddress ( address_t PAddress , address_t VAddress, uint32_t 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,17 +1,18 @@
#pragma once
#include <stdint.h>
extern "C" void loadPageDirectory (uint32_t* addr );
extern "C" void enablePaging();
typedef uintptr_t address_t;
#include "./memory.h"
#include "./../tty/kterm.h"
#define KB 1024
typedef uintptr_t address_t;
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
extern "C" void loadPageDirectory (uint32_t* addr );
extern "C" void enablePaging();
struct page_directory_entry {};
struct page_table_entry{};
@ -21,8 +22,10 @@ struct page_table_entry{};
class PageDirectory {
public:
void enable ();
void MapPhysicalToVirtualAddress ( address_t PAddress , address_t VAddress, uint32_t size );
private:
uint32_t page_directory[1024] __attribute__((aligned(4096)));
uint32_t first_page_table[1024] __attribute__((aligned(4096)));
uint32_t page_directory[1024] __attribute__((aligned(4096))); // align on 4 kiloByte pages
uint32_t first_page_table[1024] __attribute__((aligned(4096))); // align on 4 kiloByte pages
};

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

@ -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
);
}

View File

@ -0,0 +1,48 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#include "memoryinfo.h"
#include "../bootloader/multiboot.h"
#include "../tty/kterm.h"
#include "../../libc/include/mem.h"
#include "../kstructures/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);

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

54
src/kernel/pit.cpp Normal file
View File

@ -0,0 +1,54 @@
#include "pit.h"
#include "tty/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/pit.h Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#include <stdint.h>
#include "drivers/IO/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();

View File

@ -3,7 +3,12 @@
#include "tty/kterm.h"
#include "drivers/IO/io.h"
#define PORT 0x3f8
inline static int init_serial() {
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

View File

@ -0,0 +1,89 @@
#include "superVisorTerminal.h"
void startSuperVisorTerminal(BootInfo* bootinfo)
{
bool isRunning = true;
while (isRunning){
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 if(strncmp("FAT", command, characterCount) == 0){
isRunning = false;
continue;
}
else
{
printf("Unknown command\n");
}
delay(1000);
}
}

View File

@ -0,0 +1,9 @@
#pragma once
#include "../tty/kterm.h"
#include "../time.h"
#include "../pit.h"
#include "../keyboard/keyboard.h"
#include "../memory/memory.h"
#include "../bootinfo.h"
void startSuperVisorTerminal(BootInfo * );

111
src/kernel/time.cpp Normal file
View 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");
}

View File

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

View File

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

View File

@ -8,4 +8,19 @@ size_t strlen(const char* str) {
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
#include <stddef.h>
size_t strlen(const char* str);
int strncmp ( const char* str1, const char* str2, size_t num );

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