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
32 changed files with 831 additions and 830 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)/window.o $(BUILD_DIR)/cursor.o $(BUILD_DIR)/kterm.o $(BUILD_DIR)/kernel.o $(BUILD_DIR)/PhysicalMemoryManager.o $(BUILD_DIR)/io.o $(BUILD_DIR)/vesa.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,10 +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 mon:stdio -vga std -display gtk -m 2G -cpu core2duo # -monitor stdio
test_iso:
$(EMULATOR) -cdrom build/barinkOS.iso -serial mon:stdio -vga std -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 \
@ -52,7 +48,7 @@ clean:
rm -f $(BUILD_DIR)/myos.bin $(INTERNAL_OBJS)
$(BUILD_DIR)/kernel.o:
$(CPP) -c $(SRC_DIR)/kernel/kernel.cpp -o $(BUILD_DIR)/kernel.o $(CFLAGS) -fno-exceptions -fno-rtti -fpermissive
$(CPP) -c $(SRC_DIR)/kernel/kernel.cpp -o $(BUILD_DIR)/kernel.o $(CFLAGS) -fno-exceptions -fno-rtti
$(BUILD_DIR)/kterm.o:
$(CPP) -c $(SRC_DIR)/kernel/tty/kterm.cpp -o $(BUILD_DIR)/kterm.o $(CFLAGS) -fno-exceptions -fno-rtti
@ -88,11 +84,16 @@ $(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)/vesa.o:
$(CPP) -c $(SRC_DIR)/kernel/drivers/vesa/vesa.cpp -o $(BUILD_DIR)/vesa.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)/window.o:
$(CPP) -c $(SRC_DIR)/gui/window.cpp -o $(BUILD_DIR)/window.o $(CFLAGS) -fno-exceptions -fno-rtti
$(BUILD_DIR)/cursor.o:
$(CPP) -c $(SRC_DIR)/gui/cursor.cpp -o $(BUILD_DIR)/cursor.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

@ -6,9 +6,6 @@
________________________
### Screenshot(s)
![Graphics mode](screenshots/BarinkOS_VBE_GRAPHICS.png) \
It may not look like much but I am proud of it! We are in graphics mode.
![Scrolling the terminal](screenshots/Screenshot1.png) \
The first scrolling boot screen. 😲

BIN
screenshots/BarinkOS_VBE_GRAPHICS.png (Stored with Git LFS)

Binary file not shown.

View File

@ -1,5 +0,0 @@
#pragma once
class Graphics {
};

View File

@ -1,7 +0,0 @@
#pragma once
class Widget{
virtual void draw();
};

View File

@ -1,17 +0,0 @@
#include "cursor.h"
void Cursor::draw(){
for(int i = 0; i < this->width; i++){
for(int j = 0; j < this->height; j++){
if(this->bitmap[j * this->width + i] == 1 ){
putPixel(i + this->x,j + this->y, 0xFF000000);
}
}
}
}
Cursor::Cursor(int x, int y){
this->x = x;
this->y = y;
}

View File

@ -1,38 +0,0 @@
#pragma once
#include "../kernel/drivers/vesa/vesa.h"
class Cursor{
public:
void draw();
Cursor(int x, int y);
private:
int x;
int y;
const int width= 16;
const int height= 10;
const int bitmap [160] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,
0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,
0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,
0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,
0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,
0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,
0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};
};

View File

@ -1,33 +0,0 @@
#include "window.h"
int Window::getWidth(){
return this->rect.width;
}
int Window::getHeight(){
return this->rect.height;
}
void Window::setWidth(int& width){
this->rect.width = width;
}
void Window::setHeight(int& height){
this->rect.height = height;
}
int Window::getX(){
return this->rect.x;
}
int Window::getY(){
return this->rect.y;
}
Window::Window (Rect& rect , uint32_t colour){
this->rect = rect;
this->Background_colour = colour;
}
void Window::draw(){
drawRect(this->getX() , this->getY() , this->getWidth() , this->getHeight() ,this->Background_colour );
}

View File

@ -1,37 +0,0 @@
#pragma once
#include "../kernel/drivers/vesa/vesa.h"
#include "Widget.h"
struct Rect {
int width;
int height;
int x;
int y;
};
class Window : Widget{
public:
int getX();
int getY();
int getWidth();
int getHeight();
void setWidth(int&);
void setHeight(int&);
Window (Rect& rect , uint32_t colour);
void draw();
private:
Rect rect;
uint32_t Background_colour;
};

