summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimponic <loganthebean222@gmail.com>2021-03-01 15:17:24 -0700
committerSimponic <loganthebean222@gmail.com>2021-03-01 15:17:24 -0700
commitc0c846cc15bbc4a14f705eeb923ed1024f4ee1a0 (patch)
tree9556cbe258bc72d263c33dc4d9876d4fb72402dc
parent09d1dcf3b115658283cb09a08986271398e8d8f8 (diff)
downloadsimponicos-c0c846cc15bbc4a14f705eeb923ed1024f4ee1a0.tar.gz
simponicos-c0c846cc15bbc4a14f705eeb923ed1024f4ee1a0.zip
Move to GitHub for flexing
-rw-r--r--boot.obin976 -> 0 bytes
-rw-r--r--gdt.obin952 -> 0 bytes
-rw-r--r--include/gdt.h4
-rw-r--r--include/idt.h56
-rw-r--r--include/isr.h13
-rw-r--r--include/port.h11
-rw-r--r--include/print.h5
-rw-r--r--makefile2
-rw-r--r--print.obin1704 -> 0 bytes
-rw-r--r--src/boot.s110
-rw-r--r--src/gdt.c31
-rw-r--r--src/idt.c67
-rw-r--r--src/isr.c8
-rw-r--r--src/kernel.c23
-rw-r--r--src/port.c21
-rw-r--r--src/print.c74
16 files changed, 397 insertions, 28 deletions
diff --git a/boot.o b/boot.o
deleted file mode 100644
index 68fc8c6..0000000
--- a/boot.o
+++ /dev/null
Binary files differ
diff --git a/gdt.o b/gdt.o
deleted file mode 100644
index 6034c8b..0000000
--- a/gdt.o
+++ /dev/null
Binary files differ
diff --git a/include/gdt.h b/include/gdt.h
index 8b239dd..51a7112 100644
--- a/include/gdt.h
+++ b/include/gdt.h
@@ -14,4 +14,8 @@ struct GDT_ptr {
uint32_t base;
} __attribute((packed));
+uint8_t gdt_entries[8 * 3]; // (8 bytes per entry) * (num entries)
+
+void encodeGDT(uint8_t* gdtEntry, struct GDT source);
+void initializeGDT();
#endif //GDT_H
diff --git a/include/idt.h b/include/idt.h
new file mode 100644
index 0000000..c08cf75
--- /dev/null
+++ b/include/idt.h
@@ -0,0 +1,56 @@
+#ifndef IDT_H
+#define IDT_H
+
+#include "types.h"
+
+struct IDT {
+ uint32_t base;
+ uint16_t selector;
+ uint8_t flags;
+} __attribute__((packed));
+
+struct IDT_ptr {
+ uint16_t limit;
+ uint32_t base;
+} __attribute__((packed));
+
+uint8_t idt_entries[8 * 256]; // 8 bytes per entry * 256 entries
+
+struct IDT createIDT(uint32_t base, uint16_t selector, uint8_t flags);
+void encodeIDT(uint8_t* idtEntry, struct IDT source);
+void initializeIDT();
+
+extern void isr0 ();
+extern void isr1 ();
+extern void isr2 ();
+extern void isr3 ();
+extern void isr4 ();
+extern void isr5 ();
+extern void isr6 ();
+extern void isr7 ();
+extern void isr8 ();
+extern void isr9 ();
+extern void isr10();
+extern void isr11();
+extern void isr12();
+extern void isr13();
+extern void isr14();
+extern void isr15();
+extern void isr16();
+extern void isr17();
+extern void isr18();
+extern void isr19();
+extern void isr20();
+extern void isr21();
+extern void isr22();
+extern void isr23();
+extern void isr24();
+extern void isr25();
+extern void isr26();
+extern void isr27();
+extern void isr28();
+extern void isr29();
+extern void isr30();
+extern void isr31();
+
+#endif // IDT_H
diff --git a/include/isr.h b/include/isr.h
new file mode 100644
index 0000000..831a2f4
--- /dev/null
+++ b/include/isr.h
@@ -0,0 +1,13 @@
+#ifndef ISR_H
+#define ISR_H
+
+#include "types.h"
+
+struct registers{
+ uint32_t ds;
+ uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
+ uint32_t int_no, err_code;
+ uint32_t eip, cs, eflags, useresp, ss;
+} __attribute__((packed));
+
+#endif // ISR_H
diff --git a/include/port.h b/include/port.h
new file mode 100644
index 0000000..d3e6897
--- /dev/null
+++ b/include/port.h
@@ -0,0 +1,11 @@
+#ifndef PORT_H
+#define PORT_H
+
+#include "types.h"
+
+uint8_t port_byte_in (uint8_t port);
+void port_byte_out(uint8_t port, uint8_t data);
+uint16_t port_word_in (uint16_t port);
+void port_word_out(uint16_t port, uint16_t data);
+
+#endif // PORT_H
diff --git a/include/print.h b/include/print.h
index c46843c..421b1f0 100644
--- a/include/print.h
+++ b/include/print.h
@@ -11,9 +11,14 @@ typedef struct TextOutput {
uint16_t* vid_mem;
}__attribute__((packed)) TextOutput;
+TextOutput monitor;
+
TextOutput createOutput(const int max_row, const int max_column, uint16_t* vid_mem);
void scrollText(TextOutput* textOutput);
void putChar(uint8_t character, uint8_t background, uint8_t foreground, TextOutput* textOutput);
void print(char* string, uint8_t background, uint8_t foreground, TextOutput* textOutput);
+char* itoa(int value, char* buffer, int base);
+void printToMonitor(char* string);
+void printIntToMonitor(int num, int base);
#endif // PRINT_H
diff --git a/makefile b/makefile
index acda2c3..b36e070 100644
--- a/makefile
+++ b/makefile
@@ -3,7 +3,7 @@ CXX = i386-elf-gcc
CFLAGS = -std=gnu99 -ffreestanding -O2 -Wall -Wextra -nostdlib -Iinclude
ASM = nasm
-OBJECTS = gdt.o boot.o print.o kernel.o
+OBJECTS = boot.o gdt.o isr.o idt.o port.o print.o kernel.o
%.o : src/%.c
$(CXX) $(CFLAGS) -o $@ -c $<
diff --git a/print.o b/print.o
deleted file mode 100644
index 1e31a59..0000000
--- a/print.o
+++ /dev/null
Binary files differ
diff --git a/src/boot.s b/src/boot.s
index 2472103..2022ea3 100644
--- a/src/boot.s
+++ b/src/boot.s
@@ -38,19 +38,100 @@ stack_top:
; Declare _start as a function symbol with the given symbol size.
section .text
-global _gdt_flush ; Allows the C code to link to this
-extern _gp ; Says that '_gp' is in another file
-_gdt_flush:
- lgdt [_gp] ; Load the GDT with our '_gp' which is a special pointer
- mov ax, 0x10 ; 0x10 is the offset in the GDT to our data segment
- mov ds, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
- mov ss, ax
- jmp 0x08:flush2 ; 0x08 is the offset to our code segment: Far jump!
-flush2:
- ret ; Returns back to the C code!
+global reloadSegments ; Flush GDT
+reloadSegments:
+ ; Reload CS register containing code selector:
+ JMP 0x08:reload_CS ; 0x08 points at the new code selector
+reload_CS:
+ ; Reload data segment registers:
+ MOV AX, 0x10 ; 0x10 points at the new data selector
+ MOV DS, AX
+ MOV ES, AX
+ MOV FS, AX
+ MOV GS, AX
+ MOV SS, AX
+ RET
+
+%macro ISR_NOERRCODE 1 ; define a macro, taking one parameter
+ [GLOBAL isr%1] ; %1 accesses the first parameter.
+ isr%1:
+ cli
+ push byte 0
+ push byte %1
+ jmp isr_common_stub
+%endmacro
+
+%macro ISR_ERRCODE 1
+ [GLOBAL isr%1]
+ isr%1:
+ cli
+ push byte %1
+ jmp isr_common_stub
+%endmacro
+
+ISR_NOERRCODE 0
+ISR_NOERRCODE 1
+ISR_NOERRCODE 2
+ISR_NOERRCODE 3
+ISR_NOERRCODE 4
+ISR_NOERRCODE 5
+ISR_NOERRCODE 6
+ISR_NOERRCODE 7
+ISR_NOERRCODE 8
+ISR_NOERRCODE 9
+ISR_NOERRCODE 10
+ISR_NOERRCODE 11
+ISR_NOERRCODE 12
+ISR_NOERRCODE 13
+ISR_NOERRCODE 14
+ISR_NOERRCODE 15
+ISR_NOERRCODE 16
+ISR_NOERRCODE 17
+ISR_NOERRCODE 18
+ISR_NOERRCODE 19
+ISR_NOERRCODE 20
+ISR_NOERRCODE 21
+ISR_NOERRCODE 22
+ISR_NOERRCODE 23
+ISR_NOERRCODE 24
+ISR_NOERRCODE 25
+ISR_NOERRCODE 26
+ISR_NOERRCODE 27
+ISR_NOERRCODE 28
+ISR_NOERRCODE 29
+ISR_NOERRCODE 30
+ISR_NOERRCODE 31
+
+
+[EXTERN isr_handler]
+
+; This is our common ISR stub. It saves the processor state, sets
+; up for kernel mode segments, calls the C-level fault handler,
+; and finally restores the stack frame.
+isr_common_stub:
+ pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax
+
+ mov ax, ds ; Lower 16-bits of eax = ds.
+ push eax ; save the data segment descriptor
+
+ mov ax, 0x10 ; load the kernel data segment descriptor
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+
+ call isr_handler
+
+ pop eax ; reload the original data segment descriptor
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+
+ popa ; Pops edi,esi,ebp...
+ add esp, 8 ; Cleans up the pushed error code and pushed ISR number
+ sti
+ iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
global _start:function (_start.end - _start)
_start:
@@ -69,7 +150,8 @@ _start:
; stack (as it grows downwards on x86 systems). This is necessarily done
; in assembly as languages such as C cannot function without a stack.
mov esp, stack_top
-
+
+
; This is a good place to initialize crucial processor state before the
; high-level kernel is entered. It's best to minimize the early
; environment where crucial features are offline. Note that the
diff --git a/src/gdt.c b/src/gdt.c
index a9808aa..fa52f38 100644
--- a/src/gdt.c
+++ b/src/gdt.c
@@ -1,5 +1,7 @@
#include "gdt.h"
+extern void reloadSegments();
+
void encodeGDT(uint8_t* gdtEntry, struct GDT source) {
if ((source.limit > 65536) && ((source.limit & 0xFFF) == 0xFFF)) {
// Set the GDT to use paging
@@ -34,3 +36,32 @@ void encodeGDT(uint8_t* gdtEntry, struct GDT source) {
// where most of the ideas for this function are taken from shamelessly
gdtEntry[5] = source.type;
}
+
+void initializeGDT() {
+ struct GDT nullEntry;
+ nullEntry.limit = 0;
+ nullEntry.base = 0;
+ nullEntry.type = 0;
+
+ struct GDT codeSection;
+ codeSection.limit = 0xFFFFFFFF;
+ codeSection.base = 0;
+ codeSection.type = 0x9A;
+
+ struct GDT dataSection;
+ dataSection.limit = 0xFFFFFFFF;
+ dataSection.base = 0;
+ dataSection.type = 0x92;
+
+ encodeGDT(gdt_entries , nullEntry );
+ encodeGDT(gdt_entries + 8 , codeSection);
+ encodeGDT(gdt_entries + 16, dataSection);
+
+ struct GDT_ptr gdt_ptr;
+ gdt_ptr.limit = 8*3;
+ gdt_ptr.base = (uint32_t)(&gdt_entries);
+
+ asm("lgdt (%0)" : :"r" ((uint8_t*)(&gdt_ptr)));
+
+ reloadSegments();
+}
diff --git a/src/idt.c b/src/idt.c
new file mode 100644
index 0000000..cb53408
--- /dev/null
+++ b/src/idt.c
@@ -0,0 +1,67 @@
+#include "idt.h"
+
+struct IDT createIDT(uint32_t base, uint16_t selector, uint8_t flags) {
+ struct IDT result;
+ result.base = base;
+ result.selector = selector;
+ result.flags = flags;
+ return result;
+}
+
+void encodeIDT(uint8_t* idtEntry, struct IDT source) {
+ // Low base bytes
+ idtEntry[0] = source.base & 0xFF;
+ idtEntry[1] = (source.base >> 8) & 0xFF;
+ // Selector bytes
+ idtEntry[2] = source.selector & 0xFF;
+ idtEntry[3] = (source.selector >> 8) & 0xFF;
+ idtEntry[4] = 0; // Null byte
+ idtEntry[5] = source.flags; // Flag bytes
+ // High base bytes
+ idtEntry[6] = (source.base >> 16) & 0xFF;
+ idtEntry[7] = (source.base >> 24) & 0xFF;
+}
+
+void initializeIDT() {
+ struct IDT_ptr idt_ptr;
+ idt_ptr.limit = 8*256 - 1;
+ idt_ptr.base = (uint32_t)&idt_entries;
+
+ for (int i = 0; i < 256*8; i++)
+ idt_entries[i] = 0; // Just to be safe, set IDT to all 0
+
+ encodeIDT(&idt_entries[0] , createIDT((uint32_t)isr0 , 0x08, 0x8E));
+ encodeIDT(&idt_entries[1*8 - 1] , createIDT((uint32_t)isr1 , 0x08, 0x8E));
+ encodeIDT(&idt_entries[2*8 - 1] , createIDT((uint32_t)isr2 , 0x08, 0x8E));
+ encodeIDT(&idt_entries[3*8 - 1] , createIDT((uint32_t)isr3 , 0x08, 0x8E));
+ encodeIDT(&idt_entries[4*8 - 1] , createIDT((uint32_t)isr4 , 0x08, 0x8E));
+ encodeIDT(&idt_entries[5*8 - 1] , createIDT((uint32_t)isr5 , 0x08, 0x8E));
+ encodeIDT(&idt_entries[6*8 - 1] , createIDT((uint32_t)isr6 , 0x08, 0x8E));
+ encodeIDT(&idt_entries[7*8 - 1] , createIDT((uint32_t)isr7 , 0x08, 0x8E));
+ encodeIDT(&idt_entries[8*8 - 1] , createIDT((uint32_t)isr8 , 0x08, 0x8E));
+ encodeIDT(&idt_entries[9*8 - 1] , createIDT((uint32_t)isr9 , 0x08, 0x8E));
+ encodeIDT(&idt_entries[10*8 - 1], createIDT((uint32_t)isr10, 0x08, 0x8E));
+ encodeIDT(&idt_entries[11*8 - 1], createIDT((uint32_t)isr11, 0x08, 0x8E));
+ encodeIDT(&idt_entries[12*8 - 1], createIDT((uint32_t)isr12, 0x08, 0x8E));
+ encodeIDT(&idt_entries[13*8 - 1], createIDT((uint32_t)isr13, 0x08, 0x8E));
+ encodeIDT(&idt_entries[14*8 - 1], createIDT((uint32_t)isr14, 0x08, 0x8E));
+ encodeIDT(&idt_entries[15*8 - 1], createIDT((uint32_t)isr15, 0x08, 0x8E));
+ encodeIDT(&idt_entries[16*8 - 1], createIDT((uint32_t)isr16, 0x08, 0x8E));
+ encodeIDT(&idt_entries[17*8 - 1], createIDT((uint32_t)isr17, 0x08, 0x8E));
+ encodeIDT(&idt_entries[18*8 - 1], createIDT((uint32_t)isr18, 0x08, 0x8E));
+ encodeIDT(&idt_entries[19*8 - 1], createIDT((uint32_t)isr19, 0x08, 0x8E));
+ encodeIDT(&idt_entries[20*8 - 1], createIDT((uint32_t)isr20, 0x08, 0x8E));
+ encodeIDT(&idt_entries[21*8 - 1], createIDT((uint32_t)isr21, 0x08, 0x8E));
+ encodeIDT(&idt_entries[22*8 - 1], createIDT((uint32_t)isr22, 0x08, 0x8E));
+ encodeIDT(&idt_entries[23*8 - 1], createIDT((uint32_t)isr23, 0x08, 0x8E));
+ encodeIDT(&idt_entries[24*8 - 1], createIDT((uint32_t)isr24, 0x08, 0x8E));
+ encodeIDT(&idt_entries[25*8 - 1], createIDT((uint32_t)isr25, 0x08, 0x8E));
+ encodeIDT(&idt_entries[26*8 - 1], createIDT((uint32_t)isr26, 0x08, 0x8E));
+ encodeIDT(&idt_entries[27*8 - 1], createIDT((uint32_t)isr27, 0x08, 0x8E));
+ encodeIDT(&idt_entries[28*8 - 1], createIDT((uint32_t)isr28, 0x08, 0x8E));
+ encodeIDT(&idt_entries[29*8 - 1], createIDT((uint32_t)isr29, 0x08, 0x8E));
+ encodeIDT(&idt_entries[30*8 - 1], createIDT((uint32_t)isr30, 0x08, 0x8E));
+ encodeIDT(&idt_entries[31*8 - 1], createIDT((uint32_t)isr31, 0x08, 0x8E));
+
+ asm("lidt (%0)" : :"r" ((uint8_t*)(&idt_ptr)));
+}
diff --git a/src/isr.c b/src/isr.c
new file mode 100644
index 0000000..fbc61dc
--- /dev/null
+++ b/src/isr.c
@@ -0,0 +1,8 @@
+#include "isr.h"
+#include "print.h"
+
+void isr_handler(struct registers regs) {
+ printToMonitor("recieved interrupt: \n");
+ printIntToMonitor(regs.int_no, 10);
+ printToMonitor("\n");
+}
diff --git a/src/kernel.c b/src/kernel.c
index d24c24e..653cd4e 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -1,22 +1,21 @@
#include "gdt.h"
+#include "idt.h"
+#include "isr.h"
#include "types.h"
#include "print.h"
+#include "port.h"
+
+// inline function to swap two numbers
#define FOREGROUND 0x0
#define BACKGROUND 0xF
-void PrintWithScreenFill(char* string, TextOutput* output_stream) {
- // Print a string and fill the screen
- print(string, BACKGROUND, FOREGROUND, output_stream);
- int row = output_stream->terminal_row;
- while (output_stream->terminal_row < output_stream->max_row) {
- putChar('\n', BACKGROUND, FOREGROUND, output_stream);
- }
- output_stream->terminal_row = row;
-}
-
void kernel_main(void) {
- TextOutput output_stream = createOutput(25,80,(uint16_t*)0xB8000);
- PrintWithScreenFill("Hello, Logan World!\n", &output_stream);
+ initializeGDT();
+ initializeIDT();
+ printToMonitor("Hello\n");
+ printIntToMonitor(10, 10);
+ asm ("int $0x3");
+ asm ("int $0x4");
}
diff --git a/src/port.c b/src/port.c
new file mode 100644
index 0000000..2a19315
--- /dev/null
+++ b/src/port.c
@@ -0,0 +1,21 @@
+#include "port.h"
+
+uint8_t port_byte_in (uint8_t port) {
+ uint8_t result;
+ __asm__("in %%dx, %%al" : "=a" (result) : "d" (port));
+ return result;
+}
+
+void port_byte_out(uint8_t port, uint8_t data) {
+ __asm__("out %%al, %%dx" : :"a" (data), "d" (port));
+}
+
+uint16_t port_word_in (uint16_t port) {
+ uint16_t result;
+ __asm__("in %%dx, %%ax" : "=a" (result) : "d" (port));
+ return result;
+}
+
+void port_word_out (uint16_t port, uint16_t data) {
+ __asm__("out %%ax, %%dx" : :"a" (data), "d" (port));
+}
diff --git a/src/print.c b/src/print.c
index 0a0220c..3c03577 100644
--- a/src/print.c
+++ b/src/print.c
@@ -1,5 +1,8 @@
#include "print.h"
+#define FOREGROUND 0x0
+#define BACKGROUND 0xF
+
TextOutput createOutput(const int max_row, const int max_column, uint16_t* vid_mem) {
// Create a new TextOutput interface
TextOutput output;
@@ -66,8 +69,77 @@ void putChar(uint8_t character, uint8_t background, uint8_t foreground,
void print(char* string, uint8_t background, uint8_t foreground, TextOutput* textOutput) {
// Print a string
- for (string; *string; string++) {
+ while (*string) {
putChar(*string, background, foreground, textOutput);
+ string++;
}
}
+void PrintWithScreenFill(char* string, TextOutput* output_stream) {
+ // Print a string and fill the screen
+ print(string, BACKGROUND, FOREGROUND, output_stream);
+ int row = output_stream->terminal_row;
+ while (output_stream->terminal_row < output_stream->max_row) {
+ putChar('\n', BACKGROUND, FOREGROUND, output_stream);
+ }
+ output_stream->terminal_row = row;
+}
+
+
+inline void swap(char *x, char *y) {
+ char t = *x; *x = *y; *y = t;
+}
+
+int abs(int value) {
+ return (value < 0 ? -value : value);
+}
+
+// function to reverse buffer[i..j]
+char* reverse(char *buffer, int i, int j)
+{
+ while (i < j)
+ swap(&buffer[i++], &buffer[j--]);
+
+ return buffer;
+}
+
+// Iterative function to implement itoa() function in C
+char* itoa(int value, char* buffer, int base)
+{
+ if (base < 2 || base > 32)
+ return buffer;
+ int n = abs(value);
+ int i = 0;
+ while (n)
+ {
+ int r = n % base;
+ if (r >= 10)
+ buffer[i++] = 65 + (r - 10);
+ else
+ buffer[i++] = 48 + r;
+ n = n / base;
+ }
+ if (i == 0)
+ buffer[i++] = '0';
+ if (value < 0 && base == 10)
+ buffer[i++] = '-';
+ buffer[i] = '\0';
+ return reverse(buffer, 0, i - 1);
+}
+
+int haveFilledScreen = 0;
+
+void printToMonitor(char* string) {
+ if (!haveFilledScreen) {
+ monitor = createOutput(25, 80, (uint16_t*)(0xB8000));
+ PrintWithScreenFill(string, &monitor);
+ haveFilledScreen = 1;
+ }
+ else
+ print(string, BACKGROUND, FOREGROUND, &monitor);
+}
+
+void printIntToMonitor(int num, int base) {
+ char* buffer;
+ printToMonitor(itoa(num, buffer, base));
+}