Compare commits

4 Commits

Author SHA1 Message Date
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
20 changed files with 768 additions and 297 deletions

View File

@ -5,7 +5,7 @@ CC = ${HOME}/opt/cross/bin/i686-elf-gcc
CPP = ${HOME}/opt/cross/bin/i686-elf-g++
CFLAGS = -ffreestanding -O2 -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)/pit.o $(BUILD_DIR)/time.o $(BUILD_DIR)/keyboard.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)/sv-terminal.o $(BUILD_DIR)/string.o $(BUILD_DIR)/PageFrameAllocator.o
SRC_DIR = src
BUILD_DIR = build
@ -23,8 +23,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
@ -35,8 +33,8 @@ iso: clean_iso clean build
cp src/grub.cfg root/boot/grub/grub.cfg
grub-mkrescue -o build/barinkOS.iso root
test:
$(EMULATOR) -kernel $(BUILD_DIR)/myos.bin -serial stdio -vga std -monitor stdio -display gtk -m 2G -cpu core2duo
run: all
$(EMULATOR) -kernel $(BUILD_DIR)/myos.bin -serial stdio -vga std -display gtk -m 2G -cpu core2duo
build_kernel: $(OBJ_LINK_LIST)
$(CC) -T $(SRC_DIR)/kernel//linker.ld -o $(BUILD_DIR)/myos.bin \
@ -85,3 +83,17 @@ $(BUILD_DIR)/string.o:
$(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/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

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
}

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

@ -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,10 +55,4 @@ void initGDT(){
LoadGlobalDescriptorTable();
while (true)
asm volatile("hlt");
}

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

@ -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 ){

View File

@ -1,50 +1,108 @@
#include "kernel.h"
#define GB4 524288
#define GB2 262144
extern "C" void kernel_main (void);
extern "C" void early_main(unsigned long magic, unsigned long addr){
/** initialize terminal interface */
/**
* 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;
}
CheckMBT( (multiboot_info_t *) addr);
/**
* Show a little banner for cuteness
*/
printf("|=== BarinkOS ===|\n");
multiboot_info_t* mbt = (multiboot_info_t*) addr;
/* Are mmap_* valid? */
if (CHECK_FLAG(mbt->flags, 6)){
/**
* Use the address given as an argument as the pointer
* to a Multiboot information structure.
*/
multiboot_info_t* mbt = (multiboot_info_t*) addr;
/*
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))
{
printf("Preliminary results mmap scan:\n");
mapMultibootMemoryMap(mbt);
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();
init_idt();
// Enable interrupts
asm volatile("STI");
CheckMBT( (multiboot_info_t *) addr);
kernel_main();
}
extern "C" void kernel_main (void) {
printf("call to init serial\n");
init_serial();
pit_initialise();
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);
}
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("TIME", command , characterCount ) == 0 ) {
read_rtc();
printf( "UTC time: %02d-%02d-%02d %02d:%02d:%02d (Ticks: %06d)\n" ,year, month, day, hour, minute, second, pit_tick);
} else if(strncmp("TEST", command, characterCount) == 0){
// asm volatile ("MOV $4, %AX ; MOV $0, %BX ; DIV %BX"); // IRS 0
}
else{
printf("Unknown command\n");
}
delay(1000);
}
}

View File

@ -7,27 +7,21 @@ extern "C"{
#include "./bootloader/multiboot.h"
#include "bootcheck.h"
#include "memory/PhysicalMemoryManager.h"
#include "memory/physical/PhysicalMemoryManager.h"
#include "memory/frames/PageFrameAllocator.h"
#include "gdt/gdtc.h"
#include "idt/idt.h"
#include "pit.h"
#include "io.h"
#include "time.h"
#include "cpu.h"
#include "serial.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();

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 "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

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

View File

@ -0,0 +1,74 @@
#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("Kernel MemoryMap:\n");
printf("kernel: 0x%x - 0x%x\n", &kernel_begin , &kernel_end);
printf("Frames used: 0x%x blocks of 4 KiB\n", used_blocks);
//printf("\n\n");
//PrintPhysicalMemoryAllocation( );
}
else if(strncmp("TEST", command, characterCount) == 0)
{
// TEST #DE exception
asm volatile ("MOV $4, %AX ; MOV $0, %BX ; DIV %BX"); // IRS 0
}
else if (strncmp("VERSION", command , characterCount) == 0)
{
// Show version information
printf("========= Version ========\n");
printf("Kernel v%d\n", 0);
}
else if(strncmp("CLEAR", command, characterCount) == 0)
{
kterm_init();
printf("|=== BarinkOS ===|\n");
}
else
{
printf("Unknown command\n");
}
delay(1000);
}
}

View File

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

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 "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

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