View File

@ -1,27 +1,18 @@
/*
* Multiboot
*/
.set ALIGN, 1<<0 /* align loaded modules on page boundaries */
.set MEMINFO, 1<<1 /* provide memory map */
.set VIDEO, 1<<2 /* provide video mode */
.set FLAGS, ALIGN | MEMINFO | VIDEO /* 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 */
.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
.long 0 # unused
.long 0 # .
.long 0 # .
.long 0 # .
.long 0 # unused
.long 0 # set graphics mode
.long 800 # screen witdh
.long 600 # screen height
.long 32 # bpp
.section .bss
.align 16
@ -30,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"
@ -54,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

@ -1,108 +1,91 @@
#pragma once
#include "bootloader/multiboot.h"
#define CHECK_FLAG(flags, bit) ((flags) & (1 <<(bit)))
#include "../gui/window.h"
#include "../gui/cursor.h"
#include "tty/kterm.h"
#include "drivers/vesa/vesa.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;
/* 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%8x\n", (unsigned) mbi->flags);
#ifdef __VERBOSE__
/* Print out the flags */
printf("flags = 0x%x\n", (unsigned) mbi->flags);
#endif
/* Are mem_* valid? */
if ( CHECK_FLAG(mbi->flags,0)){
// Do nothing
}
/* 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))
{
#ifdef __VERBOSE__
printf("boot_device = 0x0%x\n", (unsigned) mbi->boot_device);
#endif
}
/* 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))
{
#ifdef __VERBOSE__
printf("cmdline = %s\n", (char *) mbi->cmdline);
#endif
}
/* 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;
#ifdef __VERBOSE__
printf("mods count = %d, mods_addr = 0x%x\n", (int) mbi->mods_count, (int) mbi->mods_addr);
/* Are mods_* valid? */
if(CHECK_FLAG ( mbi->flags, 3)){
multiboot_module_t *mod;
uint32_t i;
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
}
printf("mods count = %d, mods_addr = 0x%x\n", (int) mbi->mods_count, (int) mbi->mods_addr);
/* Bits 4 and 5 are mutually exclusive! */
if (CHECK_FLAG (mbi->flags, 4) && CHECK_FLAG(mbi->flags, 5))
{
#ifdef __VERBOSE__
printf("Both bits 4 and 5 are set.\n");
#endif
return;
}
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);
}
}
/* 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
}
/* 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 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
}
/* 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, 11)){
printf("Can draw!");
/* Draw diagonal blue line */
if (CHECK_FLAG (mbt->flags, 12)){
#ifdef __VERBOSE__
printf("Can draw!\n");
#endif
}
// Init vesa driver
initVBEDevice(mbt);
// Fill screen with blue
// colours AARRGGBB
drawRect(0, 0 , VbeModeInfo->width,VbeModeInfo->height, 0xFF0000FF);
// Create two windows
Rect rect_window1 {};
Rect rect_window2 {};
rect_window1.height =200;
rect_window1.width = 300;
rect_window1.x = 50;
rect_window1.y = 50;
rect_window2.height =200;
rect_window2.width = 300;
rect_window2.x = 300;
rect_window2.y = 200;
Window window_1 ( rect_window1, 0xFF00F0FF);
Window window_2 (rect_window2, 0xFFAACCDD);
window_1.draw();
window_2.draw();
Cursor cursor (70,100);
cursor.draw();
}
}

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,136 +0,0 @@
#include "vesa.h"
VbeInfoBlock* vbeInfo;
vbe_mode_info_structure* VbeModeInfo;
void initVBEDevice(multiboot_info_t* mbt){
print_serial("initVBEDevice");
vbeInfo = (VbeInfoBlock*) mbt->vbe_control_info;
printf_serial("Signature: %s, V0x%x\n", vbeInfo->VbeSignature, vbeInfo->VbeVersion);
VbeModeInfo = (vbe_mode_info_structure*) mbt->vbe_mode_info;
printf_serial("VESA video mode info: Width: %d Height: %d BPP: %d\n", VbeModeInfo->width, VbeModeInfo->height , VbeModeInfo->bpp);
printf_serial("VideoMemory Location: 0x%x \n", VbeModeInfo->framebuffer );
}
void putPixel( int x, int y , uint32_t colour){
// printf_serial("putPixel x: %d, y: %d\n", x, y);
///fb + mbt->framebuffer_pitch * y + 4 * x ,NOTE: this calculation is very important
*(uint32_t*) ( VbeModeInfo->framebuffer + VbeModeInfo->pitch * y + 4 * x ) = colour;
}
void drawLine(int x1, int y1, int x2, int y2, uint32_t colour ){
print_serial("drawline\n");
// See Bresenham's line algorithm
int deltaX = x2 - x1;
int deltaY = y2 - y1;
int D = 2 * deltaY - deltaX;
int y = y1;
for ( int x = x1; x < x2; x++){
putPixel(x,y, colour);
if( D > 0){
y +=1;
D = D - 2 * deltaX;
}
D = D + 2 * deltaY;
}
}
void drawRect ( int x, int y, int width, int height, uint32_t colour ){
print_serial("drawRect\n");
for ( int i = x; i < x + width; i ++)
{
for(int j = y; j < y + height; j++){
putPixel(i,j, colour);
}
}
}
void blueDiagnalLineTest(multiboot_info_t* mbt){
multiboot_uint32_t color;
unsigned i;
void *fb = (void *) (unsigned long) mbt->framebuffer_addr;
switch (mbt->framebuffer_type)
{
case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED:
{
unsigned best_distance, distance;
struct multiboot_color *palette;
palette = (struct multiboot_color *) mbt->framebuffer_palette_addr;
color = 0;
best_distance = 4*256*256;
for (i = 0; i < mbt->framebuffer_palette_num_colors; i++)
{
distance = (0xff - palette[i].blue) * (0xff - palette[i].blue)
+ palette[i].red * palette[i].red
+ palette[i].green * palette[i].green;
if (distance < best_distance)
{
color = i;
best_distance = distance;
}
}
}
break;
case MULTIBOOT_FRAMEBUFFER_TYPE_RGB:
color = ((1 << mbt->framebuffer_blue_mask_size) - 1)
<< mbt->framebuffer_blue_field_position;
break;
case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT:
color = '\\' | 0x0100;
break;
default:
color = 0xffffffff;
break;
}
for (i = 0; i < mbt->framebuffer_width
&& i < mbt->framebuffer_height; i++)
{
switch (mbt->framebuffer_bpp)
{
case 8:
{
multiboot_uint8_t *pixel = (multiboot_uint8_t*)fb + mbt->framebuffer_pitch * i + i;
*pixel = color;
}
break;
case 15:
case 16:
{
multiboot_uint16_t *pixel
= (multiboot_uint16_t*)fb + mbt->framebuffer_pitch * i + 2 * i;
*pixel = color;
}
break;
case 24:
{
multiboot_uint32_t *pixel
= (multiboot_uint32_t*)fb + mbt->framebuffer_pitch * i + 3 * i;
*pixel = (color & 0xffffff) | (*pixel & 0xff000000);
}
break;
case 32:
{
multiboot_uint32_t *pixel
= (multiboot_uint32_t*)fb + mbt->framebuffer_pitch * i + 4 * i;
*pixel = color;
}
break;
}
}
}

