summaryrefslogtreecommitdiff
path: root/src/c
diff options
context:
space:
mode:
authorAleksa Vučković <aleksav013@gmail.com>2021-10-25 22:41:21 +0200
committerAleksa Vučković <aleksav013@gmail.com>2021-10-25 22:41:21 +0200
commit39822cdb0acdd1eec66c2e18e0711fd3cd6f033d (patch)
tree313eb08002f6e6e1c6564f2d411287745079da22 /src/c
parent20dd72e40dc2728d3c5335d860e4b8ab8da14fcc (diff)
Adding first 32 IRQs; PIT finally working
Diffstat (limited to 'src/c')
-rw-r--r--src/c/gdt.c13
-rw-r--r--src/c/idt.c100
-rw-r--r--src/c/irq_handler.c204
-rw-r--r--src/c/kernel.c7
-rw-r--r--src/c/keyboard.c7
-rw-r--r--src/c/stack_protector.c22
-rw-r--r--src/c/timer.c45
-rw-r--r--src/c/tty.c32
-rw-r--r--src/c/vga.c43
9 files changed, 377 insertions, 96 deletions
diff --git a/src/c/gdt.c b/src/c/gdt.c
index 8fcda3a..32d070b 100644
--- a/src/c/gdt.c
+++ b/src/c/gdt.c
@@ -19,7 +19,7 @@ struct gdt_pointer
// asm function
extern void load_gdt(struct gdt_pointer *gdtp);
-struct gdt_entry gdt[3];
+struct gdt_entry gdt[5];
struct gdt_pointer gdtp;
void init_gdt_entry(size_t num, uint32_t limit, uint32_t base, uint8_t access, uint8_t limit_flags)
@@ -37,12 +37,11 @@ void init_gdt_table()
gdtp.size=sizeof(gdt)-1;
gdtp.offset=(uint32_t)&gdt;
- //null
- init_gdt_entry(0,0,0,0,0);
- //code
- init_gdt_entry(1,0xffffffff,0,0b10011010,0b11001111);
- //data
- init_gdt_entry(2,0xffffffff,0,0b10010010,0b11001111);
+ init_gdt_entry(0,0,0,0,0); // null segment
+ init_gdt_entry(1,0xffffffff,0,0b10011010,0b11001111); // code segment
+ init_gdt_entry(2,0xffffffff,0,0b10010010,0b11001111); // data segment
+ init_gdt_entry(3,0xffffffff,0,0b11111010,0b11001111); // user mode code segment
+ init_gdt_entry(4,0xffffffff,0,0b11110010,0b11001111); // user mode data segment
load_gdt(&gdtp);
}
diff --git a/src/c/idt.c b/src/c/idt.c
index 274db6d..d12015e 100644
--- a/src/c/idt.c
+++ b/src/c/idt.c
@@ -1,6 +1,8 @@
#include"../include/types.h"
+#include"../include/irq.h"
+#include"../include/asm.h"
-#define INTERRUPT_GATE_32 0x8e
+#define INTERRUPT_GATE_32 0x8E
#define KERNEL_CODE 0x08
#define KERNEL_DATA 0x10
@@ -25,10 +27,9 @@ struct idt_pointer
uint32_t offset;
} __attribute__((packed));
-// asm function
+
extern void load_idt(struct idt_pointer *idtp);
-extern void keyboard_handler();
-extern void ioport_out(uint8_t port, char data);
+extern void keyboard_irq();
struct idt_entry idt[256];
struct idt_pointer idtp;
@@ -41,57 +42,64 @@ void init_idt_entry(size_t num, uint32_t offset, uint16_t selector, uint8_t type
idt[num].type_attr=type_attr;
idt[num].offset2=(offset & 0xffff0000)>>16;
}
-
-void init_idt_table()
+void add_idt_entry(size_t num,uint32_t offset)
{
- // Program the PICs - Programmable Interrupt Controllers
- // Background:
- // In modern architectures, the PIC is not a separate chip.
- // It is emulated in the CPU for backwards compatability.
- // The APIC (Advanced Programmable Interrupt Controller)
- // is the new version of the PIC that is integrated into the CPU.
- // Default vector offset for PIC is 8
- // This maps IRQ0 to interrupt 8, IRQ1 to interrupt 9, etc.
- // This is a problem. The CPU reserves the first 32 interrupts for
- // CPU exceptions such as divide by 0, etc.
- // In programming the PICs, we move this offset to 0x2 (32) so that
- // we can handle all interrupts coming to the PICs without overlapping
- // with any CPU exceptions.
+ init_idt_entry(num,offset,KERNEL_CODE,INTERRUPT_GATE_32);
+}
- // Send ICWs - Initialization Command Words
- // PIC1: IO Port 0x20 (command), 0xA0 (data)
- // PIC2: IO Port 0x21 (command), 0xA1 (data)
- // ICW1: Initialization command
- // Send a fixed value of 0x11 to each PIC to tell it to expect ICW2-4
- // Restart PIC1
+void init_pic()
+{
ioport_out(PIC1_COMMAND_PORT, 0x11);
ioport_out(PIC2_COMMAND_PORT, 0x11);
- // ICW2: Vector Offset (this is what we are fixing)
- // Start PIC1 at 32 (0x20 in hex) (IRQ0=0x20, ..., IRQ7=0x27)
- // Start PIC2 right after, at 40 (0x28 in hex)
ioport_out(PIC1_DATA_PORT, 0x20);
ioport_out(PIC2_DATA_PORT, 0x28);
- // ICW3: Cascading (how master/slave PICs are wired/daisy chained)
- // Tell PIC1 there is a slave PIC at IRQ2 (why 4? don't ask me - https://wiki.osdev.org/8259_PIC)
- // Tell PIC2 "its cascade identity" - again, I'm shaky on this concept. More resources in notes
- ioport_out(PIC1_DATA_PORT, 0x0);
- ioport_out(PIC2_DATA_PORT, 0x0);
- // ICW4: "Gives additional information about the environemnt"
- // See notes for some potential values
- // We are using 8086/8088 (MCS-80/85) mode
- // Not sure if that's relevant, but there it is.
- // Other modes appear to be special slave/master configurations (see wiki)
- ioport_out(PIC1_DATA_PORT, 0x1);
- ioport_out(PIC2_DATA_PORT, 0x1);
- // Voila! PICs are initialized
-
- // Mask all interrupts (why? not entirely sure)
- // 0xff is 16 bits that are all 1.
- // This masks each of the 16 interrupts for that PIC.
+ ioport_out(PIC1_DATA_PORT, 0x04);
+ ioport_out(PIC2_DATA_PORT, 0x02);
+ ioport_out(PIC1_DATA_PORT, 0x01);
+ ioport_out(PIC2_DATA_PORT, 0x01);
ioport_out(PIC1_DATA_PORT, 0xff);
ioport_out(PIC2_DATA_PORT, 0xff);
- init_idt_entry(0x21,(uint32_t)keyboard_handler,KERNEL_CODE,INTERRUPT_GATE_32);
+ ioport_out(PIC1_DATA_PORT, 0xFC);
+}
+
+void init_idt_table()
+{
+ init_pic();
+ add_idt_entry(0,(uint32_t)irq0);
+ add_idt_entry(1,(uint32_t)irq1);
+ add_idt_entry(2,(uint32_t)irq2);
+ add_idt_entry(3,(uint32_t)irq3);
+ add_idt_entry(4,(uint32_t)irq4);
+ add_idt_entry(5,(uint32_t)irq5);
+ add_idt_entry(6,(uint32_t)irq6);
+ add_idt_entry(7,(uint32_t)irq7);
+ add_idt_entry(8,(uint32_t)irq8);
+ add_idt_entry(9,(uint32_t)irq9);
+ add_idt_entry(10,(uint32_t)irq10);
+ add_idt_entry(11,(uint32_t)irq11);
+ add_idt_entry(12,(uint32_t)irq12);
+ add_idt_entry(13,(uint32_t)irq13);
+ add_idt_entry(14,(uint32_t)irq14);
+ add_idt_entry(15,(uint32_t)irq15);
+ add_idt_entry(16,(uint32_t)irq16);
+ add_idt_entry(17,(uint32_t)irq17);
+ add_idt_entry(18,(uint32_t)irq18);
+ add_idt_entry(19,(uint32_t)irq19);
+ add_idt_entry(20,(uint32_t)irq20);
+ add_idt_entry(21,(uint32_t)irq21);
+ add_idt_entry(22,(uint32_t)irq22);
+ add_idt_entry(23,(uint32_t)irq23);
+ add_idt_entry(24,(uint32_t)irq24);
+ add_idt_entry(25,(uint32_t)irq25);
+ add_idt_entry(26,(uint32_t)irq26);
+ add_idt_entry(27,(uint32_t)irq27);
+ add_idt_entry(28,(uint32_t)irq28);
+ add_idt_entry(29,(uint32_t)irq29);
+ add_idt_entry(30,(uint32_t)irq30);
+ add_idt_entry(31,(uint32_t)irq31);
+ add_idt_entry(32,(uint32_t)timer_irq);
+ add_idt_entry(33,(uint32_t)keyboard_irq);
idtp.size=sizeof(struct idt_entry)*256-1;
idtp.offset=(uint32_t)&idt;
diff --git a/src/c/irq_handler.c b/src/c/irq_handler.c
new file mode 100644
index 0000000..6b80a52
--- /dev/null
+++ b/src/c/irq_handler.c
@@ -0,0 +1,204 @@
+#include"../include/stdio.h"
+#include"../include/asm.h"
+
+#define INTERRUPT_GATE_32 0x8e
+
+#define KERNEL_CODE 0x08
+#define KERNEL_DATA 0x10
+
+#define PIC1_COMMAND_PORT 0x20
+#define PIC1_DATA_PORT 0x21
+#define PIC2_COMMAND_PORT 0xA0
+#define PIC2_DATA_PORT 0xA1
+
+void irq0_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 0.\n");
+}
+
+void irq1_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 1.\n");
+}
+
+void irq2_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 2.\n");
+}
+
+void irq3_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 3.\n");
+}
+
+void irq4_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 4.\n");
+}
+
+void irq5_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 5.\n");
+}
+
+void irq6_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 6.\n");
+}
+
+void irq7_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 7.\n");
+}
+
+void irq8_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 8.\n");
+}
+
+void irq9_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 9.\n");
+}
+
+void irq10_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 10.\n");
+}
+
+void irq11_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 11.\n");
+}
+
+void irq12_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 12.\n");
+}
+
+void irq13_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 13.\n");
+}
+
+void irq14_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 14.\n");
+}
+
+void irq15_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 15.\n");
+}
+
+void irq16_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 16.\n");
+}
+
+void irq17_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 17.\n");
+}
+
+void irq18_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 18.\n");
+}
+
+void irq19_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 19.\n");
+}
+
+void irq20_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 20.\n");
+}
+
+void irq21_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 21.\n");
+}
+
+void irq22_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 22.\n");
+}
+
+void irq23_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 23.\n");
+}
+
+void irq24_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 24.\n");
+}
+
+void irq25_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 25.\n");
+}
+
+void irq26_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 26.\n");
+}
+
+void irq27_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 27.\n");
+}
+
+void irq28_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 28.\n");
+}
+
+void irq29_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 29.\n");
+}
+
+void irq30_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 30.\n");
+}
+
+void irq31_handler()
+{
+ ioport_out(PIC1_COMMAND_PORT, 0x20);
+ printf("Interrupt 31.\n");
+}
diff --git a/src/c/kernel.c b/src/c/kernel.c
index e18a7c0..62f444c 100644
--- a/src/c/kernel.c
+++ b/src/c/kernel.c
@@ -3,6 +3,7 @@
void terminal_initialize(void);
void init_idt_table(void);
void init_keyboard(void);
+void init_timer(uint32_t frequency);
void prompt(void);
void kernel_main(void)
@@ -10,8 +11,10 @@ void kernel_main(void)
terminal_initialize();
init_idt_table();
init_keyboard();
- k_heapBMInit(&kheap);
-
+ init_timer(50);
+ //k_heapBMInit(&kheap);
+ //k_heapBMAddBlock(&kheap, 0x100000, 0x100000, 16);
prompt();
+
while(1) __asm__("hlt\n\t");
}
diff --git a/src/c/keyboard.c b/src/c/keyboard.c
index 548cdda..473ec20 100644
--- a/src/c/keyboard.c
+++ b/src/c/keyboard.c
@@ -17,7 +17,6 @@ size_t buffer_index=0;
void previous_field(void);
void terminal_putchar(char c);
void tty(char *buffer);
-void prompt(void);
void clear();
void us_en(char keymap[]);
@@ -26,9 +25,6 @@ bool ispressed[128];
void init_keyboard()
{
- // 0xFD = 1111 1101 in binary. enables only IRQ1
- // Why IRQ1? Remember, IRQ0 exists, it's 0-based
- ioport_out(PIC1_DATA_PORT, 0xFD);
us_en(charcode);
}
@@ -52,7 +48,6 @@ void enter()
for(int i=0;i<BUFFER_SIZE;i++) buffer[i]='\0';
buffer_index=0;
}
- prompt();
return;
}
@@ -64,7 +59,7 @@ void space()
#define lshift ispressed[0x2A]
#define lctrl ispressed[0x1D]
-void handle_keyboard_interrupt()
+void keyboard_handler()
{
ioport_out(PIC1_COMMAND_PORT, 0x20);
uint8_t status = ioport_in(KEYBOARD_STATUS_PORT);
diff --git a/src/c/stack_protector.c b/src/c/stack_protector.c
new file mode 100644
index 0000000..50e4316
--- /dev/null
+++ b/src/c/stack_protector.c
@@ -0,0 +1,22 @@
+#include <stdint.h>
+#include"../include/stdio.h"
+
+#if UINT32_MAX == UINTPTR_MAX
+#define STACK_CHK_GUARD 0xe2dee396
+#else
+#define STACK_CHK_GUARD 0x595e9fbd94fda766
+#endif
+
+uintptr_t __stack_chk_guard = STACK_CHK_GUARD;
+
+__attribute__((noreturn))
+void __stack_chk_fail(void)
+{
+#if __STDC_HOSTED__
+ printf("Stack smashing detected\n");
+ abort();
+#elif __is_myos_kernel
+ printf("Stack smashing detected\n");
+ panic("Stack smashing detected");
+#endif
+}
diff --git a/src/c/timer.c b/src/c/timer.c
new file mode 100644
index 0000000..edeea21
--- /dev/null
+++ b/src/c/timer.c
@@ -0,0 +1,45 @@
+#include"../include/types.h"
+#include"../include/asm.h"
+#include"../include/stdio.h"
+
+void add_idt_entry(size_t num,uint32_t offset);
+
+uint32_t tick=0;
+const uint32_t TICKS_PER_SECOND=50;
+extern uint32_t time;
+uint32_t time=0;
+
+void timer_handler()
+{
+ tick++;
+ if(tick==TICKS_PER_SECOND)
+ {
+ //printf("%d seconds passed\n",time);
+ tick=0;
+ time++;
+ }
+
+ ioport_out(0x20, 0x20);
+ ioport_out(0xa0,0x20);
+}
+
+void init_timer(uint32_t frequency)
+{
+ // Firstly, register our timer callback.
+
+ // The value we send to the PIT is the value to divide it's input clock
+ // (1193180 Hz) by, to get our required frequency. Important to note is
+ // that the divisor must be small enough to fit into 16-bits.
+ uint32_t divisor = 1193180 / frequency;
+
+ // Send the command byte.
+ ioport_out(0x43, 0x36);
+
+ // Divisor has to be sent byte-wise, so split here into upper/lower bytes.
+ uint8_t l = (uint8_t)(divisor & 0xFF);
+ uint8_t h = (uint8_t)( (divisor>>8) & 0xFF );
+
+ // Send the frequency divisor.
+ ioport_out(0x40, l);
+ ioport_out(0x40, h);
+}
diff --git a/src/c/tty.c b/src/c/tty.c
index 5728a47..8516489 100644
--- a/src/c/tty.c
+++ b/src/c/tty.c
@@ -1,10 +1,12 @@
#include"../include/types.h"
#include"../include/string.h"
#include"../include/stdio.h"
+#include"../include/vga.h"
#define CMD_LENGTH 20
void clear();
+extern uint32_t time;
size_t pieces(char pieces[][CMD_LENGTH],char *buffer)
{
@@ -61,6 +63,33 @@ void number(size_t numberof,char parts[][CMD_LENGTH])
}
}
+void uptime()
+{
+ printf("System uptime is: %d seconds\n",time);
+}
+
+void prompt()
+{
+ printf("[user@myos] > ");
+}
+
+void neofetch()
+{
+ set_color(VGA_COLOR_RED,VGA_COLOR_BLACK);
+ printf(" <*>\n");
+ printf(" <*>\n");
+ printf(" <*>\n");
+ printf(" <*>\n");
+ printf(" <*>\n");
+ printf(" <*>\n");
+ printf(" <*>\n");
+ printf("<*******>\n");
+ printf(" <***>\n");
+ printf(" <*>\n");
+ set_color(VGA_COLOR_LIGHT_GREY,VGA_COLOR_BLACK);
+ uptime();
+}
+
void tty(char *buffer)
{
char parts[CMD_LENGTH][CMD_LENGTH];
@@ -71,5 +100,8 @@ void tty(char *buffer)
else if(stringcmp(parts[0],"merge")) merge(parts);
else if(stringcmp(parts[0],"ls")) ls(numberof,parts);
else if(stringcmp(parts[0],"number")) number(numberof,parts);
+ else if(stringcmp(parts[0],"uptime")) uptime();
+ else if(stringcmp(parts[0],"neofetch")) neofetch();
else printf("command not found: %s\n",parts[0]);
+ prompt();
}
diff --git a/src/c/vga.c b/src/c/vga.c
index 07dec60..8c1824b 100644
--- a/src/c/vga.c
+++ b/src/c/vga.c
@@ -1,33 +1,16 @@
#include"../include/types.h"
#include"../include/string.h"
#include"../include/asm.h"
+#include"../include/vga.h"
-static const size_t VGA_WIDTH = 80;
-static const size_t VGA_HEIGHT = 25;
-
-
-enum vga_color {
- VGA_COLOR_BLACK = 0,
- VGA_COLOR_BLUE = 1,
- VGA_COLOR_GREEN = 2,
- VGA_COLOR_CYAN = 3,
- VGA_COLOR_RED = 4,
- VGA_COLOR_MAGENTA = 5,
- VGA_COLOR_BROWN = 6,
- VGA_COLOR_LIGHT_GREY = 7,
- VGA_COLOR_DARK_GREY = 8,
- VGA_COLOR_LIGHT_BLUE = 9,
- VGA_COLOR_LIGHT_GREEN = 10,
- VGA_COLOR_LIGHT_CYAN = 11,
- VGA_COLOR_LIGHT_RED = 12,
- VGA_COLOR_LIGHT_MAGENTA = 13,
- VGA_COLOR_LIGHT_BROWN = 14,
- VGA_COLOR_WHITE = 15,
-};
+size_t terminal_row;
+size_t terminal_column;
+uint8_t terminal_color;
+uint16_t* terminal_buffer;
-static inline uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg)
+void set_color(enum vga_color fg, enum vga_color bg)
{
- return fg | bg << 4;
+ terminal_color = fg | bg << 4;
}
static inline uint16_t vga_entry(unsigned char uc, uint8_t color)
@@ -35,16 +18,11 @@ static inline uint16_t vga_entry(unsigned char uc, uint8_t color)
return (uint16_t) uc | (uint16_t) color << 8;
}
-size_t terminal_row;
-size_t terminal_column;
-uint8_t terminal_color;
-uint16_t* terminal_buffer;
-
void terminal_initialize()
{
terminal_row=0;
terminal_column=0;
- terminal_color=vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK);
+ set_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK);
terminal_buffer=(uint16_t*) 0xB8000;
for(size_t y=0;y<VGA_HEIGHT;y++)
{
@@ -113,11 +91,6 @@ void terminal_writefloat(double num)
terminal_writestring(str);
}
-void prompt()
-{
- terminal_writestring("[user@myos] > ");
-}
-
void clear()
{
for(size_t i=0;i<VGA_HEIGHT;i++) for(size_t j=0;j<VGA_WIDTH;j++) terminal_putchar(' ');