struct IDTSlot {
uint16_t offset_first;
uint16_t selector;
uint8_t zero;
uint8_t type_attr;
uint16_t offset_second;
} __attribute__((packed));
struct IDTPtr {
uint16_t limit;
uint32_t base;
} __attribute__((packed));
#pragma once
#ifndef _IDT_
#include "stdint.h"
#define IDT_SIZE 256
namespace SimpleOS {
class IDT {
struct IDTSlot;
struct IDTPtr;
static IDTSlot idt[IDT_SIZE];
static IDTPtr idt_ptr;
public:
static void init_idt();
private:
static void dividing_by_zero();
private:
static void set_in_idt_slot(int pos, uint32_t base, uint16_t sel, uint8_t flags);
static void load_idt();
struct IDTSlot {
uint16_t offset_first;
uint16_t selector;
uint8_t zero;
uint8_t type_attr;
uint16_t offset_second;
};
struct IDTPtr {
uint16_t limit;
uint32_t base;
};
};
}
#endif // _IDT_
#include "IDT/IDT.h"
#include "terminal/terminal.h"
using namespace SimpleOS;
void IDT::init_idt() {
set_in_idt_slot(0, (uint32_t)dividing_by_zero, 0x08, 0x8E); // 0x08, 0x8E
load_idt();
__asm__ __volatile__("sti");
}
void IDT::set_in_idt_slot(int pos, uint32_t base, uint16_t sel, uint8_t flags) {
idt[pos].offset_first = base & 0xFFFF;
idt[pos].selector = sel;
idt[pos].zero = 0;
idt[pos].type_attr = flags;
idt[pos].offset_second = (base >> 16) & 0xFFFF;
}
void IDT::load_idt() {
idt_ptr.limit = (sizeof(IDTSlot) * IDT_SIZE) - 1;
idt_ptr.base = (uint32_t)&idt;
__asm__ __volatile__("lidt (%0)" : : "r" (&idt_ptr));
}
void IDT::dividing_by_zero() {
Terminal::print("Failed operation dividing by zero");
__asm__ __volatile__("cli; iret");
}
IDT::IDTSlot IDT::idt[IDT_SIZE];
IDT::IDTPtr IDT::idt_ptr;
#pragma once
#ifndef _TERMINAL_
#include "utils/typedef.h"
#include <stdint.h>
#include <stddef.h>
#define VIDEO_MEMORY_ADDRESS 0xB8000
namespace SimpleOS {
class Terminal {
static size_t pos;
public:
static void print(cstr msg);
static void print(char c, size_t pos);
static void print(char c);
};
}
#endif // _TERMINAL_
#include "terminal/terminal.h"
using namespace SimpleOS;
void Terminal::print(cstr msg) {
while (*msg) {
print(*msg);
++msg;
}
}
void Terminal::print(char c, size_t pos) {
char* buffer = (char*)VIDEO_MEMORY_ADDRESS;
buffer[pos * 2] = c;
buffer[pos * 2 + 1] = 0x07;
}
void Terminal::print(char c) {
print(c, pos++);
}
size_t Terminal::pos = 0;
#pragma once
#ifndef _TYPEDEF_
namespace SimpleOS {
using str = char*;
using cstr = const char*;
}
#endif // _TYPEDEF_
#include "terminal/terminal.h"
#include "IDT/IDT.h"
using namespace SimpleOS;
extern "C" void kernel_main(void) {
IDT::init_idt();
__asm__ __volatile__("int $0");
}
ENTRY(_start)
SECTIONS
{
. = 1M;
.text BLOCK(4K) : ALIGN(4K)
{
KEEP(*(.multiboot))
*(.text)
}
.rodata BLOCK(4K) : ALIGN(4K)
{
*(.rodata)
}
.data BLOCK(4K) : ALIGN(4K)
{
*(.data)
}
.bss BLOCK(4K) : ALIGN(4K)
{
*(COMMON)
*(.bss)
}
}
.set ALIGN, 1<<0
.set MEMINFO, 1<<1
.set FLAGS, ALIGN | MEMINFO
.set MAGIC, 0x1BADB002
.set CHECKSUM, -(MAGIC + FLAGS)
.section .multiboot
.align 4
.long MAGIC
.long FLAGS
.long CHECKSUM
.section .bss
.align 16
stack_bottom:
.skip 16384
stack_top:
.section .text
.global _start
.type _start, function
_start:
mov $stack_top, %esp
call kernel_main
cli
1: hlt
jmp 1b
.size _start, . - _start
TARGET = SimpleOS
AC = i686-elf-as
LC = i686-elf-gcc
CPPC = i686-elf-g++
CPPSRC = $(wildcard src/**/*.cpp)
CPPOBJ = $(patsubst %.cpp, %.o, $(CPPSRC))
ASRC = $(wildcard *.s)
AOBJ = $(patsubst %.s, %.o, $(ASRC))
$(TARGET) : $(CPPOBJ) $(AOBJ)
$(LC) -T linker.ld -o iso/boot/$(TARGET).bin -ffreestanding -O2 -nostdlib $(AOBJ) $(CPPOBJ) -lgcc
%.o : %.s
$(AC) $< -o $@
%.o : %.cpp
$(CPPC) -c $< -o $@ -Iinclude -ffreestanding -O0 -Wall -Wextra -fno-exceptions -fno-rtti
clean :
del $(TARGET) *.o