View File

@ -1,66 +0,0 @@
#pragma once
#include <stdint.h>
#include "../../bootloader/multiboot.h"
#include "../../serial.h"
struct vbe_mode_info_structure{
uint16_t attributes;
uint8_t window_a;
uint8_t window_b;
uint16_t granularity;
uint16_t window_size;
uint16_t segment_a;
uint16_t segment_b;
uint32_t win_func_ptr;
uint16_t pitch;
uint16_t width;
uint16_t height;
uint8_t w_char;
uint8_t y_char;
uint8_t planes;
uint8_t bpp;
uint8_t banks;
uint8_t memory_model;
uint8_t bank_size;
uint8_t image_pages;
uint8_t reserved0;
uint8_t red_mask;
uint8_t red_position;
uint8_t green_mask;
uint8_t green_position;
uint8_t blue_mask;
uint8_t blue_position;
uint8_t reserved_mask;
uint8_t reserved_position;
uint8_t direct_color_attributes;
uint32_t framebuffer;
uint32_t off_screen_mem_off;
uint16_t off_screen_mem_size;
uint8_t reserved1[206];
}__attribute__((packed));
struct VbeInfoBlock {
char VbeSignature[4];
uint16_t VbeVersion;
uint16_t OemStringPtr;
uint8_t Capabilities;
uint16_t VideoModePtr;
uint16_t TotalMemory;
}__attribute__((packed));
extern VbeInfoBlock* vbeInfo;
extern vbe_mode_info_structure* VbeModeInfo;
void initVBEDevice(multiboot_info_t* mbt);
void blueDiagnalLineTest(multiboot_info_t* mbt);
// Primitive drawing functions
void putPixel( int x, int y , uint32_t colour);
void drawLine(int x1, int y1, int x2, int y2, uint32_t colour );
void drawRect ( int x, int y, int width, int height, uint32_t colour );

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);
@ -48,15 +51,8 @@ void initGDT(){
gdtDescriptor.limit = ((sizeof(SegmentDescriptor ) * 5 ) - 1);
gdtDescriptor.base = (unsigned int) &GlobalDescriptorTable;
printf("Hello GDT!\n");
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,60 +1,108 @@
#include "kernel.h"
#define GB4 524288
#define GB2 262144
extern "C" void kernel_main (void);
extern "C" void putPixel(int pos_x, int pos_y, unsigned char VGA_COLOR , unsigned char addr , unsigned char pixelWidth, unsigned pitch );
extern "C" void kernel_main (void);
extern "C" void early_main(unsigned long magic, unsigned long addr){
/** initialize terminal interface */
// kterm_init();
/**
* Initialize terminal interface
* NOTE: This should be done later on , the magic value should be checked first.
*/
kterm_init();
printf("Magic flag 0x%8x\n", magic);
printf("Magic must be 0x%8x\n", MULTIBOOT_BOOTLOADER_MAGIC);
/**
* 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%8x\n", 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();
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

@ -1,10 +1,14 @@
#pragma once
#include "tty/kterm.h"
#include "io.h"
#define PORT 0x3f8
static int init_serial() {
inline 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
@ -26,95 +30,33 @@ inline static int init_serial() {
return 0;
}
inline int is_transmit_empty() {
int is_transmit_empty() {
return inb(PORT + 5) & 0x20;
}
inline void write_serial(char a) {
void write_serial(char a) {
while (is_transmit_empty() == 0);
outb(PORT,a);
}
inline int serial_received() {
int serial_received() {
return inb(PORT + 5) & 1;
}
inline char read_serial() {
char read_serial() {
while (serial_received() == 0);
return inb(PORT);
}
inline void print_serial(const char* string ){
void print_serial(const char* string ){
for(size_t i = 0; i < strlen(string); i ++){
write_serial(string[i]);
}
}
inline void printf_serial ( const char *format, ...) {
char **arg = (char **)&format;
int c;
char buf[20];
arg++;
while ((c = *format++) != 0){
if( c != '%')
write_serial(c);
else{
char *p, *p2;
int pad0 = 0, pad = 0;
c = *format++;
if(c =='0'){
pad0 = 1;
c = *format++;
}
if ( c >= '0' && c <= '9'){
pad = c - '0';
c = *format++;
}
switch (c)
{
case 'd':
case 'u':
case 'x':
itoa(buf, c, *((int *) arg++));
p = buf;
goto string;
break;
case 's':
p = *arg++;
if(!p)
p = "(null)";
string:
for (p2 = p; *p2; p2++);
for (; p2 < p + pad; p2++)
write_serial(pad0 ? '0': ' ');
while (*p)
write_serial(*p++);
break;
default:
write_serial(*((int *)arg++));
break;
}
}
}
}
inline void test_serial(){
void test_serial(){
/** Serial test **/
kterm_writestring("Writing to COM1 serial port:");
init_serial();

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

@ -137,7 +137,7 @@ void kterm_writestring(const char* data ){
}
void itoa (char *buf, int base, int d) {
static void itoa (char *buf, int base, int d) {
char *p = buf;
char *p1, *p2;
unsigned long ud = d;
@ -174,7 +174,7 @@ void itoa (char *buf, int base, int d) {
}
void printf ( const char *format, ...) {
return;
char **arg = (char **)&format;
int c;
char buf[20];

View File

@ -33,9 +33,10 @@ uint16_t get_cursor_position();
int get_cursor_x (uint16_t cursor_pos);
int get_cursor_y (uint16_t cursor_pos);
extern "C" void itoa (char *buf, int base, int d);
void printf ( const char *format, ...);
//static void itoa (char *buf, int base, int d);
#define KernelTag "[Kernel]: "
#define AS_KERNEL() ( kterm_setcolor(VGA_COLOR_LIGHT_BLUE),\

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