diff --git a/.vscode/settings.json b/.vscode/settings.json index dd72655..36c0cfc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { - "*.h": "c" + "*.h": "c", + "type_traits": "c" } } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index dd72655..36c0cfc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { - "*.h": "c" + "*.h": "c", + "type_traits": "c" } } \ No newline at end of file diff --git a/src/headers/_stdio.h b/src/headers/_stdio.h new file mode 100644 index 0000000..b5d4f87 --- /dev/null +++ b/src/headers/_stdio.h @@ -0,0 +1,20 @@ +#ifndef STDIO_H +#define STDIO_H + +#include + +#define FRAMEBUFFER_LOCATION 0x000B8000 +#define VIDEO_WIDTH 80 +#define VIDEO_HEIGHT 25 + +extern void setTextStyle(uint8_t style); +extern void clearScreen(); +extern void printf(const char* format, ...); +extern void putCharAt(char c, uint8_t x, uint8_t y); +extern void putCharsAt(char* string, uint8_t x, uint8_t y); +extern void puts(char* string); +extern void putChars(char* string, uint32_t length); + +extern uint32_t strlen(char* string); + +#endif \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index dd72655..36c0cfc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { - "*.h": "c" + "*.h": "c", + "type_traits": "c" } } \ No newline at end of file diff --git a/src/headers/_stdio.h b/src/headers/_stdio.h new file mode 100644 index 0000000..b5d4f87 --- /dev/null +++ b/src/headers/_stdio.h @@ -0,0 +1,20 @@ +#ifndef STDIO_H +#define STDIO_H + +#include + +#define FRAMEBUFFER_LOCATION 0x000B8000 +#define VIDEO_WIDTH 80 +#define VIDEO_HEIGHT 25 + +extern void setTextStyle(uint8_t style); +extern void clearScreen(); +extern void printf(const char* format, ...); +extern void putCharAt(char c, uint8_t x, uint8_t y); +extern void putCharsAt(char* string, uint8_t x, uint8_t y); +extern void puts(char* string); +extern void putChars(char* string, uint32_t length); + +extern uint32_t strlen(char* string); + +#endif \ No newline at end of file diff --git a/src/headers/interrupts.h b/src/headers/interrupts.h new file mode 100644 index 0000000..3ca3d29 --- /dev/null +++ b/src/headers/interrupts.h @@ -0,0 +1,21 @@ +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + +#include + +typedef struct { + uint16_t isr_low; + uint16_t codeSegment; + uint8_t reserved; + uint8_t attributes; + uint16_t isr_high; +} __attribute__((packed)) IDTEntry; + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) IDTR; + +extern void initInterrupts(); + +#endif \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index dd72655..36c0cfc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { - "*.h": "c" + "*.h": "c", + "type_traits": "c" } } \ No newline at end of file diff --git a/src/headers/_stdio.h b/src/headers/_stdio.h new file mode 100644 index 0000000..b5d4f87 --- /dev/null +++ b/src/headers/_stdio.h @@ -0,0 +1,20 @@ +#ifndef STDIO_H +#define STDIO_H + +#include + +#define FRAMEBUFFER_LOCATION 0x000B8000 +#define VIDEO_WIDTH 80 +#define VIDEO_HEIGHT 25 + +extern void setTextStyle(uint8_t style); +extern void clearScreen(); +extern void printf(const char* format, ...); +extern void putCharAt(char c, uint8_t x, uint8_t y); +extern void putCharsAt(char* string, uint8_t x, uint8_t y); +extern void puts(char* string); +extern void putChars(char* string, uint32_t length); + +extern uint32_t strlen(char* string); + +#endif \ No newline at end of file diff --git a/src/headers/interrupts.h b/src/headers/interrupts.h new file mode 100644 index 0000000..3ca3d29 --- /dev/null +++ b/src/headers/interrupts.h @@ -0,0 +1,21 @@ +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + +#include + +typedef struct { + uint16_t isr_low; + uint16_t codeSegment; + uint8_t reserved; + uint8_t attributes; + uint16_t isr_high; +} __attribute__((packed)) IDTEntry; + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) IDTR; + +extern void initInterrupts(); + +#endif \ No newline at end of file diff --git a/src/headers/stdio.h b/src/headers/stdio.h deleted file mode 100644 index b5d4f87..0000000 --- a/src/headers/stdio.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef STDIO_H -#define STDIO_H - -#include - -#define FRAMEBUFFER_LOCATION 0x000B8000 -#define VIDEO_WIDTH 80 -#define VIDEO_HEIGHT 25 - -extern void setTextStyle(uint8_t style); -extern void clearScreen(); -extern void printf(const char* format, ...); -extern void putCharAt(char c, uint8_t x, uint8_t y); -extern void putCharsAt(char* string, uint8_t x, uint8_t y); -extern void puts(char* string); -extern void putChars(char* string, uint32_t length); - -extern uint32_t strlen(char* string); - -#endif \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index dd72655..36c0cfc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { - "*.h": "c" + "*.h": "c", + "type_traits": "c" } } \ No newline at end of file diff --git a/src/headers/_stdio.h b/src/headers/_stdio.h new file mode 100644 index 0000000..b5d4f87 --- /dev/null +++ b/src/headers/_stdio.h @@ -0,0 +1,20 @@ +#ifndef STDIO_H +#define STDIO_H + +#include + +#define FRAMEBUFFER_LOCATION 0x000B8000 +#define VIDEO_WIDTH 80 +#define VIDEO_HEIGHT 25 + +extern void setTextStyle(uint8_t style); +extern void clearScreen(); +extern void printf(const char* format, ...); +extern void putCharAt(char c, uint8_t x, uint8_t y); +extern void putCharsAt(char* string, uint8_t x, uint8_t y); +extern void puts(char* string); +extern void putChars(char* string, uint32_t length); + +extern uint32_t strlen(char* string); + +#endif \ No newline at end of file diff --git a/src/headers/interrupts.h b/src/headers/interrupts.h new file mode 100644 index 0000000..3ca3d29 --- /dev/null +++ b/src/headers/interrupts.h @@ -0,0 +1,21 @@ +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + +#include + +typedef struct { + uint16_t isr_low; + uint16_t codeSegment; + uint8_t reserved; + uint8_t attributes; + uint16_t isr_high; +} __attribute__((packed)) IDTEntry; + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) IDTR; + +extern void initInterrupts(); + +#endif \ No newline at end of file diff --git a/src/headers/stdio.h b/src/headers/stdio.h deleted file mode 100644 index b5d4f87..0000000 --- a/src/headers/stdio.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef STDIO_H -#define STDIO_H - -#include - -#define FRAMEBUFFER_LOCATION 0x000B8000 -#define VIDEO_WIDTH 80 -#define VIDEO_HEIGHT 25 - -extern void setTextStyle(uint8_t style); -extern void clearScreen(); -extern void printf(const char* format, ...); -extern void putCharAt(char c, uint8_t x, uint8_t y); -extern void putCharsAt(char* string, uint8_t x, uint8_t y); -extern void puts(char* string); -extern void putChars(char* string, uint32_t length); - -extern uint32_t strlen(char* string); - -#endif \ No newline at end of file diff --git a/src/interrupts/interrupts.c b/src/interrupts/interrupts.c new file mode 100644 index 0000000..74d2931 --- /dev/null +++ b/src/interrupts/interrupts.c @@ -0,0 +1,33 @@ +#include +#include <_stdio.h> +#include + +IDTR idtr; +IDTEntry* entries; +void* buffer; + +void setInterrupt(uint8_t vector, void* callback, uint8_t flags) { + IDTEntry* descriptor = &entries[vector]; + + descriptor->isr_low = (uint32_t)callback & 0xFFFF; + descriptor->codeSegment = 0x08; + descriptor->attributes = flags; + descriptor->isr_high = (uint32_t)callback >> 16; + descriptor->reserved = 0; +} + +void testInterrupt() { + printf("interrupt!\n"); +} + +void initInterrupts() { + buffer = malloc(sizeof(IDTEntry) * 257); + entries = (IDTEntry*) (((int) buffer + sizeof(IDTEntry)) & -1 ^ 0x0F); + idtr.limit = sizeof(IDTEntry) * 256 - 1; + idtr.base = entries; + for (int i = 0; i < 256; i++) { + setInterrupt(i, testInterrupt, 0x8E); + } + __asm__ volatile ("lidt %0" : : "memory"(idtr)); + __asm__ volatile ("sti"); +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index dd72655..36c0cfc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { - "*.h": "c" + "*.h": "c", + "type_traits": "c" } } \ No newline at end of file diff --git a/src/headers/_stdio.h b/src/headers/_stdio.h new file mode 100644 index 0000000..b5d4f87 --- /dev/null +++ b/src/headers/_stdio.h @@ -0,0 +1,20 @@ +#ifndef STDIO_H +#define STDIO_H + +#include + +#define FRAMEBUFFER_LOCATION 0x000B8000 +#define VIDEO_WIDTH 80 +#define VIDEO_HEIGHT 25 + +extern void setTextStyle(uint8_t style); +extern void clearScreen(); +extern void printf(const char* format, ...); +extern void putCharAt(char c, uint8_t x, uint8_t y); +extern void putCharsAt(char* string, uint8_t x, uint8_t y); +extern void puts(char* string); +extern void putChars(char* string, uint32_t length); + +extern uint32_t strlen(char* string); + +#endif \ No newline at end of file diff --git a/src/headers/interrupts.h b/src/headers/interrupts.h new file mode 100644 index 0000000..3ca3d29 --- /dev/null +++ b/src/headers/interrupts.h @@ -0,0 +1,21 @@ +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + +#include + +typedef struct { + uint16_t isr_low; + uint16_t codeSegment; + uint8_t reserved; + uint8_t attributes; + uint16_t isr_high; +} __attribute__((packed)) IDTEntry; + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) IDTR; + +extern void initInterrupts(); + +#endif \ No newline at end of file diff --git a/src/headers/stdio.h b/src/headers/stdio.h deleted file mode 100644 index b5d4f87..0000000 --- a/src/headers/stdio.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef STDIO_H -#define STDIO_H - -#include - -#define FRAMEBUFFER_LOCATION 0x000B8000 -#define VIDEO_WIDTH 80 -#define VIDEO_HEIGHT 25 - -extern void setTextStyle(uint8_t style); -extern void clearScreen(); -extern void printf(const char* format, ...); -extern void putCharAt(char c, uint8_t x, uint8_t y); -extern void putCharsAt(char* string, uint8_t x, uint8_t y); -extern void puts(char* string); -extern void putChars(char* string, uint32_t length); - -extern uint32_t strlen(char* string); - -#endif \ No newline at end of file diff --git a/src/interrupts/interrupts.c b/src/interrupts/interrupts.c new file mode 100644 index 0000000..74d2931 --- /dev/null +++ b/src/interrupts/interrupts.c @@ -0,0 +1,33 @@ +#include +#include <_stdio.h> +#include + +IDTR idtr; +IDTEntry* entries; +void* buffer; + +void setInterrupt(uint8_t vector, void* callback, uint8_t flags) { + IDTEntry* descriptor = &entries[vector]; + + descriptor->isr_low = (uint32_t)callback & 0xFFFF; + descriptor->codeSegment = 0x08; + descriptor->attributes = flags; + descriptor->isr_high = (uint32_t)callback >> 16; + descriptor->reserved = 0; +} + +void testInterrupt() { + printf("interrupt!\n"); +} + +void initInterrupts() { + buffer = malloc(sizeof(IDTEntry) * 257); + entries = (IDTEntry*) (((int) buffer + sizeof(IDTEntry)) & -1 ^ 0x0F); + idtr.limit = sizeof(IDTEntry) * 256 - 1; + idtr.base = entries; + for (int i = 0; i < 256; i++) { + setInterrupt(i, testInterrupt, 0x8E); + } + __asm__ volatile ("lidt %0" : : "memory"(idtr)); + __asm__ volatile ("sti"); +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/_stdio.c b/src/kernel/drivers/textMode/_stdio.c new file mode 100644 index 0000000..34eea3f --- /dev/null +++ b/src/kernel/drivers/textMode/_stdio.c @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <_stdio.h> + +uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; +char format = 0x0F; + +void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { + *(framebuffer + position) = c; +} + +void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { + putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +void putCharAtOffset(char c, uint16_t offset) { + putCharWithFormatAtOffset(c | format << 8, offset); +} + +void putCharAt(char c, uint8_t x, uint8_t y) { + putCharAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { + return *(framebuffer + x + y * VIDEO_WIDTH); +} + +void putCharsAt(char* string, uint8_t x, uint8_t y) { + uint16_t position = 0; + char c = *string; + while (c != 0x00) { + putCharAt(c, x + position, y); + position++; + c = *(string + position); + } +} + +void shiftUp() { + for (int y = 1; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); + } + } + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); + } +} + +void newLine() { + uint16_t offset = getCursorOffset(); + uint8_t x = offset % VIDEO_WIDTH; + uint8_t y = offset / VIDEO_WIDTH; + x = 0; + y++; + if (y >= VIDEO_HEIGHT) { + shiftUp(); + y--; + } + setCursorPosition(x, y); +} + +void putChar(char c) { + if (c == '\n') { + newLine(); + return; + } + uint16_t offset = getCursorOffset(); + putCharAtOffset(c, offset); + setCursorOffset(offset + 1); +} + +void puts(char* string) { + while (*string != 0x00) { + putChar(*string); + string++; + } +} + +char HEX_PREFIX[] = "0x"; +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char** write, uint32_t x) { + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + **write = HEX_CHARS[byte >> 8]; + (*write)++; + } + } +} + +uint8_t hexLength(uint32_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return size; +} + +uint32_t getInsertLength(char insertType, uint32_t x) { + switch (insertType) { + case 's': + return strlen((char*) x); + case 'x': + return hexLength(x); + } + return 0; +} + +void stringInsert(char** write, uint32_t x) { + char* string = (char*) x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char** write, char insertType, uint32_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + } +} + +void printf(const char* format, ...) { + uint32_t size = 0; + va_list valist; + va_start(valist, format); + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + size += getInsertLength(format[++i], va_arg(valist, uint32_t)); + continue; + } + size++; + } + va_start(valist, format); + + char* data = malloc(size); + char* write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(valist, uint32_t)); + continue; + } + *write = format[i]; + write++; + } + va_end(valist); + + Message* message = malloc(sizeof(Message)); + + message->data = data; + message->size = size; + message->next = 0x00; + sendMessage(getPrinterTask(), message); + schedule(getPrinterTask()); +} + +void clearScreen() { + setCursorOffset(0); + for (int y = 0; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharAt(' ', x, y); + } + } +} + +void setTextStyle(uint8_t style) { + format = style; +} + +void putChars(char* string, uint32_t length) { + for (uint32_t i = 0; i < length; i++) { + if (string[i] == '\n') { + newLine(); + continue; + } + putChar(string[i]); + } +} + +uint32_t strlen(char* string) { + uint32_t length = 0; + while (string[length] != 0) { + length++; + } + return length; +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index dd72655..36c0cfc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { - "*.h": "c" + "*.h": "c", + "type_traits": "c" } } \ No newline at end of file diff --git a/src/headers/_stdio.h b/src/headers/_stdio.h new file mode 100644 index 0000000..b5d4f87 --- /dev/null +++ b/src/headers/_stdio.h @@ -0,0 +1,20 @@ +#ifndef STDIO_H +#define STDIO_H + +#include + +#define FRAMEBUFFER_LOCATION 0x000B8000 +#define VIDEO_WIDTH 80 +#define VIDEO_HEIGHT 25 + +extern void setTextStyle(uint8_t style); +extern void clearScreen(); +extern void printf(const char* format, ...); +extern void putCharAt(char c, uint8_t x, uint8_t y); +extern void putCharsAt(char* string, uint8_t x, uint8_t y); +extern void puts(char* string); +extern void putChars(char* string, uint32_t length); + +extern uint32_t strlen(char* string); + +#endif \ No newline at end of file diff --git a/src/headers/interrupts.h b/src/headers/interrupts.h new file mode 100644 index 0000000..3ca3d29 --- /dev/null +++ b/src/headers/interrupts.h @@ -0,0 +1,21 @@ +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + +#include + +typedef struct { + uint16_t isr_low; + uint16_t codeSegment; + uint8_t reserved; + uint8_t attributes; + uint16_t isr_high; +} __attribute__((packed)) IDTEntry; + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) IDTR; + +extern void initInterrupts(); + +#endif \ No newline at end of file diff --git a/src/headers/stdio.h b/src/headers/stdio.h deleted file mode 100644 index b5d4f87..0000000 --- a/src/headers/stdio.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef STDIO_H -#define STDIO_H - -#include - -#define FRAMEBUFFER_LOCATION 0x000B8000 -#define VIDEO_WIDTH 80 -#define VIDEO_HEIGHT 25 - -extern void setTextStyle(uint8_t style); -extern void clearScreen(); -extern void printf(const char* format, ...); -extern void putCharAt(char c, uint8_t x, uint8_t y); -extern void putCharsAt(char* string, uint8_t x, uint8_t y); -extern void puts(char* string); -extern void putChars(char* string, uint32_t length); - -extern uint32_t strlen(char* string); - -#endif \ No newline at end of file diff --git a/src/interrupts/interrupts.c b/src/interrupts/interrupts.c new file mode 100644 index 0000000..74d2931 --- /dev/null +++ b/src/interrupts/interrupts.c @@ -0,0 +1,33 @@ +#include +#include <_stdio.h> +#include + +IDTR idtr; +IDTEntry* entries; +void* buffer; + +void setInterrupt(uint8_t vector, void* callback, uint8_t flags) { + IDTEntry* descriptor = &entries[vector]; + + descriptor->isr_low = (uint32_t)callback & 0xFFFF; + descriptor->codeSegment = 0x08; + descriptor->attributes = flags; + descriptor->isr_high = (uint32_t)callback >> 16; + descriptor->reserved = 0; +} + +void testInterrupt() { + printf("interrupt!\n"); +} + +void initInterrupts() { + buffer = malloc(sizeof(IDTEntry) * 257); + entries = (IDTEntry*) (((int) buffer + sizeof(IDTEntry)) & -1 ^ 0x0F); + idtr.limit = sizeof(IDTEntry) * 256 - 1; + idtr.base = entries; + for (int i = 0; i < 256; i++) { + setInterrupt(i, testInterrupt, 0x8E); + } + __asm__ volatile ("lidt %0" : : "memory"(idtr)); + __asm__ volatile ("sti"); +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/_stdio.c b/src/kernel/drivers/textMode/_stdio.c new file mode 100644 index 0000000..34eea3f --- /dev/null +++ b/src/kernel/drivers/textMode/_stdio.c @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <_stdio.h> + +uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; +char format = 0x0F; + +void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { + *(framebuffer + position) = c; +} + +void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { + putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +void putCharAtOffset(char c, uint16_t offset) { + putCharWithFormatAtOffset(c | format << 8, offset); +} + +void putCharAt(char c, uint8_t x, uint8_t y) { + putCharAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { + return *(framebuffer + x + y * VIDEO_WIDTH); +} + +void putCharsAt(char* string, uint8_t x, uint8_t y) { + uint16_t position = 0; + char c = *string; + while (c != 0x00) { + putCharAt(c, x + position, y); + position++; + c = *(string + position); + } +} + +void shiftUp() { + for (int y = 1; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); + } + } + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); + } +} + +void newLine() { + uint16_t offset = getCursorOffset(); + uint8_t x = offset % VIDEO_WIDTH; + uint8_t y = offset / VIDEO_WIDTH; + x = 0; + y++; + if (y >= VIDEO_HEIGHT) { + shiftUp(); + y--; + } + setCursorPosition(x, y); +} + +void putChar(char c) { + if (c == '\n') { + newLine(); + return; + } + uint16_t offset = getCursorOffset(); + putCharAtOffset(c, offset); + setCursorOffset(offset + 1); +} + +void puts(char* string) { + while (*string != 0x00) { + putChar(*string); + string++; + } +} + +char HEX_PREFIX[] = "0x"; +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char** write, uint32_t x) { + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + **write = HEX_CHARS[byte >> 8]; + (*write)++; + } + } +} + +uint8_t hexLength(uint32_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return size; +} + +uint32_t getInsertLength(char insertType, uint32_t x) { + switch (insertType) { + case 's': + return strlen((char*) x); + case 'x': + return hexLength(x); + } + return 0; +} + +void stringInsert(char** write, uint32_t x) { + char* string = (char*) x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char** write, char insertType, uint32_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + } +} + +void printf(const char* format, ...) { + uint32_t size = 0; + va_list valist; + va_start(valist, format); + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + size += getInsertLength(format[++i], va_arg(valist, uint32_t)); + continue; + } + size++; + } + va_start(valist, format); + + char* data = malloc(size); + char* write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(valist, uint32_t)); + continue; + } + *write = format[i]; + write++; + } + va_end(valist); + + Message* message = malloc(sizeof(Message)); + + message->data = data; + message->size = size; + message->next = 0x00; + sendMessage(getPrinterTask(), message); + schedule(getPrinterTask()); +} + +void clearScreen() { + setCursorOffset(0); + for (int y = 0; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharAt(' ', x, y); + } + } +} + +void setTextStyle(uint8_t style) { + format = style; +} + +void putChars(char* string, uint32_t length) { + for (uint32_t i = 0; i < length; i++) { + if (string[i] == '\n') { + newLine(); + continue; + } + putChar(string[i]); + } +} + +uint32_t strlen(char* string) { + uint32_t length = 0; + while (string[length] != 0) { + length++; + } + return length; +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/cursor.c b/src/kernel/drivers/textMode/cursor.c new file mode 100644 index 0000000..8247c5e --- /dev/null +++ b/src/kernel/drivers/textMode/cursor.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include <_stdio.h> + +void setCursorOffset(uint16_t offset) { + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (offset & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); +} + +void setCursorPosition(uint8_t x, uint8_t y) { + setCursorOffset(x + y * VIDEO_WIDTH); +} + +uint16_t getCursorOffset() { + uint16_t result = 0; + outb(0x3D4, 0x0F); + result |= inb(0x3D5); + outb(0x3D4, 0x0E); + result |= ((uint16_t)inb(0x3D5)) << 8; + return result; +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index dd72655..36c0cfc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { - "*.h": "c" + "*.h": "c", + "type_traits": "c" } } \ No newline at end of file diff --git a/src/headers/_stdio.h b/src/headers/_stdio.h new file mode 100644 index 0000000..b5d4f87 --- /dev/null +++ b/src/headers/_stdio.h @@ -0,0 +1,20 @@ +#ifndef STDIO_H +#define STDIO_H + +#include + +#define FRAMEBUFFER_LOCATION 0x000B8000 +#define VIDEO_WIDTH 80 +#define VIDEO_HEIGHT 25 + +extern void setTextStyle(uint8_t style); +extern void clearScreen(); +extern void printf(const char* format, ...); +extern void putCharAt(char c, uint8_t x, uint8_t y); +extern void putCharsAt(char* string, uint8_t x, uint8_t y); +extern void puts(char* string); +extern void putChars(char* string, uint32_t length); + +extern uint32_t strlen(char* string); + +#endif \ No newline at end of file diff --git a/src/headers/interrupts.h b/src/headers/interrupts.h new file mode 100644 index 0000000..3ca3d29 --- /dev/null +++ b/src/headers/interrupts.h @@ -0,0 +1,21 @@ +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + +#include + +typedef struct { + uint16_t isr_low; + uint16_t codeSegment; + uint8_t reserved; + uint8_t attributes; + uint16_t isr_high; +} __attribute__((packed)) IDTEntry; + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) IDTR; + +extern void initInterrupts(); + +#endif \ No newline at end of file diff --git a/src/headers/stdio.h b/src/headers/stdio.h deleted file mode 100644 index b5d4f87..0000000 --- a/src/headers/stdio.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef STDIO_H -#define STDIO_H - -#include - -#define FRAMEBUFFER_LOCATION 0x000B8000 -#define VIDEO_WIDTH 80 -#define VIDEO_HEIGHT 25 - -extern void setTextStyle(uint8_t style); -extern void clearScreen(); -extern void printf(const char* format, ...); -extern void putCharAt(char c, uint8_t x, uint8_t y); -extern void putCharsAt(char* string, uint8_t x, uint8_t y); -extern void puts(char* string); -extern void putChars(char* string, uint32_t length); - -extern uint32_t strlen(char* string); - -#endif \ No newline at end of file diff --git a/src/interrupts/interrupts.c b/src/interrupts/interrupts.c new file mode 100644 index 0000000..74d2931 --- /dev/null +++ b/src/interrupts/interrupts.c @@ -0,0 +1,33 @@ +#include +#include <_stdio.h> +#include + +IDTR idtr; +IDTEntry* entries; +void* buffer; + +void setInterrupt(uint8_t vector, void* callback, uint8_t flags) { + IDTEntry* descriptor = &entries[vector]; + + descriptor->isr_low = (uint32_t)callback & 0xFFFF; + descriptor->codeSegment = 0x08; + descriptor->attributes = flags; + descriptor->isr_high = (uint32_t)callback >> 16; + descriptor->reserved = 0; +} + +void testInterrupt() { + printf("interrupt!\n"); +} + +void initInterrupts() { + buffer = malloc(sizeof(IDTEntry) * 257); + entries = (IDTEntry*) (((int) buffer + sizeof(IDTEntry)) & -1 ^ 0x0F); + idtr.limit = sizeof(IDTEntry) * 256 - 1; + idtr.base = entries; + for (int i = 0; i < 256; i++) { + setInterrupt(i, testInterrupt, 0x8E); + } + __asm__ volatile ("lidt %0" : : "memory"(idtr)); + __asm__ volatile ("sti"); +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/_stdio.c b/src/kernel/drivers/textMode/_stdio.c new file mode 100644 index 0000000..34eea3f --- /dev/null +++ b/src/kernel/drivers/textMode/_stdio.c @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <_stdio.h> + +uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; +char format = 0x0F; + +void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { + *(framebuffer + position) = c; +} + +void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { + putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +void putCharAtOffset(char c, uint16_t offset) { + putCharWithFormatAtOffset(c | format << 8, offset); +} + +void putCharAt(char c, uint8_t x, uint8_t y) { + putCharAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { + return *(framebuffer + x + y * VIDEO_WIDTH); +} + +void putCharsAt(char* string, uint8_t x, uint8_t y) { + uint16_t position = 0; + char c = *string; + while (c != 0x00) { + putCharAt(c, x + position, y); + position++; + c = *(string + position); + } +} + +void shiftUp() { + for (int y = 1; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); + } + } + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); + } +} + +void newLine() { + uint16_t offset = getCursorOffset(); + uint8_t x = offset % VIDEO_WIDTH; + uint8_t y = offset / VIDEO_WIDTH; + x = 0; + y++; + if (y >= VIDEO_HEIGHT) { + shiftUp(); + y--; + } + setCursorPosition(x, y); +} + +void putChar(char c) { + if (c == '\n') { + newLine(); + return; + } + uint16_t offset = getCursorOffset(); + putCharAtOffset(c, offset); + setCursorOffset(offset + 1); +} + +void puts(char* string) { + while (*string != 0x00) { + putChar(*string); + string++; + } +} + +char HEX_PREFIX[] = "0x"; +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char** write, uint32_t x) { + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + **write = HEX_CHARS[byte >> 8]; + (*write)++; + } + } +} + +uint8_t hexLength(uint32_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return size; +} + +uint32_t getInsertLength(char insertType, uint32_t x) { + switch (insertType) { + case 's': + return strlen((char*) x); + case 'x': + return hexLength(x); + } + return 0; +} + +void stringInsert(char** write, uint32_t x) { + char* string = (char*) x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char** write, char insertType, uint32_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + } +} + +void printf(const char* format, ...) { + uint32_t size = 0; + va_list valist; + va_start(valist, format); + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + size += getInsertLength(format[++i], va_arg(valist, uint32_t)); + continue; + } + size++; + } + va_start(valist, format); + + char* data = malloc(size); + char* write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(valist, uint32_t)); + continue; + } + *write = format[i]; + write++; + } + va_end(valist); + + Message* message = malloc(sizeof(Message)); + + message->data = data; + message->size = size; + message->next = 0x00; + sendMessage(getPrinterTask(), message); + schedule(getPrinterTask()); +} + +void clearScreen() { + setCursorOffset(0); + for (int y = 0; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharAt(' ', x, y); + } + } +} + +void setTextStyle(uint8_t style) { + format = style; +} + +void putChars(char* string, uint32_t length) { + for (uint32_t i = 0; i < length; i++) { + if (string[i] == '\n') { + newLine(); + continue; + } + putChar(string[i]); + } +} + +uint32_t strlen(char* string) { + uint32_t length = 0; + while (string[length] != 0) { + length++; + } + return length; +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/cursor.c b/src/kernel/drivers/textMode/cursor.c new file mode 100644 index 0000000..8247c5e --- /dev/null +++ b/src/kernel/drivers/textMode/cursor.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include <_stdio.h> + +void setCursorOffset(uint16_t offset) { + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (offset & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); +} + +void setCursorPosition(uint8_t x, uint8_t y) { + setCursorOffset(x + y * VIDEO_WIDTH); +} + +uint16_t getCursorOffset() { + uint16_t result = 0; + outb(0x3D4, 0x0F); + result |= inb(0x3D5); + outb(0x3D4, 0x0E); + result |= ((uint16_t)inb(0x3D5)) << 8; + return result; +} \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index d8ff7b8..48ea59f 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,19 +1,26 @@ #include -#include +#include <_stdio.h> #include #include #include #include #include +#include extern uint32_t _kernel_end; void kernelMain() { - initMemoryAllocation(0x100000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here + initMemoryAllocation(0x1000000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here initOSTasks(); drawLogo(); - printf("Switching to otherTask... \n"); + printf("giving up control...\n"); yields(); printf("Returned to mainTask!\n\n"); + printf("initializing interrupts\n"); + initInterrupts(); + yields(); + printf("trying interrupt\n"); + asm ("int $0x80"); + printf("the interrupt worked!\n"); yield(); } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index dd72655..36c0cfc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { - "*.h": "c" + "*.h": "c", + "type_traits": "c" } } \ No newline at end of file diff --git a/src/headers/_stdio.h b/src/headers/_stdio.h new file mode 100644 index 0000000..b5d4f87 --- /dev/null +++ b/src/headers/_stdio.h @@ -0,0 +1,20 @@ +#ifndef STDIO_H +#define STDIO_H + +#include + +#define FRAMEBUFFER_LOCATION 0x000B8000 +#define VIDEO_WIDTH 80 +#define VIDEO_HEIGHT 25 + +extern void setTextStyle(uint8_t style); +extern void clearScreen(); +extern void printf(const char* format, ...); +extern void putCharAt(char c, uint8_t x, uint8_t y); +extern void putCharsAt(char* string, uint8_t x, uint8_t y); +extern void puts(char* string); +extern void putChars(char* string, uint32_t length); + +extern uint32_t strlen(char* string); + +#endif \ No newline at end of file diff --git a/src/headers/interrupts.h b/src/headers/interrupts.h new file mode 100644 index 0000000..3ca3d29 --- /dev/null +++ b/src/headers/interrupts.h @@ -0,0 +1,21 @@ +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + +#include + +typedef struct { + uint16_t isr_low; + uint16_t codeSegment; + uint8_t reserved; + uint8_t attributes; + uint16_t isr_high; +} __attribute__((packed)) IDTEntry; + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) IDTR; + +extern void initInterrupts(); + +#endif \ No newline at end of file diff --git a/src/headers/stdio.h b/src/headers/stdio.h deleted file mode 100644 index b5d4f87..0000000 --- a/src/headers/stdio.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef STDIO_H -#define STDIO_H - -#include - -#define FRAMEBUFFER_LOCATION 0x000B8000 -#define VIDEO_WIDTH 80 -#define VIDEO_HEIGHT 25 - -extern void setTextStyle(uint8_t style); -extern void clearScreen(); -extern void printf(const char* format, ...); -extern void putCharAt(char c, uint8_t x, uint8_t y); -extern void putCharsAt(char* string, uint8_t x, uint8_t y); -extern void puts(char* string); -extern void putChars(char* string, uint32_t length); - -extern uint32_t strlen(char* string); - -#endif \ No newline at end of file diff --git a/src/interrupts/interrupts.c b/src/interrupts/interrupts.c new file mode 100644 index 0000000..74d2931 --- /dev/null +++ b/src/interrupts/interrupts.c @@ -0,0 +1,33 @@ +#include +#include <_stdio.h> +#include + +IDTR idtr; +IDTEntry* entries; +void* buffer; + +void setInterrupt(uint8_t vector, void* callback, uint8_t flags) { + IDTEntry* descriptor = &entries[vector]; + + descriptor->isr_low = (uint32_t)callback & 0xFFFF; + descriptor->codeSegment = 0x08; + descriptor->attributes = flags; + descriptor->isr_high = (uint32_t)callback >> 16; + descriptor->reserved = 0; +} + +void testInterrupt() { + printf("interrupt!\n"); +} + +void initInterrupts() { + buffer = malloc(sizeof(IDTEntry) * 257); + entries = (IDTEntry*) (((int) buffer + sizeof(IDTEntry)) & -1 ^ 0x0F); + idtr.limit = sizeof(IDTEntry) * 256 - 1; + idtr.base = entries; + for (int i = 0; i < 256; i++) { + setInterrupt(i, testInterrupt, 0x8E); + } + __asm__ volatile ("lidt %0" : : "memory"(idtr)); + __asm__ volatile ("sti"); +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/_stdio.c b/src/kernel/drivers/textMode/_stdio.c new file mode 100644 index 0000000..34eea3f --- /dev/null +++ b/src/kernel/drivers/textMode/_stdio.c @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <_stdio.h> + +uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; +char format = 0x0F; + +void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { + *(framebuffer + position) = c; +} + +void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { + putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +void putCharAtOffset(char c, uint16_t offset) { + putCharWithFormatAtOffset(c | format << 8, offset); +} + +void putCharAt(char c, uint8_t x, uint8_t y) { + putCharAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { + return *(framebuffer + x + y * VIDEO_WIDTH); +} + +void putCharsAt(char* string, uint8_t x, uint8_t y) { + uint16_t position = 0; + char c = *string; + while (c != 0x00) { + putCharAt(c, x + position, y); + position++; + c = *(string + position); + } +} + +void shiftUp() { + for (int y = 1; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); + } + } + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); + } +} + +void newLine() { + uint16_t offset = getCursorOffset(); + uint8_t x = offset % VIDEO_WIDTH; + uint8_t y = offset / VIDEO_WIDTH; + x = 0; + y++; + if (y >= VIDEO_HEIGHT) { + shiftUp(); + y--; + } + setCursorPosition(x, y); +} + +void putChar(char c) { + if (c == '\n') { + newLine(); + return; + } + uint16_t offset = getCursorOffset(); + putCharAtOffset(c, offset); + setCursorOffset(offset + 1); +} + +void puts(char* string) { + while (*string != 0x00) { + putChar(*string); + string++; + } +} + +char HEX_PREFIX[] = "0x"; +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char** write, uint32_t x) { + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + **write = HEX_CHARS[byte >> 8]; + (*write)++; + } + } +} + +uint8_t hexLength(uint32_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return size; +} + +uint32_t getInsertLength(char insertType, uint32_t x) { + switch (insertType) { + case 's': + return strlen((char*) x); + case 'x': + return hexLength(x); + } + return 0; +} + +void stringInsert(char** write, uint32_t x) { + char* string = (char*) x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char** write, char insertType, uint32_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + } +} + +void printf(const char* format, ...) { + uint32_t size = 0; + va_list valist; + va_start(valist, format); + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + size += getInsertLength(format[++i], va_arg(valist, uint32_t)); + continue; + } + size++; + } + va_start(valist, format); + + char* data = malloc(size); + char* write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(valist, uint32_t)); + continue; + } + *write = format[i]; + write++; + } + va_end(valist); + + Message* message = malloc(sizeof(Message)); + + message->data = data; + message->size = size; + message->next = 0x00; + sendMessage(getPrinterTask(), message); + schedule(getPrinterTask()); +} + +void clearScreen() { + setCursorOffset(0); + for (int y = 0; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharAt(' ', x, y); + } + } +} + +void setTextStyle(uint8_t style) { + format = style; +} + +void putChars(char* string, uint32_t length) { + for (uint32_t i = 0; i < length; i++) { + if (string[i] == '\n') { + newLine(); + continue; + } + putChar(string[i]); + } +} + +uint32_t strlen(char* string) { + uint32_t length = 0; + while (string[length] != 0) { + length++; + } + return length; +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/cursor.c b/src/kernel/drivers/textMode/cursor.c new file mode 100644 index 0000000..8247c5e --- /dev/null +++ b/src/kernel/drivers/textMode/cursor.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include <_stdio.h> + +void setCursorOffset(uint16_t offset) { + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (offset & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); +} + +void setCursorPosition(uint8_t x, uint8_t y) { + setCursorOffset(x + y * VIDEO_WIDTH); +} + +uint16_t getCursorOffset() { + uint16_t result = 0; + outb(0x3D4, 0x0F); + result |= inb(0x3D5); + outb(0x3D4, 0x0E); + result |= ((uint16_t)inb(0x3D5)) << 8; + return result; +} \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index d8ff7b8..48ea59f 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,19 +1,26 @@ #include -#include +#include <_stdio.h> #include #include #include #include #include +#include extern uint32_t _kernel_end; void kernelMain() { - initMemoryAllocation(0x100000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here + initMemoryAllocation(0x1000000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here initOSTasks(); drawLogo(); - printf("Switching to otherTask... \n"); + printf("giving up control...\n"); yields(); printf("Returned to mainTask!\n\n"); + printf("initializing interrupts\n"); + initInterrupts(); + yields(); + printf("trying interrupt\n"); + asm ("int $0x80"); + printf("the interrupt worked!\n"); yield(); } \ No newline at end of file diff --git a/src/kernel/lib/memory/alloc.c b/src/kernel/lib/memory/alloc.c deleted file mode 100644 index aedcbad..0000000 --- a/src/kernel/lib/memory/alloc.c +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include -#include - -MemoryBlock* firstBlock; - -void initMemoryAllocation(uint32_t kernelEnd) { - firstBlock = (MemoryBlock*) kernelEnd; - firstBlock->next = 0x00; - firstBlock->last = 0x00; - firstBlock->state = FREE; - firstBlock->size = -1; -} - -void* mallocTask(uint32_t size, Task* task) { - MemoryBlock* current = firstBlock; - while (! (current->next == 0x00 || current->state == FREE && current->size >= size)) { - current = current->next; - } - MemoryBlock* next; - if (current->next == 0x00) { - // this is currently the last block -> initialize the new last block - next = (MemoryBlock*) ((void*) (current + 1) + size); - next->last = current; - next->state = FREE; - next->next = 0x00; - next->size = -1; - } else { - // there is a next block - next = current->next; - } - if (current->size > size + sizeof(MemoryBlock) * 2 && current->next != 0x00) { - // segment the current block if it is big enough - current->next = (MemoryBlock*) (((void*) (current + 1)) + size); - current->next->size = current->size - sizeof(MemoryBlock) - size; - current->size = size; - current->next->state = FREE; - current->next->next = next; - next->last = current->next; - } else { - current->next = next; - if (current->next->next == 0x00) { - current->size = size; - } - } - current->state = IN_USE; - current->task = task; - return (void*) (current + 1); -} - -void* malloc(uint32_t size) { - return mallocTask(size, (Task*) getCurrentTask()); -} - -void mergeNextIfPossible(MemoryBlock* current) { - if (current->next != 0x00 && current->next->state == FREE) { - current->size = current->size + sizeof(MemoryBlock) + current->next->size; - current->next = current->next->next; - current->next->next->last = current; - } -} - -void free(void* location) { - MemoryBlock* current = ((MemoryBlock*) location) - 1; - current->state = FREE; - mergeNextIfPossible(current); - if (current->last != 0x00 && current->last->state == FREE) { - current = current->last; - } - mergeNextIfPossible(current); // call this function twice in case a used block between 2 free blocks is freed - mergeNextIfPossible(current); -} - -void printMemoryStack() { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); - current = current->next; - } - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); -} - -void freeTaskAllocations(Task* task) { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - if (current->task == task) { - free(current); - } - current = current->next; - } - if (current->task == task) { - free(current); - } -} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index dd72655..36c0cfc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { - "*.h": "c" + "*.h": "c", + "type_traits": "c" } } \ No newline at end of file diff --git a/src/headers/_stdio.h b/src/headers/_stdio.h new file mode 100644 index 0000000..b5d4f87 --- /dev/null +++ b/src/headers/_stdio.h @@ -0,0 +1,20 @@ +#ifndef STDIO_H +#define STDIO_H + +#include + +#define FRAMEBUFFER_LOCATION 0x000B8000 +#define VIDEO_WIDTH 80 +#define VIDEO_HEIGHT 25 + +extern void setTextStyle(uint8_t style); +extern void clearScreen(); +extern void printf(const char* format, ...); +extern void putCharAt(char c, uint8_t x, uint8_t y); +extern void putCharsAt(char* string, uint8_t x, uint8_t y); +extern void puts(char* string); +extern void putChars(char* string, uint32_t length); + +extern uint32_t strlen(char* string); + +#endif \ No newline at end of file diff --git a/src/headers/interrupts.h b/src/headers/interrupts.h new file mode 100644 index 0000000..3ca3d29 --- /dev/null +++ b/src/headers/interrupts.h @@ -0,0 +1,21 @@ +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + +#include + +typedef struct { + uint16_t isr_low; + uint16_t codeSegment; + uint8_t reserved; + uint8_t attributes; + uint16_t isr_high; +} __attribute__((packed)) IDTEntry; + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) IDTR; + +extern void initInterrupts(); + +#endif \ No newline at end of file diff --git a/src/headers/stdio.h b/src/headers/stdio.h deleted file mode 100644 index b5d4f87..0000000 --- a/src/headers/stdio.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef STDIO_H -#define STDIO_H - -#include - -#define FRAMEBUFFER_LOCATION 0x000B8000 -#define VIDEO_WIDTH 80 -#define VIDEO_HEIGHT 25 - -extern void setTextStyle(uint8_t style); -extern void clearScreen(); -extern void printf(const char* format, ...); -extern void putCharAt(char c, uint8_t x, uint8_t y); -extern void putCharsAt(char* string, uint8_t x, uint8_t y); -extern void puts(char* string); -extern void putChars(char* string, uint32_t length); - -extern uint32_t strlen(char* string); - -#endif \ No newline at end of file diff --git a/src/interrupts/interrupts.c b/src/interrupts/interrupts.c new file mode 100644 index 0000000..74d2931 --- /dev/null +++ b/src/interrupts/interrupts.c @@ -0,0 +1,33 @@ +#include +#include <_stdio.h> +#include + +IDTR idtr; +IDTEntry* entries; +void* buffer; + +void setInterrupt(uint8_t vector, void* callback, uint8_t flags) { + IDTEntry* descriptor = &entries[vector]; + + descriptor->isr_low = (uint32_t)callback & 0xFFFF; + descriptor->codeSegment = 0x08; + descriptor->attributes = flags; + descriptor->isr_high = (uint32_t)callback >> 16; + descriptor->reserved = 0; +} + +void testInterrupt() { + printf("interrupt!\n"); +} + +void initInterrupts() { + buffer = malloc(sizeof(IDTEntry) * 257); + entries = (IDTEntry*) (((int) buffer + sizeof(IDTEntry)) & -1 ^ 0x0F); + idtr.limit = sizeof(IDTEntry) * 256 - 1; + idtr.base = entries; + for (int i = 0; i < 256; i++) { + setInterrupt(i, testInterrupt, 0x8E); + } + __asm__ volatile ("lidt %0" : : "memory"(idtr)); + __asm__ volatile ("sti"); +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/_stdio.c b/src/kernel/drivers/textMode/_stdio.c new file mode 100644 index 0000000..34eea3f --- /dev/null +++ b/src/kernel/drivers/textMode/_stdio.c @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <_stdio.h> + +uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; +char format = 0x0F; + +void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { + *(framebuffer + position) = c; +} + +void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { + putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +void putCharAtOffset(char c, uint16_t offset) { + putCharWithFormatAtOffset(c | format << 8, offset); +} + +void putCharAt(char c, uint8_t x, uint8_t y) { + putCharAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { + return *(framebuffer + x + y * VIDEO_WIDTH); +} + +void putCharsAt(char* string, uint8_t x, uint8_t y) { + uint16_t position = 0; + char c = *string; + while (c != 0x00) { + putCharAt(c, x + position, y); + position++; + c = *(string + position); + } +} + +void shiftUp() { + for (int y = 1; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); + } + } + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); + } +} + +void newLine() { + uint16_t offset = getCursorOffset(); + uint8_t x = offset % VIDEO_WIDTH; + uint8_t y = offset / VIDEO_WIDTH; + x = 0; + y++; + if (y >= VIDEO_HEIGHT) { + shiftUp(); + y--; + } + setCursorPosition(x, y); +} + +void putChar(char c) { + if (c == '\n') { + newLine(); + return; + } + uint16_t offset = getCursorOffset(); + putCharAtOffset(c, offset); + setCursorOffset(offset + 1); +} + +void puts(char* string) { + while (*string != 0x00) { + putChar(*string); + string++; + } +} + +char HEX_PREFIX[] = "0x"; +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char** write, uint32_t x) { + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + **write = HEX_CHARS[byte >> 8]; + (*write)++; + } + } +} + +uint8_t hexLength(uint32_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return size; +} + +uint32_t getInsertLength(char insertType, uint32_t x) { + switch (insertType) { + case 's': + return strlen((char*) x); + case 'x': + return hexLength(x); + } + return 0; +} + +void stringInsert(char** write, uint32_t x) { + char* string = (char*) x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char** write, char insertType, uint32_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + } +} + +void printf(const char* format, ...) { + uint32_t size = 0; + va_list valist; + va_start(valist, format); + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + size += getInsertLength(format[++i], va_arg(valist, uint32_t)); + continue; + } + size++; + } + va_start(valist, format); + + char* data = malloc(size); + char* write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(valist, uint32_t)); + continue; + } + *write = format[i]; + write++; + } + va_end(valist); + + Message* message = malloc(sizeof(Message)); + + message->data = data; + message->size = size; + message->next = 0x00; + sendMessage(getPrinterTask(), message); + schedule(getPrinterTask()); +} + +void clearScreen() { + setCursorOffset(0); + for (int y = 0; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharAt(' ', x, y); + } + } +} + +void setTextStyle(uint8_t style) { + format = style; +} + +void putChars(char* string, uint32_t length) { + for (uint32_t i = 0; i < length; i++) { + if (string[i] == '\n') { + newLine(); + continue; + } + putChar(string[i]); + } +} + +uint32_t strlen(char* string) { + uint32_t length = 0; + while (string[length] != 0) { + length++; + } + return length; +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/cursor.c b/src/kernel/drivers/textMode/cursor.c new file mode 100644 index 0000000..8247c5e --- /dev/null +++ b/src/kernel/drivers/textMode/cursor.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include <_stdio.h> + +void setCursorOffset(uint16_t offset) { + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (offset & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); +} + +void setCursorPosition(uint8_t x, uint8_t y) { + setCursorOffset(x + y * VIDEO_WIDTH); +} + +uint16_t getCursorOffset() { + uint16_t result = 0; + outb(0x3D4, 0x0F); + result |= inb(0x3D5); + outb(0x3D4, 0x0E); + result |= ((uint16_t)inb(0x3D5)) << 8; + return result; +} \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index d8ff7b8..48ea59f 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,19 +1,26 @@ #include -#include +#include <_stdio.h> #include #include #include #include #include +#include extern uint32_t _kernel_end; void kernelMain() { - initMemoryAllocation(0x100000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here + initMemoryAllocation(0x1000000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here initOSTasks(); drawLogo(); - printf("Switching to otherTask... \n"); + printf("giving up control...\n"); yields(); printf("Returned to mainTask!\n\n"); + printf("initializing interrupts\n"); + initInterrupts(); + yields(); + printf("trying interrupt\n"); + asm ("int $0x80"); + printf("the interrupt worked!\n"); yield(); } \ No newline at end of file diff --git a/src/kernel/lib/memory/alloc.c b/src/kernel/lib/memory/alloc.c deleted file mode 100644 index aedcbad..0000000 --- a/src/kernel/lib/memory/alloc.c +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include -#include - -MemoryBlock* firstBlock; - -void initMemoryAllocation(uint32_t kernelEnd) { - firstBlock = (MemoryBlock*) kernelEnd; - firstBlock->next = 0x00; - firstBlock->last = 0x00; - firstBlock->state = FREE; - firstBlock->size = -1; -} - -void* mallocTask(uint32_t size, Task* task) { - MemoryBlock* current = firstBlock; - while (! (current->next == 0x00 || current->state == FREE && current->size >= size)) { - current = current->next; - } - MemoryBlock* next; - if (current->next == 0x00) { - // this is currently the last block -> initialize the new last block - next = (MemoryBlock*) ((void*) (current + 1) + size); - next->last = current; - next->state = FREE; - next->next = 0x00; - next->size = -1; - } else { - // there is a next block - next = current->next; - } - if (current->size > size + sizeof(MemoryBlock) * 2 && current->next != 0x00) { - // segment the current block if it is big enough - current->next = (MemoryBlock*) (((void*) (current + 1)) + size); - current->next->size = current->size - sizeof(MemoryBlock) - size; - current->size = size; - current->next->state = FREE; - current->next->next = next; - next->last = current->next; - } else { - current->next = next; - if (current->next->next == 0x00) { - current->size = size; - } - } - current->state = IN_USE; - current->task = task; - return (void*) (current + 1); -} - -void* malloc(uint32_t size) { - return mallocTask(size, (Task*) getCurrentTask()); -} - -void mergeNextIfPossible(MemoryBlock* current) { - if (current->next != 0x00 && current->next->state == FREE) { - current->size = current->size + sizeof(MemoryBlock) + current->next->size; - current->next = current->next->next; - current->next->next->last = current; - } -} - -void free(void* location) { - MemoryBlock* current = ((MemoryBlock*) location) - 1; - current->state = FREE; - mergeNextIfPossible(current); - if (current->last != 0x00 && current->last->state == FREE) { - current = current->last; - } - mergeNextIfPossible(current); // call this function twice in case a used block between 2 free blocks is freed - mergeNextIfPossible(current); -} - -void printMemoryStack() { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); - current = current->next; - } - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); -} - -void freeTaskAllocations(Task* task) { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - if (current->task == task) { - free(current); - } - current = current->next; - } - if (current->task == task) { - free(current); - } -} \ No newline at end of file diff --git a/src/kernel/lib/ports.c b/src/kernel/lib/ports.c deleted file mode 100644 index 6cfbb2a..0000000 --- a/src/kernel/lib/ports.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include - -void outb(uint16_t port, uint8_t val) { - asm volatile("outb %0, %1" : : "a"(val), "Nd"(port) ); -} - -uint8_t inb(uint16_t port) { - uint8_t result; - __asm__("in %%dx, %%al" : "=a" (result) : "d" (port)); - return result; -} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index dd72655..36c0cfc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { - "*.h": "c" + "*.h": "c", + "type_traits": "c" } } \ No newline at end of file diff --git a/src/headers/_stdio.h b/src/headers/_stdio.h new file mode 100644 index 0000000..b5d4f87 --- /dev/null +++ b/src/headers/_stdio.h @@ -0,0 +1,20 @@ +#ifndef STDIO_H +#define STDIO_H + +#include + +#define FRAMEBUFFER_LOCATION 0x000B8000 +#define VIDEO_WIDTH 80 +#define VIDEO_HEIGHT 25 + +extern void setTextStyle(uint8_t style); +extern void clearScreen(); +extern void printf(const char* format, ...); +extern void putCharAt(char c, uint8_t x, uint8_t y); +extern void putCharsAt(char* string, uint8_t x, uint8_t y); +extern void puts(char* string); +extern void putChars(char* string, uint32_t length); + +extern uint32_t strlen(char* string); + +#endif \ No newline at end of file diff --git a/src/headers/interrupts.h b/src/headers/interrupts.h new file mode 100644 index 0000000..3ca3d29 --- /dev/null +++ b/src/headers/interrupts.h @@ -0,0 +1,21 @@ +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + +#include + +typedef struct { + uint16_t isr_low; + uint16_t codeSegment; + uint8_t reserved; + uint8_t attributes; + uint16_t isr_high; +} __attribute__((packed)) IDTEntry; + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) IDTR; + +extern void initInterrupts(); + +#endif \ No newline at end of file diff --git a/src/headers/stdio.h b/src/headers/stdio.h deleted file mode 100644 index b5d4f87..0000000 --- a/src/headers/stdio.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef STDIO_H -#define STDIO_H - -#include - -#define FRAMEBUFFER_LOCATION 0x000B8000 -#define VIDEO_WIDTH 80 -#define VIDEO_HEIGHT 25 - -extern void setTextStyle(uint8_t style); -extern void clearScreen(); -extern void printf(const char* format, ...); -extern void putCharAt(char c, uint8_t x, uint8_t y); -extern void putCharsAt(char* string, uint8_t x, uint8_t y); -extern void puts(char* string); -extern void putChars(char* string, uint32_t length); - -extern uint32_t strlen(char* string); - -#endif \ No newline at end of file diff --git a/src/interrupts/interrupts.c b/src/interrupts/interrupts.c new file mode 100644 index 0000000..74d2931 --- /dev/null +++ b/src/interrupts/interrupts.c @@ -0,0 +1,33 @@ +#include +#include <_stdio.h> +#include + +IDTR idtr; +IDTEntry* entries; +void* buffer; + +void setInterrupt(uint8_t vector, void* callback, uint8_t flags) { + IDTEntry* descriptor = &entries[vector]; + + descriptor->isr_low = (uint32_t)callback & 0xFFFF; + descriptor->codeSegment = 0x08; + descriptor->attributes = flags; + descriptor->isr_high = (uint32_t)callback >> 16; + descriptor->reserved = 0; +} + +void testInterrupt() { + printf("interrupt!\n"); +} + +void initInterrupts() { + buffer = malloc(sizeof(IDTEntry) * 257); + entries = (IDTEntry*) (((int) buffer + sizeof(IDTEntry)) & -1 ^ 0x0F); + idtr.limit = sizeof(IDTEntry) * 256 - 1; + idtr.base = entries; + for (int i = 0; i < 256; i++) { + setInterrupt(i, testInterrupt, 0x8E); + } + __asm__ volatile ("lidt %0" : : "memory"(idtr)); + __asm__ volatile ("sti"); +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/_stdio.c b/src/kernel/drivers/textMode/_stdio.c new file mode 100644 index 0000000..34eea3f --- /dev/null +++ b/src/kernel/drivers/textMode/_stdio.c @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <_stdio.h> + +uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; +char format = 0x0F; + +void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { + *(framebuffer + position) = c; +} + +void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { + putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +void putCharAtOffset(char c, uint16_t offset) { + putCharWithFormatAtOffset(c | format << 8, offset); +} + +void putCharAt(char c, uint8_t x, uint8_t y) { + putCharAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { + return *(framebuffer + x + y * VIDEO_WIDTH); +} + +void putCharsAt(char* string, uint8_t x, uint8_t y) { + uint16_t position = 0; + char c = *string; + while (c != 0x00) { + putCharAt(c, x + position, y); + position++; + c = *(string + position); + } +} + +void shiftUp() { + for (int y = 1; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); + } + } + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); + } +} + +void newLine() { + uint16_t offset = getCursorOffset(); + uint8_t x = offset % VIDEO_WIDTH; + uint8_t y = offset / VIDEO_WIDTH; + x = 0; + y++; + if (y >= VIDEO_HEIGHT) { + shiftUp(); + y--; + } + setCursorPosition(x, y); +} + +void putChar(char c) { + if (c == '\n') { + newLine(); + return; + } + uint16_t offset = getCursorOffset(); + putCharAtOffset(c, offset); + setCursorOffset(offset + 1); +} + +void puts(char* string) { + while (*string != 0x00) { + putChar(*string); + string++; + } +} + +char HEX_PREFIX[] = "0x"; +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char** write, uint32_t x) { + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + **write = HEX_CHARS[byte >> 8]; + (*write)++; + } + } +} + +uint8_t hexLength(uint32_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return size; +} + +uint32_t getInsertLength(char insertType, uint32_t x) { + switch (insertType) { + case 's': + return strlen((char*) x); + case 'x': + return hexLength(x); + } + return 0; +} + +void stringInsert(char** write, uint32_t x) { + char* string = (char*) x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char** write, char insertType, uint32_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + } +} + +void printf(const char* format, ...) { + uint32_t size = 0; + va_list valist; + va_start(valist, format); + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + size += getInsertLength(format[++i], va_arg(valist, uint32_t)); + continue; + } + size++; + } + va_start(valist, format); + + char* data = malloc(size); + char* write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(valist, uint32_t)); + continue; + } + *write = format[i]; + write++; + } + va_end(valist); + + Message* message = malloc(sizeof(Message)); + + message->data = data; + message->size = size; + message->next = 0x00; + sendMessage(getPrinterTask(), message); + schedule(getPrinterTask()); +} + +void clearScreen() { + setCursorOffset(0); + for (int y = 0; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharAt(' ', x, y); + } + } +} + +void setTextStyle(uint8_t style) { + format = style; +} + +void putChars(char* string, uint32_t length) { + for (uint32_t i = 0; i < length; i++) { + if (string[i] == '\n') { + newLine(); + continue; + } + putChar(string[i]); + } +} + +uint32_t strlen(char* string) { + uint32_t length = 0; + while (string[length] != 0) { + length++; + } + return length; +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/cursor.c b/src/kernel/drivers/textMode/cursor.c new file mode 100644 index 0000000..8247c5e --- /dev/null +++ b/src/kernel/drivers/textMode/cursor.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include <_stdio.h> + +void setCursorOffset(uint16_t offset) { + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (offset & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); +} + +void setCursorPosition(uint8_t x, uint8_t y) { + setCursorOffset(x + y * VIDEO_WIDTH); +} + +uint16_t getCursorOffset() { + uint16_t result = 0; + outb(0x3D4, 0x0F); + result |= inb(0x3D5); + outb(0x3D4, 0x0E); + result |= ((uint16_t)inb(0x3D5)) << 8; + return result; +} \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index d8ff7b8..48ea59f 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,19 +1,26 @@ #include -#include +#include <_stdio.h> #include #include #include #include #include +#include extern uint32_t _kernel_end; void kernelMain() { - initMemoryAllocation(0x100000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here + initMemoryAllocation(0x1000000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here initOSTasks(); drawLogo(); - printf("Switching to otherTask... \n"); + printf("giving up control...\n"); yields(); printf("Returned to mainTask!\n\n"); + printf("initializing interrupts\n"); + initInterrupts(); + yields(); + printf("trying interrupt\n"); + asm ("int $0x80"); + printf("the interrupt worked!\n"); yield(); } \ No newline at end of file diff --git a/src/kernel/lib/memory/alloc.c b/src/kernel/lib/memory/alloc.c deleted file mode 100644 index aedcbad..0000000 --- a/src/kernel/lib/memory/alloc.c +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include -#include - -MemoryBlock* firstBlock; - -void initMemoryAllocation(uint32_t kernelEnd) { - firstBlock = (MemoryBlock*) kernelEnd; - firstBlock->next = 0x00; - firstBlock->last = 0x00; - firstBlock->state = FREE; - firstBlock->size = -1; -} - -void* mallocTask(uint32_t size, Task* task) { - MemoryBlock* current = firstBlock; - while (! (current->next == 0x00 || current->state == FREE && current->size >= size)) { - current = current->next; - } - MemoryBlock* next; - if (current->next == 0x00) { - // this is currently the last block -> initialize the new last block - next = (MemoryBlock*) ((void*) (current + 1) + size); - next->last = current; - next->state = FREE; - next->next = 0x00; - next->size = -1; - } else { - // there is a next block - next = current->next; - } - if (current->size > size + sizeof(MemoryBlock) * 2 && current->next != 0x00) { - // segment the current block if it is big enough - current->next = (MemoryBlock*) (((void*) (current + 1)) + size); - current->next->size = current->size - sizeof(MemoryBlock) - size; - current->size = size; - current->next->state = FREE; - current->next->next = next; - next->last = current->next; - } else { - current->next = next; - if (current->next->next == 0x00) { - current->size = size; - } - } - current->state = IN_USE; - current->task = task; - return (void*) (current + 1); -} - -void* malloc(uint32_t size) { - return mallocTask(size, (Task*) getCurrentTask()); -} - -void mergeNextIfPossible(MemoryBlock* current) { - if (current->next != 0x00 && current->next->state == FREE) { - current->size = current->size + sizeof(MemoryBlock) + current->next->size; - current->next = current->next->next; - current->next->next->last = current; - } -} - -void free(void* location) { - MemoryBlock* current = ((MemoryBlock*) location) - 1; - current->state = FREE; - mergeNextIfPossible(current); - if (current->last != 0x00 && current->last->state == FREE) { - current = current->last; - } - mergeNextIfPossible(current); // call this function twice in case a used block between 2 free blocks is freed - mergeNextIfPossible(current); -} - -void printMemoryStack() { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); - current = current->next; - } - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); -} - -void freeTaskAllocations(Task* task) { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - if (current->task == task) { - free(current); - } - current = current->next; - } - if (current->task == task) { - free(current); - } -} \ No newline at end of file diff --git a/src/kernel/lib/ports.c b/src/kernel/lib/ports.c deleted file mode 100644 index 6cfbb2a..0000000 --- a/src/kernel/lib/ports.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include - -void outb(uint16_t port, uint8_t val) { - asm volatile("outb %0, %1" : : "a"(val), "Nd"(port) ); -} - -uint8_t inb(uint16_t port) { - uint8_t result; - __asm__("in %%dx, %%al" : "=a" (result) : "d" (port)); - return result; -} \ No newline at end of file diff --git a/src/kernel/lib/task/osTasks.c b/src/kernel/lib/task/osTasks.c deleted file mode 100644 index c3d6a43..0000000 --- a/src/kernel/lib/task/osTasks.c +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include -#include -#include - -Task mainTask; -Task printerTask; - -void printLoop() { - while (1) { - yield(); - Message* message = popMessage(&printerTask); - if (message == 0x00) { - continue; - } - putChars(message->data, message->size); - free(message->data); - free(message); - } -} - -void initOSTasks() { - setRunningTask(&mainTask); - createTask(&printerTask, (uint32_t) printLoop, 0x0, 0x0); - schedule(&printerTask); - // more tasks . . . - yields(); -} - -inline Task* getPrinterTask() { - return &printerTask; -} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index dd72655..36c0cfc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { - "*.h": "c" + "*.h": "c", + "type_traits": "c" } } \ No newline at end of file diff --git a/src/headers/_stdio.h b/src/headers/_stdio.h new file mode 100644 index 0000000..b5d4f87 --- /dev/null +++ b/src/headers/_stdio.h @@ -0,0 +1,20 @@ +#ifndef STDIO_H +#define STDIO_H + +#include + +#define FRAMEBUFFER_LOCATION 0x000B8000 +#define VIDEO_WIDTH 80 +#define VIDEO_HEIGHT 25 + +extern void setTextStyle(uint8_t style); +extern void clearScreen(); +extern void printf(const char* format, ...); +extern void putCharAt(char c, uint8_t x, uint8_t y); +extern void putCharsAt(char* string, uint8_t x, uint8_t y); +extern void puts(char* string); +extern void putChars(char* string, uint32_t length); + +extern uint32_t strlen(char* string); + +#endif \ No newline at end of file diff --git a/src/headers/interrupts.h b/src/headers/interrupts.h new file mode 100644 index 0000000..3ca3d29 --- /dev/null +++ b/src/headers/interrupts.h @@ -0,0 +1,21 @@ +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + +#include + +typedef struct { + uint16_t isr_low; + uint16_t codeSegment; + uint8_t reserved; + uint8_t attributes; + uint16_t isr_high; +} __attribute__((packed)) IDTEntry; + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) IDTR; + +extern void initInterrupts(); + +#endif \ No newline at end of file diff --git a/src/headers/stdio.h b/src/headers/stdio.h deleted file mode 100644 index b5d4f87..0000000 --- a/src/headers/stdio.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef STDIO_H -#define STDIO_H - -#include - -#define FRAMEBUFFER_LOCATION 0x000B8000 -#define VIDEO_WIDTH 80 -#define VIDEO_HEIGHT 25 - -extern void setTextStyle(uint8_t style); -extern void clearScreen(); -extern void printf(const char* format, ...); -extern void putCharAt(char c, uint8_t x, uint8_t y); -extern void putCharsAt(char* string, uint8_t x, uint8_t y); -extern void puts(char* string); -extern void putChars(char* string, uint32_t length); - -extern uint32_t strlen(char* string); - -#endif \ No newline at end of file diff --git a/src/interrupts/interrupts.c b/src/interrupts/interrupts.c new file mode 100644 index 0000000..74d2931 --- /dev/null +++ b/src/interrupts/interrupts.c @@ -0,0 +1,33 @@ +#include +#include <_stdio.h> +#include + +IDTR idtr; +IDTEntry* entries; +void* buffer; + +void setInterrupt(uint8_t vector, void* callback, uint8_t flags) { + IDTEntry* descriptor = &entries[vector]; + + descriptor->isr_low = (uint32_t)callback & 0xFFFF; + descriptor->codeSegment = 0x08; + descriptor->attributes = flags; + descriptor->isr_high = (uint32_t)callback >> 16; + descriptor->reserved = 0; +} + +void testInterrupt() { + printf("interrupt!\n"); +} + +void initInterrupts() { + buffer = malloc(sizeof(IDTEntry) * 257); + entries = (IDTEntry*) (((int) buffer + sizeof(IDTEntry)) & -1 ^ 0x0F); + idtr.limit = sizeof(IDTEntry) * 256 - 1; + idtr.base = entries; + for (int i = 0; i < 256; i++) { + setInterrupt(i, testInterrupt, 0x8E); + } + __asm__ volatile ("lidt %0" : : "memory"(idtr)); + __asm__ volatile ("sti"); +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/_stdio.c b/src/kernel/drivers/textMode/_stdio.c new file mode 100644 index 0000000..34eea3f --- /dev/null +++ b/src/kernel/drivers/textMode/_stdio.c @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <_stdio.h> + +uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; +char format = 0x0F; + +void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { + *(framebuffer + position) = c; +} + +void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { + putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +void putCharAtOffset(char c, uint16_t offset) { + putCharWithFormatAtOffset(c | format << 8, offset); +} + +void putCharAt(char c, uint8_t x, uint8_t y) { + putCharAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { + return *(framebuffer + x + y * VIDEO_WIDTH); +} + +void putCharsAt(char* string, uint8_t x, uint8_t y) { + uint16_t position = 0; + char c = *string; + while (c != 0x00) { + putCharAt(c, x + position, y); + position++; + c = *(string + position); + } +} + +void shiftUp() { + for (int y = 1; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); + } + } + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); + } +} + +void newLine() { + uint16_t offset = getCursorOffset(); + uint8_t x = offset % VIDEO_WIDTH; + uint8_t y = offset / VIDEO_WIDTH; + x = 0; + y++; + if (y >= VIDEO_HEIGHT) { + shiftUp(); + y--; + } + setCursorPosition(x, y); +} + +void putChar(char c) { + if (c == '\n') { + newLine(); + return; + } + uint16_t offset = getCursorOffset(); + putCharAtOffset(c, offset); + setCursorOffset(offset + 1); +} + +void puts(char* string) { + while (*string != 0x00) { + putChar(*string); + string++; + } +} + +char HEX_PREFIX[] = "0x"; +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char** write, uint32_t x) { + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + **write = HEX_CHARS[byte >> 8]; + (*write)++; + } + } +} + +uint8_t hexLength(uint32_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return size; +} + +uint32_t getInsertLength(char insertType, uint32_t x) { + switch (insertType) { + case 's': + return strlen((char*) x); + case 'x': + return hexLength(x); + } + return 0; +} + +void stringInsert(char** write, uint32_t x) { + char* string = (char*) x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char** write, char insertType, uint32_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + } +} + +void printf(const char* format, ...) { + uint32_t size = 0; + va_list valist; + va_start(valist, format); + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + size += getInsertLength(format[++i], va_arg(valist, uint32_t)); + continue; + } + size++; + } + va_start(valist, format); + + char* data = malloc(size); + char* write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(valist, uint32_t)); + continue; + } + *write = format[i]; + write++; + } + va_end(valist); + + Message* message = malloc(sizeof(Message)); + + message->data = data; + message->size = size; + message->next = 0x00; + sendMessage(getPrinterTask(), message); + schedule(getPrinterTask()); +} + +void clearScreen() { + setCursorOffset(0); + for (int y = 0; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharAt(' ', x, y); + } + } +} + +void setTextStyle(uint8_t style) { + format = style; +} + +void putChars(char* string, uint32_t length) { + for (uint32_t i = 0; i < length; i++) { + if (string[i] == '\n') { + newLine(); + continue; + } + putChar(string[i]); + } +} + +uint32_t strlen(char* string) { + uint32_t length = 0; + while (string[length] != 0) { + length++; + } + return length; +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/cursor.c b/src/kernel/drivers/textMode/cursor.c new file mode 100644 index 0000000..8247c5e --- /dev/null +++ b/src/kernel/drivers/textMode/cursor.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include <_stdio.h> + +void setCursorOffset(uint16_t offset) { + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (offset & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); +} + +void setCursorPosition(uint8_t x, uint8_t y) { + setCursorOffset(x + y * VIDEO_WIDTH); +} + +uint16_t getCursorOffset() { + uint16_t result = 0; + outb(0x3D4, 0x0F); + result |= inb(0x3D5); + outb(0x3D4, 0x0E); + result |= ((uint16_t)inb(0x3D5)) << 8; + return result; +} \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index d8ff7b8..48ea59f 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,19 +1,26 @@ #include -#include +#include <_stdio.h> #include #include #include #include #include +#include extern uint32_t _kernel_end; void kernelMain() { - initMemoryAllocation(0x100000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here + initMemoryAllocation(0x1000000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here initOSTasks(); drawLogo(); - printf("Switching to otherTask... \n"); + printf("giving up control...\n"); yields(); printf("Returned to mainTask!\n\n"); + printf("initializing interrupts\n"); + initInterrupts(); + yields(); + printf("trying interrupt\n"); + asm ("int $0x80"); + printf("the interrupt worked!\n"); yield(); } \ No newline at end of file diff --git a/src/kernel/lib/memory/alloc.c b/src/kernel/lib/memory/alloc.c deleted file mode 100644 index aedcbad..0000000 --- a/src/kernel/lib/memory/alloc.c +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include -#include - -MemoryBlock* firstBlock; - -void initMemoryAllocation(uint32_t kernelEnd) { - firstBlock = (MemoryBlock*) kernelEnd; - firstBlock->next = 0x00; - firstBlock->last = 0x00; - firstBlock->state = FREE; - firstBlock->size = -1; -} - -void* mallocTask(uint32_t size, Task* task) { - MemoryBlock* current = firstBlock; - while (! (current->next == 0x00 || current->state == FREE && current->size >= size)) { - current = current->next; - } - MemoryBlock* next; - if (current->next == 0x00) { - // this is currently the last block -> initialize the new last block - next = (MemoryBlock*) ((void*) (current + 1) + size); - next->last = current; - next->state = FREE; - next->next = 0x00; - next->size = -1; - } else { - // there is a next block - next = current->next; - } - if (current->size > size + sizeof(MemoryBlock) * 2 && current->next != 0x00) { - // segment the current block if it is big enough - current->next = (MemoryBlock*) (((void*) (current + 1)) + size); - current->next->size = current->size - sizeof(MemoryBlock) - size; - current->size = size; - current->next->state = FREE; - current->next->next = next; - next->last = current->next; - } else { - current->next = next; - if (current->next->next == 0x00) { - current->size = size; - } - } - current->state = IN_USE; - current->task = task; - return (void*) (current + 1); -} - -void* malloc(uint32_t size) { - return mallocTask(size, (Task*) getCurrentTask()); -} - -void mergeNextIfPossible(MemoryBlock* current) { - if (current->next != 0x00 && current->next->state == FREE) { - current->size = current->size + sizeof(MemoryBlock) + current->next->size; - current->next = current->next->next; - current->next->next->last = current; - } -} - -void free(void* location) { - MemoryBlock* current = ((MemoryBlock*) location) - 1; - current->state = FREE; - mergeNextIfPossible(current); - if (current->last != 0x00 && current->last->state == FREE) { - current = current->last; - } - mergeNextIfPossible(current); // call this function twice in case a used block between 2 free blocks is freed - mergeNextIfPossible(current); -} - -void printMemoryStack() { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); - current = current->next; - } - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); -} - -void freeTaskAllocations(Task* task) { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - if (current->task == task) { - free(current); - } - current = current->next; - } - if (current->task == task) { - free(current); - } -} \ No newline at end of file diff --git a/src/kernel/lib/ports.c b/src/kernel/lib/ports.c deleted file mode 100644 index 6cfbb2a..0000000 --- a/src/kernel/lib/ports.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include - -void outb(uint16_t port, uint8_t val) { - asm volatile("outb %0, %1" : : "a"(val), "Nd"(port) ); -} - -uint8_t inb(uint16_t port) { - uint8_t result; - __asm__("in %%dx, %%al" : "=a" (result) : "d" (port)); - return result; -} \ No newline at end of file diff --git a/src/kernel/lib/task/osTasks.c b/src/kernel/lib/task/osTasks.c deleted file mode 100644 index c3d6a43..0000000 --- a/src/kernel/lib/task/osTasks.c +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include -#include -#include - -Task mainTask; -Task printerTask; - -void printLoop() { - while (1) { - yield(); - Message* message = popMessage(&printerTask); - if (message == 0x00) { - continue; - } - putChars(message->data, message->size); - free(message->data); - free(message); - } -} - -void initOSTasks() { - setRunningTask(&mainTask); - createTask(&printerTask, (uint32_t) printLoop, 0x0, 0x0); - schedule(&printerTask); - // more tasks . . . - yields(); -} - -inline Task* getPrinterTask() { - return &printerTask; -} \ No newline at end of file diff --git a/src/kernel/lib/task/task.c b/src/kernel/lib/task/task.c deleted file mode 100644 index e4201c5..0000000 --- a/src/kernel/lib/task/task.c +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include -#include - -#define STACK_SIZE 0xF000 - -Task *currentTask; - -void createTask(Task *task, uint32_t mainFunction, uint32_t flags, uint32_t *pagedir) { - void* stack = mallocTask(STACK_SIZE, task); - task->registers.eax = 0; - task->registers.ebx = 0; - task->registers.ecx = 0; - task->registers.edx = 0; - task->registers.esi = 0; - task->registers.edi = 0; - task->registers.eflags = flags; - task->registers.eip = mainFunction; - task->registers.cr3 = (uint32_t) pagedir; - task->registers.esp = STACK_SIZE + (uint32_t) stack; - task->nextTask = 0; - task->stack = stack; -} - -void yield() { - Task* last = currentTask; - currentTask = currentTask->nextTask; - if (currentTask == 0x00) { - puts("No more tasks to run, halting . . .\n"); - while (1) { - asm("hlt"); - } - } - last->nextTask = 0x00; - switchTask(&(last->registers), &(currentTask->registers)); -} - -void schedule(Task* task) { - Task* test = currentTask; - while (test->nextTask != 0x0) { - test = test->nextTask; - if (test->nextTask == task) { - return; // don't schedule if the task is already in the queue - } - } - test->nextTask = task; -} - -void setRunningTask(Task* task) { - currentTask = task; -} - -void yields() { - schedule(currentTask); - yield(); -} - -void destroyCurrentTask() { - freeTaskAllocations(currentTask); - yield(); -} - -Task* getCurrentTask() { - return currentTask; -} - -void sendMessage(Task* task, Message* message) { - if (task->message == 0x00) { - task->message = message; - return; - } - Message* currentMessage = task->message; - while (currentMessage->next == 0x00) { - currentMessage = currentMessage->next; - } - currentMessage->next = message; -} - -Message* popMessage(Task* task) { - Message* currentMessage = task->message; - if (currentMessage != 0x00) { - task->message = currentMessage->next; - - } - return currentMessage; -} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index dd72655..36c0cfc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { - "*.h": "c" + "*.h": "c", + "type_traits": "c" } } \ No newline at end of file diff --git a/src/headers/_stdio.h b/src/headers/_stdio.h new file mode 100644 index 0000000..b5d4f87 --- /dev/null +++ b/src/headers/_stdio.h @@ -0,0 +1,20 @@ +#ifndef STDIO_H +#define STDIO_H + +#include + +#define FRAMEBUFFER_LOCATION 0x000B8000 +#define VIDEO_WIDTH 80 +#define VIDEO_HEIGHT 25 + +extern void setTextStyle(uint8_t style); +extern void clearScreen(); +extern void printf(const char* format, ...); +extern void putCharAt(char c, uint8_t x, uint8_t y); +extern void putCharsAt(char* string, uint8_t x, uint8_t y); +extern void puts(char* string); +extern void putChars(char* string, uint32_t length); + +extern uint32_t strlen(char* string); + +#endif \ No newline at end of file diff --git a/src/headers/interrupts.h b/src/headers/interrupts.h new file mode 100644 index 0000000..3ca3d29 --- /dev/null +++ b/src/headers/interrupts.h @@ -0,0 +1,21 @@ +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + +#include + +typedef struct { + uint16_t isr_low; + uint16_t codeSegment; + uint8_t reserved; + uint8_t attributes; + uint16_t isr_high; +} __attribute__((packed)) IDTEntry; + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) IDTR; + +extern void initInterrupts(); + +#endif \ No newline at end of file diff --git a/src/headers/stdio.h b/src/headers/stdio.h deleted file mode 100644 index b5d4f87..0000000 --- a/src/headers/stdio.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef STDIO_H -#define STDIO_H - -#include - -#define FRAMEBUFFER_LOCATION 0x000B8000 -#define VIDEO_WIDTH 80 -#define VIDEO_HEIGHT 25 - -extern void setTextStyle(uint8_t style); -extern void clearScreen(); -extern void printf(const char* format, ...); -extern void putCharAt(char c, uint8_t x, uint8_t y); -extern void putCharsAt(char* string, uint8_t x, uint8_t y); -extern void puts(char* string); -extern void putChars(char* string, uint32_t length); - -extern uint32_t strlen(char* string); - -#endif \ No newline at end of file diff --git a/src/interrupts/interrupts.c b/src/interrupts/interrupts.c new file mode 100644 index 0000000..74d2931 --- /dev/null +++ b/src/interrupts/interrupts.c @@ -0,0 +1,33 @@ +#include +#include <_stdio.h> +#include + +IDTR idtr; +IDTEntry* entries; +void* buffer; + +void setInterrupt(uint8_t vector, void* callback, uint8_t flags) { + IDTEntry* descriptor = &entries[vector]; + + descriptor->isr_low = (uint32_t)callback & 0xFFFF; + descriptor->codeSegment = 0x08; + descriptor->attributes = flags; + descriptor->isr_high = (uint32_t)callback >> 16; + descriptor->reserved = 0; +} + +void testInterrupt() { + printf("interrupt!\n"); +} + +void initInterrupts() { + buffer = malloc(sizeof(IDTEntry) * 257); + entries = (IDTEntry*) (((int) buffer + sizeof(IDTEntry)) & -1 ^ 0x0F); + idtr.limit = sizeof(IDTEntry) * 256 - 1; + idtr.base = entries; + for (int i = 0; i < 256; i++) { + setInterrupt(i, testInterrupt, 0x8E); + } + __asm__ volatile ("lidt %0" : : "memory"(idtr)); + __asm__ volatile ("sti"); +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/_stdio.c b/src/kernel/drivers/textMode/_stdio.c new file mode 100644 index 0000000..34eea3f --- /dev/null +++ b/src/kernel/drivers/textMode/_stdio.c @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <_stdio.h> + +uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; +char format = 0x0F; + +void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { + *(framebuffer + position) = c; +} + +void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { + putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +void putCharAtOffset(char c, uint16_t offset) { + putCharWithFormatAtOffset(c | format << 8, offset); +} + +void putCharAt(char c, uint8_t x, uint8_t y) { + putCharAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { + return *(framebuffer + x + y * VIDEO_WIDTH); +} + +void putCharsAt(char* string, uint8_t x, uint8_t y) { + uint16_t position = 0; + char c = *string; + while (c != 0x00) { + putCharAt(c, x + position, y); + position++; + c = *(string + position); + } +} + +void shiftUp() { + for (int y = 1; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); + } + } + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); + } +} + +void newLine() { + uint16_t offset = getCursorOffset(); + uint8_t x = offset % VIDEO_WIDTH; + uint8_t y = offset / VIDEO_WIDTH; + x = 0; + y++; + if (y >= VIDEO_HEIGHT) { + shiftUp(); + y--; + } + setCursorPosition(x, y); +} + +void putChar(char c) { + if (c == '\n') { + newLine(); + return; + } + uint16_t offset = getCursorOffset(); + putCharAtOffset(c, offset); + setCursorOffset(offset + 1); +} + +void puts(char* string) { + while (*string != 0x00) { + putChar(*string); + string++; + } +} + +char HEX_PREFIX[] = "0x"; +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char** write, uint32_t x) { + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + **write = HEX_CHARS[byte >> 8]; + (*write)++; + } + } +} + +uint8_t hexLength(uint32_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return size; +} + +uint32_t getInsertLength(char insertType, uint32_t x) { + switch (insertType) { + case 's': + return strlen((char*) x); + case 'x': + return hexLength(x); + } + return 0; +} + +void stringInsert(char** write, uint32_t x) { + char* string = (char*) x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char** write, char insertType, uint32_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + } +} + +void printf(const char* format, ...) { + uint32_t size = 0; + va_list valist; + va_start(valist, format); + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + size += getInsertLength(format[++i], va_arg(valist, uint32_t)); + continue; + } + size++; + } + va_start(valist, format); + + char* data = malloc(size); + char* write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(valist, uint32_t)); + continue; + } + *write = format[i]; + write++; + } + va_end(valist); + + Message* message = malloc(sizeof(Message)); + + message->data = data; + message->size = size; + message->next = 0x00; + sendMessage(getPrinterTask(), message); + schedule(getPrinterTask()); +} + +void clearScreen() { + setCursorOffset(0); + for (int y = 0; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharAt(' ', x, y); + } + } +} + +void setTextStyle(uint8_t style) { + format = style; +} + +void putChars(char* string, uint32_t length) { + for (uint32_t i = 0; i < length; i++) { + if (string[i] == '\n') { + newLine(); + continue; + } + putChar(string[i]); + } +} + +uint32_t strlen(char* string) { + uint32_t length = 0; + while (string[length] != 0) { + length++; + } + return length; +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/cursor.c b/src/kernel/drivers/textMode/cursor.c new file mode 100644 index 0000000..8247c5e --- /dev/null +++ b/src/kernel/drivers/textMode/cursor.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include <_stdio.h> + +void setCursorOffset(uint16_t offset) { + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (offset & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); +} + +void setCursorPosition(uint8_t x, uint8_t y) { + setCursorOffset(x + y * VIDEO_WIDTH); +} + +uint16_t getCursorOffset() { + uint16_t result = 0; + outb(0x3D4, 0x0F); + result |= inb(0x3D5); + outb(0x3D4, 0x0E); + result |= ((uint16_t)inb(0x3D5)) << 8; + return result; +} \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index d8ff7b8..48ea59f 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,19 +1,26 @@ #include -#include +#include <_stdio.h> #include #include #include #include #include +#include extern uint32_t _kernel_end; void kernelMain() { - initMemoryAllocation(0x100000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here + initMemoryAllocation(0x1000000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here initOSTasks(); drawLogo(); - printf("Switching to otherTask... \n"); + printf("giving up control...\n"); yields(); printf("Returned to mainTask!\n\n"); + printf("initializing interrupts\n"); + initInterrupts(); + yields(); + printf("trying interrupt\n"); + asm ("int $0x80"); + printf("the interrupt worked!\n"); yield(); } \ No newline at end of file diff --git a/src/kernel/lib/memory/alloc.c b/src/kernel/lib/memory/alloc.c deleted file mode 100644 index aedcbad..0000000 --- a/src/kernel/lib/memory/alloc.c +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include -#include - -MemoryBlock* firstBlock; - -void initMemoryAllocation(uint32_t kernelEnd) { - firstBlock = (MemoryBlock*) kernelEnd; - firstBlock->next = 0x00; - firstBlock->last = 0x00; - firstBlock->state = FREE; - firstBlock->size = -1; -} - -void* mallocTask(uint32_t size, Task* task) { - MemoryBlock* current = firstBlock; - while (! (current->next == 0x00 || current->state == FREE && current->size >= size)) { - current = current->next; - } - MemoryBlock* next; - if (current->next == 0x00) { - // this is currently the last block -> initialize the new last block - next = (MemoryBlock*) ((void*) (current + 1) + size); - next->last = current; - next->state = FREE; - next->next = 0x00; - next->size = -1; - } else { - // there is a next block - next = current->next; - } - if (current->size > size + sizeof(MemoryBlock) * 2 && current->next != 0x00) { - // segment the current block if it is big enough - current->next = (MemoryBlock*) (((void*) (current + 1)) + size); - current->next->size = current->size - sizeof(MemoryBlock) - size; - current->size = size; - current->next->state = FREE; - current->next->next = next; - next->last = current->next; - } else { - current->next = next; - if (current->next->next == 0x00) { - current->size = size; - } - } - current->state = IN_USE; - current->task = task; - return (void*) (current + 1); -} - -void* malloc(uint32_t size) { - return mallocTask(size, (Task*) getCurrentTask()); -} - -void mergeNextIfPossible(MemoryBlock* current) { - if (current->next != 0x00 && current->next->state == FREE) { - current->size = current->size + sizeof(MemoryBlock) + current->next->size; - current->next = current->next->next; - current->next->next->last = current; - } -} - -void free(void* location) { - MemoryBlock* current = ((MemoryBlock*) location) - 1; - current->state = FREE; - mergeNextIfPossible(current); - if (current->last != 0x00 && current->last->state == FREE) { - current = current->last; - } - mergeNextIfPossible(current); // call this function twice in case a used block between 2 free blocks is freed - mergeNextIfPossible(current); -} - -void printMemoryStack() { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); - current = current->next; - } - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); -} - -void freeTaskAllocations(Task* task) { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - if (current->task == task) { - free(current); - } - current = current->next; - } - if (current->task == task) { - free(current); - } -} \ No newline at end of file diff --git a/src/kernel/lib/ports.c b/src/kernel/lib/ports.c deleted file mode 100644 index 6cfbb2a..0000000 --- a/src/kernel/lib/ports.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include - -void outb(uint16_t port, uint8_t val) { - asm volatile("outb %0, %1" : : "a"(val), "Nd"(port) ); -} - -uint8_t inb(uint16_t port) { - uint8_t result; - __asm__("in %%dx, %%al" : "=a" (result) : "d" (port)); - return result; -} \ No newline at end of file diff --git a/src/kernel/lib/task/osTasks.c b/src/kernel/lib/task/osTasks.c deleted file mode 100644 index c3d6a43..0000000 --- a/src/kernel/lib/task/osTasks.c +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include -#include -#include - -Task mainTask; -Task printerTask; - -void printLoop() { - while (1) { - yield(); - Message* message = popMessage(&printerTask); - if (message == 0x00) { - continue; - } - putChars(message->data, message->size); - free(message->data); - free(message); - } -} - -void initOSTasks() { - setRunningTask(&mainTask); - createTask(&printerTask, (uint32_t) printLoop, 0x0, 0x0); - schedule(&printerTask); - // more tasks . . . - yields(); -} - -inline Task* getPrinterTask() { - return &printerTask; -} \ No newline at end of file diff --git a/src/kernel/lib/task/task.c b/src/kernel/lib/task/task.c deleted file mode 100644 index e4201c5..0000000 --- a/src/kernel/lib/task/task.c +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include -#include - -#define STACK_SIZE 0xF000 - -Task *currentTask; - -void createTask(Task *task, uint32_t mainFunction, uint32_t flags, uint32_t *pagedir) { - void* stack = mallocTask(STACK_SIZE, task); - task->registers.eax = 0; - task->registers.ebx = 0; - task->registers.ecx = 0; - task->registers.edx = 0; - task->registers.esi = 0; - task->registers.edi = 0; - task->registers.eflags = flags; - task->registers.eip = mainFunction; - task->registers.cr3 = (uint32_t) pagedir; - task->registers.esp = STACK_SIZE + (uint32_t) stack; - task->nextTask = 0; - task->stack = stack; -} - -void yield() { - Task* last = currentTask; - currentTask = currentTask->nextTask; - if (currentTask == 0x00) { - puts("No more tasks to run, halting . . .\n"); - while (1) { - asm("hlt"); - } - } - last->nextTask = 0x00; - switchTask(&(last->registers), &(currentTask->registers)); -} - -void schedule(Task* task) { - Task* test = currentTask; - while (test->nextTask != 0x0) { - test = test->nextTask; - if (test->nextTask == task) { - return; // don't schedule if the task is already in the queue - } - } - test->nextTask = task; -} - -void setRunningTask(Task* task) { - currentTask = task; -} - -void yields() { - schedule(currentTask); - yield(); -} - -void destroyCurrentTask() { - freeTaskAllocations(currentTask); - yield(); -} - -Task* getCurrentTask() { - return currentTask; -} - -void sendMessage(Task* task, Message* message) { - if (task->message == 0x00) { - task->message = message; - return; - } - Message* currentMessage = task->message; - while (currentMessage->next == 0x00) { - currentMessage = currentMessage->next; - } - currentMessage->next = message; -} - -Message* popMessage(Task* task) { - Message* currentMessage = task->message; - if (currentMessage != 0x00) { - task->message = currentMessage->next; - - } - return currentMessage; -} \ No newline at end of file diff --git a/src/kernel/lib/task/task.s b/src/kernel/lib/task/task.s deleted file mode 100644 index 88357cd..0000000 --- a/src/kernel/lib/task/task.s +++ /dev/null @@ -1,49 +0,0 @@ -.section .text -.global switchTask -switchTask: - pusha - pushf - mov %cr3, %eax #Push CR3 - push %eax - mov 44(%esp), %eax #The first argument, where to save - mov %ebx, 4(%eax) - mov %ecx, 8(%eax) - mov %edx, 12(%eax) - mov %esi, 16(%eax) - mov %edi, 20(%eax) - mov 36(%esp), %ebx #EAX - mov 40(%esp), %ecx #IP - mov 20(%esp), %edx #ESP - add $4, %edx #Remove the return value - mov 16(%esp), %esi #EBP - mov 4(%esp), %edi #EFLAGS - mov %ebx, (%eax) - mov %edx, 24(%eax) - mov %esi, 28(%eax) - mov %ecx, 32(%eax) - mov %edi, 36(%eax) - pop %ebx #CR3 - mov %ebx, 40(%eax) - push %ebx #Goodbye again - mov 48(%esp), %eax #Now it is the new object - mov 4(%eax), %ebx #EBX - mov 8(%eax), %ecx #ECX - mov 12(%eax), %edx #EDX - mov 16(%eax), %esi #ESI - mov 20(%eax), %edi #EDI - mov 28(%eax), %ebp #EBP - push %eax - mov 36(%eax), %eax #EFLAGS - push %eax - popf - pop %eax - mov 24(%eax), %esp #ESP - push %eax - mov 40(%eax), %eax #CR3 - mov %eax, %cr3 - pop %eax - push %eax - mov 32(%eax), %eax #EIP - xchg (%esp), %eax - mov (%eax), %eax #EAX - ret diff --git a/.vscode/settings.json b/.vscode/settings.json index dd72655..36c0cfc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { - "*.h": "c" + "*.h": "c", + "type_traits": "c" } } \ No newline at end of file diff --git a/src/headers/_stdio.h b/src/headers/_stdio.h new file mode 100644 index 0000000..b5d4f87 --- /dev/null +++ b/src/headers/_stdio.h @@ -0,0 +1,20 @@ +#ifndef STDIO_H +#define STDIO_H + +#include + +#define FRAMEBUFFER_LOCATION 0x000B8000 +#define VIDEO_WIDTH 80 +#define VIDEO_HEIGHT 25 + +extern void setTextStyle(uint8_t style); +extern void clearScreen(); +extern void printf(const char* format, ...); +extern void putCharAt(char c, uint8_t x, uint8_t y); +extern void putCharsAt(char* string, uint8_t x, uint8_t y); +extern void puts(char* string); +extern void putChars(char* string, uint32_t length); + +extern uint32_t strlen(char* string); + +#endif \ No newline at end of file diff --git a/src/headers/interrupts.h b/src/headers/interrupts.h new file mode 100644 index 0000000..3ca3d29 --- /dev/null +++ b/src/headers/interrupts.h @@ -0,0 +1,21 @@ +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + +#include + +typedef struct { + uint16_t isr_low; + uint16_t codeSegment; + uint8_t reserved; + uint8_t attributes; + uint16_t isr_high; +} __attribute__((packed)) IDTEntry; + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) IDTR; + +extern void initInterrupts(); + +#endif \ No newline at end of file diff --git a/src/headers/stdio.h b/src/headers/stdio.h deleted file mode 100644 index b5d4f87..0000000 --- a/src/headers/stdio.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef STDIO_H -#define STDIO_H - -#include - -#define FRAMEBUFFER_LOCATION 0x000B8000 -#define VIDEO_WIDTH 80 -#define VIDEO_HEIGHT 25 - -extern void setTextStyle(uint8_t style); -extern void clearScreen(); -extern void printf(const char* format, ...); -extern void putCharAt(char c, uint8_t x, uint8_t y); -extern void putCharsAt(char* string, uint8_t x, uint8_t y); -extern void puts(char* string); -extern void putChars(char* string, uint32_t length); - -extern uint32_t strlen(char* string); - -#endif \ No newline at end of file diff --git a/src/interrupts/interrupts.c b/src/interrupts/interrupts.c new file mode 100644 index 0000000..74d2931 --- /dev/null +++ b/src/interrupts/interrupts.c @@ -0,0 +1,33 @@ +#include +#include <_stdio.h> +#include + +IDTR idtr; +IDTEntry* entries; +void* buffer; + +void setInterrupt(uint8_t vector, void* callback, uint8_t flags) { + IDTEntry* descriptor = &entries[vector]; + + descriptor->isr_low = (uint32_t)callback & 0xFFFF; + descriptor->codeSegment = 0x08; + descriptor->attributes = flags; + descriptor->isr_high = (uint32_t)callback >> 16; + descriptor->reserved = 0; +} + +void testInterrupt() { + printf("interrupt!\n"); +} + +void initInterrupts() { + buffer = malloc(sizeof(IDTEntry) * 257); + entries = (IDTEntry*) (((int) buffer + sizeof(IDTEntry)) & -1 ^ 0x0F); + idtr.limit = sizeof(IDTEntry) * 256 - 1; + idtr.base = entries; + for (int i = 0; i < 256; i++) { + setInterrupt(i, testInterrupt, 0x8E); + } + __asm__ volatile ("lidt %0" : : "memory"(idtr)); + __asm__ volatile ("sti"); +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/_stdio.c b/src/kernel/drivers/textMode/_stdio.c new file mode 100644 index 0000000..34eea3f --- /dev/null +++ b/src/kernel/drivers/textMode/_stdio.c @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <_stdio.h> + +uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; +char format = 0x0F; + +void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { + *(framebuffer + position) = c; +} + +void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { + putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +void putCharAtOffset(char c, uint16_t offset) { + putCharWithFormatAtOffset(c | format << 8, offset); +} + +void putCharAt(char c, uint8_t x, uint8_t y) { + putCharAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { + return *(framebuffer + x + y * VIDEO_WIDTH); +} + +void putCharsAt(char* string, uint8_t x, uint8_t y) { + uint16_t position = 0; + char c = *string; + while (c != 0x00) { + putCharAt(c, x + position, y); + position++; + c = *(string + position); + } +} + +void shiftUp() { + for (int y = 1; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); + } + } + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); + } +} + +void newLine() { + uint16_t offset = getCursorOffset(); + uint8_t x = offset % VIDEO_WIDTH; + uint8_t y = offset / VIDEO_WIDTH; + x = 0; + y++; + if (y >= VIDEO_HEIGHT) { + shiftUp(); + y--; + } + setCursorPosition(x, y); +} + +void putChar(char c) { + if (c == '\n') { + newLine(); + return; + } + uint16_t offset = getCursorOffset(); + putCharAtOffset(c, offset); + setCursorOffset(offset + 1); +} + +void puts(char* string) { + while (*string != 0x00) { + putChar(*string); + string++; + } +} + +char HEX_PREFIX[] = "0x"; +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char** write, uint32_t x) { + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + **write = HEX_CHARS[byte >> 8]; + (*write)++; + } + } +} + +uint8_t hexLength(uint32_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return size; +} + +uint32_t getInsertLength(char insertType, uint32_t x) { + switch (insertType) { + case 's': + return strlen((char*) x); + case 'x': + return hexLength(x); + } + return 0; +} + +void stringInsert(char** write, uint32_t x) { + char* string = (char*) x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char** write, char insertType, uint32_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + } +} + +void printf(const char* format, ...) { + uint32_t size = 0; + va_list valist; + va_start(valist, format); + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + size += getInsertLength(format[++i], va_arg(valist, uint32_t)); + continue; + } + size++; + } + va_start(valist, format); + + char* data = malloc(size); + char* write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(valist, uint32_t)); + continue; + } + *write = format[i]; + write++; + } + va_end(valist); + + Message* message = malloc(sizeof(Message)); + + message->data = data; + message->size = size; + message->next = 0x00; + sendMessage(getPrinterTask(), message); + schedule(getPrinterTask()); +} + +void clearScreen() { + setCursorOffset(0); + for (int y = 0; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharAt(' ', x, y); + } + } +} + +void setTextStyle(uint8_t style) { + format = style; +} + +void putChars(char* string, uint32_t length) { + for (uint32_t i = 0; i < length; i++) { + if (string[i] == '\n') { + newLine(); + continue; + } + putChar(string[i]); + } +} + +uint32_t strlen(char* string) { + uint32_t length = 0; + while (string[length] != 0) { + length++; + } + return length; +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/cursor.c b/src/kernel/drivers/textMode/cursor.c new file mode 100644 index 0000000..8247c5e --- /dev/null +++ b/src/kernel/drivers/textMode/cursor.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include <_stdio.h> + +void setCursorOffset(uint16_t offset) { + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (offset & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); +} + +void setCursorPosition(uint8_t x, uint8_t y) { + setCursorOffset(x + y * VIDEO_WIDTH); +} + +uint16_t getCursorOffset() { + uint16_t result = 0; + outb(0x3D4, 0x0F); + result |= inb(0x3D5); + outb(0x3D4, 0x0E); + result |= ((uint16_t)inb(0x3D5)) << 8; + return result; +} \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index d8ff7b8..48ea59f 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,19 +1,26 @@ #include -#include +#include <_stdio.h> #include #include #include #include #include +#include extern uint32_t _kernel_end; void kernelMain() { - initMemoryAllocation(0x100000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here + initMemoryAllocation(0x1000000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here initOSTasks(); drawLogo(); - printf("Switching to otherTask... \n"); + printf("giving up control...\n"); yields(); printf("Returned to mainTask!\n\n"); + printf("initializing interrupts\n"); + initInterrupts(); + yields(); + printf("trying interrupt\n"); + asm ("int $0x80"); + printf("the interrupt worked!\n"); yield(); } \ No newline at end of file diff --git a/src/kernel/lib/memory/alloc.c b/src/kernel/lib/memory/alloc.c deleted file mode 100644 index aedcbad..0000000 --- a/src/kernel/lib/memory/alloc.c +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include -#include - -MemoryBlock* firstBlock; - -void initMemoryAllocation(uint32_t kernelEnd) { - firstBlock = (MemoryBlock*) kernelEnd; - firstBlock->next = 0x00; - firstBlock->last = 0x00; - firstBlock->state = FREE; - firstBlock->size = -1; -} - -void* mallocTask(uint32_t size, Task* task) { - MemoryBlock* current = firstBlock; - while (! (current->next == 0x00 || current->state == FREE && current->size >= size)) { - current = current->next; - } - MemoryBlock* next; - if (current->next == 0x00) { - // this is currently the last block -> initialize the new last block - next = (MemoryBlock*) ((void*) (current + 1) + size); - next->last = current; - next->state = FREE; - next->next = 0x00; - next->size = -1; - } else { - // there is a next block - next = current->next; - } - if (current->size > size + sizeof(MemoryBlock) * 2 && current->next != 0x00) { - // segment the current block if it is big enough - current->next = (MemoryBlock*) (((void*) (current + 1)) + size); - current->next->size = current->size - sizeof(MemoryBlock) - size; - current->size = size; - current->next->state = FREE; - current->next->next = next; - next->last = current->next; - } else { - current->next = next; - if (current->next->next == 0x00) { - current->size = size; - } - } - current->state = IN_USE; - current->task = task; - return (void*) (current + 1); -} - -void* malloc(uint32_t size) { - return mallocTask(size, (Task*) getCurrentTask()); -} - -void mergeNextIfPossible(MemoryBlock* current) { - if (current->next != 0x00 && current->next->state == FREE) { - current->size = current->size + sizeof(MemoryBlock) + current->next->size; - current->next = current->next->next; - current->next->next->last = current; - } -} - -void free(void* location) { - MemoryBlock* current = ((MemoryBlock*) location) - 1; - current->state = FREE; - mergeNextIfPossible(current); - if (current->last != 0x00 && current->last->state == FREE) { - current = current->last; - } - mergeNextIfPossible(current); // call this function twice in case a used block between 2 free blocks is freed - mergeNextIfPossible(current); -} - -void printMemoryStack() { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); - current = current->next; - } - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); -} - -void freeTaskAllocations(Task* task) { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - if (current->task == task) { - free(current); - } - current = current->next; - } - if (current->task == task) { - free(current); - } -} \ No newline at end of file diff --git a/src/kernel/lib/ports.c b/src/kernel/lib/ports.c deleted file mode 100644 index 6cfbb2a..0000000 --- a/src/kernel/lib/ports.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include - -void outb(uint16_t port, uint8_t val) { - asm volatile("outb %0, %1" : : "a"(val), "Nd"(port) ); -} - -uint8_t inb(uint16_t port) { - uint8_t result; - __asm__("in %%dx, %%al" : "=a" (result) : "d" (port)); - return result; -} \ No newline at end of file diff --git a/src/kernel/lib/task/osTasks.c b/src/kernel/lib/task/osTasks.c deleted file mode 100644 index c3d6a43..0000000 --- a/src/kernel/lib/task/osTasks.c +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include -#include -#include - -Task mainTask; -Task printerTask; - -void printLoop() { - while (1) { - yield(); - Message* message = popMessage(&printerTask); - if (message == 0x00) { - continue; - } - putChars(message->data, message->size); - free(message->data); - free(message); - } -} - -void initOSTasks() { - setRunningTask(&mainTask); - createTask(&printerTask, (uint32_t) printLoop, 0x0, 0x0); - schedule(&printerTask); - // more tasks . . . - yields(); -} - -inline Task* getPrinterTask() { - return &printerTask; -} \ No newline at end of file diff --git a/src/kernel/lib/task/task.c b/src/kernel/lib/task/task.c deleted file mode 100644 index e4201c5..0000000 --- a/src/kernel/lib/task/task.c +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include -#include - -#define STACK_SIZE 0xF000 - -Task *currentTask; - -void createTask(Task *task, uint32_t mainFunction, uint32_t flags, uint32_t *pagedir) { - void* stack = mallocTask(STACK_SIZE, task); - task->registers.eax = 0; - task->registers.ebx = 0; - task->registers.ecx = 0; - task->registers.edx = 0; - task->registers.esi = 0; - task->registers.edi = 0; - task->registers.eflags = flags; - task->registers.eip = mainFunction; - task->registers.cr3 = (uint32_t) pagedir; - task->registers.esp = STACK_SIZE + (uint32_t) stack; - task->nextTask = 0; - task->stack = stack; -} - -void yield() { - Task* last = currentTask; - currentTask = currentTask->nextTask; - if (currentTask == 0x00) { - puts("No more tasks to run, halting . . .\n"); - while (1) { - asm("hlt"); - } - } - last->nextTask = 0x00; - switchTask(&(last->registers), &(currentTask->registers)); -} - -void schedule(Task* task) { - Task* test = currentTask; - while (test->nextTask != 0x0) { - test = test->nextTask; - if (test->nextTask == task) { - return; // don't schedule if the task is already in the queue - } - } - test->nextTask = task; -} - -void setRunningTask(Task* task) { - currentTask = task; -} - -void yields() { - schedule(currentTask); - yield(); -} - -void destroyCurrentTask() { - freeTaskAllocations(currentTask); - yield(); -} - -Task* getCurrentTask() { - return currentTask; -} - -void sendMessage(Task* task, Message* message) { - if (task->message == 0x00) { - task->message = message; - return; - } - Message* currentMessage = task->message; - while (currentMessage->next == 0x00) { - currentMessage = currentMessage->next; - } - currentMessage->next = message; -} - -Message* popMessage(Task* task) { - Message* currentMessage = task->message; - if (currentMessage != 0x00) { - task->message = currentMessage->next; - - } - return currentMessage; -} \ No newline at end of file diff --git a/src/kernel/lib/task/task.s b/src/kernel/lib/task/task.s deleted file mode 100644 index 88357cd..0000000 --- a/src/kernel/lib/task/task.s +++ /dev/null @@ -1,49 +0,0 @@ -.section .text -.global switchTask -switchTask: - pusha - pushf - mov %cr3, %eax #Push CR3 - push %eax - mov 44(%esp), %eax #The first argument, where to save - mov %ebx, 4(%eax) - mov %ecx, 8(%eax) - mov %edx, 12(%eax) - mov %esi, 16(%eax) - mov %edi, 20(%eax) - mov 36(%esp), %ebx #EAX - mov 40(%esp), %ecx #IP - mov 20(%esp), %edx #ESP - add $4, %edx #Remove the return value - mov 16(%esp), %esi #EBP - mov 4(%esp), %edi #EFLAGS - mov %ebx, (%eax) - mov %edx, 24(%eax) - mov %esi, 28(%eax) - mov %ecx, 32(%eax) - mov %edi, 36(%eax) - pop %ebx #CR3 - mov %ebx, 40(%eax) - push %ebx #Goodbye again - mov 48(%esp), %eax #Now it is the new object - mov 4(%eax), %ebx #EBX - mov 8(%eax), %ecx #ECX - mov 12(%eax), %edx #EDX - mov 16(%eax), %esi #ESI - mov 20(%eax), %edi #EDI - mov 28(%eax), %ebp #EBP - push %eax - mov 36(%eax), %eax #EFLAGS - push %eax - popf - pop %eax - mov 24(%eax), %esp #ESP - push %eax - mov 40(%eax), %eax #CR3 - mov %eax, %cr3 - pop %eax - push %eax - mov 32(%eax), %eax #EIP - xchg (%esp), %eax - mov (%eax), %eax #EAX - ret diff --git a/src/kernel/lib/textMode/cursor.c b/src/kernel/lib/textMode/cursor.c deleted file mode 100644 index e5cc8f9..0000000 --- a/src/kernel/lib/textMode/cursor.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include -#include - -void setCursorOffset(uint16_t offset) { - outb(0x3D4, 0x0F); - outb(0x3D5, (uint8_t) (offset & 0xFF)); - outb(0x3D4, 0x0E); - outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); -} - -void setCursorPosition(uint8_t x, uint8_t y) { - setCursorOffset(x + y * VIDEO_WIDTH); -} - -uint16_t getCursorOffset() { - uint16_t result = 0; - outb(0x3D4, 0x0F); - result |= inb(0x3D5); - outb(0x3D4, 0x0E); - result |= ((uint16_t)inb(0x3D5)) << 8; - return result; -} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index dd72655..36c0cfc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { - "*.h": "c" + "*.h": "c", + "type_traits": "c" } } \ No newline at end of file diff --git a/src/headers/_stdio.h b/src/headers/_stdio.h new file mode 100644 index 0000000..b5d4f87 --- /dev/null +++ b/src/headers/_stdio.h @@ -0,0 +1,20 @@ +#ifndef STDIO_H +#define STDIO_H + +#include + +#define FRAMEBUFFER_LOCATION 0x000B8000 +#define VIDEO_WIDTH 80 +#define VIDEO_HEIGHT 25 + +extern void setTextStyle(uint8_t style); +extern void clearScreen(); +extern void printf(const char* format, ...); +extern void putCharAt(char c, uint8_t x, uint8_t y); +extern void putCharsAt(char* string, uint8_t x, uint8_t y); +extern void puts(char* string); +extern void putChars(char* string, uint32_t length); + +extern uint32_t strlen(char* string); + +#endif \ No newline at end of file diff --git a/src/headers/interrupts.h b/src/headers/interrupts.h new file mode 100644 index 0000000..3ca3d29 --- /dev/null +++ b/src/headers/interrupts.h @@ -0,0 +1,21 @@ +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + +#include + +typedef struct { + uint16_t isr_low; + uint16_t codeSegment; + uint8_t reserved; + uint8_t attributes; + uint16_t isr_high; +} __attribute__((packed)) IDTEntry; + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) IDTR; + +extern void initInterrupts(); + +#endif \ No newline at end of file diff --git a/src/headers/stdio.h b/src/headers/stdio.h deleted file mode 100644 index b5d4f87..0000000 --- a/src/headers/stdio.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef STDIO_H -#define STDIO_H - -#include - -#define FRAMEBUFFER_LOCATION 0x000B8000 -#define VIDEO_WIDTH 80 -#define VIDEO_HEIGHT 25 - -extern void setTextStyle(uint8_t style); -extern void clearScreen(); -extern void printf(const char* format, ...); -extern void putCharAt(char c, uint8_t x, uint8_t y); -extern void putCharsAt(char* string, uint8_t x, uint8_t y); -extern void puts(char* string); -extern void putChars(char* string, uint32_t length); - -extern uint32_t strlen(char* string); - -#endif \ No newline at end of file diff --git a/src/interrupts/interrupts.c b/src/interrupts/interrupts.c new file mode 100644 index 0000000..74d2931 --- /dev/null +++ b/src/interrupts/interrupts.c @@ -0,0 +1,33 @@ +#include +#include <_stdio.h> +#include + +IDTR idtr; +IDTEntry* entries; +void* buffer; + +void setInterrupt(uint8_t vector, void* callback, uint8_t flags) { + IDTEntry* descriptor = &entries[vector]; + + descriptor->isr_low = (uint32_t)callback & 0xFFFF; + descriptor->codeSegment = 0x08; + descriptor->attributes = flags; + descriptor->isr_high = (uint32_t)callback >> 16; + descriptor->reserved = 0; +} + +void testInterrupt() { + printf("interrupt!\n"); +} + +void initInterrupts() { + buffer = malloc(sizeof(IDTEntry) * 257); + entries = (IDTEntry*) (((int) buffer + sizeof(IDTEntry)) & -1 ^ 0x0F); + idtr.limit = sizeof(IDTEntry) * 256 - 1; + idtr.base = entries; + for (int i = 0; i < 256; i++) { + setInterrupt(i, testInterrupt, 0x8E); + } + __asm__ volatile ("lidt %0" : : "memory"(idtr)); + __asm__ volatile ("sti"); +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/_stdio.c b/src/kernel/drivers/textMode/_stdio.c new file mode 100644 index 0000000..34eea3f --- /dev/null +++ b/src/kernel/drivers/textMode/_stdio.c @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <_stdio.h> + +uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; +char format = 0x0F; + +void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { + *(framebuffer + position) = c; +} + +void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { + putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +void putCharAtOffset(char c, uint16_t offset) { + putCharWithFormatAtOffset(c | format << 8, offset); +} + +void putCharAt(char c, uint8_t x, uint8_t y) { + putCharAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { + return *(framebuffer + x + y * VIDEO_WIDTH); +} + +void putCharsAt(char* string, uint8_t x, uint8_t y) { + uint16_t position = 0; + char c = *string; + while (c != 0x00) { + putCharAt(c, x + position, y); + position++; + c = *(string + position); + } +} + +void shiftUp() { + for (int y = 1; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); + } + } + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); + } +} + +void newLine() { + uint16_t offset = getCursorOffset(); + uint8_t x = offset % VIDEO_WIDTH; + uint8_t y = offset / VIDEO_WIDTH; + x = 0; + y++; + if (y >= VIDEO_HEIGHT) { + shiftUp(); + y--; + } + setCursorPosition(x, y); +} + +void putChar(char c) { + if (c == '\n') { + newLine(); + return; + } + uint16_t offset = getCursorOffset(); + putCharAtOffset(c, offset); + setCursorOffset(offset + 1); +} + +void puts(char* string) { + while (*string != 0x00) { + putChar(*string); + string++; + } +} + +char HEX_PREFIX[] = "0x"; +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char** write, uint32_t x) { + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + **write = HEX_CHARS[byte >> 8]; + (*write)++; + } + } +} + +uint8_t hexLength(uint32_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return size; +} + +uint32_t getInsertLength(char insertType, uint32_t x) { + switch (insertType) { + case 's': + return strlen((char*) x); + case 'x': + return hexLength(x); + } + return 0; +} + +void stringInsert(char** write, uint32_t x) { + char* string = (char*) x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char** write, char insertType, uint32_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + } +} + +void printf(const char* format, ...) { + uint32_t size = 0; + va_list valist; + va_start(valist, format); + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + size += getInsertLength(format[++i], va_arg(valist, uint32_t)); + continue; + } + size++; + } + va_start(valist, format); + + char* data = malloc(size); + char* write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(valist, uint32_t)); + continue; + } + *write = format[i]; + write++; + } + va_end(valist); + + Message* message = malloc(sizeof(Message)); + + message->data = data; + message->size = size; + message->next = 0x00; + sendMessage(getPrinterTask(), message); + schedule(getPrinterTask()); +} + +void clearScreen() { + setCursorOffset(0); + for (int y = 0; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharAt(' ', x, y); + } + } +} + +void setTextStyle(uint8_t style) { + format = style; +} + +void putChars(char* string, uint32_t length) { + for (uint32_t i = 0; i < length; i++) { + if (string[i] == '\n') { + newLine(); + continue; + } + putChar(string[i]); + } +} + +uint32_t strlen(char* string) { + uint32_t length = 0; + while (string[length] != 0) { + length++; + } + return length; +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/cursor.c b/src/kernel/drivers/textMode/cursor.c new file mode 100644 index 0000000..8247c5e --- /dev/null +++ b/src/kernel/drivers/textMode/cursor.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include <_stdio.h> + +void setCursorOffset(uint16_t offset) { + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (offset & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); +} + +void setCursorPosition(uint8_t x, uint8_t y) { + setCursorOffset(x + y * VIDEO_WIDTH); +} + +uint16_t getCursorOffset() { + uint16_t result = 0; + outb(0x3D4, 0x0F); + result |= inb(0x3D5); + outb(0x3D4, 0x0E); + result |= ((uint16_t)inb(0x3D5)) << 8; + return result; +} \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index d8ff7b8..48ea59f 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,19 +1,26 @@ #include -#include +#include <_stdio.h> #include #include #include #include #include +#include extern uint32_t _kernel_end; void kernelMain() { - initMemoryAllocation(0x100000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here + initMemoryAllocation(0x1000000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here initOSTasks(); drawLogo(); - printf("Switching to otherTask... \n"); + printf("giving up control...\n"); yields(); printf("Returned to mainTask!\n\n"); + printf("initializing interrupts\n"); + initInterrupts(); + yields(); + printf("trying interrupt\n"); + asm ("int $0x80"); + printf("the interrupt worked!\n"); yield(); } \ No newline at end of file diff --git a/src/kernel/lib/memory/alloc.c b/src/kernel/lib/memory/alloc.c deleted file mode 100644 index aedcbad..0000000 --- a/src/kernel/lib/memory/alloc.c +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include -#include - -MemoryBlock* firstBlock; - -void initMemoryAllocation(uint32_t kernelEnd) { - firstBlock = (MemoryBlock*) kernelEnd; - firstBlock->next = 0x00; - firstBlock->last = 0x00; - firstBlock->state = FREE; - firstBlock->size = -1; -} - -void* mallocTask(uint32_t size, Task* task) { - MemoryBlock* current = firstBlock; - while (! (current->next == 0x00 || current->state == FREE && current->size >= size)) { - current = current->next; - } - MemoryBlock* next; - if (current->next == 0x00) { - // this is currently the last block -> initialize the new last block - next = (MemoryBlock*) ((void*) (current + 1) + size); - next->last = current; - next->state = FREE; - next->next = 0x00; - next->size = -1; - } else { - // there is a next block - next = current->next; - } - if (current->size > size + sizeof(MemoryBlock) * 2 && current->next != 0x00) { - // segment the current block if it is big enough - current->next = (MemoryBlock*) (((void*) (current + 1)) + size); - current->next->size = current->size - sizeof(MemoryBlock) - size; - current->size = size; - current->next->state = FREE; - current->next->next = next; - next->last = current->next; - } else { - current->next = next; - if (current->next->next == 0x00) { - current->size = size; - } - } - current->state = IN_USE; - current->task = task; - return (void*) (current + 1); -} - -void* malloc(uint32_t size) { - return mallocTask(size, (Task*) getCurrentTask()); -} - -void mergeNextIfPossible(MemoryBlock* current) { - if (current->next != 0x00 && current->next->state == FREE) { - current->size = current->size + sizeof(MemoryBlock) + current->next->size; - current->next = current->next->next; - current->next->next->last = current; - } -} - -void free(void* location) { - MemoryBlock* current = ((MemoryBlock*) location) - 1; - current->state = FREE; - mergeNextIfPossible(current); - if (current->last != 0x00 && current->last->state == FREE) { - current = current->last; - } - mergeNextIfPossible(current); // call this function twice in case a used block between 2 free blocks is freed - mergeNextIfPossible(current); -} - -void printMemoryStack() { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); - current = current->next; - } - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); -} - -void freeTaskAllocations(Task* task) { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - if (current->task == task) { - free(current); - } - current = current->next; - } - if (current->task == task) { - free(current); - } -} \ No newline at end of file diff --git a/src/kernel/lib/ports.c b/src/kernel/lib/ports.c deleted file mode 100644 index 6cfbb2a..0000000 --- a/src/kernel/lib/ports.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include - -void outb(uint16_t port, uint8_t val) { - asm volatile("outb %0, %1" : : "a"(val), "Nd"(port) ); -} - -uint8_t inb(uint16_t port) { - uint8_t result; - __asm__("in %%dx, %%al" : "=a" (result) : "d" (port)); - return result; -} \ No newline at end of file diff --git a/src/kernel/lib/task/osTasks.c b/src/kernel/lib/task/osTasks.c deleted file mode 100644 index c3d6a43..0000000 --- a/src/kernel/lib/task/osTasks.c +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include -#include -#include - -Task mainTask; -Task printerTask; - -void printLoop() { - while (1) { - yield(); - Message* message = popMessage(&printerTask); - if (message == 0x00) { - continue; - } - putChars(message->data, message->size); - free(message->data); - free(message); - } -} - -void initOSTasks() { - setRunningTask(&mainTask); - createTask(&printerTask, (uint32_t) printLoop, 0x0, 0x0); - schedule(&printerTask); - // more tasks . . . - yields(); -} - -inline Task* getPrinterTask() { - return &printerTask; -} \ No newline at end of file diff --git a/src/kernel/lib/task/task.c b/src/kernel/lib/task/task.c deleted file mode 100644 index e4201c5..0000000 --- a/src/kernel/lib/task/task.c +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include -#include - -#define STACK_SIZE 0xF000 - -Task *currentTask; - -void createTask(Task *task, uint32_t mainFunction, uint32_t flags, uint32_t *pagedir) { - void* stack = mallocTask(STACK_SIZE, task); - task->registers.eax = 0; - task->registers.ebx = 0; - task->registers.ecx = 0; - task->registers.edx = 0; - task->registers.esi = 0; - task->registers.edi = 0; - task->registers.eflags = flags; - task->registers.eip = mainFunction; - task->registers.cr3 = (uint32_t) pagedir; - task->registers.esp = STACK_SIZE + (uint32_t) stack; - task->nextTask = 0; - task->stack = stack; -} - -void yield() { - Task* last = currentTask; - currentTask = currentTask->nextTask; - if (currentTask == 0x00) { - puts("No more tasks to run, halting . . .\n"); - while (1) { - asm("hlt"); - } - } - last->nextTask = 0x00; - switchTask(&(last->registers), &(currentTask->registers)); -} - -void schedule(Task* task) { - Task* test = currentTask; - while (test->nextTask != 0x0) { - test = test->nextTask; - if (test->nextTask == task) { - return; // don't schedule if the task is already in the queue - } - } - test->nextTask = task; -} - -void setRunningTask(Task* task) { - currentTask = task; -} - -void yields() { - schedule(currentTask); - yield(); -} - -void destroyCurrentTask() { - freeTaskAllocations(currentTask); - yield(); -} - -Task* getCurrentTask() { - return currentTask; -} - -void sendMessage(Task* task, Message* message) { - if (task->message == 0x00) { - task->message = message; - return; - } - Message* currentMessage = task->message; - while (currentMessage->next == 0x00) { - currentMessage = currentMessage->next; - } - currentMessage->next = message; -} - -Message* popMessage(Task* task) { - Message* currentMessage = task->message; - if (currentMessage != 0x00) { - task->message = currentMessage->next; - - } - return currentMessage; -} \ No newline at end of file diff --git a/src/kernel/lib/task/task.s b/src/kernel/lib/task/task.s deleted file mode 100644 index 88357cd..0000000 --- a/src/kernel/lib/task/task.s +++ /dev/null @@ -1,49 +0,0 @@ -.section .text -.global switchTask -switchTask: - pusha - pushf - mov %cr3, %eax #Push CR3 - push %eax - mov 44(%esp), %eax #The first argument, where to save - mov %ebx, 4(%eax) - mov %ecx, 8(%eax) - mov %edx, 12(%eax) - mov %esi, 16(%eax) - mov %edi, 20(%eax) - mov 36(%esp), %ebx #EAX - mov 40(%esp), %ecx #IP - mov 20(%esp), %edx #ESP - add $4, %edx #Remove the return value - mov 16(%esp), %esi #EBP - mov 4(%esp), %edi #EFLAGS - mov %ebx, (%eax) - mov %edx, 24(%eax) - mov %esi, 28(%eax) - mov %ecx, 32(%eax) - mov %edi, 36(%eax) - pop %ebx #CR3 - mov %ebx, 40(%eax) - push %ebx #Goodbye again - mov 48(%esp), %eax #Now it is the new object - mov 4(%eax), %ebx #EBX - mov 8(%eax), %ecx #ECX - mov 12(%eax), %edx #EDX - mov 16(%eax), %esi #ESI - mov 20(%eax), %edi #EDI - mov 28(%eax), %ebp #EBP - push %eax - mov 36(%eax), %eax #EFLAGS - push %eax - popf - pop %eax - mov 24(%eax), %esp #ESP - push %eax - mov 40(%eax), %eax #CR3 - mov %eax, %cr3 - pop %eax - push %eax - mov 32(%eax), %eax #EIP - xchg (%esp), %eax - mov (%eax), %eax #EAX - ret diff --git a/src/kernel/lib/textMode/cursor.c b/src/kernel/lib/textMode/cursor.c deleted file mode 100644 index e5cc8f9..0000000 --- a/src/kernel/lib/textMode/cursor.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include -#include - -void setCursorOffset(uint16_t offset) { - outb(0x3D4, 0x0F); - outb(0x3D5, (uint8_t) (offset & 0xFF)); - outb(0x3D4, 0x0E); - outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); -} - -void setCursorPosition(uint8_t x, uint8_t y) { - setCursorOffset(x + y * VIDEO_WIDTH); -} - -uint16_t getCursorOffset() { - uint16_t result = 0; - outb(0x3D4, 0x0F); - result |= inb(0x3D5); - outb(0x3D4, 0x0E); - result |= ((uint16_t)inb(0x3D5)) << 8; - return result; -} \ No newline at end of file diff --git a/src/kernel/lib/textMode/stdio.c b/src/kernel/lib/textMode/stdio.c deleted file mode 100644 index 5f1b3a0..0000000 --- a/src/kernel/lib/textMode/stdio.c +++ /dev/null @@ -1,200 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; -char format = 0x0F; - -void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { - *(framebuffer + position) = c; -} - -void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { - putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); -} - -void putCharAtOffset(char c, uint16_t offset) { - putCharWithFormatAtOffset(c | format << 8, offset); -} - -void putCharAt(char c, uint8_t x, uint8_t y) { - putCharAtOffset(c, (x + y * VIDEO_WIDTH)); -} - -uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { - return *(framebuffer + x + y * VIDEO_WIDTH); -} - -void putCharsAt(char* string, uint8_t x, uint8_t y) { - uint16_t position = 0; - char c = *string; - while (c != 0x00) { - putCharAt(c, x + position, y); - position++; - c = *(string + position); - } -} - -void shiftUp() { - for (int y = 1; y < VIDEO_HEIGHT; y++) { - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); - } - } - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); - } -} - -void newLine() { - uint16_t offset = getCursorOffset(); - uint8_t x = offset % VIDEO_WIDTH; - uint8_t y = offset / VIDEO_WIDTH; - x = 0; - y++; - if (y >= VIDEO_HEIGHT) { - shiftUp(); - y--; - } - setCursorPosition(x, y); -} - -void putChar(char c) { - if (c == '\n') { - newLine(); - return; - } - uint16_t offset = getCursorOffset(); - putCharAtOffset(c, offset); - setCursorOffset(offset + 1); -} - -void puts(char* string) { - while (*string != 0x00) { - putChar(*string); - string++; - } -} - -char HEX_PREFIX[] = "0x"; -char HEX_CHARS[] = "0123456789ABCDEF"; - -void putHex(char** write, uint32_t x) { - uint8_t alreadyWriting = 0; - for (uint8_t position = 3; position >= 0; position--) { - uint8_t byte = (x >> (position * 8)) & 0xFF; - if (byte != 0x00) { - alreadyWriting = 0x01; - } - if (alreadyWriting) { - **write = HEX_CHARS[byte % 256]; - *write++; - **write = HEX_CHARS[byte / 256]; - *write++; - } - } -} - -uint32_t getInsertLength(char insertType, uint32_t x) { - switch (insertType) - { - case 's': - return strlen((char*) x); - case 'x': - for (uint8_t position = 3; position >= 0; position--) { - uint8_t byte = (x >> (position * 8)) & 0xFF; - if (byte != 0x00) { - return 2*position; - } - } - return 0; - } - return 0; -} - -void handleInsert(char** write, char insertType, uint32_t x) { - if (insertType == 's') { - char* string = (char*) x; - uint32_t length = strlen(string); - for (uint32_t position = 0; position < length; position++) { - **write = string[position]; - *write++; - } - return; - } - if (insertType == 'x') { - putHex(write, x); - } -} - -void printf(const char* format, ...) { - uint32_t size = 0; - va_list valist; - va_start(valist, format); - for (int i = 0; format[i] != 0; i++) { - if (format[i] == '%') { - size += getInsertLength(format[++i], va_arg(valist, uint32_t)); - continue; - } - size++; - } - va_start(valist, format); - - char* data = malloc(size); - char* write = data; - for (int i = 0; format[i] != 0; i++) { - if (format[i] == '%') { - handleInsert(&write, format[++i], va_arg(valist, uint32_t)); - continue; - } - *write = format[i]; - write++; - } - va_end(valist); - - Message message = { - message.data = data, - message.size = size, - message.next = 0x00 - }; - sendMessage(getPrinterTask(), &message); - schedule(getPrinterTask()); - yields(); -} - -void clearScreen() { - setCursorOffset(0); - for (int y = 0; y < VIDEO_HEIGHT; y++) { - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharAt(' ', x, y); - } - } -} - -void setTextStyle(uint8_t style) { - format = style; -} - -void putChars(char* string, uint32_t length) { - for (uint32_t i = 0; i < length; i++) { - if (string[i] == '\n') { - newLine(); - continue; - } - putChar(string[i]); - } -} - -uint32_t strlen(char* string) { - uint32_t length = 0; - while (string[length] != 0) { - length++; - } - return length; -} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index dd72655..36c0cfc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { - "*.h": "c" + "*.h": "c", + "type_traits": "c" } } \ No newline at end of file diff --git a/src/headers/_stdio.h b/src/headers/_stdio.h new file mode 100644 index 0000000..b5d4f87 --- /dev/null +++ b/src/headers/_stdio.h @@ -0,0 +1,20 @@ +#ifndef STDIO_H +#define STDIO_H + +#include + +#define FRAMEBUFFER_LOCATION 0x000B8000 +#define VIDEO_WIDTH 80 +#define VIDEO_HEIGHT 25 + +extern void setTextStyle(uint8_t style); +extern void clearScreen(); +extern void printf(const char* format, ...); +extern void putCharAt(char c, uint8_t x, uint8_t y); +extern void putCharsAt(char* string, uint8_t x, uint8_t y); +extern void puts(char* string); +extern void putChars(char* string, uint32_t length); + +extern uint32_t strlen(char* string); + +#endif \ No newline at end of file diff --git a/src/headers/interrupts.h b/src/headers/interrupts.h new file mode 100644 index 0000000..3ca3d29 --- /dev/null +++ b/src/headers/interrupts.h @@ -0,0 +1,21 @@ +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + +#include + +typedef struct { + uint16_t isr_low; + uint16_t codeSegment; + uint8_t reserved; + uint8_t attributes; + uint16_t isr_high; +} __attribute__((packed)) IDTEntry; + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) IDTR; + +extern void initInterrupts(); + +#endif \ No newline at end of file diff --git a/src/headers/stdio.h b/src/headers/stdio.h deleted file mode 100644 index b5d4f87..0000000 --- a/src/headers/stdio.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef STDIO_H -#define STDIO_H - -#include - -#define FRAMEBUFFER_LOCATION 0x000B8000 -#define VIDEO_WIDTH 80 -#define VIDEO_HEIGHT 25 - -extern void setTextStyle(uint8_t style); -extern void clearScreen(); -extern void printf(const char* format, ...); -extern void putCharAt(char c, uint8_t x, uint8_t y); -extern void putCharsAt(char* string, uint8_t x, uint8_t y); -extern void puts(char* string); -extern void putChars(char* string, uint32_t length); - -extern uint32_t strlen(char* string); - -#endif \ No newline at end of file diff --git a/src/interrupts/interrupts.c b/src/interrupts/interrupts.c new file mode 100644 index 0000000..74d2931 --- /dev/null +++ b/src/interrupts/interrupts.c @@ -0,0 +1,33 @@ +#include +#include <_stdio.h> +#include + +IDTR idtr; +IDTEntry* entries; +void* buffer; + +void setInterrupt(uint8_t vector, void* callback, uint8_t flags) { + IDTEntry* descriptor = &entries[vector]; + + descriptor->isr_low = (uint32_t)callback & 0xFFFF; + descriptor->codeSegment = 0x08; + descriptor->attributes = flags; + descriptor->isr_high = (uint32_t)callback >> 16; + descriptor->reserved = 0; +} + +void testInterrupt() { + printf("interrupt!\n"); +} + +void initInterrupts() { + buffer = malloc(sizeof(IDTEntry) * 257); + entries = (IDTEntry*) (((int) buffer + sizeof(IDTEntry)) & -1 ^ 0x0F); + idtr.limit = sizeof(IDTEntry) * 256 - 1; + idtr.base = entries; + for (int i = 0; i < 256; i++) { + setInterrupt(i, testInterrupt, 0x8E); + } + __asm__ volatile ("lidt %0" : : "memory"(idtr)); + __asm__ volatile ("sti"); +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/_stdio.c b/src/kernel/drivers/textMode/_stdio.c new file mode 100644 index 0000000..34eea3f --- /dev/null +++ b/src/kernel/drivers/textMode/_stdio.c @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <_stdio.h> + +uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; +char format = 0x0F; + +void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { + *(framebuffer + position) = c; +} + +void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { + putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +void putCharAtOffset(char c, uint16_t offset) { + putCharWithFormatAtOffset(c | format << 8, offset); +} + +void putCharAt(char c, uint8_t x, uint8_t y) { + putCharAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { + return *(framebuffer + x + y * VIDEO_WIDTH); +} + +void putCharsAt(char* string, uint8_t x, uint8_t y) { + uint16_t position = 0; + char c = *string; + while (c != 0x00) { + putCharAt(c, x + position, y); + position++; + c = *(string + position); + } +} + +void shiftUp() { + for (int y = 1; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); + } + } + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); + } +} + +void newLine() { + uint16_t offset = getCursorOffset(); + uint8_t x = offset % VIDEO_WIDTH; + uint8_t y = offset / VIDEO_WIDTH; + x = 0; + y++; + if (y >= VIDEO_HEIGHT) { + shiftUp(); + y--; + } + setCursorPosition(x, y); +} + +void putChar(char c) { + if (c == '\n') { + newLine(); + return; + } + uint16_t offset = getCursorOffset(); + putCharAtOffset(c, offset); + setCursorOffset(offset + 1); +} + +void puts(char* string) { + while (*string != 0x00) { + putChar(*string); + string++; + } +} + +char HEX_PREFIX[] = "0x"; +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char** write, uint32_t x) { + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + **write = HEX_CHARS[byte >> 8]; + (*write)++; + } + } +} + +uint8_t hexLength(uint32_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return size; +} + +uint32_t getInsertLength(char insertType, uint32_t x) { + switch (insertType) { + case 's': + return strlen((char*) x); + case 'x': + return hexLength(x); + } + return 0; +} + +void stringInsert(char** write, uint32_t x) { + char* string = (char*) x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char** write, char insertType, uint32_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + } +} + +void printf(const char* format, ...) { + uint32_t size = 0; + va_list valist; + va_start(valist, format); + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + size += getInsertLength(format[++i], va_arg(valist, uint32_t)); + continue; + } + size++; + } + va_start(valist, format); + + char* data = malloc(size); + char* write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(valist, uint32_t)); + continue; + } + *write = format[i]; + write++; + } + va_end(valist); + + Message* message = malloc(sizeof(Message)); + + message->data = data; + message->size = size; + message->next = 0x00; + sendMessage(getPrinterTask(), message); + schedule(getPrinterTask()); +} + +void clearScreen() { + setCursorOffset(0); + for (int y = 0; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharAt(' ', x, y); + } + } +} + +void setTextStyle(uint8_t style) { + format = style; +} + +void putChars(char* string, uint32_t length) { + for (uint32_t i = 0; i < length; i++) { + if (string[i] == '\n') { + newLine(); + continue; + } + putChar(string[i]); + } +} + +uint32_t strlen(char* string) { + uint32_t length = 0; + while (string[length] != 0) { + length++; + } + return length; +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/cursor.c b/src/kernel/drivers/textMode/cursor.c new file mode 100644 index 0000000..8247c5e --- /dev/null +++ b/src/kernel/drivers/textMode/cursor.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include <_stdio.h> + +void setCursorOffset(uint16_t offset) { + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (offset & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); +} + +void setCursorPosition(uint8_t x, uint8_t y) { + setCursorOffset(x + y * VIDEO_WIDTH); +} + +uint16_t getCursorOffset() { + uint16_t result = 0; + outb(0x3D4, 0x0F); + result |= inb(0x3D5); + outb(0x3D4, 0x0E); + result |= ((uint16_t)inb(0x3D5)) << 8; + return result; +} \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index d8ff7b8..48ea59f 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,19 +1,26 @@ #include -#include +#include <_stdio.h> #include #include #include #include #include +#include extern uint32_t _kernel_end; void kernelMain() { - initMemoryAllocation(0x100000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here + initMemoryAllocation(0x1000000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here initOSTasks(); drawLogo(); - printf("Switching to otherTask... \n"); + printf("giving up control...\n"); yields(); printf("Returned to mainTask!\n\n"); + printf("initializing interrupts\n"); + initInterrupts(); + yields(); + printf("trying interrupt\n"); + asm ("int $0x80"); + printf("the interrupt worked!\n"); yield(); } \ No newline at end of file diff --git a/src/kernel/lib/memory/alloc.c b/src/kernel/lib/memory/alloc.c deleted file mode 100644 index aedcbad..0000000 --- a/src/kernel/lib/memory/alloc.c +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include -#include - -MemoryBlock* firstBlock; - -void initMemoryAllocation(uint32_t kernelEnd) { - firstBlock = (MemoryBlock*) kernelEnd; - firstBlock->next = 0x00; - firstBlock->last = 0x00; - firstBlock->state = FREE; - firstBlock->size = -1; -} - -void* mallocTask(uint32_t size, Task* task) { - MemoryBlock* current = firstBlock; - while (! (current->next == 0x00 || current->state == FREE && current->size >= size)) { - current = current->next; - } - MemoryBlock* next; - if (current->next == 0x00) { - // this is currently the last block -> initialize the new last block - next = (MemoryBlock*) ((void*) (current + 1) + size); - next->last = current; - next->state = FREE; - next->next = 0x00; - next->size = -1; - } else { - // there is a next block - next = current->next; - } - if (current->size > size + sizeof(MemoryBlock) * 2 && current->next != 0x00) { - // segment the current block if it is big enough - current->next = (MemoryBlock*) (((void*) (current + 1)) + size); - current->next->size = current->size - sizeof(MemoryBlock) - size; - current->size = size; - current->next->state = FREE; - current->next->next = next; - next->last = current->next; - } else { - current->next = next; - if (current->next->next == 0x00) { - current->size = size; - } - } - current->state = IN_USE; - current->task = task; - return (void*) (current + 1); -} - -void* malloc(uint32_t size) { - return mallocTask(size, (Task*) getCurrentTask()); -} - -void mergeNextIfPossible(MemoryBlock* current) { - if (current->next != 0x00 && current->next->state == FREE) { - current->size = current->size + sizeof(MemoryBlock) + current->next->size; - current->next = current->next->next; - current->next->next->last = current; - } -} - -void free(void* location) { - MemoryBlock* current = ((MemoryBlock*) location) - 1; - current->state = FREE; - mergeNextIfPossible(current); - if (current->last != 0x00 && current->last->state == FREE) { - current = current->last; - } - mergeNextIfPossible(current); // call this function twice in case a used block between 2 free blocks is freed - mergeNextIfPossible(current); -} - -void printMemoryStack() { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); - current = current->next; - } - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); -} - -void freeTaskAllocations(Task* task) { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - if (current->task == task) { - free(current); - } - current = current->next; - } - if (current->task == task) { - free(current); - } -} \ No newline at end of file diff --git a/src/kernel/lib/ports.c b/src/kernel/lib/ports.c deleted file mode 100644 index 6cfbb2a..0000000 --- a/src/kernel/lib/ports.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include - -void outb(uint16_t port, uint8_t val) { - asm volatile("outb %0, %1" : : "a"(val), "Nd"(port) ); -} - -uint8_t inb(uint16_t port) { - uint8_t result; - __asm__("in %%dx, %%al" : "=a" (result) : "d" (port)); - return result; -} \ No newline at end of file diff --git a/src/kernel/lib/task/osTasks.c b/src/kernel/lib/task/osTasks.c deleted file mode 100644 index c3d6a43..0000000 --- a/src/kernel/lib/task/osTasks.c +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include -#include -#include - -Task mainTask; -Task printerTask; - -void printLoop() { - while (1) { - yield(); - Message* message = popMessage(&printerTask); - if (message == 0x00) { - continue; - } - putChars(message->data, message->size); - free(message->data); - free(message); - } -} - -void initOSTasks() { - setRunningTask(&mainTask); - createTask(&printerTask, (uint32_t) printLoop, 0x0, 0x0); - schedule(&printerTask); - // more tasks . . . - yields(); -} - -inline Task* getPrinterTask() { - return &printerTask; -} \ No newline at end of file diff --git a/src/kernel/lib/task/task.c b/src/kernel/lib/task/task.c deleted file mode 100644 index e4201c5..0000000 --- a/src/kernel/lib/task/task.c +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include -#include - -#define STACK_SIZE 0xF000 - -Task *currentTask; - -void createTask(Task *task, uint32_t mainFunction, uint32_t flags, uint32_t *pagedir) { - void* stack = mallocTask(STACK_SIZE, task); - task->registers.eax = 0; - task->registers.ebx = 0; - task->registers.ecx = 0; - task->registers.edx = 0; - task->registers.esi = 0; - task->registers.edi = 0; - task->registers.eflags = flags; - task->registers.eip = mainFunction; - task->registers.cr3 = (uint32_t) pagedir; - task->registers.esp = STACK_SIZE + (uint32_t) stack; - task->nextTask = 0; - task->stack = stack; -} - -void yield() { - Task* last = currentTask; - currentTask = currentTask->nextTask; - if (currentTask == 0x00) { - puts("No more tasks to run, halting . . .\n"); - while (1) { - asm("hlt"); - } - } - last->nextTask = 0x00; - switchTask(&(last->registers), &(currentTask->registers)); -} - -void schedule(Task* task) { - Task* test = currentTask; - while (test->nextTask != 0x0) { - test = test->nextTask; - if (test->nextTask == task) { - return; // don't schedule if the task is already in the queue - } - } - test->nextTask = task; -} - -void setRunningTask(Task* task) { - currentTask = task; -} - -void yields() { - schedule(currentTask); - yield(); -} - -void destroyCurrentTask() { - freeTaskAllocations(currentTask); - yield(); -} - -Task* getCurrentTask() { - return currentTask; -} - -void sendMessage(Task* task, Message* message) { - if (task->message == 0x00) { - task->message = message; - return; - } - Message* currentMessage = task->message; - while (currentMessage->next == 0x00) { - currentMessage = currentMessage->next; - } - currentMessage->next = message; -} - -Message* popMessage(Task* task) { - Message* currentMessage = task->message; - if (currentMessage != 0x00) { - task->message = currentMessage->next; - - } - return currentMessage; -} \ No newline at end of file diff --git a/src/kernel/lib/task/task.s b/src/kernel/lib/task/task.s deleted file mode 100644 index 88357cd..0000000 --- a/src/kernel/lib/task/task.s +++ /dev/null @@ -1,49 +0,0 @@ -.section .text -.global switchTask -switchTask: - pusha - pushf - mov %cr3, %eax #Push CR3 - push %eax - mov 44(%esp), %eax #The first argument, where to save - mov %ebx, 4(%eax) - mov %ecx, 8(%eax) - mov %edx, 12(%eax) - mov %esi, 16(%eax) - mov %edi, 20(%eax) - mov 36(%esp), %ebx #EAX - mov 40(%esp), %ecx #IP - mov 20(%esp), %edx #ESP - add $4, %edx #Remove the return value - mov 16(%esp), %esi #EBP - mov 4(%esp), %edi #EFLAGS - mov %ebx, (%eax) - mov %edx, 24(%eax) - mov %esi, 28(%eax) - mov %ecx, 32(%eax) - mov %edi, 36(%eax) - pop %ebx #CR3 - mov %ebx, 40(%eax) - push %ebx #Goodbye again - mov 48(%esp), %eax #Now it is the new object - mov 4(%eax), %ebx #EBX - mov 8(%eax), %ecx #ECX - mov 12(%eax), %edx #EDX - mov 16(%eax), %esi #ESI - mov 20(%eax), %edi #EDI - mov 28(%eax), %ebp #EBP - push %eax - mov 36(%eax), %eax #EFLAGS - push %eax - popf - pop %eax - mov 24(%eax), %esp #ESP - push %eax - mov 40(%eax), %eax #CR3 - mov %eax, %cr3 - pop %eax - push %eax - mov 32(%eax), %eax #EIP - xchg (%esp), %eax - mov (%eax), %eax #EAX - ret diff --git a/src/kernel/lib/textMode/cursor.c b/src/kernel/lib/textMode/cursor.c deleted file mode 100644 index e5cc8f9..0000000 --- a/src/kernel/lib/textMode/cursor.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include -#include - -void setCursorOffset(uint16_t offset) { - outb(0x3D4, 0x0F); - outb(0x3D5, (uint8_t) (offset & 0xFF)); - outb(0x3D4, 0x0E); - outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); -} - -void setCursorPosition(uint8_t x, uint8_t y) { - setCursorOffset(x + y * VIDEO_WIDTH); -} - -uint16_t getCursorOffset() { - uint16_t result = 0; - outb(0x3D4, 0x0F); - result |= inb(0x3D5); - outb(0x3D4, 0x0E); - result |= ((uint16_t)inb(0x3D5)) << 8; - return result; -} \ No newline at end of file diff --git a/src/kernel/lib/textMode/stdio.c b/src/kernel/lib/textMode/stdio.c deleted file mode 100644 index 5f1b3a0..0000000 --- a/src/kernel/lib/textMode/stdio.c +++ /dev/null @@ -1,200 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; -char format = 0x0F; - -void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { - *(framebuffer + position) = c; -} - -void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { - putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); -} - -void putCharAtOffset(char c, uint16_t offset) { - putCharWithFormatAtOffset(c | format << 8, offset); -} - -void putCharAt(char c, uint8_t x, uint8_t y) { - putCharAtOffset(c, (x + y * VIDEO_WIDTH)); -} - -uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { - return *(framebuffer + x + y * VIDEO_WIDTH); -} - -void putCharsAt(char* string, uint8_t x, uint8_t y) { - uint16_t position = 0; - char c = *string; - while (c != 0x00) { - putCharAt(c, x + position, y); - position++; - c = *(string + position); - } -} - -void shiftUp() { - for (int y = 1; y < VIDEO_HEIGHT; y++) { - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); - } - } - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); - } -} - -void newLine() { - uint16_t offset = getCursorOffset(); - uint8_t x = offset % VIDEO_WIDTH; - uint8_t y = offset / VIDEO_WIDTH; - x = 0; - y++; - if (y >= VIDEO_HEIGHT) { - shiftUp(); - y--; - } - setCursorPosition(x, y); -} - -void putChar(char c) { - if (c == '\n') { - newLine(); - return; - } - uint16_t offset = getCursorOffset(); - putCharAtOffset(c, offset); - setCursorOffset(offset + 1); -} - -void puts(char* string) { - while (*string != 0x00) { - putChar(*string); - string++; - } -} - -char HEX_PREFIX[] = "0x"; -char HEX_CHARS[] = "0123456789ABCDEF"; - -void putHex(char** write, uint32_t x) { - uint8_t alreadyWriting = 0; - for (uint8_t position = 3; position >= 0; position--) { - uint8_t byte = (x >> (position * 8)) & 0xFF; - if (byte != 0x00) { - alreadyWriting = 0x01; - } - if (alreadyWriting) { - **write = HEX_CHARS[byte % 256]; - *write++; - **write = HEX_CHARS[byte / 256]; - *write++; - } - } -} - -uint32_t getInsertLength(char insertType, uint32_t x) { - switch (insertType) - { - case 's': - return strlen((char*) x); - case 'x': - for (uint8_t position = 3; position >= 0; position--) { - uint8_t byte = (x >> (position * 8)) & 0xFF; - if (byte != 0x00) { - return 2*position; - } - } - return 0; - } - return 0; -} - -void handleInsert(char** write, char insertType, uint32_t x) { - if (insertType == 's') { - char* string = (char*) x; - uint32_t length = strlen(string); - for (uint32_t position = 0; position < length; position++) { - **write = string[position]; - *write++; - } - return; - } - if (insertType == 'x') { - putHex(write, x); - } -} - -void printf(const char* format, ...) { - uint32_t size = 0; - va_list valist; - va_start(valist, format); - for (int i = 0; format[i] != 0; i++) { - if (format[i] == '%') { - size += getInsertLength(format[++i], va_arg(valist, uint32_t)); - continue; - } - size++; - } - va_start(valist, format); - - char* data = malloc(size); - char* write = data; - for (int i = 0; format[i] != 0; i++) { - if (format[i] == '%') { - handleInsert(&write, format[++i], va_arg(valist, uint32_t)); - continue; - } - *write = format[i]; - write++; - } - va_end(valist); - - Message message = { - message.data = data, - message.size = size, - message.next = 0x00 - }; - sendMessage(getPrinterTask(), &message); - schedule(getPrinterTask()); - yields(); -} - -void clearScreen() { - setCursorOffset(0); - for (int y = 0; y < VIDEO_HEIGHT; y++) { - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharAt(' ', x, y); - } - } -} - -void setTextStyle(uint8_t style) { - format = style; -} - -void putChars(char* string, uint32_t length) { - for (uint32_t i = 0; i < length; i++) { - if (string[i] == '\n') { - newLine(); - continue; - } - putChar(string[i]); - } -} - -uint32_t strlen(char* string) { - uint32_t length = 0; - while (string[length] != 0) { - length++; - } - return length; -} \ No newline at end of file diff --git a/src/kernel/memory/alloc.c b/src/kernel/memory/alloc.c new file mode 100644 index 0000000..97d0a84 --- /dev/null +++ b/src/kernel/memory/alloc.c @@ -0,0 +1,94 @@ +#include +#include +#include <_stdio.h> + +MemoryBlock* firstBlock; + +void initMemoryAllocation(uint32_t kernelEnd) { + firstBlock = (MemoryBlock*) kernelEnd; + firstBlock->next = 0x00; + firstBlock->last = 0x00; + firstBlock->state = FREE; + firstBlock->size = -1; +} + +void* mallocTask(uint32_t size, Task* task) { + MemoryBlock* current = firstBlock; + while (! (current->next == 0x00 || current->state == FREE && current->size >= size)) { + current = current->next; + } + MemoryBlock* next; + if (current->next == 0x00) { + // this is currently the last block -> initialize the new last block + next = (MemoryBlock*) ((void*) (current + 1) + size); + next->last = current; + next->state = FREE; + next->next = 0x00; + next->size = -1; + } else { + // there is a next block + next = current->next; + } + if (current->size > size + sizeof(MemoryBlock) * 2 && current->next != 0x00) { + // segment the current block if it is big enough + current->next = (MemoryBlock*) (((void*) (current + 1)) + size); + current->next->size = current->size - sizeof(MemoryBlock) - size; + current->size = size; + current->next->state = FREE; + current->next->next = next; + next->last = current->next; + } else { + current->next = next; + if (current->next->next == 0x00) { + current->size = size; + } + } + current->state = IN_USE; + current->task = task; + return (void*) (current + 1); +} + +void* malloc(uint32_t size) { + return mallocTask(size, (Task*) getCurrentTask()); +} + +void mergeNextIfPossible(MemoryBlock* current) { + if (current->next != 0x00 && current->next->state == FREE) { + current->size = current->size + sizeof(MemoryBlock) + current->next->size; + current->next = current->next->next; + current->next->next->last = current; + } +} + +void free(void* location) { + MemoryBlock* current = ((MemoryBlock*) location) - 1; + current->state = FREE; + mergeNextIfPossible(current); + if (current->last != 0x00 && current->last->state == FREE) { + current = current->last; + } + mergeNextIfPossible(current); // call this function twice in case a used block between 2 free blocks is freed + mergeNextIfPossible(current); +} + +void printMemoryStack() { + MemoryBlock* current = firstBlock; + while (current->next != 0x00) { + printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); + current = current->next; + } + printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); +} + +void freeTaskAllocations(Task* task) { + MemoryBlock* current = firstBlock; + while (current->next != 0x00) { + if (current->task == task) { + free(current); + } + current = current->next; + } + if (current->task == task) { + free(current); + } +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index dd72655..36c0cfc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { - "*.h": "c" + "*.h": "c", + "type_traits": "c" } } \ No newline at end of file diff --git a/src/headers/_stdio.h b/src/headers/_stdio.h new file mode 100644 index 0000000..b5d4f87 --- /dev/null +++ b/src/headers/_stdio.h @@ -0,0 +1,20 @@ +#ifndef STDIO_H +#define STDIO_H + +#include + +#define FRAMEBUFFER_LOCATION 0x000B8000 +#define VIDEO_WIDTH 80 +#define VIDEO_HEIGHT 25 + +extern void setTextStyle(uint8_t style); +extern void clearScreen(); +extern void printf(const char* format, ...); +extern void putCharAt(char c, uint8_t x, uint8_t y); +extern void putCharsAt(char* string, uint8_t x, uint8_t y); +extern void puts(char* string); +extern void putChars(char* string, uint32_t length); + +extern uint32_t strlen(char* string); + +#endif \ No newline at end of file diff --git a/src/headers/interrupts.h b/src/headers/interrupts.h new file mode 100644 index 0000000..3ca3d29 --- /dev/null +++ b/src/headers/interrupts.h @@ -0,0 +1,21 @@ +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + +#include + +typedef struct { + uint16_t isr_low; + uint16_t codeSegment; + uint8_t reserved; + uint8_t attributes; + uint16_t isr_high; +} __attribute__((packed)) IDTEntry; + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) IDTR; + +extern void initInterrupts(); + +#endif \ No newline at end of file diff --git a/src/headers/stdio.h b/src/headers/stdio.h deleted file mode 100644 index b5d4f87..0000000 --- a/src/headers/stdio.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef STDIO_H -#define STDIO_H - -#include - -#define FRAMEBUFFER_LOCATION 0x000B8000 -#define VIDEO_WIDTH 80 -#define VIDEO_HEIGHT 25 - -extern void setTextStyle(uint8_t style); -extern void clearScreen(); -extern void printf(const char* format, ...); -extern void putCharAt(char c, uint8_t x, uint8_t y); -extern void putCharsAt(char* string, uint8_t x, uint8_t y); -extern void puts(char* string); -extern void putChars(char* string, uint32_t length); - -extern uint32_t strlen(char* string); - -#endif \ No newline at end of file diff --git a/src/interrupts/interrupts.c b/src/interrupts/interrupts.c new file mode 100644 index 0000000..74d2931 --- /dev/null +++ b/src/interrupts/interrupts.c @@ -0,0 +1,33 @@ +#include +#include <_stdio.h> +#include + +IDTR idtr; +IDTEntry* entries; +void* buffer; + +void setInterrupt(uint8_t vector, void* callback, uint8_t flags) { + IDTEntry* descriptor = &entries[vector]; + + descriptor->isr_low = (uint32_t)callback & 0xFFFF; + descriptor->codeSegment = 0x08; + descriptor->attributes = flags; + descriptor->isr_high = (uint32_t)callback >> 16; + descriptor->reserved = 0; +} + +void testInterrupt() { + printf("interrupt!\n"); +} + +void initInterrupts() { + buffer = malloc(sizeof(IDTEntry) * 257); + entries = (IDTEntry*) (((int) buffer + sizeof(IDTEntry)) & -1 ^ 0x0F); + idtr.limit = sizeof(IDTEntry) * 256 - 1; + idtr.base = entries; + for (int i = 0; i < 256; i++) { + setInterrupt(i, testInterrupt, 0x8E); + } + __asm__ volatile ("lidt %0" : : "memory"(idtr)); + __asm__ volatile ("sti"); +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/_stdio.c b/src/kernel/drivers/textMode/_stdio.c new file mode 100644 index 0000000..34eea3f --- /dev/null +++ b/src/kernel/drivers/textMode/_stdio.c @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <_stdio.h> + +uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; +char format = 0x0F; + +void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { + *(framebuffer + position) = c; +} + +void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { + putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +void putCharAtOffset(char c, uint16_t offset) { + putCharWithFormatAtOffset(c | format << 8, offset); +} + +void putCharAt(char c, uint8_t x, uint8_t y) { + putCharAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { + return *(framebuffer + x + y * VIDEO_WIDTH); +} + +void putCharsAt(char* string, uint8_t x, uint8_t y) { + uint16_t position = 0; + char c = *string; + while (c != 0x00) { + putCharAt(c, x + position, y); + position++; + c = *(string + position); + } +} + +void shiftUp() { + for (int y = 1; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); + } + } + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); + } +} + +void newLine() { + uint16_t offset = getCursorOffset(); + uint8_t x = offset % VIDEO_WIDTH; + uint8_t y = offset / VIDEO_WIDTH; + x = 0; + y++; + if (y >= VIDEO_HEIGHT) { + shiftUp(); + y--; + } + setCursorPosition(x, y); +} + +void putChar(char c) { + if (c == '\n') { + newLine(); + return; + } + uint16_t offset = getCursorOffset(); + putCharAtOffset(c, offset); + setCursorOffset(offset + 1); +} + +void puts(char* string) { + while (*string != 0x00) { + putChar(*string); + string++; + } +} + +char HEX_PREFIX[] = "0x"; +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char** write, uint32_t x) { + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + **write = HEX_CHARS[byte >> 8]; + (*write)++; + } + } +} + +uint8_t hexLength(uint32_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return size; +} + +uint32_t getInsertLength(char insertType, uint32_t x) { + switch (insertType) { + case 's': + return strlen((char*) x); + case 'x': + return hexLength(x); + } + return 0; +} + +void stringInsert(char** write, uint32_t x) { + char* string = (char*) x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char** write, char insertType, uint32_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + } +} + +void printf(const char* format, ...) { + uint32_t size = 0; + va_list valist; + va_start(valist, format); + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + size += getInsertLength(format[++i], va_arg(valist, uint32_t)); + continue; + } + size++; + } + va_start(valist, format); + + char* data = malloc(size); + char* write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(valist, uint32_t)); + continue; + } + *write = format[i]; + write++; + } + va_end(valist); + + Message* message = malloc(sizeof(Message)); + + message->data = data; + message->size = size; + message->next = 0x00; + sendMessage(getPrinterTask(), message); + schedule(getPrinterTask()); +} + +void clearScreen() { + setCursorOffset(0); + for (int y = 0; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharAt(' ', x, y); + } + } +} + +void setTextStyle(uint8_t style) { + format = style; +} + +void putChars(char* string, uint32_t length) { + for (uint32_t i = 0; i < length; i++) { + if (string[i] == '\n') { + newLine(); + continue; + } + putChar(string[i]); + } +} + +uint32_t strlen(char* string) { + uint32_t length = 0; + while (string[length] != 0) { + length++; + } + return length; +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/cursor.c b/src/kernel/drivers/textMode/cursor.c new file mode 100644 index 0000000..8247c5e --- /dev/null +++ b/src/kernel/drivers/textMode/cursor.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include <_stdio.h> + +void setCursorOffset(uint16_t offset) { + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (offset & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); +} + +void setCursorPosition(uint8_t x, uint8_t y) { + setCursorOffset(x + y * VIDEO_WIDTH); +} + +uint16_t getCursorOffset() { + uint16_t result = 0; + outb(0x3D4, 0x0F); + result |= inb(0x3D5); + outb(0x3D4, 0x0E); + result |= ((uint16_t)inb(0x3D5)) << 8; + return result; +} \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index d8ff7b8..48ea59f 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,19 +1,26 @@ #include -#include +#include <_stdio.h> #include #include #include #include #include +#include extern uint32_t _kernel_end; void kernelMain() { - initMemoryAllocation(0x100000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here + initMemoryAllocation(0x1000000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here initOSTasks(); drawLogo(); - printf("Switching to otherTask... \n"); + printf("giving up control...\n"); yields(); printf("Returned to mainTask!\n\n"); + printf("initializing interrupts\n"); + initInterrupts(); + yields(); + printf("trying interrupt\n"); + asm ("int $0x80"); + printf("the interrupt worked!\n"); yield(); } \ No newline at end of file diff --git a/src/kernel/lib/memory/alloc.c b/src/kernel/lib/memory/alloc.c deleted file mode 100644 index aedcbad..0000000 --- a/src/kernel/lib/memory/alloc.c +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include -#include - -MemoryBlock* firstBlock; - -void initMemoryAllocation(uint32_t kernelEnd) { - firstBlock = (MemoryBlock*) kernelEnd; - firstBlock->next = 0x00; - firstBlock->last = 0x00; - firstBlock->state = FREE; - firstBlock->size = -1; -} - -void* mallocTask(uint32_t size, Task* task) { - MemoryBlock* current = firstBlock; - while (! (current->next == 0x00 || current->state == FREE && current->size >= size)) { - current = current->next; - } - MemoryBlock* next; - if (current->next == 0x00) { - // this is currently the last block -> initialize the new last block - next = (MemoryBlock*) ((void*) (current + 1) + size); - next->last = current; - next->state = FREE; - next->next = 0x00; - next->size = -1; - } else { - // there is a next block - next = current->next; - } - if (current->size > size + sizeof(MemoryBlock) * 2 && current->next != 0x00) { - // segment the current block if it is big enough - current->next = (MemoryBlock*) (((void*) (current + 1)) + size); - current->next->size = current->size - sizeof(MemoryBlock) - size; - current->size = size; - current->next->state = FREE; - current->next->next = next; - next->last = current->next; - } else { - current->next = next; - if (current->next->next == 0x00) { - current->size = size; - } - } - current->state = IN_USE; - current->task = task; - return (void*) (current + 1); -} - -void* malloc(uint32_t size) { - return mallocTask(size, (Task*) getCurrentTask()); -} - -void mergeNextIfPossible(MemoryBlock* current) { - if (current->next != 0x00 && current->next->state == FREE) { - current->size = current->size + sizeof(MemoryBlock) + current->next->size; - current->next = current->next->next; - current->next->next->last = current; - } -} - -void free(void* location) { - MemoryBlock* current = ((MemoryBlock*) location) - 1; - current->state = FREE; - mergeNextIfPossible(current); - if (current->last != 0x00 && current->last->state == FREE) { - current = current->last; - } - mergeNextIfPossible(current); // call this function twice in case a used block between 2 free blocks is freed - mergeNextIfPossible(current); -} - -void printMemoryStack() { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); - current = current->next; - } - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); -} - -void freeTaskAllocations(Task* task) { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - if (current->task == task) { - free(current); - } - current = current->next; - } - if (current->task == task) { - free(current); - } -} \ No newline at end of file diff --git a/src/kernel/lib/ports.c b/src/kernel/lib/ports.c deleted file mode 100644 index 6cfbb2a..0000000 --- a/src/kernel/lib/ports.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include - -void outb(uint16_t port, uint8_t val) { - asm volatile("outb %0, %1" : : "a"(val), "Nd"(port) ); -} - -uint8_t inb(uint16_t port) { - uint8_t result; - __asm__("in %%dx, %%al" : "=a" (result) : "d" (port)); - return result; -} \ No newline at end of file diff --git a/src/kernel/lib/task/osTasks.c b/src/kernel/lib/task/osTasks.c deleted file mode 100644 index c3d6a43..0000000 --- a/src/kernel/lib/task/osTasks.c +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include -#include -#include - -Task mainTask; -Task printerTask; - -void printLoop() { - while (1) { - yield(); - Message* message = popMessage(&printerTask); - if (message == 0x00) { - continue; - } - putChars(message->data, message->size); - free(message->data); - free(message); - } -} - -void initOSTasks() { - setRunningTask(&mainTask); - createTask(&printerTask, (uint32_t) printLoop, 0x0, 0x0); - schedule(&printerTask); - // more tasks . . . - yields(); -} - -inline Task* getPrinterTask() { - return &printerTask; -} \ No newline at end of file diff --git a/src/kernel/lib/task/task.c b/src/kernel/lib/task/task.c deleted file mode 100644 index e4201c5..0000000 --- a/src/kernel/lib/task/task.c +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include -#include - -#define STACK_SIZE 0xF000 - -Task *currentTask; - -void createTask(Task *task, uint32_t mainFunction, uint32_t flags, uint32_t *pagedir) { - void* stack = mallocTask(STACK_SIZE, task); - task->registers.eax = 0; - task->registers.ebx = 0; - task->registers.ecx = 0; - task->registers.edx = 0; - task->registers.esi = 0; - task->registers.edi = 0; - task->registers.eflags = flags; - task->registers.eip = mainFunction; - task->registers.cr3 = (uint32_t) pagedir; - task->registers.esp = STACK_SIZE + (uint32_t) stack; - task->nextTask = 0; - task->stack = stack; -} - -void yield() { - Task* last = currentTask; - currentTask = currentTask->nextTask; - if (currentTask == 0x00) { - puts("No more tasks to run, halting . . .\n"); - while (1) { - asm("hlt"); - } - } - last->nextTask = 0x00; - switchTask(&(last->registers), &(currentTask->registers)); -} - -void schedule(Task* task) { - Task* test = currentTask; - while (test->nextTask != 0x0) { - test = test->nextTask; - if (test->nextTask == task) { - return; // don't schedule if the task is already in the queue - } - } - test->nextTask = task; -} - -void setRunningTask(Task* task) { - currentTask = task; -} - -void yields() { - schedule(currentTask); - yield(); -} - -void destroyCurrentTask() { - freeTaskAllocations(currentTask); - yield(); -} - -Task* getCurrentTask() { - return currentTask; -} - -void sendMessage(Task* task, Message* message) { - if (task->message == 0x00) { - task->message = message; - return; - } - Message* currentMessage = task->message; - while (currentMessage->next == 0x00) { - currentMessage = currentMessage->next; - } - currentMessage->next = message; -} - -Message* popMessage(Task* task) { - Message* currentMessage = task->message; - if (currentMessage != 0x00) { - task->message = currentMessage->next; - - } - return currentMessage; -} \ No newline at end of file diff --git a/src/kernel/lib/task/task.s b/src/kernel/lib/task/task.s deleted file mode 100644 index 88357cd..0000000 --- a/src/kernel/lib/task/task.s +++ /dev/null @@ -1,49 +0,0 @@ -.section .text -.global switchTask -switchTask: - pusha - pushf - mov %cr3, %eax #Push CR3 - push %eax - mov 44(%esp), %eax #The first argument, where to save - mov %ebx, 4(%eax) - mov %ecx, 8(%eax) - mov %edx, 12(%eax) - mov %esi, 16(%eax) - mov %edi, 20(%eax) - mov 36(%esp), %ebx #EAX - mov 40(%esp), %ecx #IP - mov 20(%esp), %edx #ESP - add $4, %edx #Remove the return value - mov 16(%esp), %esi #EBP - mov 4(%esp), %edi #EFLAGS - mov %ebx, (%eax) - mov %edx, 24(%eax) - mov %esi, 28(%eax) - mov %ecx, 32(%eax) - mov %edi, 36(%eax) - pop %ebx #CR3 - mov %ebx, 40(%eax) - push %ebx #Goodbye again - mov 48(%esp), %eax #Now it is the new object - mov 4(%eax), %ebx #EBX - mov 8(%eax), %ecx #ECX - mov 12(%eax), %edx #EDX - mov 16(%eax), %esi #ESI - mov 20(%eax), %edi #EDI - mov 28(%eax), %ebp #EBP - push %eax - mov 36(%eax), %eax #EFLAGS - push %eax - popf - pop %eax - mov 24(%eax), %esp #ESP - push %eax - mov 40(%eax), %eax #CR3 - mov %eax, %cr3 - pop %eax - push %eax - mov 32(%eax), %eax #EIP - xchg (%esp), %eax - mov (%eax), %eax #EAX - ret diff --git a/src/kernel/lib/textMode/cursor.c b/src/kernel/lib/textMode/cursor.c deleted file mode 100644 index e5cc8f9..0000000 --- a/src/kernel/lib/textMode/cursor.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include -#include - -void setCursorOffset(uint16_t offset) { - outb(0x3D4, 0x0F); - outb(0x3D5, (uint8_t) (offset & 0xFF)); - outb(0x3D4, 0x0E); - outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); -} - -void setCursorPosition(uint8_t x, uint8_t y) { - setCursorOffset(x + y * VIDEO_WIDTH); -} - -uint16_t getCursorOffset() { - uint16_t result = 0; - outb(0x3D4, 0x0F); - result |= inb(0x3D5); - outb(0x3D4, 0x0E); - result |= ((uint16_t)inb(0x3D5)) << 8; - return result; -} \ No newline at end of file diff --git a/src/kernel/lib/textMode/stdio.c b/src/kernel/lib/textMode/stdio.c deleted file mode 100644 index 5f1b3a0..0000000 --- a/src/kernel/lib/textMode/stdio.c +++ /dev/null @@ -1,200 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; -char format = 0x0F; - -void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { - *(framebuffer + position) = c; -} - -void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { - putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); -} - -void putCharAtOffset(char c, uint16_t offset) { - putCharWithFormatAtOffset(c | format << 8, offset); -} - -void putCharAt(char c, uint8_t x, uint8_t y) { - putCharAtOffset(c, (x + y * VIDEO_WIDTH)); -} - -uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { - return *(framebuffer + x + y * VIDEO_WIDTH); -} - -void putCharsAt(char* string, uint8_t x, uint8_t y) { - uint16_t position = 0; - char c = *string; - while (c != 0x00) { - putCharAt(c, x + position, y); - position++; - c = *(string + position); - } -} - -void shiftUp() { - for (int y = 1; y < VIDEO_HEIGHT; y++) { - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); - } - } - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); - } -} - -void newLine() { - uint16_t offset = getCursorOffset(); - uint8_t x = offset % VIDEO_WIDTH; - uint8_t y = offset / VIDEO_WIDTH; - x = 0; - y++; - if (y >= VIDEO_HEIGHT) { - shiftUp(); - y--; - } - setCursorPosition(x, y); -} - -void putChar(char c) { - if (c == '\n') { - newLine(); - return; - } - uint16_t offset = getCursorOffset(); - putCharAtOffset(c, offset); - setCursorOffset(offset + 1); -} - -void puts(char* string) { - while (*string != 0x00) { - putChar(*string); - string++; - } -} - -char HEX_PREFIX[] = "0x"; -char HEX_CHARS[] = "0123456789ABCDEF"; - -void putHex(char** write, uint32_t x) { - uint8_t alreadyWriting = 0; - for (uint8_t position = 3; position >= 0; position--) { - uint8_t byte = (x >> (position * 8)) & 0xFF; - if (byte != 0x00) { - alreadyWriting = 0x01; - } - if (alreadyWriting) { - **write = HEX_CHARS[byte % 256]; - *write++; - **write = HEX_CHARS[byte / 256]; - *write++; - } - } -} - -uint32_t getInsertLength(char insertType, uint32_t x) { - switch (insertType) - { - case 's': - return strlen((char*) x); - case 'x': - for (uint8_t position = 3; position >= 0; position--) { - uint8_t byte = (x >> (position * 8)) & 0xFF; - if (byte != 0x00) { - return 2*position; - } - } - return 0; - } - return 0; -} - -void handleInsert(char** write, char insertType, uint32_t x) { - if (insertType == 's') { - char* string = (char*) x; - uint32_t length = strlen(string); - for (uint32_t position = 0; position < length; position++) { - **write = string[position]; - *write++; - } - return; - } - if (insertType == 'x') { - putHex(write, x); - } -} - -void printf(const char* format, ...) { - uint32_t size = 0; - va_list valist; - va_start(valist, format); - for (int i = 0; format[i] != 0; i++) { - if (format[i] == '%') { - size += getInsertLength(format[++i], va_arg(valist, uint32_t)); - continue; - } - size++; - } - va_start(valist, format); - - char* data = malloc(size); - char* write = data; - for (int i = 0; format[i] != 0; i++) { - if (format[i] == '%') { - handleInsert(&write, format[++i], va_arg(valist, uint32_t)); - continue; - } - *write = format[i]; - write++; - } - va_end(valist); - - Message message = { - message.data = data, - message.size = size, - message.next = 0x00 - }; - sendMessage(getPrinterTask(), &message); - schedule(getPrinterTask()); - yields(); -} - -void clearScreen() { - setCursorOffset(0); - for (int y = 0; y < VIDEO_HEIGHT; y++) { - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharAt(' ', x, y); - } - } -} - -void setTextStyle(uint8_t style) { - format = style; -} - -void putChars(char* string, uint32_t length) { - for (uint32_t i = 0; i < length; i++) { - if (string[i] == '\n') { - newLine(); - continue; - } - putChar(string[i]); - } -} - -uint32_t strlen(char* string) { - uint32_t length = 0; - while (string[length] != 0) { - length++; - } - return length; -} \ No newline at end of file diff --git a/src/kernel/memory/alloc.c b/src/kernel/memory/alloc.c new file mode 100644 index 0000000..97d0a84 --- /dev/null +++ b/src/kernel/memory/alloc.c @@ -0,0 +1,94 @@ +#include +#include +#include <_stdio.h> + +MemoryBlock* firstBlock; + +void initMemoryAllocation(uint32_t kernelEnd) { + firstBlock = (MemoryBlock*) kernelEnd; + firstBlock->next = 0x00; + firstBlock->last = 0x00; + firstBlock->state = FREE; + firstBlock->size = -1; +} + +void* mallocTask(uint32_t size, Task* task) { + MemoryBlock* current = firstBlock; + while (! (current->next == 0x00 || current->state == FREE && current->size >= size)) { + current = current->next; + } + MemoryBlock* next; + if (current->next == 0x00) { + // this is currently the last block -> initialize the new last block + next = (MemoryBlock*) ((void*) (current + 1) + size); + next->last = current; + next->state = FREE; + next->next = 0x00; + next->size = -1; + } else { + // there is a next block + next = current->next; + } + if (current->size > size + sizeof(MemoryBlock) * 2 && current->next != 0x00) { + // segment the current block if it is big enough + current->next = (MemoryBlock*) (((void*) (current + 1)) + size); + current->next->size = current->size - sizeof(MemoryBlock) - size; + current->size = size; + current->next->state = FREE; + current->next->next = next; + next->last = current->next; + } else { + current->next = next; + if (current->next->next == 0x00) { + current->size = size; + } + } + current->state = IN_USE; + current->task = task; + return (void*) (current + 1); +} + +void* malloc(uint32_t size) { + return mallocTask(size, (Task*) getCurrentTask()); +} + +void mergeNextIfPossible(MemoryBlock* current) { + if (current->next != 0x00 && current->next->state == FREE) { + current->size = current->size + sizeof(MemoryBlock) + current->next->size; + current->next = current->next->next; + current->next->next->last = current; + } +} + +void free(void* location) { + MemoryBlock* current = ((MemoryBlock*) location) - 1; + current->state = FREE; + mergeNextIfPossible(current); + if (current->last != 0x00 && current->last->state == FREE) { + current = current->last; + } + mergeNextIfPossible(current); // call this function twice in case a used block between 2 free blocks is freed + mergeNextIfPossible(current); +} + +void printMemoryStack() { + MemoryBlock* current = firstBlock; + while (current->next != 0x00) { + printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); + current = current->next; + } + printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); +} + +void freeTaskAllocations(Task* task) { + MemoryBlock* current = firstBlock; + while (current->next != 0x00) { + if (current->task == task) { + free(current); + } + current = current->next; + } + if (current->task == task) { + free(current); + } +} \ No newline at end of file diff --git a/src/kernel/task/osTasks.c b/src/kernel/task/osTasks.c new file mode 100644 index 0000000..5d52a79 --- /dev/null +++ b/src/kernel/task/osTasks.c @@ -0,0 +1,35 @@ +#include +#include +#include <_stdio.h> +#include +#include + +Task mainTask; +Task printerTask; + +void printLoop() { + clearScreen(); + setTextStyle(0x0F); + while (1) { + Message* message = popMessage(&printerTask); + if (message == 0) { + yield(); + continue; + } + putChars(message->data, message->size); + free(message->data); + free(message); + } +} + +void initOSTasks() { + setRunningTask(&mainTask); + createTask(&printerTask, (uint32_t) printLoop, 0x0, 0x0); + schedule(&printerTask); + // more tasks . . . + yields(); +} + +inline Task* getPrinterTask() { + return &printerTask; +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index dd72655..36c0cfc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { - "*.h": "c" + "*.h": "c", + "type_traits": "c" } } \ No newline at end of file diff --git a/src/headers/_stdio.h b/src/headers/_stdio.h new file mode 100644 index 0000000..b5d4f87 --- /dev/null +++ b/src/headers/_stdio.h @@ -0,0 +1,20 @@ +#ifndef STDIO_H +#define STDIO_H + +#include + +#define FRAMEBUFFER_LOCATION 0x000B8000 +#define VIDEO_WIDTH 80 +#define VIDEO_HEIGHT 25 + +extern void setTextStyle(uint8_t style); +extern void clearScreen(); +extern void printf(const char* format, ...); +extern void putCharAt(char c, uint8_t x, uint8_t y); +extern void putCharsAt(char* string, uint8_t x, uint8_t y); +extern void puts(char* string); +extern void putChars(char* string, uint32_t length); + +extern uint32_t strlen(char* string); + +#endif \ No newline at end of file diff --git a/src/headers/interrupts.h b/src/headers/interrupts.h new file mode 100644 index 0000000..3ca3d29 --- /dev/null +++ b/src/headers/interrupts.h @@ -0,0 +1,21 @@ +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + +#include + +typedef struct { + uint16_t isr_low; + uint16_t codeSegment; + uint8_t reserved; + uint8_t attributes; + uint16_t isr_high; +} __attribute__((packed)) IDTEntry; + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) IDTR; + +extern void initInterrupts(); + +#endif \ No newline at end of file diff --git a/src/headers/stdio.h b/src/headers/stdio.h deleted file mode 100644 index b5d4f87..0000000 --- a/src/headers/stdio.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef STDIO_H -#define STDIO_H - -#include - -#define FRAMEBUFFER_LOCATION 0x000B8000 -#define VIDEO_WIDTH 80 -#define VIDEO_HEIGHT 25 - -extern void setTextStyle(uint8_t style); -extern void clearScreen(); -extern void printf(const char* format, ...); -extern void putCharAt(char c, uint8_t x, uint8_t y); -extern void putCharsAt(char* string, uint8_t x, uint8_t y); -extern void puts(char* string); -extern void putChars(char* string, uint32_t length); - -extern uint32_t strlen(char* string); - -#endif \ No newline at end of file diff --git a/src/interrupts/interrupts.c b/src/interrupts/interrupts.c new file mode 100644 index 0000000..74d2931 --- /dev/null +++ b/src/interrupts/interrupts.c @@ -0,0 +1,33 @@ +#include +#include <_stdio.h> +#include + +IDTR idtr; +IDTEntry* entries; +void* buffer; + +void setInterrupt(uint8_t vector, void* callback, uint8_t flags) { + IDTEntry* descriptor = &entries[vector]; + + descriptor->isr_low = (uint32_t)callback & 0xFFFF; + descriptor->codeSegment = 0x08; + descriptor->attributes = flags; + descriptor->isr_high = (uint32_t)callback >> 16; + descriptor->reserved = 0; +} + +void testInterrupt() { + printf("interrupt!\n"); +} + +void initInterrupts() { + buffer = malloc(sizeof(IDTEntry) * 257); + entries = (IDTEntry*) (((int) buffer + sizeof(IDTEntry)) & -1 ^ 0x0F); + idtr.limit = sizeof(IDTEntry) * 256 - 1; + idtr.base = entries; + for (int i = 0; i < 256; i++) { + setInterrupt(i, testInterrupt, 0x8E); + } + __asm__ volatile ("lidt %0" : : "memory"(idtr)); + __asm__ volatile ("sti"); +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/_stdio.c b/src/kernel/drivers/textMode/_stdio.c new file mode 100644 index 0000000..34eea3f --- /dev/null +++ b/src/kernel/drivers/textMode/_stdio.c @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <_stdio.h> + +uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; +char format = 0x0F; + +void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { + *(framebuffer + position) = c; +} + +void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { + putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +void putCharAtOffset(char c, uint16_t offset) { + putCharWithFormatAtOffset(c | format << 8, offset); +} + +void putCharAt(char c, uint8_t x, uint8_t y) { + putCharAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { + return *(framebuffer + x + y * VIDEO_WIDTH); +} + +void putCharsAt(char* string, uint8_t x, uint8_t y) { + uint16_t position = 0; + char c = *string; + while (c != 0x00) { + putCharAt(c, x + position, y); + position++; + c = *(string + position); + } +} + +void shiftUp() { + for (int y = 1; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); + } + } + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); + } +} + +void newLine() { + uint16_t offset = getCursorOffset(); + uint8_t x = offset % VIDEO_WIDTH; + uint8_t y = offset / VIDEO_WIDTH; + x = 0; + y++; + if (y >= VIDEO_HEIGHT) { + shiftUp(); + y--; + } + setCursorPosition(x, y); +} + +void putChar(char c) { + if (c == '\n') { + newLine(); + return; + } + uint16_t offset = getCursorOffset(); + putCharAtOffset(c, offset); + setCursorOffset(offset + 1); +} + +void puts(char* string) { + while (*string != 0x00) { + putChar(*string); + string++; + } +} + +char HEX_PREFIX[] = "0x"; +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char** write, uint32_t x) { + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + **write = HEX_CHARS[byte >> 8]; + (*write)++; + } + } +} + +uint8_t hexLength(uint32_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return size; +} + +uint32_t getInsertLength(char insertType, uint32_t x) { + switch (insertType) { + case 's': + return strlen((char*) x); + case 'x': + return hexLength(x); + } + return 0; +} + +void stringInsert(char** write, uint32_t x) { + char* string = (char*) x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char** write, char insertType, uint32_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + } +} + +void printf(const char* format, ...) { + uint32_t size = 0; + va_list valist; + va_start(valist, format); + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + size += getInsertLength(format[++i], va_arg(valist, uint32_t)); + continue; + } + size++; + } + va_start(valist, format); + + char* data = malloc(size); + char* write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(valist, uint32_t)); + continue; + } + *write = format[i]; + write++; + } + va_end(valist); + + Message* message = malloc(sizeof(Message)); + + message->data = data; + message->size = size; + message->next = 0x00; + sendMessage(getPrinterTask(), message); + schedule(getPrinterTask()); +} + +void clearScreen() { + setCursorOffset(0); + for (int y = 0; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharAt(' ', x, y); + } + } +} + +void setTextStyle(uint8_t style) { + format = style; +} + +void putChars(char* string, uint32_t length) { + for (uint32_t i = 0; i < length; i++) { + if (string[i] == '\n') { + newLine(); + continue; + } + putChar(string[i]); + } +} + +uint32_t strlen(char* string) { + uint32_t length = 0; + while (string[length] != 0) { + length++; + } + return length; +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/cursor.c b/src/kernel/drivers/textMode/cursor.c new file mode 100644 index 0000000..8247c5e --- /dev/null +++ b/src/kernel/drivers/textMode/cursor.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include <_stdio.h> + +void setCursorOffset(uint16_t offset) { + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (offset & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); +} + +void setCursorPosition(uint8_t x, uint8_t y) { + setCursorOffset(x + y * VIDEO_WIDTH); +} + +uint16_t getCursorOffset() { + uint16_t result = 0; + outb(0x3D4, 0x0F); + result |= inb(0x3D5); + outb(0x3D4, 0x0E); + result |= ((uint16_t)inb(0x3D5)) << 8; + return result; +} \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index d8ff7b8..48ea59f 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,19 +1,26 @@ #include -#include +#include <_stdio.h> #include #include #include #include #include +#include extern uint32_t _kernel_end; void kernelMain() { - initMemoryAllocation(0x100000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here + initMemoryAllocation(0x1000000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here initOSTasks(); drawLogo(); - printf("Switching to otherTask... \n"); + printf("giving up control...\n"); yields(); printf("Returned to mainTask!\n\n"); + printf("initializing interrupts\n"); + initInterrupts(); + yields(); + printf("trying interrupt\n"); + asm ("int $0x80"); + printf("the interrupt worked!\n"); yield(); } \ No newline at end of file diff --git a/src/kernel/lib/memory/alloc.c b/src/kernel/lib/memory/alloc.c deleted file mode 100644 index aedcbad..0000000 --- a/src/kernel/lib/memory/alloc.c +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include -#include - -MemoryBlock* firstBlock; - -void initMemoryAllocation(uint32_t kernelEnd) { - firstBlock = (MemoryBlock*) kernelEnd; - firstBlock->next = 0x00; - firstBlock->last = 0x00; - firstBlock->state = FREE; - firstBlock->size = -1; -} - -void* mallocTask(uint32_t size, Task* task) { - MemoryBlock* current = firstBlock; - while (! (current->next == 0x00 || current->state == FREE && current->size >= size)) { - current = current->next; - } - MemoryBlock* next; - if (current->next == 0x00) { - // this is currently the last block -> initialize the new last block - next = (MemoryBlock*) ((void*) (current + 1) + size); - next->last = current; - next->state = FREE; - next->next = 0x00; - next->size = -1; - } else { - // there is a next block - next = current->next; - } - if (current->size > size + sizeof(MemoryBlock) * 2 && current->next != 0x00) { - // segment the current block if it is big enough - current->next = (MemoryBlock*) (((void*) (current + 1)) + size); - current->next->size = current->size - sizeof(MemoryBlock) - size; - current->size = size; - current->next->state = FREE; - current->next->next = next; - next->last = current->next; - } else { - current->next = next; - if (current->next->next == 0x00) { - current->size = size; - } - } - current->state = IN_USE; - current->task = task; - return (void*) (current + 1); -} - -void* malloc(uint32_t size) { - return mallocTask(size, (Task*) getCurrentTask()); -} - -void mergeNextIfPossible(MemoryBlock* current) { - if (current->next != 0x00 && current->next->state == FREE) { - current->size = current->size + sizeof(MemoryBlock) + current->next->size; - current->next = current->next->next; - current->next->next->last = current; - } -} - -void free(void* location) { - MemoryBlock* current = ((MemoryBlock*) location) - 1; - current->state = FREE; - mergeNextIfPossible(current); - if (current->last != 0x00 && current->last->state == FREE) { - current = current->last; - } - mergeNextIfPossible(current); // call this function twice in case a used block between 2 free blocks is freed - mergeNextIfPossible(current); -} - -void printMemoryStack() { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); - current = current->next; - } - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); -} - -void freeTaskAllocations(Task* task) { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - if (current->task == task) { - free(current); - } - current = current->next; - } - if (current->task == task) { - free(current); - } -} \ No newline at end of file diff --git a/src/kernel/lib/ports.c b/src/kernel/lib/ports.c deleted file mode 100644 index 6cfbb2a..0000000 --- a/src/kernel/lib/ports.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include - -void outb(uint16_t port, uint8_t val) { - asm volatile("outb %0, %1" : : "a"(val), "Nd"(port) ); -} - -uint8_t inb(uint16_t port) { - uint8_t result; - __asm__("in %%dx, %%al" : "=a" (result) : "d" (port)); - return result; -} \ No newline at end of file diff --git a/src/kernel/lib/task/osTasks.c b/src/kernel/lib/task/osTasks.c deleted file mode 100644 index c3d6a43..0000000 --- a/src/kernel/lib/task/osTasks.c +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include -#include -#include - -Task mainTask; -Task printerTask; - -void printLoop() { - while (1) { - yield(); - Message* message = popMessage(&printerTask); - if (message == 0x00) { - continue; - } - putChars(message->data, message->size); - free(message->data); - free(message); - } -} - -void initOSTasks() { - setRunningTask(&mainTask); - createTask(&printerTask, (uint32_t) printLoop, 0x0, 0x0); - schedule(&printerTask); - // more tasks . . . - yields(); -} - -inline Task* getPrinterTask() { - return &printerTask; -} \ No newline at end of file diff --git a/src/kernel/lib/task/task.c b/src/kernel/lib/task/task.c deleted file mode 100644 index e4201c5..0000000 --- a/src/kernel/lib/task/task.c +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include -#include - -#define STACK_SIZE 0xF000 - -Task *currentTask; - -void createTask(Task *task, uint32_t mainFunction, uint32_t flags, uint32_t *pagedir) { - void* stack = mallocTask(STACK_SIZE, task); - task->registers.eax = 0; - task->registers.ebx = 0; - task->registers.ecx = 0; - task->registers.edx = 0; - task->registers.esi = 0; - task->registers.edi = 0; - task->registers.eflags = flags; - task->registers.eip = mainFunction; - task->registers.cr3 = (uint32_t) pagedir; - task->registers.esp = STACK_SIZE + (uint32_t) stack; - task->nextTask = 0; - task->stack = stack; -} - -void yield() { - Task* last = currentTask; - currentTask = currentTask->nextTask; - if (currentTask == 0x00) { - puts("No more tasks to run, halting . . .\n"); - while (1) { - asm("hlt"); - } - } - last->nextTask = 0x00; - switchTask(&(last->registers), &(currentTask->registers)); -} - -void schedule(Task* task) { - Task* test = currentTask; - while (test->nextTask != 0x0) { - test = test->nextTask; - if (test->nextTask == task) { - return; // don't schedule if the task is already in the queue - } - } - test->nextTask = task; -} - -void setRunningTask(Task* task) { - currentTask = task; -} - -void yields() { - schedule(currentTask); - yield(); -} - -void destroyCurrentTask() { - freeTaskAllocations(currentTask); - yield(); -} - -Task* getCurrentTask() { - return currentTask; -} - -void sendMessage(Task* task, Message* message) { - if (task->message == 0x00) { - task->message = message; - return; - } - Message* currentMessage = task->message; - while (currentMessage->next == 0x00) { - currentMessage = currentMessage->next; - } - currentMessage->next = message; -} - -Message* popMessage(Task* task) { - Message* currentMessage = task->message; - if (currentMessage != 0x00) { - task->message = currentMessage->next; - - } - return currentMessage; -} \ No newline at end of file diff --git a/src/kernel/lib/task/task.s b/src/kernel/lib/task/task.s deleted file mode 100644 index 88357cd..0000000 --- a/src/kernel/lib/task/task.s +++ /dev/null @@ -1,49 +0,0 @@ -.section .text -.global switchTask -switchTask: - pusha - pushf - mov %cr3, %eax #Push CR3 - push %eax - mov 44(%esp), %eax #The first argument, where to save - mov %ebx, 4(%eax) - mov %ecx, 8(%eax) - mov %edx, 12(%eax) - mov %esi, 16(%eax) - mov %edi, 20(%eax) - mov 36(%esp), %ebx #EAX - mov 40(%esp), %ecx #IP - mov 20(%esp), %edx #ESP - add $4, %edx #Remove the return value - mov 16(%esp), %esi #EBP - mov 4(%esp), %edi #EFLAGS - mov %ebx, (%eax) - mov %edx, 24(%eax) - mov %esi, 28(%eax) - mov %ecx, 32(%eax) - mov %edi, 36(%eax) - pop %ebx #CR3 - mov %ebx, 40(%eax) - push %ebx #Goodbye again - mov 48(%esp), %eax #Now it is the new object - mov 4(%eax), %ebx #EBX - mov 8(%eax), %ecx #ECX - mov 12(%eax), %edx #EDX - mov 16(%eax), %esi #ESI - mov 20(%eax), %edi #EDI - mov 28(%eax), %ebp #EBP - push %eax - mov 36(%eax), %eax #EFLAGS - push %eax - popf - pop %eax - mov 24(%eax), %esp #ESP - push %eax - mov 40(%eax), %eax #CR3 - mov %eax, %cr3 - pop %eax - push %eax - mov 32(%eax), %eax #EIP - xchg (%esp), %eax - mov (%eax), %eax #EAX - ret diff --git a/src/kernel/lib/textMode/cursor.c b/src/kernel/lib/textMode/cursor.c deleted file mode 100644 index e5cc8f9..0000000 --- a/src/kernel/lib/textMode/cursor.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include -#include - -void setCursorOffset(uint16_t offset) { - outb(0x3D4, 0x0F); - outb(0x3D5, (uint8_t) (offset & 0xFF)); - outb(0x3D4, 0x0E); - outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); -} - -void setCursorPosition(uint8_t x, uint8_t y) { - setCursorOffset(x + y * VIDEO_WIDTH); -} - -uint16_t getCursorOffset() { - uint16_t result = 0; - outb(0x3D4, 0x0F); - result |= inb(0x3D5); - outb(0x3D4, 0x0E); - result |= ((uint16_t)inb(0x3D5)) << 8; - return result; -} \ No newline at end of file diff --git a/src/kernel/lib/textMode/stdio.c b/src/kernel/lib/textMode/stdio.c deleted file mode 100644 index 5f1b3a0..0000000 --- a/src/kernel/lib/textMode/stdio.c +++ /dev/null @@ -1,200 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; -char format = 0x0F; - -void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { - *(framebuffer + position) = c; -} - -void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { - putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); -} - -void putCharAtOffset(char c, uint16_t offset) { - putCharWithFormatAtOffset(c | format << 8, offset); -} - -void putCharAt(char c, uint8_t x, uint8_t y) { - putCharAtOffset(c, (x + y * VIDEO_WIDTH)); -} - -uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { - return *(framebuffer + x + y * VIDEO_WIDTH); -} - -void putCharsAt(char* string, uint8_t x, uint8_t y) { - uint16_t position = 0; - char c = *string; - while (c != 0x00) { - putCharAt(c, x + position, y); - position++; - c = *(string + position); - } -} - -void shiftUp() { - for (int y = 1; y < VIDEO_HEIGHT; y++) { - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); - } - } - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); - } -} - -void newLine() { - uint16_t offset = getCursorOffset(); - uint8_t x = offset % VIDEO_WIDTH; - uint8_t y = offset / VIDEO_WIDTH; - x = 0; - y++; - if (y >= VIDEO_HEIGHT) { - shiftUp(); - y--; - } - setCursorPosition(x, y); -} - -void putChar(char c) { - if (c == '\n') { - newLine(); - return; - } - uint16_t offset = getCursorOffset(); - putCharAtOffset(c, offset); - setCursorOffset(offset + 1); -} - -void puts(char* string) { - while (*string != 0x00) { - putChar(*string); - string++; - } -} - -char HEX_PREFIX[] = "0x"; -char HEX_CHARS[] = "0123456789ABCDEF"; - -void putHex(char** write, uint32_t x) { - uint8_t alreadyWriting = 0; - for (uint8_t position = 3; position >= 0; position--) { - uint8_t byte = (x >> (position * 8)) & 0xFF; - if (byte != 0x00) { - alreadyWriting = 0x01; - } - if (alreadyWriting) { - **write = HEX_CHARS[byte % 256]; - *write++; - **write = HEX_CHARS[byte / 256]; - *write++; - } - } -} - -uint32_t getInsertLength(char insertType, uint32_t x) { - switch (insertType) - { - case 's': - return strlen((char*) x); - case 'x': - for (uint8_t position = 3; position >= 0; position--) { - uint8_t byte = (x >> (position * 8)) & 0xFF; - if (byte != 0x00) { - return 2*position; - } - } - return 0; - } - return 0; -} - -void handleInsert(char** write, char insertType, uint32_t x) { - if (insertType == 's') { - char* string = (char*) x; - uint32_t length = strlen(string); - for (uint32_t position = 0; position < length; position++) { - **write = string[position]; - *write++; - } - return; - } - if (insertType == 'x') { - putHex(write, x); - } -} - -void printf(const char* format, ...) { - uint32_t size = 0; - va_list valist; - va_start(valist, format); - for (int i = 0; format[i] != 0; i++) { - if (format[i] == '%') { - size += getInsertLength(format[++i], va_arg(valist, uint32_t)); - continue; - } - size++; - } - va_start(valist, format); - - char* data = malloc(size); - char* write = data; - for (int i = 0; format[i] != 0; i++) { - if (format[i] == '%') { - handleInsert(&write, format[++i], va_arg(valist, uint32_t)); - continue; - } - *write = format[i]; - write++; - } - va_end(valist); - - Message message = { - message.data = data, - message.size = size, - message.next = 0x00 - }; - sendMessage(getPrinterTask(), &message); - schedule(getPrinterTask()); - yields(); -} - -void clearScreen() { - setCursorOffset(0); - for (int y = 0; y < VIDEO_HEIGHT; y++) { - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharAt(' ', x, y); - } - } -} - -void setTextStyle(uint8_t style) { - format = style; -} - -void putChars(char* string, uint32_t length) { - for (uint32_t i = 0; i < length; i++) { - if (string[i] == '\n') { - newLine(); - continue; - } - putChar(string[i]); - } -} - -uint32_t strlen(char* string) { - uint32_t length = 0; - while (string[length] != 0) { - length++; - } - return length; -} \ No newline at end of file diff --git a/src/kernel/memory/alloc.c b/src/kernel/memory/alloc.c new file mode 100644 index 0000000..97d0a84 --- /dev/null +++ b/src/kernel/memory/alloc.c @@ -0,0 +1,94 @@ +#include +#include +#include <_stdio.h> + +MemoryBlock* firstBlock; + +void initMemoryAllocation(uint32_t kernelEnd) { + firstBlock = (MemoryBlock*) kernelEnd; + firstBlock->next = 0x00; + firstBlock->last = 0x00; + firstBlock->state = FREE; + firstBlock->size = -1; +} + +void* mallocTask(uint32_t size, Task* task) { + MemoryBlock* current = firstBlock; + while (! (current->next == 0x00 || current->state == FREE && current->size >= size)) { + current = current->next; + } + MemoryBlock* next; + if (current->next == 0x00) { + // this is currently the last block -> initialize the new last block + next = (MemoryBlock*) ((void*) (current + 1) + size); + next->last = current; + next->state = FREE; + next->next = 0x00; + next->size = -1; + } else { + // there is a next block + next = current->next; + } + if (current->size > size + sizeof(MemoryBlock) * 2 && current->next != 0x00) { + // segment the current block if it is big enough + current->next = (MemoryBlock*) (((void*) (current + 1)) + size); + current->next->size = current->size - sizeof(MemoryBlock) - size; + current->size = size; + current->next->state = FREE; + current->next->next = next; + next->last = current->next; + } else { + current->next = next; + if (current->next->next == 0x00) { + current->size = size; + } + } + current->state = IN_USE; + current->task = task; + return (void*) (current + 1); +} + +void* malloc(uint32_t size) { + return mallocTask(size, (Task*) getCurrentTask()); +} + +void mergeNextIfPossible(MemoryBlock* current) { + if (current->next != 0x00 && current->next->state == FREE) { + current->size = current->size + sizeof(MemoryBlock) + current->next->size; + current->next = current->next->next; + current->next->next->last = current; + } +} + +void free(void* location) { + MemoryBlock* current = ((MemoryBlock*) location) - 1; + current->state = FREE; + mergeNextIfPossible(current); + if (current->last != 0x00 && current->last->state == FREE) { + current = current->last; + } + mergeNextIfPossible(current); // call this function twice in case a used block between 2 free blocks is freed + mergeNextIfPossible(current); +} + +void printMemoryStack() { + MemoryBlock* current = firstBlock; + while (current->next != 0x00) { + printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); + current = current->next; + } + printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); +} + +void freeTaskAllocations(Task* task) { + MemoryBlock* current = firstBlock; + while (current->next != 0x00) { + if (current->task == task) { + free(current); + } + current = current->next; + } + if (current->task == task) { + free(current); + } +} \ No newline at end of file diff --git a/src/kernel/task/osTasks.c b/src/kernel/task/osTasks.c new file mode 100644 index 0000000..5d52a79 --- /dev/null +++ b/src/kernel/task/osTasks.c @@ -0,0 +1,35 @@ +#include +#include +#include <_stdio.h> +#include +#include + +Task mainTask; +Task printerTask; + +void printLoop() { + clearScreen(); + setTextStyle(0x0F); + while (1) { + Message* message = popMessage(&printerTask); + if (message == 0) { + yield(); + continue; + } + putChars(message->data, message->size); + free(message->data); + free(message); + } +} + +void initOSTasks() { + setRunningTask(&mainTask); + createTask(&printerTask, (uint32_t) printLoop, 0x0, 0x0); + schedule(&printerTask); + // more tasks . . . + yields(); +} + +inline Task* getPrinterTask() { + return &printerTask; +} \ No newline at end of file diff --git a/src/kernel/task/task.c b/src/kernel/task/task.c new file mode 100644 index 0000000..4b93d2d --- /dev/null +++ b/src/kernel/task/task.c @@ -0,0 +1,86 @@ +#include +#include +#include <_stdio.h> + +#define STACK_SIZE 0x1000 + +Task *currentTask; + +void createTask(Task *task, uint32_t mainFunction, uint32_t flags, uint32_t *pagedir) { + void* stack = mallocTask(STACK_SIZE, task); + task->registers.eax = 0; + task->registers.ebx = 0; + task->registers.ecx = 0; + task->registers.edx = 0; + task->registers.esi = 0; + task->registers.edi = 0; + task->registers.eflags = flags; + task->registers.eip = mainFunction; + task->registers.cr3 = (uint32_t) pagedir; + task->registers.esp = STACK_SIZE + (uint32_t) stack; + task->nextTask = 0; + task->stack = stack; +} + +void yield() { + Task* last = currentTask; + currentTask = last->nextTask; + if (currentTask == 0x00) { + puts("No more tasks to run, halting . . .\n"); + asm("hlt"); + } + last->nextTask = 0x00; + switchTask(&(last->registers), &(currentTask->registers)); +} + +void schedule(Task* task) { + Task* test = currentTask; + while (test->nextTask != 0x0) { + if (test->nextTask == task) { + return; // don't schedule if the task is already in the queue + } + test = test->nextTask; + } + if (test->nextTask == task) { + return; + } + test->nextTask = task; +} + +void setRunningTask(Task* task) { + currentTask = task; +} + +void yields() { + schedule(currentTask); + yield(); +} + +void destroyCurrentTask() { + freeTaskAllocations(currentTask); + yield(); +} + +Task* getCurrentTask() { + return currentTask; +} + +void sendMessage(Task* task, Message* message) { + Message* currentMessage = task->message; + if (currentMessage == 0) { + task->message = message; + return; + } + while (currentMessage->next != 0) { + currentMessage = currentMessage->next; + } + currentMessage->next = message; +} + +Message* popMessage(Task* task) { + Message* currentMessage = task->message; + if (currentMessage != 0) { + task->message = currentMessage->next; + } + return currentMessage; +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index dd72655..36c0cfc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { - "*.h": "c" + "*.h": "c", + "type_traits": "c" } } \ No newline at end of file diff --git a/src/headers/_stdio.h b/src/headers/_stdio.h new file mode 100644 index 0000000..b5d4f87 --- /dev/null +++ b/src/headers/_stdio.h @@ -0,0 +1,20 @@ +#ifndef STDIO_H +#define STDIO_H + +#include + +#define FRAMEBUFFER_LOCATION 0x000B8000 +#define VIDEO_WIDTH 80 +#define VIDEO_HEIGHT 25 + +extern void setTextStyle(uint8_t style); +extern void clearScreen(); +extern void printf(const char* format, ...); +extern void putCharAt(char c, uint8_t x, uint8_t y); +extern void putCharsAt(char* string, uint8_t x, uint8_t y); +extern void puts(char* string); +extern void putChars(char* string, uint32_t length); + +extern uint32_t strlen(char* string); + +#endif \ No newline at end of file diff --git a/src/headers/interrupts.h b/src/headers/interrupts.h new file mode 100644 index 0000000..3ca3d29 --- /dev/null +++ b/src/headers/interrupts.h @@ -0,0 +1,21 @@ +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + +#include + +typedef struct { + uint16_t isr_low; + uint16_t codeSegment; + uint8_t reserved; + uint8_t attributes; + uint16_t isr_high; +} __attribute__((packed)) IDTEntry; + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) IDTR; + +extern void initInterrupts(); + +#endif \ No newline at end of file diff --git a/src/headers/stdio.h b/src/headers/stdio.h deleted file mode 100644 index b5d4f87..0000000 --- a/src/headers/stdio.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef STDIO_H -#define STDIO_H - -#include - -#define FRAMEBUFFER_LOCATION 0x000B8000 -#define VIDEO_WIDTH 80 -#define VIDEO_HEIGHT 25 - -extern void setTextStyle(uint8_t style); -extern void clearScreen(); -extern void printf(const char* format, ...); -extern void putCharAt(char c, uint8_t x, uint8_t y); -extern void putCharsAt(char* string, uint8_t x, uint8_t y); -extern void puts(char* string); -extern void putChars(char* string, uint32_t length); - -extern uint32_t strlen(char* string); - -#endif \ No newline at end of file diff --git a/src/interrupts/interrupts.c b/src/interrupts/interrupts.c new file mode 100644 index 0000000..74d2931 --- /dev/null +++ b/src/interrupts/interrupts.c @@ -0,0 +1,33 @@ +#include +#include <_stdio.h> +#include + +IDTR idtr; +IDTEntry* entries; +void* buffer; + +void setInterrupt(uint8_t vector, void* callback, uint8_t flags) { + IDTEntry* descriptor = &entries[vector]; + + descriptor->isr_low = (uint32_t)callback & 0xFFFF; + descriptor->codeSegment = 0x08; + descriptor->attributes = flags; + descriptor->isr_high = (uint32_t)callback >> 16; + descriptor->reserved = 0; +} + +void testInterrupt() { + printf("interrupt!\n"); +} + +void initInterrupts() { + buffer = malloc(sizeof(IDTEntry) * 257); + entries = (IDTEntry*) (((int) buffer + sizeof(IDTEntry)) & -1 ^ 0x0F); + idtr.limit = sizeof(IDTEntry) * 256 - 1; + idtr.base = entries; + for (int i = 0; i < 256; i++) { + setInterrupt(i, testInterrupt, 0x8E); + } + __asm__ volatile ("lidt %0" : : "memory"(idtr)); + __asm__ volatile ("sti"); +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/_stdio.c b/src/kernel/drivers/textMode/_stdio.c new file mode 100644 index 0000000..34eea3f --- /dev/null +++ b/src/kernel/drivers/textMode/_stdio.c @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <_stdio.h> + +uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; +char format = 0x0F; + +void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { + *(framebuffer + position) = c; +} + +void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { + putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +void putCharAtOffset(char c, uint16_t offset) { + putCharWithFormatAtOffset(c | format << 8, offset); +} + +void putCharAt(char c, uint8_t x, uint8_t y) { + putCharAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { + return *(framebuffer + x + y * VIDEO_WIDTH); +} + +void putCharsAt(char* string, uint8_t x, uint8_t y) { + uint16_t position = 0; + char c = *string; + while (c != 0x00) { + putCharAt(c, x + position, y); + position++; + c = *(string + position); + } +} + +void shiftUp() { + for (int y = 1; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); + } + } + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); + } +} + +void newLine() { + uint16_t offset = getCursorOffset(); + uint8_t x = offset % VIDEO_WIDTH; + uint8_t y = offset / VIDEO_WIDTH; + x = 0; + y++; + if (y >= VIDEO_HEIGHT) { + shiftUp(); + y--; + } + setCursorPosition(x, y); +} + +void putChar(char c) { + if (c == '\n') { + newLine(); + return; + } + uint16_t offset = getCursorOffset(); + putCharAtOffset(c, offset); + setCursorOffset(offset + 1); +} + +void puts(char* string) { + while (*string != 0x00) { + putChar(*string); + string++; + } +} + +char HEX_PREFIX[] = "0x"; +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char** write, uint32_t x) { + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + **write = HEX_CHARS[byte >> 8]; + (*write)++; + } + } +} + +uint8_t hexLength(uint32_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return size; +} + +uint32_t getInsertLength(char insertType, uint32_t x) { + switch (insertType) { + case 's': + return strlen((char*) x); + case 'x': + return hexLength(x); + } + return 0; +} + +void stringInsert(char** write, uint32_t x) { + char* string = (char*) x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char** write, char insertType, uint32_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + } +} + +void printf(const char* format, ...) { + uint32_t size = 0; + va_list valist; + va_start(valist, format); + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + size += getInsertLength(format[++i], va_arg(valist, uint32_t)); + continue; + } + size++; + } + va_start(valist, format); + + char* data = malloc(size); + char* write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(valist, uint32_t)); + continue; + } + *write = format[i]; + write++; + } + va_end(valist); + + Message* message = malloc(sizeof(Message)); + + message->data = data; + message->size = size; + message->next = 0x00; + sendMessage(getPrinterTask(), message); + schedule(getPrinterTask()); +} + +void clearScreen() { + setCursorOffset(0); + for (int y = 0; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharAt(' ', x, y); + } + } +} + +void setTextStyle(uint8_t style) { + format = style; +} + +void putChars(char* string, uint32_t length) { + for (uint32_t i = 0; i < length; i++) { + if (string[i] == '\n') { + newLine(); + continue; + } + putChar(string[i]); + } +} + +uint32_t strlen(char* string) { + uint32_t length = 0; + while (string[length] != 0) { + length++; + } + return length; +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/cursor.c b/src/kernel/drivers/textMode/cursor.c new file mode 100644 index 0000000..8247c5e --- /dev/null +++ b/src/kernel/drivers/textMode/cursor.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include <_stdio.h> + +void setCursorOffset(uint16_t offset) { + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (offset & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); +} + +void setCursorPosition(uint8_t x, uint8_t y) { + setCursorOffset(x + y * VIDEO_WIDTH); +} + +uint16_t getCursorOffset() { + uint16_t result = 0; + outb(0x3D4, 0x0F); + result |= inb(0x3D5); + outb(0x3D4, 0x0E); + result |= ((uint16_t)inb(0x3D5)) << 8; + return result; +} \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index d8ff7b8..48ea59f 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,19 +1,26 @@ #include -#include +#include <_stdio.h> #include #include #include #include #include +#include extern uint32_t _kernel_end; void kernelMain() { - initMemoryAllocation(0x100000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here + initMemoryAllocation(0x1000000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here initOSTasks(); drawLogo(); - printf("Switching to otherTask... \n"); + printf("giving up control...\n"); yields(); printf("Returned to mainTask!\n\n"); + printf("initializing interrupts\n"); + initInterrupts(); + yields(); + printf("trying interrupt\n"); + asm ("int $0x80"); + printf("the interrupt worked!\n"); yield(); } \ No newline at end of file diff --git a/src/kernel/lib/memory/alloc.c b/src/kernel/lib/memory/alloc.c deleted file mode 100644 index aedcbad..0000000 --- a/src/kernel/lib/memory/alloc.c +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include -#include - -MemoryBlock* firstBlock; - -void initMemoryAllocation(uint32_t kernelEnd) { - firstBlock = (MemoryBlock*) kernelEnd; - firstBlock->next = 0x00; - firstBlock->last = 0x00; - firstBlock->state = FREE; - firstBlock->size = -1; -} - -void* mallocTask(uint32_t size, Task* task) { - MemoryBlock* current = firstBlock; - while (! (current->next == 0x00 || current->state == FREE && current->size >= size)) { - current = current->next; - } - MemoryBlock* next; - if (current->next == 0x00) { - // this is currently the last block -> initialize the new last block - next = (MemoryBlock*) ((void*) (current + 1) + size); - next->last = current; - next->state = FREE; - next->next = 0x00; - next->size = -1; - } else { - // there is a next block - next = current->next; - } - if (current->size > size + sizeof(MemoryBlock) * 2 && current->next != 0x00) { - // segment the current block if it is big enough - current->next = (MemoryBlock*) (((void*) (current + 1)) + size); - current->next->size = current->size - sizeof(MemoryBlock) - size; - current->size = size; - current->next->state = FREE; - current->next->next = next; - next->last = current->next; - } else { - current->next = next; - if (current->next->next == 0x00) { - current->size = size; - } - } - current->state = IN_USE; - current->task = task; - return (void*) (current + 1); -} - -void* malloc(uint32_t size) { - return mallocTask(size, (Task*) getCurrentTask()); -} - -void mergeNextIfPossible(MemoryBlock* current) { - if (current->next != 0x00 && current->next->state == FREE) { - current->size = current->size + sizeof(MemoryBlock) + current->next->size; - current->next = current->next->next; - current->next->next->last = current; - } -} - -void free(void* location) { - MemoryBlock* current = ((MemoryBlock*) location) - 1; - current->state = FREE; - mergeNextIfPossible(current); - if (current->last != 0x00 && current->last->state == FREE) { - current = current->last; - } - mergeNextIfPossible(current); // call this function twice in case a used block between 2 free blocks is freed - mergeNextIfPossible(current); -} - -void printMemoryStack() { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); - current = current->next; - } - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); -} - -void freeTaskAllocations(Task* task) { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - if (current->task == task) { - free(current); - } - current = current->next; - } - if (current->task == task) { - free(current); - } -} \ No newline at end of file diff --git a/src/kernel/lib/ports.c b/src/kernel/lib/ports.c deleted file mode 100644 index 6cfbb2a..0000000 --- a/src/kernel/lib/ports.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include - -void outb(uint16_t port, uint8_t val) { - asm volatile("outb %0, %1" : : "a"(val), "Nd"(port) ); -} - -uint8_t inb(uint16_t port) { - uint8_t result; - __asm__("in %%dx, %%al" : "=a" (result) : "d" (port)); - return result; -} \ No newline at end of file diff --git a/src/kernel/lib/task/osTasks.c b/src/kernel/lib/task/osTasks.c deleted file mode 100644 index c3d6a43..0000000 --- a/src/kernel/lib/task/osTasks.c +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include -#include -#include - -Task mainTask; -Task printerTask; - -void printLoop() { - while (1) { - yield(); - Message* message = popMessage(&printerTask); - if (message == 0x00) { - continue; - } - putChars(message->data, message->size); - free(message->data); - free(message); - } -} - -void initOSTasks() { - setRunningTask(&mainTask); - createTask(&printerTask, (uint32_t) printLoop, 0x0, 0x0); - schedule(&printerTask); - // more tasks . . . - yields(); -} - -inline Task* getPrinterTask() { - return &printerTask; -} \ No newline at end of file diff --git a/src/kernel/lib/task/task.c b/src/kernel/lib/task/task.c deleted file mode 100644 index e4201c5..0000000 --- a/src/kernel/lib/task/task.c +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include -#include - -#define STACK_SIZE 0xF000 - -Task *currentTask; - -void createTask(Task *task, uint32_t mainFunction, uint32_t flags, uint32_t *pagedir) { - void* stack = mallocTask(STACK_SIZE, task); - task->registers.eax = 0; - task->registers.ebx = 0; - task->registers.ecx = 0; - task->registers.edx = 0; - task->registers.esi = 0; - task->registers.edi = 0; - task->registers.eflags = flags; - task->registers.eip = mainFunction; - task->registers.cr3 = (uint32_t) pagedir; - task->registers.esp = STACK_SIZE + (uint32_t) stack; - task->nextTask = 0; - task->stack = stack; -} - -void yield() { - Task* last = currentTask; - currentTask = currentTask->nextTask; - if (currentTask == 0x00) { - puts("No more tasks to run, halting . . .\n"); - while (1) { - asm("hlt"); - } - } - last->nextTask = 0x00; - switchTask(&(last->registers), &(currentTask->registers)); -} - -void schedule(Task* task) { - Task* test = currentTask; - while (test->nextTask != 0x0) { - test = test->nextTask; - if (test->nextTask == task) { - return; // don't schedule if the task is already in the queue - } - } - test->nextTask = task; -} - -void setRunningTask(Task* task) { - currentTask = task; -} - -void yields() { - schedule(currentTask); - yield(); -} - -void destroyCurrentTask() { - freeTaskAllocations(currentTask); - yield(); -} - -Task* getCurrentTask() { - return currentTask; -} - -void sendMessage(Task* task, Message* message) { - if (task->message == 0x00) { - task->message = message; - return; - } - Message* currentMessage = task->message; - while (currentMessage->next == 0x00) { - currentMessage = currentMessage->next; - } - currentMessage->next = message; -} - -Message* popMessage(Task* task) { - Message* currentMessage = task->message; - if (currentMessage != 0x00) { - task->message = currentMessage->next; - - } - return currentMessage; -} \ No newline at end of file diff --git a/src/kernel/lib/task/task.s b/src/kernel/lib/task/task.s deleted file mode 100644 index 88357cd..0000000 --- a/src/kernel/lib/task/task.s +++ /dev/null @@ -1,49 +0,0 @@ -.section .text -.global switchTask -switchTask: - pusha - pushf - mov %cr3, %eax #Push CR3 - push %eax - mov 44(%esp), %eax #The first argument, where to save - mov %ebx, 4(%eax) - mov %ecx, 8(%eax) - mov %edx, 12(%eax) - mov %esi, 16(%eax) - mov %edi, 20(%eax) - mov 36(%esp), %ebx #EAX - mov 40(%esp), %ecx #IP - mov 20(%esp), %edx #ESP - add $4, %edx #Remove the return value - mov 16(%esp), %esi #EBP - mov 4(%esp), %edi #EFLAGS - mov %ebx, (%eax) - mov %edx, 24(%eax) - mov %esi, 28(%eax) - mov %ecx, 32(%eax) - mov %edi, 36(%eax) - pop %ebx #CR3 - mov %ebx, 40(%eax) - push %ebx #Goodbye again - mov 48(%esp), %eax #Now it is the new object - mov 4(%eax), %ebx #EBX - mov 8(%eax), %ecx #ECX - mov 12(%eax), %edx #EDX - mov 16(%eax), %esi #ESI - mov 20(%eax), %edi #EDI - mov 28(%eax), %ebp #EBP - push %eax - mov 36(%eax), %eax #EFLAGS - push %eax - popf - pop %eax - mov 24(%eax), %esp #ESP - push %eax - mov 40(%eax), %eax #CR3 - mov %eax, %cr3 - pop %eax - push %eax - mov 32(%eax), %eax #EIP - xchg (%esp), %eax - mov (%eax), %eax #EAX - ret diff --git a/src/kernel/lib/textMode/cursor.c b/src/kernel/lib/textMode/cursor.c deleted file mode 100644 index e5cc8f9..0000000 --- a/src/kernel/lib/textMode/cursor.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include -#include - -void setCursorOffset(uint16_t offset) { - outb(0x3D4, 0x0F); - outb(0x3D5, (uint8_t) (offset & 0xFF)); - outb(0x3D4, 0x0E); - outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); -} - -void setCursorPosition(uint8_t x, uint8_t y) { - setCursorOffset(x + y * VIDEO_WIDTH); -} - -uint16_t getCursorOffset() { - uint16_t result = 0; - outb(0x3D4, 0x0F); - result |= inb(0x3D5); - outb(0x3D4, 0x0E); - result |= ((uint16_t)inb(0x3D5)) << 8; - return result; -} \ No newline at end of file diff --git a/src/kernel/lib/textMode/stdio.c b/src/kernel/lib/textMode/stdio.c deleted file mode 100644 index 5f1b3a0..0000000 --- a/src/kernel/lib/textMode/stdio.c +++ /dev/null @@ -1,200 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; -char format = 0x0F; - -void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { - *(framebuffer + position) = c; -} - -void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { - putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); -} - -void putCharAtOffset(char c, uint16_t offset) { - putCharWithFormatAtOffset(c | format << 8, offset); -} - -void putCharAt(char c, uint8_t x, uint8_t y) { - putCharAtOffset(c, (x + y * VIDEO_WIDTH)); -} - -uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { - return *(framebuffer + x + y * VIDEO_WIDTH); -} - -void putCharsAt(char* string, uint8_t x, uint8_t y) { - uint16_t position = 0; - char c = *string; - while (c != 0x00) { - putCharAt(c, x + position, y); - position++; - c = *(string + position); - } -} - -void shiftUp() { - for (int y = 1; y < VIDEO_HEIGHT; y++) { - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); - } - } - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); - } -} - -void newLine() { - uint16_t offset = getCursorOffset(); - uint8_t x = offset % VIDEO_WIDTH; - uint8_t y = offset / VIDEO_WIDTH; - x = 0; - y++; - if (y >= VIDEO_HEIGHT) { - shiftUp(); - y--; - } - setCursorPosition(x, y); -} - -void putChar(char c) { - if (c == '\n') { - newLine(); - return; - } - uint16_t offset = getCursorOffset(); - putCharAtOffset(c, offset); - setCursorOffset(offset + 1); -} - -void puts(char* string) { - while (*string != 0x00) { - putChar(*string); - string++; - } -} - -char HEX_PREFIX[] = "0x"; -char HEX_CHARS[] = "0123456789ABCDEF"; - -void putHex(char** write, uint32_t x) { - uint8_t alreadyWriting = 0; - for (uint8_t position = 3; position >= 0; position--) { - uint8_t byte = (x >> (position * 8)) & 0xFF; - if (byte != 0x00) { - alreadyWriting = 0x01; - } - if (alreadyWriting) { - **write = HEX_CHARS[byte % 256]; - *write++; - **write = HEX_CHARS[byte / 256]; - *write++; - } - } -} - -uint32_t getInsertLength(char insertType, uint32_t x) { - switch (insertType) - { - case 's': - return strlen((char*) x); - case 'x': - for (uint8_t position = 3; position >= 0; position--) { - uint8_t byte = (x >> (position * 8)) & 0xFF; - if (byte != 0x00) { - return 2*position; - } - } - return 0; - } - return 0; -} - -void handleInsert(char** write, char insertType, uint32_t x) { - if (insertType == 's') { - char* string = (char*) x; - uint32_t length = strlen(string); - for (uint32_t position = 0; position < length; position++) { - **write = string[position]; - *write++; - } - return; - } - if (insertType == 'x') { - putHex(write, x); - } -} - -void printf(const char* format, ...) { - uint32_t size = 0; - va_list valist; - va_start(valist, format); - for (int i = 0; format[i] != 0; i++) { - if (format[i] == '%') { - size += getInsertLength(format[++i], va_arg(valist, uint32_t)); - continue; - } - size++; - } - va_start(valist, format); - - char* data = malloc(size); - char* write = data; - for (int i = 0; format[i] != 0; i++) { - if (format[i] == '%') { - handleInsert(&write, format[++i], va_arg(valist, uint32_t)); - continue; - } - *write = format[i]; - write++; - } - va_end(valist); - - Message message = { - message.data = data, - message.size = size, - message.next = 0x00 - }; - sendMessage(getPrinterTask(), &message); - schedule(getPrinterTask()); - yields(); -} - -void clearScreen() { - setCursorOffset(0); - for (int y = 0; y < VIDEO_HEIGHT; y++) { - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharAt(' ', x, y); - } - } -} - -void setTextStyle(uint8_t style) { - format = style; -} - -void putChars(char* string, uint32_t length) { - for (uint32_t i = 0; i < length; i++) { - if (string[i] == '\n') { - newLine(); - continue; - } - putChar(string[i]); - } -} - -uint32_t strlen(char* string) { - uint32_t length = 0; - while (string[length] != 0) { - length++; - } - return length; -} \ No newline at end of file diff --git a/src/kernel/memory/alloc.c b/src/kernel/memory/alloc.c new file mode 100644 index 0000000..97d0a84 --- /dev/null +++ b/src/kernel/memory/alloc.c @@ -0,0 +1,94 @@ +#include +#include +#include <_stdio.h> + +MemoryBlock* firstBlock; + +void initMemoryAllocation(uint32_t kernelEnd) { + firstBlock = (MemoryBlock*) kernelEnd; + firstBlock->next = 0x00; + firstBlock->last = 0x00; + firstBlock->state = FREE; + firstBlock->size = -1; +} + +void* mallocTask(uint32_t size, Task* task) { + MemoryBlock* current = firstBlock; + while (! (current->next == 0x00 || current->state == FREE && current->size >= size)) { + current = current->next; + } + MemoryBlock* next; + if (current->next == 0x00) { + // this is currently the last block -> initialize the new last block + next = (MemoryBlock*) ((void*) (current + 1) + size); + next->last = current; + next->state = FREE; + next->next = 0x00; + next->size = -1; + } else { + // there is a next block + next = current->next; + } + if (current->size > size + sizeof(MemoryBlock) * 2 && current->next != 0x00) { + // segment the current block if it is big enough + current->next = (MemoryBlock*) (((void*) (current + 1)) + size); + current->next->size = current->size - sizeof(MemoryBlock) - size; + current->size = size; + current->next->state = FREE; + current->next->next = next; + next->last = current->next; + } else { + current->next = next; + if (current->next->next == 0x00) { + current->size = size; + } + } + current->state = IN_USE; + current->task = task; + return (void*) (current + 1); +} + +void* malloc(uint32_t size) { + return mallocTask(size, (Task*) getCurrentTask()); +} + +void mergeNextIfPossible(MemoryBlock* current) { + if (current->next != 0x00 && current->next->state == FREE) { + current->size = current->size + sizeof(MemoryBlock) + current->next->size; + current->next = current->next->next; + current->next->next->last = current; + } +} + +void free(void* location) { + MemoryBlock* current = ((MemoryBlock*) location) - 1; + current->state = FREE; + mergeNextIfPossible(current); + if (current->last != 0x00 && current->last->state == FREE) { + current = current->last; + } + mergeNextIfPossible(current); // call this function twice in case a used block between 2 free blocks is freed + mergeNextIfPossible(current); +} + +void printMemoryStack() { + MemoryBlock* current = firstBlock; + while (current->next != 0x00) { + printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); + current = current->next; + } + printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); +} + +void freeTaskAllocations(Task* task) { + MemoryBlock* current = firstBlock; + while (current->next != 0x00) { + if (current->task == task) { + free(current); + } + current = current->next; + } + if (current->task == task) { + free(current); + } +} \ No newline at end of file diff --git a/src/kernel/task/osTasks.c b/src/kernel/task/osTasks.c new file mode 100644 index 0000000..5d52a79 --- /dev/null +++ b/src/kernel/task/osTasks.c @@ -0,0 +1,35 @@ +#include +#include +#include <_stdio.h> +#include +#include + +Task mainTask; +Task printerTask; + +void printLoop() { + clearScreen(); + setTextStyle(0x0F); + while (1) { + Message* message = popMessage(&printerTask); + if (message == 0) { + yield(); + continue; + } + putChars(message->data, message->size); + free(message->data); + free(message); + } +} + +void initOSTasks() { + setRunningTask(&mainTask); + createTask(&printerTask, (uint32_t) printLoop, 0x0, 0x0); + schedule(&printerTask); + // more tasks . . . + yields(); +} + +inline Task* getPrinterTask() { + return &printerTask; +} \ No newline at end of file diff --git a/src/kernel/task/task.c b/src/kernel/task/task.c new file mode 100644 index 0000000..4b93d2d --- /dev/null +++ b/src/kernel/task/task.c @@ -0,0 +1,86 @@ +#include +#include +#include <_stdio.h> + +#define STACK_SIZE 0x1000 + +Task *currentTask; + +void createTask(Task *task, uint32_t mainFunction, uint32_t flags, uint32_t *pagedir) { + void* stack = mallocTask(STACK_SIZE, task); + task->registers.eax = 0; + task->registers.ebx = 0; + task->registers.ecx = 0; + task->registers.edx = 0; + task->registers.esi = 0; + task->registers.edi = 0; + task->registers.eflags = flags; + task->registers.eip = mainFunction; + task->registers.cr3 = (uint32_t) pagedir; + task->registers.esp = STACK_SIZE + (uint32_t) stack; + task->nextTask = 0; + task->stack = stack; +} + +void yield() { + Task* last = currentTask; + currentTask = last->nextTask; + if (currentTask == 0x00) { + puts("No more tasks to run, halting . . .\n"); + asm("hlt"); + } + last->nextTask = 0x00; + switchTask(&(last->registers), &(currentTask->registers)); +} + +void schedule(Task* task) { + Task* test = currentTask; + while (test->nextTask != 0x0) { + if (test->nextTask == task) { + return; // don't schedule if the task is already in the queue + } + test = test->nextTask; + } + if (test->nextTask == task) { + return; + } + test->nextTask = task; +} + +void setRunningTask(Task* task) { + currentTask = task; +} + +void yields() { + schedule(currentTask); + yield(); +} + +void destroyCurrentTask() { + freeTaskAllocations(currentTask); + yield(); +} + +Task* getCurrentTask() { + return currentTask; +} + +void sendMessage(Task* task, Message* message) { + Message* currentMessage = task->message; + if (currentMessage == 0) { + task->message = message; + return; + } + while (currentMessage->next != 0) { + currentMessage = currentMessage->next; + } + currentMessage->next = message; +} + +Message* popMessage(Task* task) { + Message* currentMessage = task->message; + if (currentMessage != 0) { + task->message = currentMessage->next; + } + return currentMessage; +} \ No newline at end of file diff --git a/src/kernel/task/task.s b/src/kernel/task/task.s new file mode 100644 index 0000000..88357cd --- /dev/null +++ b/src/kernel/task/task.s @@ -0,0 +1,49 @@ +.section .text +.global switchTask +switchTask: + pusha + pushf + mov %cr3, %eax #Push CR3 + push %eax + mov 44(%esp), %eax #The first argument, where to save + mov %ebx, 4(%eax) + mov %ecx, 8(%eax) + mov %edx, 12(%eax) + mov %esi, 16(%eax) + mov %edi, 20(%eax) + mov 36(%esp), %ebx #EAX + mov 40(%esp), %ecx #IP + mov 20(%esp), %edx #ESP + add $4, %edx #Remove the return value + mov 16(%esp), %esi #EBP + mov 4(%esp), %edi #EFLAGS + mov %ebx, (%eax) + mov %edx, 24(%eax) + mov %esi, 28(%eax) + mov %ecx, 32(%eax) + mov %edi, 36(%eax) + pop %ebx #CR3 + mov %ebx, 40(%eax) + push %ebx #Goodbye again + mov 48(%esp), %eax #Now it is the new object + mov 4(%eax), %ebx #EBX + mov 8(%eax), %ecx #ECX + mov 12(%eax), %edx #EDX + mov 16(%eax), %esi #ESI + mov 20(%eax), %edi #EDI + mov 28(%eax), %ebp #EBP + push %eax + mov 36(%eax), %eax #EFLAGS + push %eax + popf + pop %eax + mov 24(%eax), %esp #ESP + push %eax + mov 40(%eax), %eax #CR3 + mov %eax, %cr3 + pop %eax + push %eax + mov 32(%eax), %eax #EIP + xchg (%esp), %eax + mov (%eax), %eax #EAX + ret diff --git a/.vscode/settings.json b/.vscode/settings.json index dd72655..36c0cfc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { - "*.h": "c" + "*.h": "c", + "type_traits": "c" } } \ No newline at end of file diff --git a/src/headers/_stdio.h b/src/headers/_stdio.h new file mode 100644 index 0000000..b5d4f87 --- /dev/null +++ b/src/headers/_stdio.h @@ -0,0 +1,20 @@ +#ifndef STDIO_H +#define STDIO_H + +#include + +#define FRAMEBUFFER_LOCATION 0x000B8000 +#define VIDEO_WIDTH 80 +#define VIDEO_HEIGHT 25 + +extern void setTextStyle(uint8_t style); +extern void clearScreen(); +extern void printf(const char* format, ...); +extern void putCharAt(char c, uint8_t x, uint8_t y); +extern void putCharsAt(char* string, uint8_t x, uint8_t y); +extern void puts(char* string); +extern void putChars(char* string, uint32_t length); + +extern uint32_t strlen(char* string); + +#endif \ No newline at end of file diff --git a/src/headers/interrupts.h b/src/headers/interrupts.h new file mode 100644 index 0000000..3ca3d29 --- /dev/null +++ b/src/headers/interrupts.h @@ -0,0 +1,21 @@ +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + +#include + +typedef struct { + uint16_t isr_low; + uint16_t codeSegment; + uint8_t reserved; + uint8_t attributes; + uint16_t isr_high; +} __attribute__((packed)) IDTEntry; + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) IDTR; + +extern void initInterrupts(); + +#endif \ No newline at end of file diff --git a/src/headers/stdio.h b/src/headers/stdio.h deleted file mode 100644 index b5d4f87..0000000 --- a/src/headers/stdio.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef STDIO_H -#define STDIO_H - -#include - -#define FRAMEBUFFER_LOCATION 0x000B8000 -#define VIDEO_WIDTH 80 -#define VIDEO_HEIGHT 25 - -extern void setTextStyle(uint8_t style); -extern void clearScreen(); -extern void printf(const char* format, ...); -extern void putCharAt(char c, uint8_t x, uint8_t y); -extern void putCharsAt(char* string, uint8_t x, uint8_t y); -extern void puts(char* string); -extern void putChars(char* string, uint32_t length); - -extern uint32_t strlen(char* string); - -#endif \ No newline at end of file diff --git a/src/interrupts/interrupts.c b/src/interrupts/interrupts.c new file mode 100644 index 0000000..74d2931 --- /dev/null +++ b/src/interrupts/interrupts.c @@ -0,0 +1,33 @@ +#include +#include <_stdio.h> +#include + +IDTR idtr; +IDTEntry* entries; +void* buffer; + +void setInterrupt(uint8_t vector, void* callback, uint8_t flags) { + IDTEntry* descriptor = &entries[vector]; + + descriptor->isr_low = (uint32_t)callback & 0xFFFF; + descriptor->codeSegment = 0x08; + descriptor->attributes = flags; + descriptor->isr_high = (uint32_t)callback >> 16; + descriptor->reserved = 0; +} + +void testInterrupt() { + printf("interrupt!\n"); +} + +void initInterrupts() { + buffer = malloc(sizeof(IDTEntry) * 257); + entries = (IDTEntry*) (((int) buffer + sizeof(IDTEntry)) & -1 ^ 0x0F); + idtr.limit = sizeof(IDTEntry) * 256 - 1; + idtr.base = entries; + for (int i = 0; i < 256; i++) { + setInterrupt(i, testInterrupt, 0x8E); + } + __asm__ volatile ("lidt %0" : : "memory"(idtr)); + __asm__ volatile ("sti"); +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/_stdio.c b/src/kernel/drivers/textMode/_stdio.c new file mode 100644 index 0000000..34eea3f --- /dev/null +++ b/src/kernel/drivers/textMode/_stdio.c @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <_stdio.h> + +uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; +char format = 0x0F; + +void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { + *(framebuffer + position) = c; +} + +void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { + putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +void putCharAtOffset(char c, uint16_t offset) { + putCharWithFormatAtOffset(c | format << 8, offset); +} + +void putCharAt(char c, uint8_t x, uint8_t y) { + putCharAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { + return *(framebuffer + x + y * VIDEO_WIDTH); +} + +void putCharsAt(char* string, uint8_t x, uint8_t y) { + uint16_t position = 0; + char c = *string; + while (c != 0x00) { + putCharAt(c, x + position, y); + position++; + c = *(string + position); + } +} + +void shiftUp() { + for (int y = 1; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); + } + } + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); + } +} + +void newLine() { + uint16_t offset = getCursorOffset(); + uint8_t x = offset % VIDEO_WIDTH; + uint8_t y = offset / VIDEO_WIDTH; + x = 0; + y++; + if (y >= VIDEO_HEIGHT) { + shiftUp(); + y--; + } + setCursorPosition(x, y); +} + +void putChar(char c) { + if (c == '\n') { + newLine(); + return; + } + uint16_t offset = getCursorOffset(); + putCharAtOffset(c, offset); + setCursorOffset(offset + 1); +} + +void puts(char* string) { + while (*string != 0x00) { + putChar(*string); + string++; + } +} + +char HEX_PREFIX[] = "0x"; +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char** write, uint32_t x) { + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + **write = HEX_CHARS[byte >> 8]; + (*write)++; + } + } +} + +uint8_t hexLength(uint32_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return size; +} + +uint32_t getInsertLength(char insertType, uint32_t x) { + switch (insertType) { + case 's': + return strlen((char*) x); + case 'x': + return hexLength(x); + } + return 0; +} + +void stringInsert(char** write, uint32_t x) { + char* string = (char*) x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char** write, char insertType, uint32_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + } +} + +void printf(const char* format, ...) { + uint32_t size = 0; + va_list valist; + va_start(valist, format); + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + size += getInsertLength(format[++i], va_arg(valist, uint32_t)); + continue; + } + size++; + } + va_start(valist, format); + + char* data = malloc(size); + char* write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(valist, uint32_t)); + continue; + } + *write = format[i]; + write++; + } + va_end(valist); + + Message* message = malloc(sizeof(Message)); + + message->data = data; + message->size = size; + message->next = 0x00; + sendMessage(getPrinterTask(), message); + schedule(getPrinterTask()); +} + +void clearScreen() { + setCursorOffset(0); + for (int y = 0; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharAt(' ', x, y); + } + } +} + +void setTextStyle(uint8_t style) { + format = style; +} + +void putChars(char* string, uint32_t length) { + for (uint32_t i = 0; i < length; i++) { + if (string[i] == '\n') { + newLine(); + continue; + } + putChar(string[i]); + } +} + +uint32_t strlen(char* string) { + uint32_t length = 0; + while (string[length] != 0) { + length++; + } + return length; +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/cursor.c b/src/kernel/drivers/textMode/cursor.c new file mode 100644 index 0000000..8247c5e --- /dev/null +++ b/src/kernel/drivers/textMode/cursor.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include <_stdio.h> + +void setCursorOffset(uint16_t offset) { + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (offset & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); +} + +void setCursorPosition(uint8_t x, uint8_t y) { + setCursorOffset(x + y * VIDEO_WIDTH); +} + +uint16_t getCursorOffset() { + uint16_t result = 0; + outb(0x3D4, 0x0F); + result |= inb(0x3D5); + outb(0x3D4, 0x0E); + result |= ((uint16_t)inb(0x3D5)) << 8; + return result; +} \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index d8ff7b8..48ea59f 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,19 +1,26 @@ #include -#include +#include <_stdio.h> #include #include #include #include #include +#include extern uint32_t _kernel_end; void kernelMain() { - initMemoryAllocation(0x100000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here + initMemoryAllocation(0x1000000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here initOSTasks(); drawLogo(); - printf("Switching to otherTask... \n"); + printf("giving up control...\n"); yields(); printf("Returned to mainTask!\n\n"); + printf("initializing interrupts\n"); + initInterrupts(); + yields(); + printf("trying interrupt\n"); + asm ("int $0x80"); + printf("the interrupt worked!\n"); yield(); } \ No newline at end of file diff --git a/src/kernel/lib/memory/alloc.c b/src/kernel/lib/memory/alloc.c deleted file mode 100644 index aedcbad..0000000 --- a/src/kernel/lib/memory/alloc.c +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include -#include - -MemoryBlock* firstBlock; - -void initMemoryAllocation(uint32_t kernelEnd) { - firstBlock = (MemoryBlock*) kernelEnd; - firstBlock->next = 0x00; - firstBlock->last = 0x00; - firstBlock->state = FREE; - firstBlock->size = -1; -} - -void* mallocTask(uint32_t size, Task* task) { - MemoryBlock* current = firstBlock; - while (! (current->next == 0x00 || current->state == FREE && current->size >= size)) { - current = current->next; - } - MemoryBlock* next; - if (current->next == 0x00) { - // this is currently the last block -> initialize the new last block - next = (MemoryBlock*) ((void*) (current + 1) + size); - next->last = current; - next->state = FREE; - next->next = 0x00; - next->size = -1; - } else { - // there is a next block - next = current->next; - } - if (current->size > size + sizeof(MemoryBlock) * 2 && current->next != 0x00) { - // segment the current block if it is big enough - current->next = (MemoryBlock*) (((void*) (current + 1)) + size); - current->next->size = current->size - sizeof(MemoryBlock) - size; - current->size = size; - current->next->state = FREE; - current->next->next = next; - next->last = current->next; - } else { - current->next = next; - if (current->next->next == 0x00) { - current->size = size; - } - } - current->state = IN_USE; - current->task = task; - return (void*) (current + 1); -} - -void* malloc(uint32_t size) { - return mallocTask(size, (Task*) getCurrentTask()); -} - -void mergeNextIfPossible(MemoryBlock* current) { - if (current->next != 0x00 && current->next->state == FREE) { - current->size = current->size + sizeof(MemoryBlock) + current->next->size; - current->next = current->next->next; - current->next->next->last = current; - } -} - -void free(void* location) { - MemoryBlock* current = ((MemoryBlock*) location) - 1; - current->state = FREE; - mergeNextIfPossible(current); - if (current->last != 0x00 && current->last->state == FREE) { - current = current->last; - } - mergeNextIfPossible(current); // call this function twice in case a used block between 2 free blocks is freed - mergeNextIfPossible(current); -} - -void printMemoryStack() { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); - current = current->next; - } - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); -} - -void freeTaskAllocations(Task* task) { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - if (current->task == task) { - free(current); - } - current = current->next; - } - if (current->task == task) { - free(current); - } -} \ No newline at end of file diff --git a/src/kernel/lib/ports.c b/src/kernel/lib/ports.c deleted file mode 100644 index 6cfbb2a..0000000 --- a/src/kernel/lib/ports.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include - -void outb(uint16_t port, uint8_t val) { - asm volatile("outb %0, %1" : : "a"(val), "Nd"(port) ); -} - -uint8_t inb(uint16_t port) { - uint8_t result; - __asm__("in %%dx, %%al" : "=a" (result) : "d" (port)); - return result; -} \ No newline at end of file diff --git a/src/kernel/lib/task/osTasks.c b/src/kernel/lib/task/osTasks.c deleted file mode 100644 index c3d6a43..0000000 --- a/src/kernel/lib/task/osTasks.c +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include -#include -#include - -Task mainTask; -Task printerTask; - -void printLoop() { - while (1) { - yield(); - Message* message = popMessage(&printerTask); - if (message == 0x00) { - continue; - } - putChars(message->data, message->size); - free(message->data); - free(message); - } -} - -void initOSTasks() { - setRunningTask(&mainTask); - createTask(&printerTask, (uint32_t) printLoop, 0x0, 0x0); - schedule(&printerTask); - // more tasks . . . - yields(); -} - -inline Task* getPrinterTask() { - return &printerTask; -} \ No newline at end of file diff --git a/src/kernel/lib/task/task.c b/src/kernel/lib/task/task.c deleted file mode 100644 index e4201c5..0000000 --- a/src/kernel/lib/task/task.c +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include -#include - -#define STACK_SIZE 0xF000 - -Task *currentTask; - -void createTask(Task *task, uint32_t mainFunction, uint32_t flags, uint32_t *pagedir) { - void* stack = mallocTask(STACK_SIZE, task); - task->registers.eax = 0; - task->registers.ebx = 0; - task->registers.ecx = 0; - task->registers.edx = 0; - task->registers.esi = 0; - task->registers.edi = 0; - task->registers.eflags = flags; - task->registers.eip = mainFunction; - task->registers.cr3 = (uint32_t) pagedir; - task->registers.esp = STACK_SIZE + (uint32_t) stack; - task->nextTask = 0; - task->stack = stack; -} - -void yield() { - Task* last = currentTask; - currentTask = currentTask->nextTask; - if (currentTask == 0x00) { - puts("No more tasks to run, halting . . .\n"); - while (1) { - asm("hlt"); - } - } - last->nextTask = 0x00; - switchTask(&(last->registers), &(currentTask->registers)); -} - -void schedule(Task* task) { - Task* test = currentTask; - while (test->nextTask != 0x0) { - test = test->nextTask; - if (test->nextTask == task) { - return; // don't schedule if the task is already in the queue - } - } - test->nextTask = task; -} - -void setRunningTask(Task* task) { - currentTask = task; -} - -void yields() { - schedule(currentTask); - yield(); -} - -void destroyCurrentTask() { - freeTaskAllocations(currentTask); - yield(); -} - -Task* getCurrentTask() { - return currentTask; -} - -void sendMessage(Task* task, Message* message) { - if (task->message == 0x00) { - task->message = message; - return; - } - Message* currentMessage = task->message; - while (currentMessage->next == 0x00) { - currentMessage = currentMessage->next; - } - currentMessage->next = message; -} - -Message* popMessage(Task* task) { - Message* currentMessage = task->message; - if (currentMessage != 0x00) { - task->message = currentMessage->next; - - } - return currentMessage; -} \ No newline at end of file diff --git a/src/kernel/lib/task/task.s b/src/kernel/lib/task/task.s deleted file mode 100644 index 88357cd..0000000 --- a/src/kernel/lib/task/task.s +++ /dev/null @@ -1,49 +0,0 @@ -.section .text -.global switchTask -switchTask: - pusha - pushf - mov %cr3, %eax #Push CR3 - push %eax - mov 44(%esp), %eax #The first argument, where to save - mov %ebx, 4(%eax) - mov %ecx, 8(%eax) - mov %edx, 12(%eax) - mov %esi, 16(%eax) - mov %edi, 20(%eax) - mov 36(%esp), %ebx #EAX - mov 40(%esp), %ecx #IP - mov 20(%esp), %edx #ESP - add $4, %edx #Remove the return value - mov 16(%esp), %esi #EBP - mov 4(%esp), %edi #EFLAGS - mov %ebx, (%eax) - mov %edx, 24(%eax) - mov %esi, 28(%eax) - mov %ecx, 32(%eax) - mov %edi, 36(%eax) - pop %ebx #CR3 - mov %ebx, 40(%eax) - push %ebx #Goodbye again - mov 48(%esp), %eax #Now it is the new object - mov 4(%eax), %ebx #EBX - mov 8(%eax), %ecx #ECX - mov 12(%eax), %edx #EDX - mov 16(%eax), %esi #ESI - mov 20(%eax), %edi #EDI - mov 28(%eax), %ebp #EBP - push %eax - mov 36(%eax), %eax #EFLAGS - push %eax - popf - pop %eax - mov 24(%eax), %esp #ESP - push %eax - mov 40(%eax), %eax #CR3 - mov %eax, %cr3 - pop %eax - push %eax - mov 32(%eax), %eax #EIP - xchg (%esp), %eax - mov (%eax), %eax #EAX - ret diff --git a/src/kernel/lib/textMode/cursor.c b/src/kernel/lib/textMode/cursor.c deleted file mode 100644 index e5cc8f9..0000000 --- a/src/kernel/lib/textMode/cursor.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include -#include - -void setCursorOffset(uint16_t offset) { - outb(0x3D4, 0x0F); - outb(0x3D5, (uint8_t) (offset & 0xFF)); - outb(0x3D4, 0x0E); - outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); -} - -void setCursorPosition(uint8_t x, uint8_t y) { - setCursorOffset(x + y * VIDEO_WIDTH); -} - -uint16_t getCursorOffset() { - uint16_t result = 0; - outb(0x3D4, 0x0F); - result |= inb(0x3D5); - outb(0x3D4, 0x0E); - result |= ((uint16_t)inb(0x3D5)) << 8; - return result; -} \ No newline at end of file diff --git a/src/kernel/lib/textMode/stdio.c b/src/kernel/lib/textMode/stdio.c deleted file mode 100644 index 5f1b3a0..0000000 --- a/src/kernel/lib/textMode/stdio.c +++ /dev/null @@ -1,200 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; -char format = 0x0F; - -void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { - *(framebuffer + position) = c; -} - -void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { - putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); -} - -void putCharAtOffset(char c, uint16_t offset) { - putCharWithFormatAtOffset(c | format << 8, offset); -} - -void putCharAt(char c, uint8_t x, uint8_t y) { - putCharAtOffset(c, (x + y * VIDEO_WIDTH)); -} - -uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { - return *(framebuffer + x + y * VIDEO_WIDTH); -} - -void putCharsAt(char* string, uint8_t x, uint8_t y) { - uint16_t position = 0; - char c = *string; - while (c != 0x00) { - putCharAt(c, x + position, y); - position++; - c = *(string + position); - } -} - -void shiftUp() { - for (int y = 1; y < VIDEO_HEIGHT; y++) { - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); - } - } - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); - } -} - -void newLine() { - uint16_t offset = getCursorOffset(); - uint8_t x = offset % VIDEO_WIDTH; - uint8_t y = offset / VIDEO_WIDTH; - x = 0; - y++; - if (y >= VIDEO_HEIGHT) { - shiftUp(); - y--; - } - setCursorPosition(x, y); -} - -void putChar(char c) { - if (c == '\n') { - newLine(); - return; - } - uint16_t offset = getCursorOffset(); - putCharAtOffset(c, offset); - setCursorOffset(offset + 1); -} - -void puts(char* string) { - while (*string != 0x00) { - putChar(*string); - string++; - } -} - -char HEX_PREFIX[] = "0x"; -char HEX_CHARS[] = "0123456789ABCDEF"; - -void putHex(char** write, uint32_t x) { - uint8_t alreadyWriting = 0; - for (uint8_t position = 3; position >= 0; position--) { - uint8_t byte = (x >> (position * 8)) & 0xFF; - if (byte != 0x00) { - alreadyWriting = 0x01; - } - if (alreadyWriting) { - **write = HEX_CHARS[byte % 256]; - *write++; - **write = HEX_CHARS[byte / 256]; - *write++; - } - } -} - -uint32_t getInsertLength(char insertType, uint32_t x) { - switch (insertType) - { - case 's': - return strlen((char*) x); - case 'x': - for (uint8_t position = 3; position >= 0; position--) { - uint8_t byte = (x >> (position * 8)) & 0xFF; - if (byte != 0x00) { - return 2*position; - } - } - return 0; - } - return 0; -} - -void handleInsert(char** write, char insertType, uint32_t x) { - if (insertType == 's') { - char* string = (char*) x; - uint32_t length = strlen(string); - for (uint32_t position = 0; position < length; position++) { - **write = string[position]; - *write++; - } - return; - } - if (insertType == 'x') { - putHex(write, x); - } -} - -void printf(const char* format, ...) { - uint32_t size = 0; - va_list valist; - va_start(valist, format); - for (int i = 0; format[i] != 0; i++) { - if (format[i] == '%') { - size += getInsertLength(format[++i], va_arg(valist, uint32_t)); - continue; - } - size++; - } - va_start(valist, format); - - char* data = malloc(size); - char* write = data; - for (int i = 0; format[i] != 0; i++) { - if (format[i] == '%') { - handleInsert(&write, format[++i], va_arg(valist, uint32_t)); - continue; - } - *write = format[i]; - write++; - } - va_end(valist); - - Message message = { - message.data = data, - message.size = size, - message.next = 0x00 - }; - sendMessage(getPrinterTask(), &message); - schedule(getPrinterTask()); - yields(); -} - -void clearScreen() { - setCursorOffset(0); - for (int y = 0; y < VIDEO_HEIGHT; y++) { - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharAt(' ', x, y); - } - } -} - -void setTextStyle(uint8_t style) { - format = style; -} - -void putChars(char* string, uint32_t length) { - for (uint32_t i = 0; i < length; i++) { - if (string[i] == '\n') { - newLine(); - continue; - } - putChar(string[i]); - } -} - -uint32_t strlen(char* string) { - uint32_t length = 0; - while (string[length] != 0) { - length++; - } - return length; -} \ No newline at end of file diff --git a/src/kernel/memory/alloc.c b/src/kernel/memory/alloc.c new file mode 100644 index 0000000..97d0a84 --- /dev/null +++ b/src/kernel/memory/alloc.c @@ -0,0 +1,94 @@ +#include +#include +#include <_stdio.h> + +MemoryBlock* firstBlock; + +void initMemoryAllocation(uint32_t kernelEnd) { + firstBlock = (MemoryBlock*) kernelEnd; + firstBlock->next = 0x00; + firstBlock->last = 0x00; + firstBlock->state = FREE; + firstBlock->size = -1; +} + +void* mallocTask(uint32_t size, Task* task) { + MemoryBlock* current = firstBlock; + while (! (current->next == 0x00 || current->state == FREE && current->size >= size)) { + current = current->next; + } + MemoryBlock* next; + if (current->next == 0x00) { + // this is currently the last block -> initialize the new last block + next = (MemoryBlock*) ((void*) (current + 1) + size); + next->last = current; + next->state = FREE; + next->next = 0x00; + next->size = -1; + } else { + // there is a next block + next = current->next; + } + if (current->size > size + sizeof(MemoryBlock) * 2 && current->next != 0x00) { + // segment the current block if it is big enough + current->next = (MemoryBlock*) (((void*) (current + 1)) + size); + current->next->size = current->size - sizeof(MemoryBlock) - size; + current->size = size; + current->next->state = FREE; + current->next->next = next; + next->last = current->next; + } else { + current->next = next; + if (current->next->next == 0x00) { + current->size = size; + } + } + current->state = IN_USE; + current->task = task; + return (void*) (current + 1); +} + +void* malloc(uint32_t size) { + return mallocTask(size, (Task*) getCurrentTask()); +} + +void mergeNextIfPossible(MemoryBlock* current) { + if (current->next != 0x00 && current->next->state == FREE) { + current->size = current->size + sizeof(MemoryBlock) + current->next->size; + current->next = current->next->next; + current->next->next->last = current; + } +} + +void free(void* location) { + MemoryBlock* current = ((MemoryBlock*) location) - 1; + current->state = FREE; + mergeNextIfPossible(current); + if (current->last != 0x00 && current->last->state == FREE) { + current = current->last; + } + mergeNextIfPossible(current); // call this function twice in case a used block between 2 free blocks is freed + mergeNextIfPossible(current); +} + +void printMemoryStack() { + MemoryBlock* current = firstBlock; + while (current->next != 0x00) { + printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); + current = current->next; + } + printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); +} + +void freeTaskAllocations(Task* task) { + MemoryBlock* current = firstBlock; + while (current->next != 0x00) { + if (current->task == task) { + free(current); + } + current = current->next; + } + if (current->task == task) { + free(current); + } +} \ No newline at end of file diff --git a/src/kernel/task/osTasks.c b/src/kernel/task/osTasks.c new file mode 100644 index 0000000..5d52a79 --- /dev/null +++ b/src/kernel/task/osTasks.c @@ -0,0 +1,35 @@ +#include +#include +#include <_stdio.h> +#include +#include + +Task mainTask; +Task printerTask; + +void printLoop() { + clearScreen(); + setTextStyle(0x0F); + while (1) { + Message* message = popMessage(&printerTask); + if (message == 0) { + yield(); + continue; + } + putChars(message->data, message->size); + free(message->data); + free(message); + } +} + +void initOSTasks() { + setRunningTask(&mainTask); + createTask(&printerTask, (uint32_t) printLoop, 0x0, 0x0); + schedule(&printerTask); + // more tasks . . . + yields(); +} + +inline Task* getPrinterTask() { + return &printerTask; +} \ No newline at end of file diff --git a/src/kernel/task/task.c b/src/kernel/task/task.c new file mode 100644 index 0000000..4b93d2d --- /dev/null +++ b/src/kernel/task/task.c @@ -0,0 +1,86 @@ +#include +#include +#include <_stdio.h> + +#define STACK_SIZE 0x1000 + +Task *currentTask; + +void createTask(Task *task, uint32_t mainFunction, uint32_t flags, uint32_t *pagedir) { + void* stack = mallocTask(STACK_SIZE, task); + task->registers.eax = 0; + task->registers.ebx = 0; + task->registers.ecx = 0; + task->registers.edx = 0; + task->registers.esi = 0; + task->registers.edi = 0; + task->registers.eflags = flags; + task->registers.eip = mainFunction; + task->registers.cr3 = (uint32_t) pagedir; + task->registers.esp = STACK_SIZE + (uint32_t) stack; + task->nextTask = 0; + task->stack = stack; +} + +void yield() { + Task* last = currentTask; + currentTask = last->nextTask; + if (currentTask == 0x00) { + puts("No more tasks to run, halting . . .\n"); + asm("hlt"); + } + last->nextTask = 0x00; + switchTask(&(last->registers), &(currentTask->registers)); +} + +void schedule(Task* task) { + Task* test = currentTask; + while (test->nextTask != 0x0) { + if (test->nextTask == task) { + return; // don't schedule if the task is already in the queue + } + test = test->nextTask; + } + if (test->nextTask == task) { + return; + } + test->nextTask = task; +} + +void setRunningTask(Task* task) { + currentTask = task; +} + +void yields() { + schedule(currentTask); + yield(); +} + +void destroyCurrentTask() { + freeTaskAllocations(currentTask); + yield(); +} + +Task* getCurrentTask() { + return currentTask; +} + +void sendMessage(Task* task, Message* message) { + Message* currentMessage = task->message; + if (currentMessage == 0) { + task->message = message; + return; + } + while (currentMessage->next != 0) { + currentMessage = currentMessage->next; + } + currentMessage->next = message; +} + +Message* popMessage(Task* task) { + Message* currentMessage = task->message; + if (currentMessage != 0) { + task->message = currentMessage->next; + } + return currentMessage; +} \ No newline at end of file diff --git a/src/kernel/task/task.s b/src/kernel/task/task.s new file mode 100644 index 0000000..88357cd --- /dev/null +++ b/src/kernel/task/task.s @@ -0,0 +1,49 @@ +.section .text +.global switchTask +switchTask: + pusha + pushf + mov %cr3, %eax #Push CR3 + push %eax + mov 44(%esp), %eax #The first argument, where to save + mov %ebx, 4(%eax) + mov %ecx, 8(%eax) + mov %edx, 12(%eax) + mov %esi, 16(%eax) + mov %edi, 20(%eax) + mov 36(%esp), %ebx #EAX + mov 40(%esp), %ecx #IP + mov 20(%esp), %edx #ESP + add $4, %edx #Remove the return value + mov 16(%esp), %esi #EBP + mov 4(%esp), %edi #EFLAGS + mov %ebx, (%eax) + mov %edx, 24(%eax) + mov %esi, 28(%eax) + mov %ecx, 32(%eax) + mov %edi, 36(%eax) + pop %ebx #CR3 + mov %ebx, 40(%eax) + push %ebx #Goodbye again + mov 48(%esp), %eax #Now it is the new object + mov 4(%eax), %ebx #EBX + mov 8(%eax), %ecx #ECX + mov 12(%eax), %edx #EDX + mov 16(%eax), %esi #ESI + mov 20(%eax), %edi #EDI + mov 28(%eax), %ebp #EBP + push %eax + mov 36(%eax), %eax #EFLAGS + push %eax + popf + pop %eax + mov 24(%eax), %esp #ESP + push %eax + mov 40(%eax), %eax #CR3 + mov %eax, %cr3 + pop %eax + push %eax + mov 32(%eax), %eax #EIP + xchg (%esp), %eax + mov (%eax), %eax #EAX + ret diff --git a/src/kernel/textMode/_stdio.c b/src/kernel/textMode/_stdio.c new file mode 100644 index 0000000..fcecf6f --- /dev/null +++ b/src/kernel/textMode/_stdio.c @@ -0,0 +1,199 @@ +#include +#include +#include <_stdio.h> +#include +#include +#include +#include +#include +#include + +uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; +char format = 0x0F; + +void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { + *(framebuffer + position) = c; +} + +void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { + putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +void putCharAtOffset(char c, uint16_t offset) { + putCharWithFormatAtOffset(c | format << 8, offset); +} + +void putCharAt(char c, uint8_t x, uint8_t y) { + putCharAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { + return *(framebuffer + x + y * VIDEO_WIDTH); +} + +void putCharsAt(char* string, uint8_t x, uint8_t y) { + uint16_t position = 0; + char c = *string; + while (c != 0x00) { + putCharAt(c, x + position, y); + position++; + c = *(string + position); + } +} + +void shiftUp() { + for (int y = 1; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); + } + } + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); + } +} + +void newLine() { + uint16_t offset = getCursorOffset(); + uint8_t x = offset % VIDEO_WIDTH; + uint8_t y = offset / VIDEO_WIDTH; + x = 0; + y++; + if (y >= VIDEO_HEIGHT) { + shiftUp(); + y--; + } + setCursorPosition(x, y); +} + +void putChar(char c) { + if (c == '\n') { + newLine(); + return; + } + uint16_t offset = getCursorOffset(); + putCharAtOffset(c, offset); + setCursorOffset(offset + 1); +} + +void puts(char* string) { + while (*string != 0x00) { + putChar(*string); + string++; + } +} + +char HEX_PREFIX[] = "0x"; +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char** write, uint32_t x) { + uint8_t alreadyWriting = 0; + for (uint8_t position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = 0x01; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte % 256]; + *write++; + **write = HEX_CHARS[byte / 256]; + *write++; + } + } +} + +uint32_t getInsertLength(char insertType, uint32_t x) { + switch (insertType) + { + case 's': + return strlen((char*) x); + case 'x': + for (uint8_t position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + return 2*position; + } + } + return 0; + } + return 0; +} + +void handleInsert(char** write, char insertType, uint32_t x) { + if (insertType == 's') { + char* string = (char*) x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + *write++; + } + return; + } + if (insertType == 'x') { + putHex(write, x); + } +} + +void printf(const char* format, ...) { + uint32_t size = 0; + va_list valist; + va_start(valist, format); + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + size += getInsertLength(format[++i], va_arg(valist, uint32_t)); + continue; + } + size++; + } + va_start(valist, format); + + char* data = malloc(size); + char* write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(valist, uint32_t)); + continue; + } + *write = format[i]; + write++; + } + va_end(valist); + + Message* message = malloc(sizeof(Message)); + + message->data = data; + message->size = size; + message->next = 0x00; + sendMessage(getPrinterTask(), message); + schedule(getPrinterTask()); +} + +void clearScreen() { + setCursorOffset(0); + for (int y = 0; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharAt(' ', x, y); + } + } +} + +void setTextStyle(uint8_t style) { + format = style; +} + +void putChars(char* string, uint32_t length) { + for (uint32_t i = 0; i < length; i++) { + if (string[i] == '\n') { + newLine(); + continue; + } + putChar(string[i]); + } +} + +uint32_t strlen(char* string) { + uint32_t length = 0; + while (string[length] != 0) { + length++; + } + return length; +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index dd72655..36c0cfc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { - "*.h": "c" + "*.h": "c", + "type_traits": "c" } } \ No newline at end of file diff --git a/src/headers/_stdio.h b/src/headers/_stdio.h new file mode 100644 index 0000000..b5d4f87 --- /dev/null +++ b/src/headers/_stdio.h @@ -0,0 +1,20 @@ +#ifndef STDIO_H +#define STDIO_H + +#include + +#define FRAMEBUFFER_LOCATION 0x000B8000 +#define VIDEO_WIDTH 80 +#define VIDEO_HEIGHT 25 + +extern void setTextStyle(uint8_t style); +extern void clearScreen(); +extern void printf(const char* format, ...); +extern void putCharAt(char c, uint8_t x, uint8_t y); +extern void putCharsAt(char* string, uint8_t x, uint8_t y); +extern void puts(char* string); +extern void putChars(char* string, uint32_t length); + +extern uint32_t strlen(char* string); + +#endif \ No newline at end of file diff --git a/src/headers/interrupts.h b/src/headers/interrupts.h new file mode 100644 index 0000000..3ca3d29 --- /dev/null +++ b/src/headers/interrupts.h @@ -0,0 +1,21 @@ +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + +#include + +typedef struct { + uint16_t isr_low; + uint16_t codeSegment; + uint8_t reserved; + uint8_t attributes; + uint16_t isr_high; +} __attribute__((packed)) IDTEntry; + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) IDTR; + +extern void initInterrupts(); + +#endif \ No newline at end of file diff --git a/src/headers/stdio.h b/src/headers/stdio.h deleted file mode 100644 index b5d4f87..0000000 --- a/src/headers/stdio.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef STDIO_H -#define STDIO_H - -#include - -#define FRAMEBUFFER_LOCATION 0x000B8000 -#define VIDEO_WIDTH 80 -#define VIDEO_HEIGHT 25 - -extern void setTextStyle(uint8_t style); -extern void clearScreen(); -extern void printf(const char* format, ...); -extern void putCharAt(char c, uint8_t x, uint8_t y); -extern void putCharsAt(char* string, uint8_t x, uint8_t y); -extern void puts(char* string); -extern void putChars(char* string, uint32_t length); - -extern uint32_t strlen(char* string); - -#endif \ No newline at end of file diff --git a/src/interrupts/interrupts.c b/src/interrupts/interrupts.c new file mode 100644 index 0000000..74d2931 --- /dev/null +++ b/src/interrupts/interrupts.c @@ -0,0 +1,33 @@ +#include +#include <_stdio.h> +#include + +IDTR idtr; +IDTEntry* entries; +void* buffer; + +void setInterrupt(uint8_t vector, void* callback, uint8_t flags) { + IDTEntry* descriptor = &entries[vector]; + + descriptor->isr_low = (uint32_t)callback & 0xFFFF; + descriptor->codeSegment = 0x08; + descriptor->attributes = flags; + descriptor->isr_high = (uint32_t)callback >> 16; + descriptor->reserved = 0; +} + +void testInterrupt() { + printf("interrupt!\n"); +} + +void initInterrupts() { + buffer = malloc(sizeof(IDTEntry) * 257); + entries = (IDTEntry*) (((int) buffer + sizeof(IDTEntry)) & -1 ^ 0x0F); + idtr.limit = sizeof(IDTEntry) * 256 - 1; + idtr.base = entries; + for (int i = 0; i < 256; i++) { + setInterrupt(i, testInterrupt, 0x8E); + } + __asm__ volatile ("lidt %0" : : "memory"(idtr)); + __asm__ volatile ("sti"); +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/_stdio.c b/src/kernel/drivers/textMode/_stdio.c new file mode 100644 index 0000000..34eea3f --- /dev/null +++ b/src/kernel/drivers/textMode/_stdio.c @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <_stdio.h> + +uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; +char format = 0x0F; + +void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { + *(framebuffer + position) = c; +} + +void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { + putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +void putCharAtOffset(char c, uint16_t offset) { + putCharWithFormatAtOffset(c | format << 8, offset); +} + +void putCharAt(char c, uint8_t x, uint8_t y) { + putCharAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { + return *(framebuffer + x + y * VIDEO_WIDTH); +} + +void putCharsAt(char* string, uint8_t x, uint8_t y) { + uint16_t position = 0; + char c = *string; + while (c != 0x00) { + putCharAt(c, x + position, y); + position++; + c = *(string + position); + } +} + +void shiftUp() { + for (int y = 1; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); + } + } + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); + } +} + +void newLine() { + uint16_t offset = getCursorOffset(); + uint8_t x = offset % VIDEO_WIDTH; + uint8_t y = offset / VIDEO_WIDTH; + x = 0; + y++; + if (y >= VIDEO_HEIGHT) { + shiftUp(); + y--; + } + setCursorPosition(x, y); +} + +void putChar(char c) { + if (c == '\n') { + newLine(); + return; + } + uint16_t offset = getCursorOffset(); + putCharAtOffset(c, offset); + setCursorOffset(offset + 1); +} + +void puts(char* string) { + while (*string != 0x00) { + putChar(*string); + string++; + } +} + +char HEX_PREFIX[] = "0x"; +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char** write, uint32_t x) { + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + **write = HEX_CHARS[byte >> 8]; + (*write)++; + } + } +} + +uint8_t hexLength(uint32_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return size; +} + +uint32_t getInsertLength(char insertType, uint32_t x) { + switch (insertType) { + case 's': + return strlen((char*) x); + case 'x': + return hexLength(x); + } + return 0; +} + +void stringInsert(char** write, uint32_t x) { + char* string = (char*) x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char** write, char insertType, uint32_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + } +} + +void printf(const char* format, ...) { + uint32_t size = 0; + va_list valist; + va_start(valist, format); + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + size += getInsertLength(format[++i], va_arg(valist, uint32_t)); + continue; + } + size++; + } + va_start(valist, format); + + char* data = malloc(size); + char* write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(valist, uint32_t)); + continue; + } + *write = format[i]; + write++; + } + va_end(valist); + + Message* message = malloc(sizeof(Message)); + + message->data = data; + message->size = size; + message->next = 0x00; + sendMessage(getPrinterTask(), message); + schedule(getPrinterTask()); +} + +void clearScreen() { + setCursorOffset(0); + for (int y = 0; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharAt(' ', x, y); + } + } +} + +void setTextStyle(uint8_t style) { + format = style; +} + +void putChars(char* string, uint32_t length) { + for (uint32_t i = 0; i < length; i++) { + if (string[i] == '\n') { + newLine(); + continue; + } + putChar(string[i]); + } +} + +uint32_t strlen(char* string) { + uint32_t length = 0; + while (string[length] != 0) { + length++; + } + return length; +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/cursor.c b/src/kernel/drivers/textMode/cursor.c new file mode 100644 index 0000000..8247c5e --- /dev/null +++ b/src/kernel/drivers/textMode/cursor.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include <_stdio.h> + +void setCursorOffset(uint16_t offset) { + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (offset & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); +} + +void setCursorPosition(uint8_t x, uint8_t y) { + setCursorOffset(x + y * VIDEO_WIDTH); +} + +uint16_t getCursorOffset() { + uint16_t result = 0; + outb(0x3D4, 0x0F); + result |= inb(0x3D5); + outb(0x3D4, 0x0E); + result |= ((uint16_t)inb(0x3D5)) << 8; + return result; +} \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index d8ff7b8..48ea59f 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,19 +1,26 @@ #include -#include +#include <_stdio.h> #include #include #include #include #include +#include extern uint32_t _kernel_end; void kernelMain() { - initMemoryAllocation(0x100000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here + initMemoryAllocation(0x1000000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here initOSTasks(); drawLogo(); - printf("Switching to otherTask... \n"); + printf("giving up control...\n"); yields(); printf("Returned to mainTask!\n\n"); + printf("initializing interrupts\n"); + initInterrupts(); + yields(); + printf("trying interrupt\n"); + asm ("int $0x80"); + printf("the interrupt worked!\n"); yield(); } \ No newline at end of file diff --git a/src/kernel/lib/memory/alloc.c b/src/kernel/lib/memory/alloc.c deleted file mode 100644 index aedcbad..0000000 --- a/src/kernel/lib/memory/alloc.c +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include -#include - -MemoryBlock* firstBlock; - -void initMemoryAllocation(uint32_t kernelEnd) { - firstBlock = (MemoryBlock*) kernelEnd; - firstBlock->next = 0x00; - firstBlock->last = 0x00; - firstBlock->state = FREE; - firstBlock->size = -1; -} - -void* mallocTask(uint32_t size, Task* task) { - MemoryBlock* current = firstBlock; - while (! (current->next == 0x00 || current->state == FREE && current->size >= size)) { - current = current->next; - } - MemoryBlock* next; - if (current->next == 0x00) { - // this is currently the last block -> initialize the new last block - next = (MemoryBlock*) ((void*) (current + 1) + size); - next->last = current; - next->state = FREE; - next->next = 0x00; - next->size = -1; - } else { - // there is a next block - next = current->next; - } - if (current->size > size + sizeof(MemoryBlock) * 2 && current->next != 0x00) { - // segment the current block if it is big enough - current->next = (MemoryBlock*) (((void*) (current + 1)) + size); - current->next->size = current->size - sizeof(MemoryBlock) - size; - current->size = size; - current->next->state = FREE; - current->next->next = next; - next->last = current->next; - } else { - current->next = next; - if (current->next->next == 0x00) { - current->size = size; - } - } - current->state = IN_USE; - current->task = task; - return (void*) (current + 1); -} - -void* malloc(uint32_t size) { - return mallocTask(size, (Task*) getCurrentTask()); -} - -void mergeNextIfPossible(MemoryBlock* current) { - if (current->next != 0x00 && current->next->state == FREE) { - current->size = current->size + sizeof(MemoryBlock) + current->next->size; - current->next = current->next->next; - current->next->next->last = current; - } -} - -void free(void* location) { - MemoryBlock* current = ((MemoryBlock*) location) - 1; - current->state = FREE; - mergeNextIfPossible(current); - if (current->last != 0x00 && current->last->state == FREE) { - current = current->last; - } - mergeNextIfPossible(current); // call this function twice in case a used block between 2 free blocks is freed - mergeNextIfPossible(current); -} - -void printMemoryStack() { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); - current = current->next; - } - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); -} - -void freeTaskAllocations(Task* task) { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - if (current->task == task) { - free(current); - } - current = current->next; - } - if (current->task == task) { - free(current); - } -} \ No newline at end of file diff --git a/src/kernel/lib/ports.c b/src/kernel/lib/ports.c deleted file mode 100644 index 6cfbb2a..0000000 --- a/src/kernel/lib/ports.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include - -void outb(uint16_t port, uint8_t val) { - asm volatile("outb %0, %1" : : "a"(val), "Nd"(port) ); -} - -uint8_t inb(uint16_t port) { - uint8_t result; - __asm__("in %%dx, %%al" : "=a" (result) : "d" (port)); - return result; -} \ No newline at end of file diff --git a/src/kernel/lib/task/osTasks.c b/src/kernel/lib/task/osTasks.c deleted file mode 100644 index c3d6a43..0000000 --- a/src/kernel/lib/task/osTasks.c +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include -#include -#include - -Task mainTask; -Task printerTask; - -void printLoop() { - while (1) { - yield(); - Message* message = popMessage(&printerTask); - if (message == 0x00) { - continue; - } - putChars(message->data, message->size); - free(message->data); - free(message); - } -} - -void initOSTasks() { - setRunningTask(&mainTask); - createTask(&printerTask, (uint32_t) printLoop, 0x0, 0x0); - schedule(&printerTask); - // more tasks . . . - yields(); -} - -inline Task* getPrinterTask() { - return &printerTask; -} \ No newline at end of file diff --git a/src/kernel/lib/task/task.c b/src/kernel/lib/task/task.c deleted file mode 100644 index e4201c5..0000000 --- a/src/kernel/lib/task/task.c +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include -#include - -#define STACK_SIZE 0xF000 - -Task *currentTask; - -void createTask(Task *task, uint32_t mainFunction, uint32_t flags, uint32_t *pagedir) { - void* stack = mallocTask(STACK_SIZE, task); - task->registers.eax = 0; - task->registers.ebx = 0; - task->registers.ecx = 0; - task->registers.edx = 0; - task->registers.esi = 0; - task->registers.edi = 0; - task->registers.eflags = flags; - task->registers.eip = mainFunction; - task->registers.cr3 = (uint32_t) pagedir; - task->registers.esp = STACK_SIZE + (uint32_t) stack; - task->nextTask = 0; - task->stack = stack; -} - -void yield() { - Task* last = currentTask; - currentTask = currentTask->nextTask; - if (currentTask == 0x00) { - puts("No more tasks to run, halting . . .\n"); - while (1) { - asm("hlt"); - } - } - last->nextTask = 0x00; - switchTask(&(last->registers), &(currentTask->registers)); -} - -void schedule(Task* task) { - Task* test = currentTask; - while (test->nextTask != 0x0) { - test = test->nextTask; - if (test->nextTask == task) { - return; // don't schedule if the task is already in the queue - } - } - test->nextTask = task; -} - -void setRunningTask(Task* task) { - currentTask = task; -} - -void yields() { - schedule(currentTask); - yield(); -} - -void destroyCurrentTask() { - freeTaskAllocations(currentTask); - yield(); -} - -Task* getCurrentTask() { - return currentTask; -} - -void sendMessage(Task* task, Message* message) { - if (task->message == 0x00) { - task->message = message; - return; - } - Message* currentMessage = task->message; - while (currentMessage->next == 0x00) { - currentMessage = currentMessage->next; - } - currentMessage->next = message; -} - -Message* popMessage(Task* task) { - Message* currentMessage = task->message; - if (currentMessage != 0x00) { - task->message = currentMessage->next; - - } - return currentMessage; -} \ No newline at end of file diff --git a/src/kernel/lib/task/task.s b/src/kernel/lib/task/task.s deleted file mode 100644 index 88357cd..0000000 --- a/src/kernel/lib/task/task.s +++ /dev/null @@ -1,49 +0,0 @@ -.section .text -.global switchTask -switchTask: - pusha - pushf - mov %cr3, %eax #Push CR3 - push %eax - mov 44(%esp), %eax #The first argument, where to save - mov %ebx, 4(%eax) - mov %ecx, 8(%eax) - mov %edx, 12(%eax) - mov %esi, 16(%eax) - mov %edi, 20(%eax) - mov 36(%esp), %ebx #EAX - mov 40(%esp), %ecx #IP - mov 20(%esp), %edx #ESP - add $4, %edx #Remove the return value - mov 16(%esp), %esi #EBP - mov 4(%esp), %edi #EFLAGS - mov %ebx, (%eax) - mov %edx, 24(%eax) - mov %esi, 28(%eax) - mov %ecx, 32(%eax) - mov %edi, 36(%eax) - pop %ebx #CR3 - mov %ebx, 40(%eax) - push %ebx #Goodbye again - mov 48(%esp), %eax #Now it is the new object - mov 4(%eax), %ebx #EBX - mov 8(%eax), %ecx #ECX - mov 12(%eax), %edx #EDX - mov 16(%eax), %esi #ESI - mov 20(%eax), %edi #EDI - mov 28(%eax), %ebp #EBP - push %eax - mov 36(%eax), %eax #EFLAGS - push %eax - popf - pop %eax - mov 24(%eax), %esp #ESP - push %eax - mov 40(%eax), %eax #CR3 - mov %eax, %cr3 - pop %eax - push %eax - mov 32(%eax), %eax #EIP - xchg (%esp), %eax - mov (%eax), %eax #EAX - ret diff --git a/src/kernel/lib/textMode/cursor.c b/src/kernel/lib/textMode/cursor.c deleted file mode 100644 index e5cc8f9..0000000 --- a/src/kernel/lib/textMode/cursor.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include -#include - -void setCursorOffset(uint16_t offset) { - outb(0x3D4, 0x0F); - outb(0x3D5, (uint8_t) (offset & 0xFF)); - outb(0x3D4, 0x0E); - outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); -} - -void setCursorPosition(uint8_t x, uint8_t y) { - setCursorOffset(x + y * VIDEO_WIDTH); -} - -uint16_t getCursorOffset() { - uint16_t result = 0; - outb(0x3D4, 0x0F); - result |= inb(0x3D5); - outb(0x3D4, 0x0E); - result |= ((uint16_t)inb(0x3D5)) << 8; - return result; -} \ No newline at end of file diff --git a/src/kernel/lib/textMode/stdio.c b/src/kernel/lib/textMode/stdio.c deleted file mode 100644 index 5f1b3a0..0000000 --- a/src/kernel/lib/textMode/stdio.c +++ /dev/null @@ -1,200 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; -char format = 0x0F; - -void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { - *(framebuffer + position) = c; -} - -void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { - putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); -} - -void putCharAtOffset(char c, uint16_t offset) { - putCharWithFormatAtOffset(c | format << 8, offset); -} - -void putCharAt(char c, uint8_t x, uint8_t y) { - putCharAtOffset(c, (x + y * VIDEO_WIDTH)); -} - -uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { - return *(framebuffer + x + y * VIDEO_WIDTH); -} - -void putCharsAt(char* string, uint8_t x, uint8_t y) { - uint16_t position = 0; - char c = *string; - while (c != 0x00) { - putCharAt(c, x + position, y); - position++; - c = *(string + position); - } -} - -void shiftUp() { - for (int y = 1; y < VIDEO_HEIGHT; y++) { - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); - } - } - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); - } -} - -void newLine() { - uint16_t offset = getCursorOffset(); - uint8_t x = offset % VIDEO_WIDTH; - uint8_t y = offset / VIDEO_WIDTH; - x = 0; - y++; - if (y >= VIDEO_HEIGHT) { - shiftUp(); - y--; - } - setCursorPosition(x, y); -} - -void putChar(char c) { - if (c == '\n') { - newLine(); - return; - } - uint16_t offset = getCursorOffset(); - putCharAtOffset(c, offset); - setCursorOffset(offset + 1); -} - -void puts(char* string) { - while (*string != 0x00) { - putChar(*string); - string++; - } -} - -char HEX_PREFIX[] = "0x"; -char HEX_CHARS[] = "0123456789ABCDEF"; - -void putHex(char** write, uint32_t x) { - uint8_t alreadyWriting = 0; - for (uint8_t position = 3; position >= 0; position--) { - uint8_t byte = (x >> (position * 8)) & 0xFF; - if (byte != 0x00) { - alreadyWriting = 0x01; - } - if (alreadyWriting) { - **write = HEX_CHARS[byte % 256]; - *write++; - **write = HEX_CHARS[byte / 256]; - *write++; - } - } -} - -uint32_t getInsertLength(char insertType, uint32_t x) { - switch (insertType) - { - case 's': - return strlen((char*) x); - case 'x': - for (uint8_t position = 3; position >= 0; position--) { - uint8_t byte = (x >> (position * 8)) & 0xFF; - if (byte != 0x00) { - return 2*position; - } - } - return 0; - } - return 0; -} - -void handleInsert(char** write, char insertType, uint32_t x) { - if (insertType == 's') { - char* string = (char*) x; - uint32_t length = strlen(string); - for (uint32_t position = 0; position < length; position++) { - **write = string[position]; - *write++; - } - return; - } - if (insertType == 'x') { - putHex(write, x); - } -} - -void printf(const char* format, ...) { - uint32_t size = 0; - va_list valist; - va_start(valist, format); - for (int i = 0; format[i] != 0; i++) { - if (format[i] == '%') { - size += getInsertLength(format[++i], va_arg(valist, uint32_t)); - continue; - } - size++; - } - va_start(valist, format); - - char* data = malloc(size); - char* write = data; - for (int i = 0; format[i] != 0; i++) { - if (format[i] == '%') { - handleInsert(&write, format[++i], va_arg(valist, uint32_t)); - continue; - } - *write = format[i]; - write++; - } - va_end(valist); - - Message message = { - message.data = data, - message.size = size, - message.next = 0x00 - }; - sendMessage(getPrinterTask(), &message); - schedule(getPrinterTask()); - yields(); -} - -void clearScreen() { - setCursorOffset(0); - for (int y = 0; y < VIDEO_HEIGHT; y++) { - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharAt(' ', x, y); - } - } -} - -void setTextStyle(uint8_t style) { - format = style; -} - -void putChars(char* string, uint32_t length) { - for (uint32_t i = 0; i < length; i++) { - if (string[i] == '\n') { - newLine(); - continue; - } - putChar(string[i]); - } -} - -uint32_t strlen(char* string) { - uint32_t length = 0; - while (string[length] != 0) { - length++; - } - return length; -} \ No newline at end of file diff --git a/src/kernel/memory/alloc.c b/src/kernel/memory/alloc.c new file mode 100644 index 0000000..97d0a84 --- /dev/null +++ b/src/kernel/memory/alloc.c @@ -0,0 +1,94 @@ +#include +#include +#include <_stdio.h> + +MemoryBlock* firstBlock; + +void initMemoryAllocation(uint32_t kernelEnd) { + firstBlock = (MemoryBlock*) kernelEnd; + firstBlock->next = 0x00; + firstBlock->last = 0x00; + firstBlock->state = FREE; + firstBlock->size = -1; +} + +void* mallocTask(uint32_t size, Task* task) { + MemoryBlock* current = firstBlock; + while (! (current->next == 0x00 || current->state == FREE && current->size >= size)) { + current = current->next; + } + MemoryBlock* next; + if (current->next == 0x00) { + // this is currently the last block -> initialize the new last block + next = (MemoryBlock*) ((void*) (current + 1) + size); + next->last = current; + next->state = FREE; + next->next = 0x00; + next->size = -1; + } else { + // there is a next block + next = current->next; + } + if (current->size > size + sizeof(MemoryBlock) * 2 && current->next != 0x00) { + // segment the current block if it is big enough + current->next = (MemoryBlock*) (((void*) (current + 1)) + size); + current->next->size = current->size - sizeof(MemoryBlock) - size; + current->size = size; + current->next->state = FREE; + current->next->next = next; + next->last = current->next; + } else { + current->next = next; + if (current->next->next == 0x00) { + current->size = size; + } + } + current->state = IN_USE; + current->task = task; + return (void*) (current + 1); +} + +void* malloc(uint32_t size) { + return mallocTask(size, (Task*) getCurrentTask()); +} + +void mergeNextIfPossible(MemoryBlock* current) { + if (current->next != 0x00 && current->next->state == FREE) { + current->size = current->size + sizeof(MemoryBlock) + current->next->size; + current->next = current->next->next; + current->next->next->last = current; + } +} + +void free(void* location) { + MemoryBlock* current = ((MemoryBlock*) location) - 1; + current->state = FREE; + mergeNextIfPossible(current); + if (current->last != 0x00 && current->last->state == FREE) { + current = current->last; + } + mergeNextIfPossible(current); // call this function twice in case a used block between 2 free blocks is freed + mergeNextIfPossible(current); +} + +void printMemoryStack() { + MemoryBlock* current = firstBlock; + while (current->next != 0x00) { + printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); + current = current->next; + } + printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); +} + +void freeTaskAllocations(Task* task) { + MemoryBlock* current = firstBlock; + while (current->next != 0x00) { + if (current->task == task) { + free(current); + } + current = current->next; + } + if (current->task == task) { + free(current); + } +} \ No newline at end of file diff --git a/src/kernel/task/osTasks.c b/src/kernel/task/osTasks.c new file mode 100644 index 0000000..5d52a79 --- /dev/null +++ b/src/kernel/task/osTasks.c @@ -0,0 +1,35 @@ +#include +#include +#include <_stdio.h> +#include +#include + +Task mainTask; +Task printerTask; + +void printLoop() { + clearScreen(); + setTextStyle(0x0F); + while (1) { + Message* message = popMessage(&printerTask); + if (message == 0) { + yield(); + continue; + } + putChars(message->data, message->size); + free(message->data); + free(message); + } +} + +void initOSTasks() { + setRunningTask(&mainTask); + createTask(&printerTask, (uint32_t) printLoop, 0x0, 0x0); + schedule(&printerTask); + // more tasks . . . + yields(); +} + +inline Task* getPrinterTask() { + return &printerTask; +} \ No newline at end of file diff --git a/src/kernel/task/task.c b/src/kernel/task/task.c new file mode 100644 index 0000000..4b93d2d --- /dev/null +++ b/src/kernel/task/task.c @@ -0,0 +1,86 @@ +#include +#include +#include <_stdio.h> + +#define STACK_SIZE 0x1000 + +Task *currentTask; + +void createTask(Task *task, uint32_t mainFunction, uint32_t flags, uint32_t *pagedir) { + void* stack = mallocTask(STACK_SIZE, task); + task->registers.eax = 0; + task->registers.ebx = 0; + task->registers.ecx = 0; + task->registers.edx = 0; + task->registers.esi = 0; + task->registers.edi = 0; + task->registers.eflags = flags; + task->registers.eip = mainFunction; + task->registers.cr3 = (uint32_t) pagedir; + task->registers.esp = STACK_SIZE + (uint32_t) stack; + task->nextTask = 0; + task->stack = stack; +} + +void yield() { + Task* last = currentTask; + currentTask = last->nextTask; + if (currentTask == 0x00) { + puts("No more tasks to run, halting . . .\n"); + asm("hlt"); + } + last->nextTask = 0x00; + switchTask(&(last->registers), &(currentTask->registers)); +} + +void schedule(Task* task) { + Task* test = currentTask; + while (test->nextTask != 0x0) { + if (test->nextTask == task) { + return; // don't schedule if the task is already in the queue + } + test = test->nextTask; + } + if (test->nextTask == task) { + return; + } + test->nextTask = task; +} + +void setRunningTask(Task* task) { + currentTask = task; +} + +void yields() { + schedule(currentTask); + yield(); +} + +void destroyCurrentTask() { + freeTaskAllocations(currentTask); + yield(); +} + +Task* getCurrentTask() { + return currentTask; +} + +void sendMessage(Task* task, Message* message) { + Message* currentMessage = task->message; + if (currentMessage == 0) { + task->message = message; + return; + } + while (currentMessage->next != 0) { + currentMessage = currentMessage->next; + } + currentMessage->next = message; +} + +Message* popMessage(Task* task) { + Message* currentMessage = task->message; + if (currentMessage != 0) { + task->message = currentMessage->next; + } + return currentMessage; +} \ No newline at end of file diff --git a/src/kernel/task/task.s b/src/kernel/task/task.s new file mode 100644 index 0000000..88357cd --- /dev/null +++ b/src/kernel/task/task.s @@ -0,0 +1,49 @@ +.section .text +.global switchTask +switchTask: + pusha + pushf + mov %cr3, %eax #Push CR3 + push %eax + mov 44(%esp), %eax #The first argument, where to save + mov %ebx, 4(%eax) + mov %ecx, 8(%eax) + mov %edx, 12(%eax) + mov %esi, 16(%eax) + mov %edi, 20(%eax) + mov 36(%esp), %ebx #EAX + mov 40(%esp), %ecx #IP + mov 20(%esp), %edx #ESP + add $4, %edx #Remove the return value + mov 16(%esp), %esi #EBP + mov 4(%esp), %edi #EFLAGS + mov %ebx, (%eax) + mov %edx, 24(%eax) + mov %esi, 28(%eax) + mov %ecx, 32(%eax) + mov %edi, 36(%eax) + pop %ebx #CR3 + mov %ebx, 40(%eax) + push %ebx #Goodbye again + mov 48(%esp), %eax #Now it is the new object + mov 4(%eax), %ebx #EBX + mov 8(%eax), %ecx #ECX + mov 12(%eax), %edx #EDX + mov 16(%eax), %esi #ESI + mov 20(%eax), %edi #EDI + mov 28(%eax), %ebp #EBP + push %eax + mov 36(%eax), %eax #EFLAGS + push %eax + popf + pop %eax + mov 24(%eax), %esp #ESP + push %eax + mov 40(%eax), %eax #CR3 + mov %eax, %cr3 + pop %eax + push %eax + mov 32(%eax), %eax #EIP + xchg (%esp), %eax + mov (%eax), %eax #EAX + ret diff --git a/src/kernel/textMode/_stdio.c b/src/kernel/textMode/_stdio.c new file mode 100644 index 0000000..fcecf6f --- /dev/null +++ b/src/kernel/textMode/_stdio.c @@ -0,0 +1,199 @@ +#include +#include +#include <_stdio.h> +#include +#include +#include +#include +#include +#include + +uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; +char format = 0x0F; + +void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { + *(framebuffer + position) = c; +} + +void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { + putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +void putCharAtOffset(char c, uint16_t offset) { + putCharWithFormatAtOffset(c | format << 8, offset); +} + +void putCharAt(char c, uint8_t x, uint8_t y) { + putCharAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { + return *(framebuffer + x + y * VIDEO_WIDTH); +} + +void putCharsAt(char* string, uint8_t x, uint8_t y) { + uint16_t position = 0; + char c = *string; + while (c != 0x00) { + putCharAt(c, x + position, y); + position++; + c = *(string + position); + } +} + +void shiftUp() { + for (int y = 1; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); + } + } + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); + } +} + +void newLine() { + uint16_t offset = getCursorOffset(); + uint8_t x = offset % VIDEO_WIDTH; + uint8_t y = offset / VIDEO_WIDTH; + x = 0; + y++; + if (y >= VIDEO_HEIGHT) { + shiftUp(); + y--; + } + setCursorPosition(x, y); +} + +void putChar(char c) { + if (c == '\n') { + newLine(); + return; + } + uint16_t offset = getCursorOffset(); + putCharAtOffset(c, offset); + setCursorOffset(offset + 1); +} + +void puts(char* string) { + while (*string != 0x00) { + putChar(*string); + string++; + } +} + +char HEX_PREFIX[] = "0x"; +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char** write, uint32_t x) { + uint8_t alreadyWriting = 0; + for (uint8_t position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = 0x01; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte % 256]; + *write++; + **write = HEX_CHARS[byte / 256]; + *write++; + } + } +} + +uint32_t getInsertLength(char insertType, uint32_t x) { + switch (insertType) + { + case 's': + return strlen((char*) x); + case 'x': + for (uint8_t position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + return 2*position; + } + } + return 0; + } + return 0; +} + +void handleInsert(char** write, char insertType, uint32_t x) { + if (insertType == 's') { + char* string = (char*) x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + *write++; + } + return; + } + if (insertType == 'x') { + putHex(write, x); + } +} + +void printf(const char* format, ...) { + uint32_t size = 0; + va_list valist; + va_start(valist, format); + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + size += getInsertLength(format[++i], va_arg(valist, uint32_t)); + continue; + } + size++; + } + va_start(valist, format); + + char* data = malloc(size); + char* write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(valist, uint32_t)); + continue; + } + *write = format[i]; + write++; + } + va_end(valist); + + Message* message = malloc(sizeof(Message)); + + message->data = data; + message->size = size; + message->next = 0x00; + sendMessage(getPrinterTask(), message); + schedule(getPrinterTask()); +} + +void clearScreen() { + setCursorOffset(0); + for (int y = 0; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharAt(' ', x, y); + } + } +} + +void setTextStyle(uint8_t style) { + format = style; +} + +void putChars(char* string, uint32_t length) { + for (uint32_t i = 0; i < length; i++) { + if (string[i] == '\n') { + newLine(); + continue; + } + putChar(string[i]); + } +} + +uint32_t strlen(char* string) { + uint32_t length = 0; + while (string[length] != 0) { + length++; + } + return length; +} \ No newline at end of file diff --git a/src/kernel/textMode/cursor.c b/src/kernel/textMode/cursor.c new file mode 100644 index 0000000..8247c5e --- /dev/null +++ b/src/kernel/textMode/cursor.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include <_stdio.h> + +void setCursorOffset(uint16_t offset) { + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (offset & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); +} + +void setCursorPosition(uint8_t x, uint8_t y) { + setCursorOffset(x + y * VIDEO_WIDTH); +} + +uint16_t getCursorOffset() { + uint16_t result = 0; + outb(0x3D4, 0x0F); + result |= inb(0x3D5); + outb(0x3D4, 0x0E); + result |= ((uint16_t)inb(0x3D5)) << 8; + return result; +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index dd72655..36c0cfc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { - "*.h": "c" + "*.h": "c", + "type_traits": "c" } } \ No newline at end of file diff --git a/src/headers/_stdio.h b/src/headers/_stdio.h new file mode 100644 index 0000000..b5d4f87 --- /dev/null +++ b/src/headers/_stdio.h @@ -0,0 +1,20 @@ +#ifndef STDIO_H +#define STDIO_H + +#include + +#define FRAMEBUFFER_LOCATION 0x000B8000 +#define VIDEO_WIDTH 80 +#define VIDEO_HEIGHT 25 + +extern void setTextStyle(uint8_t style); +extern void clearScreen(); +extern void printf(const char* format, ...); +extern void putCharAt(char c, uint8_t x, uint8_t y); +extern void putCharsAt(char* string, uint8_t x, uint8_t y); +extern void puts(char* string); +extern void putChars(char* string, uint32_t length); + +extern uint32_t strlen(char* string); + +#endif \ No newline at end of file diff --git a/src/headers/interrupts.h b/src/headers/interrupts.h new file mode 100644 index 0000000..3ca3d29 --- /dev/null +++ b/src/headers/interrupts.h @@ -0,0 +1,21 @@ +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + +#include + +typedef struct { + uint16_t isr_low; + uint16_t codeSegment; + uint8_t reserved; + uint8_t attributes; + uint16_t isr_high; +} __attribute__((packed)) IDTEntry; + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) IDTR; + +extern void initInterrupts(); + +#endif \ No newline at end of file diff --git a/src/headers/stdio.h b/src/headers/stdio.h deleted file mode 100644 index b5d4f87..0000000 --- a/src/headers/stdio.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef STDIO_H -#define STDIO_H - -#include - -#define FRAMEBUFFER_LOCATION 0x000B8000 -#define VIDEO_WIDTH 80 -#define VIDEO_HEIGHT 25 - -extern void setTextStyle(uint8_t style); -extern void clearScreen(); -extern void printf(const char* format, ...); -extern void putCharAt(char c, uint8_t x, uint8_t y); -extern void putCharsAt(char* string, uint8_t x, uint8_t y); -extern void puts(char* string); -extern void putChars(char* string, uint32_t length); - -extern uint32_t strlen(char* string); - -#endif \ No newline at end of file diff --git a/src/interrupts/interrupts.c b/src/interrupts/interrupts.c new file mode 100644 index 0000000..74d2931 --- /dev/null +++ b/src/interrupts/interrupts.c @@ -0,0 +1,33 @@ +#include +#include <_stdio.h> +#include + +IDTR idtr; +IDTEntry* entries; +void* buffer; + +void setInterrupt(uint8_t vector, void* callback, uint8_t flags) { + IDTEntry* descriptor = &entries[vector]; + + descriptor->isr_low = (uint32_t)callback & 0xFFFF; + descriptor->codeSegment = 0x08; + descriptor->attributes = flags; + descriptor->isr_high = (uint32_t)callback >> 16; + descriptor->reserved = 0; +} + +void testInterrupt() { + printf("interrupt!\n"); +} + +void initInterrupts() { + buffer = malloc(sizeof(IDTEntry) * 257); + entries = (IDTEntry*) (((int) buffer + sizeof(IDTEntry)) & -1 ^ 0x0F); + idtr.limit = sizeof(IDTEntry) * 256 - 1; + idtr.base = entries; + for (int i = 0; i < 256; i++) { + setInterrupt(i, testInterrupt, 0x8E); + } + __asm__ volatile ("lidt %0" : : "memory"(idtr)); + __asm__ volatile ("sti"); +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/_stdio.c b/src/kernel/drivers/textMode/_stdio.c new file mode 100644 index 0000000..34eea3f --- /dev/null +++ b/src/kernel/drivers/textMode/_stdio.c @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <_stdio.h> + +uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; +char format = 0x0F; + +void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { + *(framebuffer + position) = c; +} + +void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { + putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +void putCharAtOffset(char c, uint16_t offset) { + putCharWithFormatAtOffset(c | format << 8, offset); +} + +void putCharAt(char c, uint8_t x, uint8_t y) { + putCharAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { + return *(framebuffer + x + y * VIDEO_WIDTH); +} + +void putCharsAt(char* string, uint8_t x, uint8_t y) { + uint16_t position = 0; + char c = *string; + while (c != 0x00) { + putCharAt(c, x + position, y); + position++; + c = *(string + position); + } +} + +void shiftUp() { + for (int y = 1; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); + } + } + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); + } +} + +void newLine() { + uint16_t offset = getCursorOffset(); + uint8_t x = offset % VIDEO_WIDTH; + uint8_t y = offset / VIDEO_WIDTH; + x = 0; + y++; + if (y >= VIDEO_HEIGHT) { + shiftUp(); + y--; + } + setCursorPosition(x, y); +} + +void putChar(char c) { + if (c == '\n') { + newLine(); + return; + } + uint16_t offset = getCursorOffset(); + putCharAtOffset(c, offset); + setCursorOffset(offset + 1); +} + +void puts(char* string) { + while (*string != 0x00) { + putChar(*string); + string++; + } +} + +char HEX_PREFIX[] = "0x"; +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char** write, uint32_t x) { + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + **write = HEX_CHARS[byte >> 8]; + (*write)++; + } + } +} + +uint8_t hexLength(uint32_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return size; +} + +uint32_t getInsertLength(char insertType, uint32_t x) { + switch (insertType) { + case 's': + return strlen((char*) x); + case 'x': + return hexLength(x); + } + return 0; +} + +void stringInsert(char** write, uint32_t x) { + char* string = (char*) x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char** write, char insertType, uint32_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + } +} + +void printf(const char* format, ...) { + uint32_t size = 0; + va_list valist; + va_start(valist, format); + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + size += getInsertLength(format[++i], va_arg(valist, uint32_t)); + continue; + } + size++; + } + va_start(valist, format); + + char* data = malloc(size); + char* write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(valist, uint32_t)); + continue; + } + *write = format[i]; + write++; + } + va_end(valist); + + Message* message = malloc(sizeof(Message)); + + message->data = data; + message->size = size; + message->next = 0x00; + sendMessage(getPrinterTask(), message); + schedule(getPrinterTask()); +} + +void clearScreen() { + setCursorOffset(0); + for (int y = 0; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharAt(' ', x, y); + } + } +} + +void setTextStyle(uint8_t style) { + format = style; +} + +void putChars(char* string, uint32_t length) { + for (uint32_t i = 0; i < length; i++) { + if (string[i] == '\n') { + newLine(); + continue; + } + putChar(string[i]); + } +} + +uint32_t strlen(char* string) { + uint32_t length = 0; + while (string[length] != 0) { + length++; + } + return length; +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/cursor.c b/src/kernel/drivers/textMode/cursor.c new file mode 100644 index 0000000..8247c5e --- /dev/null +++ b/src/kernel/drivers/textMode/cursor.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include <_stdio.h> + +void setCursorOffset(uint16_t offset) { + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (offset & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); +} + +void setCursorPosition(uint8_t x, uint8_t y) { + setCursorOffset(x + y * VIDEO_WIDTH); +} + +uint16_t getCursorOffset() { + uint16_t result = 0; + outb(0x3D4, 0x0F); + result |= inb(0x3D5); + outb(0x3D4, 0x0E); + result |= ((uint16_t)inb(0x3D5)) << 8; + return result; +} \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index d8ff7b8..48ea59f 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,19 +1,26 @@ #include -#include +#include <_stdio.h> #include #include #include #include #include +#include extern uint32_t _kernel_end; void kernelMain() { - initMemoryAllocation(0x100000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here + initMemoryAllocation(0x1000000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here initOSTasks(); drawLogo(); - printf("Switching to otherTask... \n"); + printf("giving up control...\n"); yields(); printf("Returned to mainTask!\n\n"); + printf("initializing interrupts\n"); + initInterrupts(); + yields(); + printf("trying interrupt\n"); + asm ("int $0x80"); + printf("the interrupt worked!\n"); yield(); } \ No newline at end of file diff --git a/src/kernel/lib/memory/alloc.c b/src/kernel/lib/memory/alloc.c deleted file mode 100644 index aedcbad..0000000 --- a/src/kernel/lib/memory/alloc.c +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include -#include - -MemoryBlock* firstBlock; - -void initMemoryAllocation(uint32_t kernelEnd) { - firstBlock = (MemoryBlock*) kernelEnd; - firstBlock->next = 0x00; - firstBlock->last = 0x00; - firstBlock->state = FREE; - firstBlock->size = -1; -} - -void* mallocTask(uint32_t size, Task* task) { - MemoryBlock* current = firstBlock; - while (! (current->next == 0x00 || current->state == FREE && current->size >= size)) { - current = current->next; - } - MemoryBlock* next; - if (current->next == 0x00) { - // this is currently the last block -> initialize the new last block - next = (MemoryBlock*) ((void*) (current + 1) + size); - next->last = current; - next->state = FREE; - next->next = 0x00; - next->size = -1; - } else { - // there is a next block - next = current->next; - } - if (current->size > size + sizeof(MemoryBlock) * 2 && current->next != 0x00) { - // segment the current block if it is big enough - current->next = (MemoryBlock*) (((void*) (current + 1)) + size); - current->next->size = current->size - sizeof(MemoryBlock) - size; - current->size = size; - current->next->state = FREE; - current->next->next = next; - next->last = current->next; - } else { - current->next = next; - if (current->next->next == 0x00) { - current->size = size; - } - } - current->state = IN_USE; - current->task = task; - return (void*) (current + 1); -} - -void* malloc(uint32_t size) { - return mallocTask(size, (Task*) getCurrentTask()); -} - -void mergeNextIfPossible(MemoryBlock* current) { - if (current->next != 0x00 && current->next->state == FREE) { - current->size = current->size + sizeof(MemoryBlock) + current->next->size; - current->next = current->next->next; - current->next->next->last = current; - } -} - -void free(void* location) { - MemoryBlock* current = ((MemoryBlock*) location) - 1; - current->state = FREE; - mergeNextIfPossible(current); - if (current->last != 0x00 && current->last->state == FREE) { - current = current->last; - } - mergeNextIfPossible(current); // call this function twice in case a used block between 2 free blocks is freed - mergeNextIfPossible(current); -} - -void printMemoryStack() { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); - current = current->next; - } - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); -} - -void freeTaskAllocations(Task* task) { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - if (current->task == task) { - free(current); - } - current = current->next; - } - if (current->task == task) { - free(current); - } -} \ No newline at end of file diff --git a/src/kernel/lib/ports.c b/src/kernel/lib/ports.c deleted file mode 100644 index 6cfbb2a..0000000 --- a/src/kernel/lib/ports.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include - -void outb(uint16_t port, uint8_t val) { - asm volatile("outb %0, %1" : : "a"(val), "Nd"(port) ); -} - -uint8_t inb(uint16_t port) { - uint8_t result; - __asm__("in %%dx, %%al" : "=a" (result) : "d" (port)); - return result; -} \ No newline at end of file diff --git a/src/kernel/lib/task/osTasks.c b/src/kernel/lib/task/osTasks.c deleted file mode 100644 index c3d6a43..0000000 --- a/src/kernel/lib/task/osTasks.c +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include -#include -#include - -Task mainTask; -Task printerTask; - -void printLoop() { - while (1) { - yield(); - Message* message = popMessage(&printerTask); - if (message == 0x00) { - continue; - } - putChars(message->data, message->size); - free(message->data); - free(message); - } -} - -void initOSTasks() { - setRunningTask(&mainTask); - createTask(&printerTask, (uint32_t) printLoop, 0x0, 0x0); - schedule(&printerTask); - // more tasks . . . - yields(); -} - -inline Task* getPrinterTask() { - return &printerTask; -} \ No newline at end of file diff --git a/src/kernel/lib/task/task.c b/src/kernel/lib/task/task.c deleted file mode 100644 index e4201c5..0000000 --- a/src/kernel/lib/task/task.c +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include -#include - -#define STACK_SIZE 0xF000 - -Task *currentTask; - -void createTask(Task *task, uint32_t mainFunction, uint32_t flags, uint32_t *pagedir) { - void* stack = mallocTask(STACK_SIZE, task); - task->registers.eax = 0; - task->registers.ebx = 0; - task->registers.ecx = 0; - task->registers.edx = 0; - task->registers.esi = 0; - task->registers.edi = 0; - task->registers.eflags = flags; - task->registers.eip = mainFunction; - task->registers.cr3 = (uint32_t) pagedir; - task->registers.esp = STACK_SIZE + (uint32_t) stack; - task->nextTask = 0; - task->stack = stack; -} - -void yield() { - Task* last = currentTask; - currentTask = currentTask->nextTask; - if (currentTask == 0x00) { - puts("No more tasks to run, halting . . .\n"); - while (1) { - asm("hlt"); - } - } - last->nextTask = 0x00; - switchTask(&(last->registers), &(currentTask->registers)); -} - -void schedule(Task* task) { - Task* test = currentTask; - while (test->nextTask != 0x0) { - test = test->nextTask; - if (test->nextTask == task) { - return; // don't schedule if the task is already in the queue - } - } - test->nextTask = task; -} - -void setRunningTask(Task* task) { - currentTask = task; -} - -void yields() { - schedule(currentTask); - yield(); -} - -void destroyCurrentTask() { - freeTaskAllocations(currentTask); - yield(); -} - -Task* getCurrentTask() { - return currentTask; -} - -void sendMessage(Task* task, Message* message) { - if (task->message == 0x00) { - task->message = message; - return; - } - Message* currentMessage = task->message; - while (currentMessage->next == 0x00) { - currentMessage = currentMessage->next; - } - currentMessage->next = message; -} - -Message* popMessage(Task* task) { - Message* currentMessage = task->message; - if (currentMessage != 0x00) { - task->message = currentMessage->next; - - } - return currentMessage; -} \ No newline at end of file diff --git a/src/kernel/lib/task/task.s b/src/kernel/lib/task/task.s deleted file mode 100644 index 88357cd..0000000 --- a/src/kernel/lib/task/task.s +++ /dev/null @@ -1,49 +0,0 @@ -.section .text -.global switchTask -switchTask: - pusha - pushf - mov %cr3, %eax #Push CR3 - push %eax - mov 44(%esp), %eax #The first argument, where to save - mov %ebx, 4(%eax) - mov %ecx, 8(%eax) - mov %edx, 12(%eax) - mov %esi, 16(%eax) - mov %edi, 20(%eax) - mov 36(%esp), %ebx #EAX - mov 40(%esp), %ecx #IP - mov 20(%esp), %edx #ESP - add $4, %edx #Remove the return value - mov 16(%esp), %esi #EBP - mov 4(%esp), %edi #EFLAGS - mov %ebx, (%eax) - mov %edx, 24(%eax) - mov %esi, 28(%eax) - mov %ecx, 32(%eax) - mov %edi, 36(%eax) - pop %ebx #CR3 - mov %ebx, 40(%eax) - push %ebx #Goodbye again - mov 48(%esp), %eax #Now it is the new object - mov 4(%eax), %ebx #EBX - mov 8(%eax), %ecx #ECX - mov 12(%eax), %edx #EDX - mov 16(%eax), %esi #ESI - mov 20(%eax), %edi #EDI - mov 28(%eax), %ebp #EBP - push %eax - mov 36(%eax), %eax #EFLAGS - push %eax - popf - pop %eax - mov 24(%eax), %esp #ESP - push %eax - mov 40(%eax), %eax #CR3 - mov %eax, %cr3 - pop %eax - push %eax - mov 32(%eax), %eax #EIP - xchg (%esp), %eax - mov (%eax), %eax #EAX - ret diff --git a/src/kernel/lib/textMode/cursor.c b/src/kernel/lib/textMode/cursor.c deleted file mode 100644 index e5cc8f9..0000000 --- a/src/kernel/lib/textMode/cursor.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include -#include - -void setCursorOffset(uint16_t offset) { - outb(0x3D4, 0x0F); - outb(0x3D5, (uint8_t) (offset & 0xFF)); - outb(0x3D4, 0x0E); - outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); -} - -void setCursorPosition(uint8_t x, uint8_t y) { - setCursorOffset(x + y * VIDEO_WIDTH); -} - -uint16_t getCursorOffset() { - uint16_t result = 0; - outb(0x3D4, 0x0F); - result |= inb(0x3D5); - outb(0x3D4, 0x0E); - result |= ((uint16_t)inb(0x3D5)) << 8; - return result; -} \ No newline at end of file diff --git a/src/kernel/lib/textMode/stdio.c b/src/kernel/lib/textMode/stdio.c deleted file mode 100644 index 5f1b3a0..0000000 --- a/src/kernel/lib/textMode/stdio.c +++ /dev/null @@ -1,200 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; -char format = 0x0F; - -void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { - *(framebuffer + position) = c; -} - -void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { - putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); -} - -void putCharAtOffset(char c, uint16_t offset) { - putCharWithFormatAtOffset(c | format << 8, offset); -} - -void putCharAt(char c, uint8_t x, uint8_t y) { - putCharAtOffset(c, (x + y * VIDEO_WIDTH)); -} - -uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { - return *(framebuffer + x + y * VIDEO_WIDTH); -} - -void putCharsAt(char* string, uint8_t x, uint8_t y) { - uint16_t position = 0; - char c = *string; - while (c != 0x00) { - putCharAt(c, x + position, y); - position++; - c = *(string + position); - } -} - -void shiftUp() { - for (int y = 1; y < VIDEO_HEIGHT; y++) { - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); - } - } - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); - } -} - -void newLine() { - uint16_t offset = getCursorOffset(); - uint8_t x = offset % VIDEO_WIDTH; - uint8_t y = offset / VIDEO_WIDTH; - x = 0; - y++; - if (y >= VIDEO_HEIGHT) { - shiftUp(); - y--; - } - setCursorPosition(x, y); -} - -void putChar(char c) { - if (c == '\n') { - newLine(); - return; - } - uint16_t offset = getCursorOffset(); - putCharAtOffset(c, offset); - setCursorOffset(offset + 1); -} - -void puts(char* string) { - while (*string != 0x00) { - putChar(*string); - string++; - } -} - -char HEX_PREFIX[] = "0x"; -char HEX_CHARS[] = "0123456789ABCDEF"; - -void putHex(char** write, uint32_t x) { - uint8_t alreadyWriting = 0; - for (uint8_t position = 3; position >= 0; position--) { - uint8_t byte = (x >> (position * 8)) & 0xFF; - if (byte != 0x00) { - alreadyWriting = 0x01; - } - if (alreadyWriting) { - **write = HEX_CHARS[byte % 256]; - *write++; - **write = HEX_CHARS[byte / 256]; - *write++; - } - } -} - -uint32_t getInsertLength(char insertType, uint32_t x) { - switch (insertType) - { - case 's': - return strlen((char*) x); - case 'x': - for (uint8_t position = 3; position >= 0; position--) { - uint8_t byte = (x >> (position * 8)) & 0xFF; - if (byte != 0x00) { - return 2*position; - } - } - return 0; - } - return 0; -} - -void handleInsert(char** write, char insertType, uint32_t x) { - if (insertType == 's') { - char* string = (char*) x; - uint32_t length = strlen(string); - for (uint32_t position = 0; position < length; position++) { - **write = string[position]; - *write++; - } - return; - } - if (insertType == 'x') { - putHex(write, x); - } -} - -void printf(const char* format, ...) { - uint32_t size = 0; - va_list valist; - va_start(valist, format); - for (int i = 0; format[i] != 0; i++) { - if (format[i] == '%') { - size += getInsertLength(format[++i], va_arg(valist, uint32_t)); - continue; - } - size++; - } - va_start(valist, format); - - char* data = malloc(size); - char* write = data; - for (int i = 0; format[i] != 0; i++) { - if (format[i] == '%') { - handleInsert(&write, format[++i], va_arg(valist, uint32_t)); - continue; - } - *write = format[i]; - write++; - } - va_end(valist); - - Message message = { - message.data = data, - message.size = size, - message.next = 0x00 - }; - sendMessage(getPrinterTask(), &message); - schedule(getPrinterTask()); - yields(); -} - -void clearScreen() { - setCursorOffset(0); - for (int y = 0; y < VIDEO_HEIGHT; y++) { - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharAt(' ', x, y); - } - } -} - -void setTextStyle(uint8_t style) { - format = style; -} - -void putChars(char* string, uint32_t length) { - for (uint32_t i = 0; i < length; i++) { - if (string[i] == '\n') { - newLine(); - continue; - } - putChar(string[i]); - } -} - -uint32_t strlen(char* string) { - uint32_t length = 0; - while (string[length] != 0) { - length++; - } - return length; -} \ No newline at end of file diff --git a/src/kernel/memory/alloc.c b/src/kernel/memory/alloc.c new file mode 100644 index 0000000..97d0a84 --- /dev/null +++ b/src/kernel/memory/alloc.c @@ -0,0 +1,94 @@ +#include +#include +#include <_stdio.h> + +MemoryBlock* firstBlock; + +void initMemoryAllocation(uint32_t kernelEnd) { + firstBlock = (MemoryBlock*) kernelEnd; + firstBlock->next = 0x00; + firstBlock->last = 0x00; + firstBlock->state = FREE; + firstBlock->size = -1; +} + +void* mallocTask(uint32_t size, Task* task) { + MemoryBlock* current = firstBlock; + while (! (current->next == 0x00 || current->state == FREE && current->size >= size)) { + current = current->next; + } + MemoryBlock* next; + if (current->next == 0x00) { + // this is currently the last block -> initialize the new last block + next = (MemoryBlock*) ((void*) (current + 1) + size); + next->last = current; + next->state = FREE; + next->next = 0x00; + next->size = -1; + } else { + // there is a next block + next = current->next; + } + if (current->size > size + sizeof(MemoryBlock) * 2 && current->next != 0x00) { + // segment the current block if it is big enough + current->next = (MemoryBlock*) (((void*) (current + 1)) + size); + current->next->size = current->size - sizeof(MemoryBlock) - size; + current->size = size; + current->next->state = FREE; + current->next->next = next; + next->last = current->next; + } else { + current->next = next; + if (current->next->next == 0x00) { + current->size = size; + } + } + current->state = IN_USE; + current->task = task; + return (void*) (current + 1); +} + +void* malloc(uint32_t size) { + return mallocTask(size, (Task*) getCurrentTask()); +} + +void mergeNextIfPossible(MemoryBlock* current) { + if (current->next != 0x00 && current->next->state == FREE) { + current->size = current->size + sizeof(MemoryBlock) + current->next->size; + current->next = current->next->next; + current->next->next->last = current; + } +} + +void free(void* location) { + MemoryBlock* current = ((MemoryBlock*) location) - 1; + current->state = FREE; + mergeNextIfPossible(current); + if (current->last != 0x00 && current->last->state == FREE) { + current = current->last; + } + mergeNextIfPossible(current); // call this function twice in case a used block between 2 free blocks is freed + mergeNextIfPossible(current); +} + +void printMemoryStack() { + MemoryBlock* current = firstBlock; + while (current->next != 0x00) { + printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); + current = current->next; + } + printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); +} + +void freeTaskAllocations(Task* task) { + MemoryBlock* current = firstBlock; + while (current->next != 0x00) { + if (current->task == task) { + free(current); + } + current = current->next; + } + if (current->task == task) { + free(current); + } +} \ No newline at end of file diff --git a/src/kernel/task/osTasks.c b/src/kernel/task/osTasks.c new file mode 100644 index 0000000..5d52a79 --- /dev/null +++ b/src/kernel/task/osTasks.c @@ -0,0 +1,35 @@ +#include +#include +#include <_stdio.h> +#include +#include + +Task mainTask; +Task printerTask; + +void printLoop() { + clearScreen(); + setTextStyle(0x0F); + while (1) { + Message* message = popMessage(&printerTask); + if (message == 0) { + yield(); + continue; + } + putChars(message->data, message->size); + free(message->data); + free(message); + } +} + +void initOSTasks() { + setRunningTask(&mainTask); + createTask(&printerTask, (uint32_t) printLoop, 0x0, 0x0); + schedule(&printerTask); + // more tasks . . . + yields(); +} + +inline Task* getPrinterTask() { + return &printerTask; +} \ No newline at end of file diff --git a/src/kernel/task/task.c b/src/kernel/task/task.c new file mode 100644 index 0000000..4b93d2d --- /dev/null +++ b/src/kernel/task/task.c @@ -0,0 +1,86 @@ +#include +#include +#include <_stdio.h> + +#define STACK_SIZE 0x1000 + +Task *currentTask; + +void createTask(Task *task, uint32_t mainFunction, uint32_t flags, uint32_t *pagedir) { + void* stack = mallocTask(STACK_SIZE, task); + task->registers.eax = 0; + task->registers.ebx = 0; + task->registers.ecx = 0; + task->registers.edx = 0; + task->registers.esi = 0; + task->registers.edi = 0; + task->registers.eflags = flags; + task->registers.eip = mainFunction; + task->registers.cr3 = (uint32_t) pagedir; + task->registers.esp = STACK_SIZE + (uint32_t) stack; + task->nextTask = 0; + task->stack = stack; +} + +void yield() { + Task* last = currentTask; + currentTask = last->nextTask; + if (currentTask == 0x00) { + puts("No more tasks to run, halting . . .\n"); + asm("hlt"); + } + last->nextTask = 0x00; + switchTask(&(last->registers), &(currentTask->registers)); +} + +void schedule(Task* task) { + Task* test = currentTask; + while (test->nextTask != 0x0) { + if (test->nextTask == task) { + return; // don't schedule if the task is already in the queue + } + test = test->nextTask; + } + if (test->nextTask == task) { + return; + } + test->nextTask = task; +} + +void setRunningTask(Task* task) { + currentTask = task; +} + +void yields() { + schedule(currentTask); + yield(); +} + +void destroyCurrentTask() { + freeTaskAllocations(currentTask); + yield(); +} + +Task* getCurrentTask() { + return currentTask; +} + +void sendMessage(Task* task, Message* message) { + Message* currentMessage = task->message; + if (currentMessage == 0) { + task->message = message; + return; + } + while (currentMessage->next != 0) { + currentMessage = currentMessage->next; + } + currentMessage->next = message; +} + +Message* popMessage(Task* task) { + Message* currentMessage = task->message; + if (currentMessage != 0) { + task->message = currentMessage->next; + } + return currentMessage; +} \ No newline at end of file diff --git a/src/kernel/task/task.s b/src/kernel/task/task.s new file mode 100644 index 0000000..88357cd --- /dev/null +++ b/src/kernel/task/task.s @@ -0,0 +1,49 @@ +.section .text +.global switchTask +switchTask: + pusha + pushf + mov %cr3, %eax #Push CR3 + push %eax + mov 44(%esp), %eax #The first argument, where to save + mov %ebx, 4(%eax) + mov %ecx, 8(%eax) + mov %edx, 12(%eax) + mov %esi, 16(%eax) + mov %edi, 20(%eax) + mov 36(%esp), %ebx #EAX + mov 40(%esp), %ecx #IP + mov 20(%esp), %edx #ESP + add $4, %edx #Remove the return value + mov 16(%esp), %esi #EBP + mov 4(%esp), %edi #EFLAGS + mov %ebx, (%eax) + mov %edx, 24(%eax) + mov %esi, 28(%eax) + mov %ecx, 32(%eax) + mov %edi, 36(%eax) + pop %ebx #CR3 + mov %ebx, 40(%eax) + push %ebx #Goodbye again + mov 48(%esp), %eax #Now it is the new object + mov 4(%eax), %ebx #EBX + mov 8(%eax), %ecx #ECX + mov 12(%eax), %edx #EDX + mov 16(%eax), %esi #ESI + mov 20(%eax), %edi #EDI + mov 28(%eax), %ebp #EBP + push %eax + mov 36(%eax), %eax #EFLAGS + push %eax + popf + pop %eax + mov 24(%eax), %esp #ESP + push %eax + mov 40(%eax), %eax #CR3 + mov %eax, %cr3 + pop %eax + push %eax + mov 32(%eax), %eax #EIP + xchg (%esp), %eax + mov (%eax), %eax #EAX + ret diff --git a/src/kernel/textMode/_stdio.c b/src/kernel/textMode/_stdio.c new file mode 100644 index 0000000..fcecf6f --- /dev/null +++ b/src/kernel/textMode/_stdio.c @@ -0,0 +1,199 @@ +#include +#include +#include <_stdio.h> +#include +#include +#include +#include +#include +#include + +uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; +char format = 0x0F; + +void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { + *(framebuffer + position) = c; +} + +void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { + putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +void putCharAtOffset(char c, uint16_t offset) { + putCharWithFormatAtOffset(c | format << 8, offset); +} + +void putCharAt(char c, uint8_t x, uint8_t y) { + putCharAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { + return *(framebuffer + x + y * VIDEO_WIDTH); +} + +void putCharsAt(char* string, uint8_t x, uint8_t y) { + uint16_t position = 0; + char c = *string; + while (c != 0x00) { + putCharAt(c, x + position, y); + position++; + c = *(string + position); + } +} + +void shiftUp() { + for (int y = 1; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); + } + } + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); + } +} + +void newLine() { + uint16_t offset = getCursorOffset(); + uint8_t x = offset % VIDEO_WIDTH; + uint8_t y = offset / VIDEO_WIDTH; + x = 0; + y++; + if (y >= VIDEO_HEIGHT) { + shiftUp(); + y--; + } + setCursorPosition(x, y); +} + +void putChar(char c) { + if (c == '\n') { + newLine(); + return; + } + uint16_t offset = getCursorOffset(); + putCharAtOffset(c, offset); + setCursorOffset(offset + 1); +} + +void puts(char* string) { + while (*string != 0x00) { + putChar(*string); + string++; + } +} + +char HEX_PREFIX[] = "0x"; +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char** write, uint32_t x) { + uint8_t alreadyWriting = 0; + for (uint8_t position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = 0x01; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte % 256]; + *write++; + **write = HEX_CHARS[byte / 256]; + *write++; + } + } +} + +uint32_t getInsertLength(char insertType, uint32_t x) { + switch (insertType) + { + case 's': + return strlen((char*) x); + case 'x': + for (uint8_t position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + return 2*position; + } + } + return 0; + } + return 0; +} + +void handleInsert(char** write, char insertType, uint32_t x) { + if (insertType == 's') { + char* string = (char*) x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + *write++; + } + return; + } + if (insertType == 'x') { + putHex(write, x); + } +} + +void printf(const char* format, ...) { + uint32_t size = 0; + va_list valist; + va_start(valist, format); + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + size += getInsertLength(format[++i], va_arg(valist, uint32_t)); + continue; + } + size++; + } + va_start(valist, format); + + char* data = malloc(size); + char* write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(valist, uint32_t)); + continue; + } + *write = format[i]; + write++; + } + va_end(valist); + + Message* message = malloc(sizeof(Message)); + + message->data = data; + message->size = size; + message->next = 0x00; + sendMessage(getPrinterTask(), message); + schedule(getPrinterTask()); +} + +void clearScreen() { + setCursorOffset(0); + for (int y = 0; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharAt(' ', x, y); + } + } +} + +void setTextStyle(uint8_t style) { + format = style; +} + +void putChars(char* string, uint32_t length) { + for (uint32_t i = 0; i < length; i++) { + if (string[i] == '\n') { + newLine(); + continue; + } + putChar(string[i]); + } +} + +uint32_t strlen(char* string) { + uint32_t length = 0; + while (string[length] != 0) { + length++; + } + return length; +} \ No newline at end of file diff --git a/src/kernel/textMode/cursor.c b/src/kernel/textMode/cursor.c new file mode 100644 index 0000000..8247c5e --- /dev/null +++ b/src/kernel/textMode/cursor.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include <_stdio.h> + +void setCursorOffset(uint16_t offset) { + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (offset & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); +} + +void setCursorPosition(uint8_t x, uint8_t y) { + setCursorOffset(x + y * VIDEO_WIDTH); +} + +uint16_t getCursorOffset() { + uint16_t result = 0; + outb(0x3D4, 0x0F); + result |= inb(0x3D5); + outb(0x3D4, 0x0E); + result |= ((uint16_t)inb(0x3D5)) << 8; + return result; +} \ No newline at end of file diff --git a/src/kernel/tree-os.c b/src/kernel/tree-os.c deleted file mode 100644 index 913bb93..0000000 --- a/src/kernel/tree-os.c +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include - -const char* logo = "\ - _______ \n\ -|__ __| \n\ - | |_ __ ___ ___ ___ ___ \n\ - | | '__/ _ \\/ _ \\ / _ \\/ __| \n\ - | | | | __/ __/ | (_) \\__ \\ \n\ - |_|_| \\___|\\___| \\___/|___/ \n\n"; - -void drawLogo() { - clearScreen(); - setTextStyle(0x0F); - printf(logo); - printf("TREE-OS v. alpha 0.1 (IN DEVELOPMENT)\n\n"); -} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index dd72655..36c0cfc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { - "*.h": "c" + "*.h": "c", + "type_traits": "c" } } \ No newline at end of file diff --git a/src/headers/_stdio.h b/src/headers/_stdio.h new file mode 100644 index 0000000..b5d4f87 --- /dev/null +++ b/src/headers/_stdio.h @@ -0,0 +1,20 @@ +#ifndef STDIO_H +#define STDIO_H + +#include + +#define FRAMEBUFFER_LOCATION 0x000B8000 +#define VIDEO_WIDTH 80 +#define VIDEO_HEIGHT 25 + +extern void setTextStyle(uint8_t style); +extern void clearScreen(); +extern void printf(const char* format, ...); +extern void putCharAt(char c, uint8_t x, uint8_t y); +extern void putCharsAt(char* string, uint8_t x, uint8_t y); +extern void puts(char* string); +extern void putChars(char* string, uint32_t length); + +extern uint32_t strlen(char* string); + +#endif \ No newline at end of file diff --git a/src/headers/interrupts.h b/src/headers/interrupts.h new file mode 100644 index 0000000..3ca3d29 --- /dev/null +++ b/src/headers/interrupts.h @@ -0,0 +1,21 @@ +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + +#include + +typedef struct { + uint16_t isr_low; + uint16_t codeSegment; + uint8_t reserved; + uint8_t attributes; + uint16_t isr_high; +} __attribute__((packed)) IDTEntry; + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) IDTR; + +extern void initInterrupts(); + +#endif \ No newline at end of file diff --git a/src/headers/stdio.h b/src/headers/stdio.h deleted file mode 100644 index b5d4f87..0000000 --- a/src/headers/stdio.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef STDIO_H -#define STDIO_H - -#include - -#define FRAMEBUFFER_LOCATION 0x000B8000 -#define VIDEO_WIDTH 80 -#define VIDEO_HEIGHT 25 - -extern void setTextStyle(uint8_t style); -extern void clearScreen(); -extern void printf(const char* format, ...); -extern void putCharAt(char c, uint8_t x, uint8_t y); -extern void putCharsAt(char* string, uint8_t x, uint8_t y); -extern void puts(char* string); -extern void putChars(char* string, uint32_t length); - -extern uint32_t strlen(char* string); - -#endif \ No newline at end of file diff --git a/src/interrupts/interrupts.c b/src/interrupts/interrupts.c new file mode 100644 index 0000000..74d2931 --- /dev/null +++ b/src/interrupts/interrupts.c @@ -0,0 +1,33 @@ +#include +#include <_stdio.h> +#include + +IDTR idtr; +IDTEntry* entries; +void* buffer; + +void setInterrupt(uint8_t vector, void* callback, uint8_t flags) { + IDTEntry* descriptor = &entries[vector]; + + descriptor->isr_low = (uint32_t)callback & 0xFFFF; + descriptor->codeSegment = 0x08; + descriptor->attributes = flags; + descriptor->isr_high = (uint32_t)callback >> 16; + descriptor->reserved = 0; +} + +void testInterrupt() { + printf("interrupt!\n"); +} + +void initInterrupts() { + buffer = malloc(sizeof(IDTEntry) * 257); + entries = (IDTEntry*) (((int) buffer + sizeof(IDTEntry)) & -1 ^ 0x0F); + idtr.limit = sizeof(IDTEntry) * 256 - 1; + idtr.base = entries; + for (int i = 0; i < 256; i++) { + setInterrupt(i, testInterrupt, 0x8E); + } + __asm__ volatile ("lidt %0" : : "memory"(idtr)); + __asm__ volatile ("sti"); +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/_stdio.c b/src/kernel/drivers/textMode/_stdio.c new file mode 100644 index 0000000..34eea3f --- /dev/null +++ b/src/kernel/drivers/textMode/_stdio.c @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <_stdio.h> + +uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; +char format = 0x0F; + +void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { + *(framebuffer + position) = c; +} + +void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { + putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +void putCharAtOffset(char c, uint16_t offset) { + putCharWithFormatAtOffset(c | format << 8, offset); +} + +void putCharAt(char c, uint8_t x, uint8_t y) { + putCharAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { + return *(framebuffer + x + y * VIDEO_WIDTH); +} + +void putCharsAt(char* string, uint8_t x, uint8_t y) { + uint16_t position = 0; + char c = *string; + while (c != 0x00) { + putCharAt(c, x + position, y); + position++; + c = *(string + position); + } +} + +void shiftUp() { + for (int y = 1; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); + } + } + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); + } +} + +void newLine() { + uint16_t offset = getCursorOffset(); + uint8_t x = offset % VIDEO_WIDTH; + uint8_t y = offset / VIDEO_WIDTH; + x = 0; + y++; + if (y >= VIDEO_HEIGHT) { + shiftUp(); + y--; + } + setCursorPosition(x, y); +} + +void putChar(char c) { + if (c == '\n') { + newLine(); + return; + } + uint16_t offset = getCursorOffset(); + putCharAtOffset(c, offset); + setCursorOffset(offset + 1); +} + +void puts(char* string) { + while (*string != 0x00) { + putChar(*string); + string++; + } +} + +char HEX_PREFIX[] = "0x"; +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char** write, uint32_t x) { + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + **write = HEX_CHARS[byte >> 8]; + (*write)++; + } + } +} + +uint8_t hexLength(uint32_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return size; +} + +uint32_t getInsertLength(char insertType, uint32_t x) { + switch (insertType) { + case 's': + return strlen((char*) x); + case 'x': + return hexLength(x); + } + return 0; +} + +void stringInsert(char** write, uint32_t x) { + char* string = (char*) x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char** write, char insertType, uint32_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + } +} + +void printf(const char* format, ...) { + uint32_t size = 0; + va_list valist; + va_start(valist, format); + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + size += getInsertLength(format[++i], va_arg(valist, uint32_t)); + continue; + } + size++; + } + va_start(valist, format); + + char* data = malloc(size); + char* write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(valist, uint32_t)); + continue; + } + *write = format[i]; + write++; + } + va_end(valist); + + Message* message = malloc(sizeof(Message)); + + message->data = data; + message->size = size; + message->next = 0x00; + sendMessage(getPrinterTask(), message); + schedule(getPrinterTask()); +} + +void clearScreen() { + setCursorOffset(0); + for (int y = 0; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharAt(' ', x, y); + } + } +} + +void setTextStyle(uint8_t style) { + format = style; +} + +void putChars(char* string, uint32_t length) { + for (uint32_t i = 0; i < length; i++) { + if (string[i] == '\n') { + newLine(); + continue; + } + putChar(string[i]); + } +} + +uint32_t strlen(char* string) { + uint32_t length = 0; + while (string[length] != 0) { + length++; + } + return length; +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/cursor.c b/src/kernel/drivers/textMode/cursor.c new file mode 100644 index 0000000..8247c5e --- /dev/null +++ b/src/kernel/drivers/textMode/cursor.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include <_stdio.h> + +void setCursorOffset(uint16_t offset) { + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (offset & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); +} + +void setCursorPosition(uint8_t x, uint8_t y) { + setCursorOffset(x + y * VIDEO_WIDTH); +} + +uint16_t getCursorOffset() { + uint16_t result = 0; + outb(0x3D4, 0x0F); + result |= inb(0x3D5); + outb(0x3D4, 0x0E); + result |= ((uint16_t)inb(0x3D5)) << 8; + return result; +} \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index d8ff7b8..48ea59f 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,19 +1,26 @@ #include -#include +#include <_stdio.h> #include #include #include #include #include +#include extern uint32_t _kernel_end; void kernelMain() { - initMemoryAllocation(0x100000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here + initMemoryAllocation(0x1000000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here initOSTasks(); drawLogo(); - printf("Switching to otherTask... \n"); + printf("giving up control...\n"); yields(); printf("Returned to mainTask!\n\n"); + printf("initializing interrupts\n"); + initInterrupts(); + yields(); + printf("trying interrupt\n"); + asm ("int $0x80"); + printf("the interrupt worked!\n"); yield(); } \ No newline at end of file diff --git a/src/kernel/lib/memory/alloc.c b/src/kernel/lib/memory/alloc.c deleted file mode 100644 index aedcbad..0000000 --- a/src/kernel/lib/memory/alloc.c +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include -#include - -MemoryBlock* firstBlock; - -void initMemoryAllocation(uint32_t kernelEnd) { - firstBlock = (MemoryBlock*) kernelEnd; - firstBlock->next = 0x00; - firstBlock->last = 0x00; - firstBlock->state = FREE; - firstBlock->size = -1; -} - -void* mallocTask(uint32_t size, Task* task) { - MemoryBlock* current = firstBlock; - while (! (current->next == 0x00 || current->state == FREE && current->size >= size)) { - current = current->next; - } - MemoryBlock* next; - if (current->next == 0x00) { - // this is currently the last block -> initialize the new last block - next = (MemoryBlock*) ((void*) (current + 1) + size); - next->last = current; - next->state = FREE; - next->next = 0x00; - next->size = -1; - } else { - // there is a next block - next = current->next; - } - if (current->size > size + sizeof(MemoryBlock) * 2 && current->next != 0x00) { - // segment the current block if it is big enough - current->next = (MemoryBlock*) (((void*) (current + 1)) + size); - current->next->size = current->size - sizeof(MemoryBlock) - size; - current->size = size; - current->next->state = FREE; - current->next->next = next; - next->last = current->next; - } else { - current->next = next; - if (current->next->next == 0x00) { - current->size = size; - } - } - current->state = IN_USE; - current->task = task; - return (void*) (current + 1); -} - -void* malloc(uint32_t size) { - return mallocTask(size, (Task*) getCurrentTask()); -} - -void mergeNextIfPossible(MemoryBlock* current) { - if (current->next != 0x00 && current->next->state == FREE) { - current->size = current->size + sizeof(MemoryBlock) + current->next->size; - current->next = current->next->next; - current->next->next->last = current; - } -} - -void free(void* location) { - MemoryBlock* current = ((MemoryBlock*) location) - 1; - current->state = FREE; - mergeNextIfPossible(current); - if (current->last != 0x00 && current->last->state == FREE) { - current = current->last; - } - mergeNextIfPossible(current); // call this function twice in case a used block between 2 free blocks is freed - mergeNextIfPossible(current); -} - -void printMemoryStack() { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); - current = current->next; - } - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); -} - -void freeTaskAllocations(Task* task) { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - if (current->task == task) { - free(current); - } - current = current->next; - } - if (current->task == task) { - free(current); - } -} \ No newline at end of file diff --git a/src/kernel/lib/ports.c b/src/kernel/lib/ports.c deleted file mode 100644 index 6cfbb2a..0000000 --- a/src/kernel/lib/ports.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include - -void outb(uint16_t port, uint8_t val) { - asm volatile("outb %0, %1" : : "a"(val), "Nd"(port) ); -} - -uint8_t inb(uint16_t port) { - uint8_t result; - __asm__("in %%dx, %%al" : "=a" (result) : "d" (port)); - return result; -} \ No newline at end of file diff --git a/src/kernel/lib/task/osTasks.c b/src/kernel/lib/task/osTasks.c deleted file mode 100644 index c3d6a43..0000000 --- a/src/kernel/lib/task/osTasks.c +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include -#include -#include - -Task mainTask; -Task printerTask; - -void printLoop() { - while (1) { - yield(); - Message* message = popMessage(&printerTask); - if (message == 0x00) { - continue; - } - putChars(message->data, message->size); - free(message->data); - free(message); - } -} - -void initOSTasks() { - setRunningTask(&mainTask); - createTask(&printerTask, (uint32_t) printLoop, 0x0, 0x0); - schedule(&printerTask); - // more tasks . . . - yields(); -} - -inline Task* getPrinterTask() { - return &printerTask; -} \ No newline at end of file diff --git a/src/kernel/lib/task/task.c b/src/kernel/lib/task/task.c deleted file mode 100644 index e4201c5..0000000 --- a/src/kernel/lib/task/task.c +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include -#include - -#define STACK_SIZE 0xF000 - -Task *currentTask; - -void createTask(Task *task, uint32_t mainFunction, uint32_t flags, uint32_t *pagedir) { - void* stack = mallocTask(STACK_SIZE, task); - task->registers.eax = 0; - task->registers.ebx = 0; - task->registers.ecx = 0; - task->registers.edx = 0; - task->registers.esi = 0; - task->registers.edi = 0; - task->registers.eflags = flags; - task->registers.eip = mainFunction; - task->registers.cr3 = (uint32_t) pagedir; - task->registers.esp = STACK_SIZE + (uint32_t) stack; - task->nextTask = 0; - task->stack = stack; -} - -void yield() { - Task* last = currentTask; - currentTask = currentTask->nextTask; - if (currentTask == 0x00) { - puts("No more tasks to run, halting . . .\n"); - while (1) { - asm("hlt"); - } - } - last->nextTask = 0x00; - switchTask(&(last->registers), &(currentTask->registers)); -} - -void schedule(Task* task) { - Task* test = currentTask; - while (test->nextTask != 0x0) { - test = test->nextTask; - if (test->nextTask == task) { - return; // don't schedule if the task is already in the queue - } - } - test->nextTask = task; -} - -void setRunningTask(Task* task) { - currentTask = task; -} - -void yields() { - schedule(currentTask); - yield(); -} - -void destroyCurrentTask() { - freeTaskAllocations(currentTask); - yield(); -} - -Task* getCurrentTask() { - return currentTask; -} - -void sendMessage(Task* task, Message* message) { - if (task->message == 0x00) { - task->message = message; - return; - } - Message* currentMessage = task->message; - while (currentMessage->next == 0x00) { - currentMessage = currentMessage->next; - } - currentMessage->next = message; -} - -Message* popMessage(Task* task) { - Message* currentMessage = task->message; - if (currentMessage != 0x00) { - task->message = currentMessage->next; - - } - return currentMessage; -} \ No newline at end of file diff --git a/src/kernel/lib/task/task.s b/src/kernel/lib/task/task.s deleted file mode 100644 index 88357cd..0000000 --- a/src/kernel/lib/task/task.s +++ /dev/null @@ -1,49 +0,0 @@ -.section .text -.global switchTask -switchTask: - pusha - pushf - mov %cr3, %eax #Push CR3 - push %eax - mov 44(%esp), %eax #The first argument, where to save - mov %ebx, 4(%eax) - mov %ecx, 8(%eax) - mov %edx, 12(%eax) - mov %esi, 16(%eax) - mov %edi, 20(%eax) - mov 36(%esp), %ebx #EAX - mov 40(%esp), %ecx #IP - mov 20(%esp), %edx #ESP - add $4, %edx #Remove the return value - mov 16(%esp), %esi #EBP - mov 4(%esp), %edi #EFLAGS - mov %ebx, (%eax) - mov %edx, 24(%eax) - mov %esi, 28(%eax) - mov %ecx, 32(%eax) - mov %edi, 36(%eax) - pop %ebx #CR3 - mov %ebx, 40(%eax) - push %ebx #Goodbye again - mov 48(%esp), %eax #Now it is the new object - mov 4(%eax), %ebx #EBX - mov 8(%eax), %ecx #ECX - mov 12(%eax), %edx #EDX - mov 16(%eax), %esi #ESI - mov 20(%eax), %edi #EDI - mov 28(%eax), %ebp #EBP - push %eax - mov 36(%eax), %eax #EFLAGS - push %eax - popf - pop %eax - mov 24(%eax), %esp #ESP - push %eax - mov 40(%eax), %eax #CR3 - mov %eax, %cr3 - pop %eax - push %eax - mov 32(%eax), %eax #EIP - xchg (%esp), %eax - mov (%eax), %eax #EAX - ret diff --git a/src/kernel/lib/textMode/cursor.c b/src/kernel/lib/textMode/cursor.c deleted file mode 100644 index e5cc8f9..0000000 --- a/src/kernel/lib/textMode/cursor.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include -#include - -void setCursorOffset(uint16_t offset) { - outb(0x3D4, 0x0F); - outb(0x3D5, (uint8_t) (offset & 0xFF)); - outb(0x3D4, 0x0E); - outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); -} - -void setCursorPosition(uint8_t x, uint8_t y) { - setCursorOffset(x + y * VIDEO_WIDTH); -} - -uint16_t getCursorOffset() { - uint16_t result = 0; - outb(0x3D4, 0x0F); - result |= inb(0x3D5); - outb(0x3D4, 0x0E); - result |= ((uint16_t)inb(0x3D5)) << 8; - return result; -} \ No newline at end of file diff --git a/src/kernel/lib/textMode/stdio.c b/src/kernel/lib/textMode/stdio.c deleted file mode 100644 index 5f1b3a0..0000000 --- a/src/kernel/lib/textMode/stdio.c +++ /dev/null @@ -1,200 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; -char format = 0x0F; - -void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { - *(framebuffer + position) = c; -} - -void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { - putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); -} - -void putCharAtOffset(char c, uint16_t offset) { - putCharWithFormatAtOffset(c | format << 8, offset); -} - -void putCharAt(char c, uint8_t x, uint8_t y) { - putCharAtOffset(c, (x + y * VIDEO_WIDTH)); -} - -uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { - return *(framebuffer + x + y * VIDEO_WIDTH); -} - -void putCharsAt(char* string, uint8_t x, uint8_t y) { - uint16_t position = 0; - char c = *string; - while (c != 0x00) { - putCharAt(c, x + position, y); - position++; - c = *(string + position); - } -} - -void shiftUp() { - for (int y = 1; y < VIDEO_HEIGHT; y++) { - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); - } - } - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); - } -} - -void newLine() { - uint16_t offset = getCursorOffset(); - uint8_t x = offset % VIDEO_WIDTH; - uint8_t y = offset / VIDEO_WIDTH; - x = 0; - y++; - if (y >= VIDEO_HEIGHT) { - shiftUp(); - y--; - } - setCursorPosition(x, y); -} - -void putChar(char c) { - if (c == '\n') { - newLine(); - return; - } - uint16_t offset = getCursorOffset(); - putCharAtOffset(c, offset); - setCursorOffset(offset + 1); -} - -void puts(char* string) { - while (*string != 0x00) { - putChar(*string); - string++; - } -} - -char HEX_PREFIX[] = "0x"; -char HEX_CHARS[] = "0123456789ABCDEF"; - -void putHex(char** write, uint32_t x) { - uint8_t alreadyWriting = 0; - for (uint8_t position = 3; position >= 0; position--) { - uint8_t byte = (x >> (position * 8)) & 0xFF; - if (byte != 0x00) { - alreadyWriting = 0x01; - } - if (alreadyWriting) { - **write = HEX_CHARS[byte % 256]; - *write++; - **write = HEX_CHARS[byte / 256]; - *write++; - } - } -} - -uint32_t getInsertLength(char insertType, uint32_t x) { - switch (insertType) - { - case 's': - return strlen((char*) x); - case 'x': - for (uint8_t position = 3; position >= 0; position--) { - uint8_t byte = (x >> (position * 8)) & 0xFF; - if (byte != 0x00) { - return 2*position; - } - } - return 0; - } - return 0; -} - -void handleInsert(char** write, char insertType, uint32_t x) { - if (insertType == 's') { - char* string = (char*) x; - uint32_t length = strlen(string); - for (uint32_t position = 0; position < length; position++) { - **write = string[position]; - *write++; - } - return; - } - if (insertType == 'x') { - putHex(write, x); - } -} - -void printf(const char* format, ...) { - uint32_t size = 0; - va_list valist; - va_start(valist, format); - for (int i = 0; format[i] != 0; i++) { - if (format[i] == '%') { - size += getInsertLength(format[++i], va_arg(valist, uint32_t)); - continue; - } - size++; - } - va_start(valist, format); - - char* data = malloc(size); - char* write = data; - for (int i = 0; format[i] != 0; i++) { - if (format[i] == '%') { - handleInsert(&write, format[++i], va_arg(valist, uint32_t)); - continue; - } - *write = format[i]; - write++; - } - va_end(valist); - - Message message = { - message.data = data, - message.size = size, - message.next = 0x00 - }; - sendMessage(getPrinterTask(), &message); - schedule(getPrinterTask()); - yields(); -} - -void clearScreen() { - setCursorOffset(0); - for (int y = 0; y < VIDEO_HEIGHT; y++) { - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharAt(' ', x, y); - } - } -} - -void setTextStyle(uint8_t style) { - format = style; -} - -void putChars(char* string, uint32_t length) { - for (uint32_t i = 0; i < length; i++) { - if (string[i] == '\n') { - newLine(); - continue; - } - putChar(string[i]); - } -} - -uint32_t strlen(char* string) { - uint32_t length = 0; - while (string[length] != 0) { - length++; - } - return length; -} \ No newline at end of file diff --git a/src/kernel/memory/alloc.c b/src/kernel/memory/alloc.c new file mode 100644 index 0000000..97d0a84 --- /dev/null +++ b/src/kernel/memory/alloc.c @@ -0,0 +1,94 @@ +#include +#include +#include <_stdio.h> + +MemoryBlock* firstBlock; + +void initMemoryAllocation(uint32_t kernelEnd) { + firstBlock = (MemoryBlock*) kernelEnd; + firstBlock->next = 0x00; + firstBlock->last = 0x00; + firstBlock->state = FREE; + firstBlock->size = -1; +} + +void* mallocTask(uint32_t size, Task* task) { + MemoryBlock* current = firstBlock; + while (! (current->next == 0x00 || current->state == FREE && current->size >= size)) { + current = current->next; + } + MemoryBlock* next; + if (current->next == 0x00) { + // this is currently the last block -> initialize the new last block + next = (MemoryBlock*) ((void*) (current + 1) + size); + next->last = current; + next->state = FREE; + next->next = 0x00; + next->size = -1; + } else { + // there is a next block + next = current->next; + } + if (current->size > size + sizeof(MemoryBlock) * 2 && current->next != 0x00) { + // segment the current block if it is big enough + current->next = (MemoryBlock*) (((void*) (current + 1)) + size); + current->next->size = current->size - sizeof(MemoryBlock) - size; + current->size = size; + current->next->state = FREE; + current->next->next = next; + next->last = current->next; + } else { + current->next = next; + if (current->next->next == 0x00) { + current->size = size; + } + } + current->state = IN_USE; + current->task = task; + return (void*) (current + 1); +} + +void* malloc(uint32_t size) { + return mallocTask(size, (Task*) getCurrentTask()); +} + +void mergeNextIfPossible(MemoryBlock* current) { + if (current->next != 0x00 && current->next->state == FREE) { + current->size = current->size + sizeof(MemoryBlock) + current->next->size; + current->next = current->next->next; + current->next->next->last = current; + } +} + +void free(void* location) { + MemoryBlock* current = ((MemoryBlock*) location) - 1; + current->state = FREE; + mergeNextIfPossible(current); + if (current->last != 0x00 && current->last->state == FREE) { + current = current->last; + } + mergeNextIfPossible(current); // call this function twice in case a used block between 2 free blocks is freed + mergeNextIfPossible(current); +} + +void printMemoryStack() { + MemoryBlock* current = firstBlock; + while (current->next != 0x00) { + printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); + current = current->next; + } + printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); +} + +void freeTaskAllocations(Task* task) { + MemoryBlock* current = firstBlock; + while (current->next != 0x00) { + if (current->task == task) { + free(current); + } + current = current->next; + } + if (current->task == task) { + free(current); + } +} \ No newline at end of file diff --git a/src/kernel/task/osTasks.c b/src/kernel/task/osTasks.c new file mode 100644 index 0000000..5d52a79 --- /dev/null +++ b/src/kernel/task/osTasks.c @@ -0,0 +1,35 @@ +#include +#include +#include <_stdio.h> +#include +#include + +Task mainTask; +Task printerTask; + +void printLoop() { + clearScreen(); + setTextStyle(0x0F); + while (1) { + Message* message = popMessage(&printerTask); + if (message == 0) { + yield(); + continue; + } + putChars(message->data, message->size); + free(message->data); + free(message); + } +} + +void initOSTasks() { + setRunningTask(&mainTask); + createTask(&printerTask, (uint32_t) printLoop, 0x0, 0x0); + schedule(&printerTask); + // more tasks . . . + yields(); +} + +inline Task* getPrinterTask() { + return &printerTask; +} \ No newline at end of file diff --git a/src/kernel/task/task.c b/src/kernel/task/task.c new file mode 100644 index 0000000..4b93d2d --- /dev/null +++ b/src/kernel/task/task.c @@ -0,0 +1,86 @@ +#include +#include +#include <_stdio.h> + +#define STACK_SIZE 0x1000 + +Task *currentTask; + +void createTask(Task *task, uint32_t mainFunction, uint32_t flags, uint32_t *pagedir) { + void* stack = mallocTask(STACK_SIZE, task); + task->registers.eax = 0; + task->registers.ebx = 0; + task->registers.ecx = 0; + task->registers.edx = 0; + task->registers.esi = 0; + task->registers.edi = 0; + task->registers.eflags = flags; + task->registers.eip = mainFunction; + task->registers.cr3 = (uint32_t) pagedir; + task->registers.esp = STACK_SIZE + (uint32_t) stack; + task->nextTask = 0; + task->stack = stack; +} + +void yield() { + Task* last = currentTask; + currentTask = last->nextTask; + if (currentTask == 0x00) { + puts("No more tasks to run, halting . . .\n"); + asm("hlt"); + } + last->nextTask = 0x00; + switchTask(&(last->registers), &(currentTask->registers)); +} + +void schedule(Task* task) { + Task* test = currentTask; + while (test->nextTask != 0x0) { + if (test->nextTask == task) { + return; // don't schedule if the task is already in the queue + } + test = test->nextTask; + } + if (test->nextTask == task) { + return; + } + test->nextTask = task; +} + +void setRunningTask(Task* task) { + currentTask = task; +} + +void yields() { + schedule(currentTask); + yield(); +} + +void destroyCurrentTask() { + freeTaskAllocations(currentTask); + yield(); +} + +Task* getCurrentTask() { + return currentTask; +} + +void sendMessage(Task* task, Message* message) { + Message* currentMessage = task->message; + if (currentMessage == 0) { + task->message = message; + return; + } + while (currentMessage->next != 0) { + currentMessage = currentMessage->next; + } + currentMessage->next = message; +} + +Message* popMessage(Task* task) { + Message* currentMessage = task->message; + if (currentMessage != 0) { + task->message = currentMessage->next; + } + return currentMessage; +} \ No newline at end of file diff --git a/src/kernel/task/task.s b/src/kernel/task/task.s new file mode 100644 index 0000000..88357cd --- /dev/null +++ b/src/kernel/task/task.s @@ -0,0 +1,49 @@ +.section .text +.global switchTask +switchTask: + pusha + pushf + mov %cr3, %eax #Push CR3 + push %eax + mov 44(%esp), %eax #The first argument, where to save + mov %ebx, 4(%eax) + mov %ecx, 8(%eax) + mov %edx, 12(%eax) + mov %esi, 16(%eax) + mov %edi, 20(%eax) + mov 36(%esp), %ebx #EAX + mov 40(%esp), %ecx #IP + mov 20(%esp), %edx #ESP + add $4, %edx #Remove the return value + mov 16(%esp), %esi #EBP + mov 4(%esp), %edi #EFLAGS + mov %ebx, (%eax) + mov %edx, 24(%eax) + mov %esi, 28(%eax) + mov %ecx, 32(%eax) + mov %edi, 36(%eax) + pop %ebx #CR3 + mov %ebx, 40(%eax) + push %ebx #Goodbye again + mov 48(%esp), %eax #Now it is the new object + mov 4(%eax), %ebx #EBX + mov 8(%eax), %ecx #ECX + mov 12(%eax), %edx #EDX + mov 16(%eax), %esi #ESI + mov 20(%eax), %edi #EDI + mov 28(%eax), %ebp #EBP + push %eax + mov 36(%eax), %eax #EFLAGS + push %eax + popf + pop %eax + mov 24(%eax), %esp #ESP + push %eax + mov 40(%eax), %eax #CR3 + mov %eax, %cr3 + pop %eax + push %eax + mov 32(%eax), %eax #EIP + xchg (%esp), %eax + mov (%eax), %eax #EAX + ret diff --git a/src/kernel/textMode/_stdio.c b/src/kernel/textMode/_stdio.c new file mode 100644 index 0000000..fcecf6f --- /dev/null +++ b/src/kernel/textMode/_stdio.c @@ -0,0 +1,199 @@ +#include +#include +#include <_stdio.h> +#include +#include +#include +#include +#include +#include + +uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; +char format = 0x0F; + +void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { + *(framebuffer + position) = c; +} + +void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { + putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +void putCharAtOffset(char c, uint16_t offset) { + putCharWithFormatAtOffset(c | format << 8, offset); +} + +void putCharAt(char c, uint8_t x, uint8_t y) { + putCharAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { + return *(framebuffer + x + y * VIDEO_WIDTH); +} + +void putCharsAt(char* string, uint8_t x, uint8_t y) { + uint16_t position = 0; + char c = *string; + while (c != 0x00) { + putCharAt(c, x + position, y); + position++; + c = *(string + position); + } +} + +void shiftUp() { + for (int y = 1; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); + } + } + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); + } +} + +void newLine() { + uint16_t offset = getCursorOffset(); + uint8_t x = offset % VIDEO_WIDTH; + uint8_t y = offset / VIDEO_WIDTH; + x = 0; + y++; + if (y >= VIDEO_HEIGHT) { + shiftUp(); + y--; + } + setCursorPosition(x, y); +} + +void putChar(char c) { + if (c == '\n') { + newLine(); + return; + } + uint16_t offset = getCursorOffset(); + putCharAtOffset(c, offset); + setCursorOffset(offset + 1); +} + +void puts(char* string) { + while (*string != 0x00) { + putChar(*string); + string++; + } +} + +char HEX_PREFIX[] = "0x"; +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char** write, uint32_t x) { + uint8_t alreadyWriting = 0; + for (uint8_t position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = 0x01; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte % 256]; + *write++; + **write = HEX_CHARS[byte / 256]; + *write++; + } + } +} + +uint32_t getInsertLength(char insertType, uint32_t x) { + switch (insertType) + { + case 's': + return strlen((char*) x); + case 'x': + for (uint8_t position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + return 2*position; + } + } + return 0; + } + return 0; +} + +void handleInsert(char** write, char insertType, uint32_t x) { + if (insertType == 's') { + char* string = (char*) x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + *write++; + } + return; + } + if (insertType == 'x') { + putHex(write, x); + } +} + +void printf(const char* format, ...) { + uint32_t size = 0; + va_list valist; + va_start(valist, format); + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + size += getInsertLength(format[++i], va_arg(valist, uint32_t)); + continue; + } + size++; + } + va_start(valist, format); + + char* data = malloc(size); + char* write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(valist, uint32_t)); + continue; + } + *write = format[i]; + write++; + } + va_end(valist); + + Message* message = malloc(sizeof(Message)); + + message->data = data; + message->size = size; + message->next = 0x00; + sendMessage(getPrinterTask(), message); + schedule(getPrinterTask()); +} + +void clearScreen() { + setCursorOffset(0); + for (int y = 0; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharAt(' ', x, y); + } + } +} + +void setTextStyle(uint8_t style) { + format = style; +} + +void putChars(char* string, uint32_t length) { + for (uint32_t i = 0; i < length; i++) { + if (string[i] == '\n') { + newLine(); + continue; + } + putChar(string[i]); + } +} + +uint32_t strlen(char* string) { + uint32_t length = 0; + while (string[length] != 0) { + length++; + } + return length; +} \ No newline at end of file diff --git a/src/kernel/textMode/cursor.c b/src/kernel/textMode/cursor.c new file mode 100644 index 0000000..8247c5e --- /dev/null +++ b/src/kernel/textMode/cursor.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include <_stdio.h> + +void setCursorOffset(uint16_t offset) { + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (offset & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); +} + +void setCursorPosition(uint8_t x, uint8_t y) { + setCursorOffset(x + y * VIDEO_WIDTH); +} + +uint16_t getCursorOffset() { + uint16_t result = 0; + outb(0x3D4, 0x0F); + result |= inb(0x3D5); + outb(0x3D4, 0x0E); + result |= ((uint16_t)inb(0x3D5)) << 8; + return result; +} \ No newline at end of file diff --git a/src/kernel/tree-os.c b/src/kernel/tree-os.c deleted file mode 100644 index 913bb93..0000000 --- a/src/kernel/tree-os.c +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include - -const char* logo = "\ - _______ \n\ -|__ __| \n\ - | |_ __ ___ ___ ___ ___ \n\ - | | '__/ _ \\/ _ \\ / _ \\/ __| \n\ - | | | | __/ __/ | (_) \\__ \\ \n\ - |_|_| \\___|\\___| \\___/|___/ \n\n"; - -void drawLogo() { - clearScreen(); - setTextStyle(0x0F); - printf(logo); - printf("TREE-OS v. alpha 0.1 (IN DEVELOPMENT)\n\n"); -} \ No newline at end of file diff --git a/src/kernel/util/ports.c b/src/kernel/util/ports.c new file mode 100644 index 0000000..6cfbb2a --- /dev/null +++ b/src/kernel/util/ports.c @@ -0,0 +1,12 @@ +#include +#include + +void outb(uint16_t port, uint8_t val) { + asm volatile("outb %0, %1" : : "a"(val), "Nd"(port) ); +} + +uint8_t inb(uint16_t port) { + uint8_t result; + __asm__("in %%dx, %%al" : "=a" (result) : "d" (port)); + return result; +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index dd72655..36c0cfc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { - "*.h": "c" + "*.h": "c", + "type_traits": "c" } } \ No newline at end of file diff --git a/src/headers/_stdio.h b/src/headers/_stdio.h new file mode 100644 index 0000000..b5d4f87 --- /dev/null +++ b/src/headers/_stdio.h @@ -0,0 +1,20 @@ +#ifndef STDIO_H +#define STDIO_H + +#include + +#define FRAMEBUFFER_LOCATION 0x000B8000 +#define VIDEO_WIDTH 80 +#define VIDEO_HEIGHT 25 + +extern void setTextStyle(uint8_t style); +extern void clearScreen(); +extern void printf(const char* format, ...); +extern void putCharAt(char c, uint8_t x, uint8_t y); +extern void putCharsAt(char* string, uint8_t x, uint8_t y); +extern void puts(char* string); +extern void putChars(char* string, uint32_t length); + +extern uint32_t strlen(char* string); + +#endif \ No newline at end of file diff --git a/src/headers/interrupts.h b/src/headers/interrupts.h new file mode 100644 index 0000000..3ca3d29 --- /dev/null +++ b/src/headers/interrupts.h @@ -0,0 +1,21 @@ +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + +#include + +typedef struct { + uint16_t isr_low; + uint16_t codeSegment; + uint8_t reserved; + uint8_t attributes; + uint16_t isr_high; +} __attribute__((packed)) IDTEntry; + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) IDTR; + +extern void initInterrupts(); + +#endif \ No newline at end of file diff --git a/src/headers/stdio.h b/src/headers/stdio.h deleted file mode 100644 index b5d4f87..0000000 --- a/src/headers/stdio.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef STDIO_H -#define STDIO_H - -#include - -#define FRAMEBUFFER_LOCATION 0x000B8000 -#define VIDEO_WIDTH 80 -#define VIDEO_HEIGHT 25 - -extern void setTextStyle(uint8_t style); -extern void clearScreen(); -extern void printf(const char* format, ...); -extern void putCharAt(char c, uint8_t x, uint8_t y); -extern void putCharsAt(char* string, uint8_t x, uint8_t y); -extern void puts(char* string); -extern void putChars(char* string, uint32_t length); - -extern uint32_t strlen(char* string); - -#endif \ No newline at end of file diff --git a/src/interrupts/interrupts.c b/src/interrupts/interrupts.c new file mode 100644 index 0000000..74d2931 --- /dev/null +++ b/src/interrupts/interrupts.c @@ -0,0 +1,33 @@ +#include +#include <_stdio.h> +#include + +IDTR idtr; +IDTEntry* entries; +void* buffer; + +void setInterrupt(uint8_t vector, void* callback, uint8_t flags) { + IDTEntry* descriptor = &entries[vector]; + + descriptor->isr_low = (uint32_t)callback & 0xFFFF; + descriptor->codeSegment = 0x08; + descriptor->attributes = flags; + descriptor->isr_high = (uint32_t)callback >> 16; + descriptor->reserved = 0; +} + +void testInterrupt() { + printf("interrupt!\n"); +} + +void initInterrupts() { + buffer = malloc(sizeof(IDTEntry) * 257); + entries = (IDTEntry*) (((int) buffer + sizeof(IDTEntry)) & -1 ^ 0x0F); + idtr.limit = sizeof(IDTEntry) * 256 - 1; + idtr.base = entries; + for (int i = 0; i < 256; i++) { + setInterrupt(i, testInterrupt, 0x8E); + } + __asm__ volatile ("lidt %0" : : "memory"(idtr)); + __asm__ volatile ("sti"); +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/_stdio.c b/src/kernel/drivers/textMode/_stdio.c new file mode 100644 index 0000000..34eea3f --- /dev/null +++ b/src/kernel/drivers/textMode/_stdio.c @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <_stdio.h> + +uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; +char format = 0x0F; + +void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { + *(framebuffer + position) = c; +} + +void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { + putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +void putCharAtOffset(char c, uint16_t offset) { + putCharWithFormatAtOffset(c | format << 8, offset); +} + +void putCharAt(char c, uint8_t x, uint8_t y) { + putCharAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { + return *(framebuffer + x + y * VIDEO_WIDTH); +} + +void putCharsAt(char* string, uint8_t x, uint8_t y) { + uint16_t position = 0; + char c = *string; + while (c != 0x00) { + putCharAt(c, x + position, y); + position++; + c = *(string + position); + } +} + +void shiftUp() { + for (int y = 1; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); + } + } + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); + } +} + +void newLine() { + uint16_t offset = getCursorOffset(); + uint8_t x = offset % VIDEO_WIDTH; + uint8_t y = offset / VIDEO_WIDTH; + x = 0; + y++; + if (y >= VIDEO_HEIGHT) { + shiftUp(); + y--; + } + setCursorPosition(x, y); +} + +void putChar(char c) { + if (c == '\n') { + newLine(); + return; + } + uint16_t offset = getCursorOffset(); + putCharAtOffset(c, offset); + setCursorOffset(offset + 1); +} + +void puts(char* string) { + while (*string != 0x00) { + putChar(*string); + string++; + } +} + +char HEX_PREFIX[] = "0x"; +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char** write, uint32_t x) { + bool alreadyWriting = false; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte & 0x0F]; + (*write)++; + **write = HEX_CHARS[byte >> 8]; + (*write)++; + } + } +} + +uint8_t hexLength(uint32_t x) { + bool alreadyWriting = false; + uint8_t size = 0; + for (int position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = true; + } + if (alreadyWriting) { + size += 2; + } + } + return size; +} + +uint32_t getInsertLength(char insertType, uint32_t x) { + switch (insertType) { + case 's': + return strlen((char*) x); + case 'x': + return hexLength(x); + } + return 0; +} + +void stringInsert(char** write, uint32_t x) { + char* string = (char*) x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + (*write)++; + } +} + +void handleInsert(char** write, char insertType, uint32_t x) { + switch (insertType) { + case 's': + stringInsert(write, x); + return; + case 'x': + putHex(write, x); + return; + } +} + +void printf(const char* format, ...) { + uint32_t size = 0; + va_list valist; + va_start(valist, format); + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + size += getInsertLength(format[++i], va_arg(valist, uint32_t)); + continue; + } + size++; + } + va_start(valist, format); + + char* data = malloc(size); + char* write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(valist, uint32_t)); + continue; + } + *write = format[i]; + write++; + } + va_end(valist); + + Message* message = malloc(sizeof(Message)); + + message->data = data; + message->size = size; + message->next = 0x00; + sendMessage(getPrinterTask(), message); + schedule(getPrinterTask()); +} + +void clearScreen() { + setCursorOffset(0); + for (int y = 0; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharAt(' ', x, y); + } + } +} + +void setTextStyle(uint8_t style) { + format = style; +} + +void putChars(char* string, uint32_t length) { + for (uint32_t i = 0; i < length; i++) { + if (string[i] == '\n') { + newLine(); + continue; + } + putChar(string[i]); + } +} + +uint32_t strlen(char* string) { + uint32_t length = 0; + while (string[length] != 0) { + length++; + } + return length; +} \ No newline at end of file diff --git a/src/kernel/drivers/textMode/cursor.c b/src/kernel/drivers/textMode/cursor.c new file mode 100644 index 0000000..8247c5e --- /dev/null +++ b/src/kernel/drivers/textMode/cursor.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include <_stdio.h> + +void setCursorOffset(uint16_t offset) { + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (offset & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); +} + +void setCursorPosition(uint8_t x, uint8_t y) { + setCursorOffset(x + y * VIDEO_WIDTH); +} + +uint16_t getCursorOffset() { + uint16_t result = 0; + outb(0x3D4, 0x0F); + result |= inb(0x3D5); + outb(0x3D4, 0x0E); + result |= ((uint16_t)inb(0x3D5)) << 8; + return result; +} \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index d8ff7b8..48ea59f 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,19 +1,26 @@ #include -#include +#include <_stdio.h> #include #include #include #include #include +#include extern uint32_t _kernel_end; void kernelMain() { - initMemoryAllocation(0x100000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here + initMemoryAllocation(0x1000000); // initializing stacks after the kernel seems not to work :( otherwise, _kernel_end should be passed here initOSTasks(); drawLogo(); - printf("Switching to otherTask... \n"); + printf("giving up control...\n"); yields(); printf("Returned to mainTask!\n\n"); + printf("initializing interrupts\n"); + initInterrupts(); + yields(); + printf("trying interrupt\n"); + asm ("int $0x80"); + printf("the interrupt worked!\n"); yield(); } \ No newline at end of file diff --git a/src/kernel/lib/memory/alloc.c b/src/kernel/lib/memory/alloc.c deleted file mode 100644 index aedcbad..0000000 --- a/src/kernel/lib/memory/alloc.c +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include -#include - -MemoryBlock* firstBlock; - -void initMemoryAllocation(uint32_t kernelEnd) { - firstBlock = (MemoryBlock*) kernelEnd; - firstBlock->next = 0x00; - firstBlock->last = 0x00; - firstBlock->state = FREE; - firstBlock->size = -1; -} - -void* mallocTask(uint32_t size, Task* task) { - MemoryBlock* current = firstBlock; - while (! (current->next == 0x00 || current->state == FREE && current->size >= size)) { - current = current->next; - } - MemoryBlock* next; - if (current->next == 0x00) { - // this is currently the last block -> initialize the new last block - next = (MemoryBlock*) ((void*) (current + 1) + size); - next->last = current; - next->state = FREE; - next->next = 0x00; - next->size = -1; - } else { - // there is a next block - next = current->next; - } - if (current->size > size + sizeof(MemoryBlock) * 2 && current->next != 0x00) { - // segment the current block if it is big enough - current->next = (MemoryBlock*) (((void*) (current + 1)) + size); - current->next->size = current->size - sizeof(MemoryBlock) - size; - current->size = size; - current->next->state = FREE; - current->next->next = next; - next->last = current->next; - } else { - current->next = next; - if (current->next->next == 0x00) { - current->size = size; - } - } - current->state = IN_USE; - current->task = task; - return (void*) (current + 1); -} - -void* malloc(uint32_t size) { - return mallocTask(size, (Task*) getCurrentTask()); -} - -void mergeNextIfPossible(MemoryBlock* current) { - if (current->next != 0x00 && current->next->state == FREE) { - current->size = current->size + sizeof(MemoryBlock) + current->next->size; - current->next = current->next->next; - current->next->next->last = current; - } -} - -void free(void* location) { - MemoryBlock* current = ((MemoryBlock*) location) - 1; - current->state = FREE; - mergeNextIfPossible(current); - if (current->last != 0x00 && current->last->state == FREE) { - current = current->last; - } - mergeNextIfPossible(current); // call this function twice in case a used block between 2 free blocks is freed - mergeNextIfPossible(current); -} - -void printMemoryStack() { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); - current = current->next; - } - printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); -} - -void freeTaskAllocations(Task* task) { - MemoryBlock* current = firstBlock; - while (current->next != 0x00) { - if (current->task == task) { - free(current); - } - current = current->next; - } - if (current->task == task) { - free(current); - } -} \ No newline at end of file diff --git a/src/kernel/lib/ports.c b/src/kernel/lib/ports.c deleted file mode 100644 index 6cfbb2a..0000000 --- a/src/kernel/lib/ports.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include - -void outb(uint16_t port, uint8_t val) { - asm volatile("outb %0, %1" : : "a"(val), "Nd"(port) ); -} - -uint8_t inb(uint16_t port) { - uint8_t result; - __asm__("in %%dx, %%al" : "=a" (result) : "d" (port)); - return result; -} \ No newline at end of file diff --git a/src/kernel/lib/task/osTasks.c b/src/kernel/lib/task/osTasks.c deleted file mode 100644 index c3d6a43..0000000 --- a/src/kernel/lib/task/osTasks.c +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include -#include -#include - -Task mainTask; -Task printerTask; - -void printLoop() { - while (1) { - yield(); - Message* message = popMessage(&printerTask); - if (message == 0x00) { - continue; - } - putChars(message->data, message->size); - free(message->data); - free(message); - } -} - -void initOSTasks() { - setRunningTask(&mainTask); - createTask(&printerTask, (uint32_t) printLoop, 0x0, 0x0); - schedule(&printerTask); - // more tasks . . . - yields(); -} - -inline Task* getPrinterTask() { - return &printerTask; -} \ No newline at end of file diff --git a/src/kernel/lib/task/task.c b/src/kernel/lib/task/task.c deleted file mode 100644 index e4201c5..0000000 --- a/src/kernel/lib/task/task.c +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include -#include - -#define STACK_SIZE 0xF000 - -Task *currentTask; - -void createTask(Task *task, uint32_t mainFunction, uint32_t flags, uint32_t *pagedir) { - void* stack = mallocTask(STACK_SIZE, task); - task->registers.eax = 0; - task->registers.ebx = 0; - task->registers.ecx = 0; - task->registers.edx = 0; - task->registers.esi = 0; - task->registers.edi = 0; - task->registers.eflags = flags; - task->registers.eip = mainFunction; - task->registers.cr3 = (uint32_t) pagedir; - task->registers.esp = STACK_SIZE + (uint32_t) stack; - task->nextTask = 0; - task->stack = stack; -} - -void yield() { - Task* last = currentTask; - currentTask = currentTask->nextTask; - if (currentTask == 0x00) { - puts("No more tasks to run, halting . . .\n"); - while (1) { - asm("hlt"); - } - } - last->nextTask = 0x00; - switchTask(&(last->registers), &(currentTask->registers)); -} - -void schedule(Task* task) { - Task* test = currentTask; - while (test->nextTask != 0x0) { - test = test->nextTask; - if (test->nextTask == task) { - return; // don't schedule if the task is already in the queue - } - } - test->nextTask = task; -} - -void setRunningTask(Task* task) { - currentTask = task; -} - -void yields() { - schedule(currentTask); - yield(); -} - -void destroyCurrentTask() { - freeTaskAllocations(currentTask); - yield(); -} - -Task* getCurrentTask() { - return currentTask; -} - -void sendMessage(Task* task, Message* message) { - if (task->message == 0x00) { - task->message = message; - return; - } - Message* currentMessage = task->message; - while (currentMessage->next == 0x00) { - currentMessage = currentMessage->next; - } - currentMessage->next = message; -} - -Message* popMessage(Task* task) { - Message* currentMessage = task->message; - if (currentMessage != 0x00) { - task->message = currentMessage->next; - - } - return currentMessage; -} \ No newline at end of file diff --git a/src/kernel/lib/task/task.s b/src/kernel/lib/task/task.s deleted file mode 100644 index 88357cd..0000000 --- a/src/kernel/lib/task/task.s +++ /dev/null @@ -1,49 +0,0 @@ -.section .text -.global switchTask -switchTask: - pusha - pushf - mov %cr3, %eax #Push CR3 - push %eax - mov 44(%esp), %eax #The first argument, where to save - mov %ebx, 4(%eax) - mov %ecx, 8(%eax) - mov %edx, 12(%eax) - mov %esi, 16(%eax) - mov %edi, 20(%eax) - mov 36(%esp), %ebx #EAX - mov 40(%esp), %ecx #IP - mov 20(%esp), %edx #ESP - add $4, %edx #Remove the return value - mov 16(%esp), %esi #EBP - mov 4(%esp), %edi #EFLAGS - mov %ebx, (%eax) - mov %edx, 24(%eax) - mov %esi, 28(%eax) - mov %ecx, 32(%eax) - mov %edi, 36(%eax) - pop %ebx #CR3 - mov %ebx, 40(%eax) - push %ebx #Goodbye again - mov 48(%esp), %eax #Now it is the new object - mov 4(%eax), %ebx #EBX - mov 8(%eax), %ecx #ECX - mov 12(%eax), %edx #EDX - mov 16(%eax), %esi #ESI - mov 20(%eax), %edi #EDI - mov 28(%eax), %ebp #EBP - push %eax - mov 36(%eax), %eax #EFLAGS - push %eax - popf - pop %eax - mov 24(%eax), %esp #ESP - push %eax - mov 40(%eax), %eax #CR3 - mov %eax, %cr3 - pop %eax - push %eax - mov 32(%eax), %eax #EIP - xchg (%esp), %eax - mov (%eax), %eax #EAX - ret diff --git a/src/kernel/lib/textMode/cursor.c b/src/kernel/lib/textMode/cursor.c deleted file mode 100644 index e5cc8f9..0000000 --- a/src/kernel/lib/textMode/cursor.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include -#include - -void setCursorOffset(uint16_t offset) { - outb(0x3D4, 0x0F); - outb(0x3D5, (uint8_t) (offset & 0xFF)); - outb(0x3D4, 0x0E); - outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); -} - -void setCursorPosition(uint8_t x, uint8_t y) { - setCursorOffset(x + y * VIDEO_WIDTH); -} - -uint16_t getCursorOffset() { - uint16_t result = 0; - outb(0x3D4, 0x0F); - result |= inb(0x3D5); - outb(0x3D4, 0x0E); - result |= ((uint16_t)inb(0x3D5)) << 8; - return result; -} \ No newline at end of file diff --git a/src/kernel/lib/textMode/stdio.c b/src/kernel/lib/textMode/stdio.c deleted file mode 100644 index 5f1b3a0..0000000 --- a/src/kernel/lib/textMode/stdio.c +++ /dev/null @@ -1,200 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; -char format = 0x0F; - -void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { - *(framebuffer + position) = c; -} - -void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { - putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); -} - -void putCharAtOffset(char c, uint16_t offset) { - putCharWithFormatAtOffset(c | format << 8, offset); -} - -void putCharAt(char c, uint8_t x, uint8_t y) { - putCharAtOffset(c, (x + y * VIDEO_WIDTH)); -} - -uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { - return *(framebuffer + x + y * VIDEO_WIDTH); -} - -void putCharsAt(char* string, uint8_t x, uint8_t y) { - uint16_t position = 0; - char c = *string; - while (c != 0x00) { - putCharAt(c, x + position, y); - position++; - c = *(string + position); - } -} - -void shiftUp() { - for (int y = 1; y < VIDEO_HEIGHT; y++) { - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); - } - } - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); - } -} - -void newLine() { - uint16_t offset = getCursorOffset(); - uint8_t x = offset % VIDEO_WIDTH; - uint8_t y = offset / VIDEO_WIDTH; - x = 0; - y++; - if (y >= VIDEO_HEIGHT) { - shiftUp(); - y--; - } - setCursorPosition(x, y); -} - -void putChar(char c) { - if (c == '\n') { - newLine(); - return; - } - uint16_t offset = getCursorOffset(); - putCharAtOffset(c, offset); - setCursorOffset(offset + 1); -} - -void puts(char* string) { - while (*string != 0x00) { - putChar(*string); - string++; - } -} - -char HEX_PREFIX[] = "0x"; -char HEX_CHARS[] = "0123456789ABCDEF"; - -void putHex(char** write, uint32_t x) { - uint8_t alreadyWriting = 0; - for (uint8_t position = 3; position >= 0; position--) { - uint8_t byte = (x >> (position * 8)) & 0xFF; - if (byte != 0x00) { - alreadyWriting = 0x01; - } - if (alreadyWriting) { - **write = HEX_CHARS[byte % 256]; - *write++; - **write = HEX_CHARS[byte / 256]; - *write++; - } - } -} - -uint32_t getInsertLength(char insertType, uint32_t x) { - switch (insertType) - { - case 's': - return strlen((char*) x); - case 'x': - for (uint8_t position = 3; position >= 0; position--) { - uint8_t byte = (x >> (position * 8)) & 0xFF; - if (byte != 0x00) { - return 2*position; - } - } - return 0; - } - return 0; -} - -void handleInsert(char** write, char insertType, uint32_t x) { - if (insertType == 's') { - char* string = (char*) x; - uint32_t length = strlen(string); - for (uint32_t position = 0; position < length; position++) { - **write = string[position]; - *write++; - } - return; - } - if (insertType == 'x') { - putHex(write, x); - } -} - -void printf(const char* format, ...) { - uint32_t size = 0; - va_list valist; - va_start(valist, format); - for (int i = 0; format[i] != 0; i++) { - if (format[i] == '%') { - size += getInsertLength(format[++i], va_arg(valist, uint32_t)); - continue; - } - size++; - } - va_start(valist, format); - - char* data = malloc(size); - char* write = data; - for (int i = 0; format[i] != 0; i++) { - if (format[i] == '%') { - handleInsert(&write, format[++i], va_arg(valist, uint32_t)); - continue; - } - *write = format[i]; - write++; - } - va_end(valist); - - Message message = { - message.data = data, - message.size = size, - message.next = 0x00 - }; - sendMessage(getPrinterTask(), &message); - schedule(getPrinterTask()); - yields(); -} - -void clearScreen() { - setCursorOffset(0); - for (int y = 0; y < VIDEO_HEIGHT; y++) { - for (int x = 0; x < VIDEO_WIDTH; x++) { - putCharAt(' ', x, y); - } - } -} - -void setTextStyle(uint8_t style) { - format = style; -} - -void putChars(char* string, uint32_t length) { - for (uint32_t i = 0; i < length; i++) { - if (string[i] == '\n') { - newLine(); - continue; - } - putChar(string[i]); - } -} - -uint32_t strlen(char* string) { - uint32_t length = 0; - while (string[length] != 0) { - length++; - } - return length; -} \ No newline at end of file diff --git a/src/kernel/memory/alloc.c b/src/kernel/memory/alloc.c new file mode 100644 index 0000000..97d0a84 --- /dev/null +++ b/src/kernel/memory/alloc.c @@ -0,0 +1,94 @@ +#include +#include +#include <_stdio.h> + +MemoryBlock* firstBlock; + +void initMemoryAllocation(uint32_t kernelEnd) { + firstBlock = (MemoryBlock*) kernelEnd; + firstBlock->next = 0x00; + firstBlock->last = 0x00; + firstBlock->state = FREE; + firstBlock->size = -1; +} + +void* mallocTask(uint32_t size, Task* task) { + MemoryBlock* current = firstBlock; + while (! (current->next == 0x00 || current->state == FREE && current->size >= size)) { + current = current->next; + } + MemoryBlock* next; + if (current->next == 0x00) { + // this is currently the last block -> initialize the new last block + next = (MemoryBlock*) ((void*) (current + 1) + size); + next->last = current; + next->state = FREE; + next->next = 0x00; + next->size = -1; + } else { + // there is a next block + next = current->next; + } + if (current->size > size + sizeof(MemoryBlock) * 2 && current->next != 0x00) { + // segment the current block if it is big enough + current->next = (MemoryBlock*) (((void*) (current + 1)) + size); + current->next->size = current->size - sizeof(MemoryBlock) - size; + current->size = size; + current->next->state = FREE; + current->next->next = next; + next->last = current->next; + } else { + current->next = next; + if (current->next->next == 0x00) { + current->size = size; + } + } + current->state = IN_USE; + current->task = task; + return (void*) (current + 1); +} + +void* malloc(uint32_t size) { + return mallocTask(size, (Task*) getCurrentTask()); +} + +void mergeNextIfPossible(MemoryBlock* current) { + if (current->next != 0x00 && current->next->state == FREE) { + current->size = current->size + sizeof(MemoryBlock) + current->next->size; + current->next = current->next->next; + current->next->next->last = current; + } +} + +void free(void* location) { + MemoryBlock* current = ((MemoryBlock*) location) - 1; + current->state = FREE; + mergeNextIfPossible(current); + if (current->last != 0x00 && current->last->state == FREE) { + current = current->last; + } + mergeNextIfPossible(current); // call this function twice in case a used block between 2 free blocks is freed + mergeNextIfPossible(current); +} + +void printMemoryStack() { + MemoryBlock* current = firstBlock; + while (current->next != 0x00) { + printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); + current = current->next; + } + printf("AT: %x size: %x next: %x last: %x, state: %x\n", current, current->size, current->next, current->last, current->state); +} + +void freeTaskAllocations(Task* task) { + MemoryBlock* current = firstBlock; + while (current->next != 0x00) { + if (current->task == task) { + free(current); + } + current = current->next; + } + if (current->task == task) { + free(current); + } +} \ No newline at end of file diff --git a/src/kernel/task/osTasks.c b/src/kernel/task/osTasks.c new file mode 100644 index 0000000..5d52a79 --- /dev/null +++ b/src/kernel/task/osTasks.c @@ -0,0 +1,35 @@ +#include +#include +#include <_stdio.h> +#include +#include + +Task mainTask; +Task printerTask; + +void printLoop() { + clearScreen(); + setTextStyle(0x0F); + while (1) { + Message* message = popMessage(&printerTask); + if (message == 0) { + yield(); + continue; + } + putChars(message->data, message->size); + free(message->data); + free(message); + } +} + +void initOSTasks() { + setRunningTask(&mainTask); + createTask(&printerTask, (uint32_t) printLoop, 0x0, 0x0); + schedule(&printerTask); + // more tasks . . . + yields(); +} + +inline Task* getPrinterTask() { + return &printerTask; +} \ No newline at end of file diff --git a/src/kernel/task/task.c b/src/kernel/task/task.c new file mode 100644 index 0000000..4b93d2d --- /dev/null +++ b/src/kernel/task/task.c @@ -0,0 +1,86 @@ +#include +#include +#include <_stdio.h> + +#define STACK_SIZE 0x1000 + +Task *currentTask; + +void createTask(Task *task, uint32_t mainFunction, uint32_t flags, uint32_t *pagedir) { + void* stack = mallocTask(STACK_SIZE, task); + task->registers.eax = 0; + task->registers.ebx = 0; + task->registers.ecx = 0; + task->registers.edx = 0; + task->registers.esi = 0; + task->registers.edi = 0; + task->registers.eflags = flags; + task->registers.eip = mainFunction; + task->registers.cr3 = (uint32_t) pagedir; + task->registers.esp = STACK_SIZE + (uint32_t) stack; + task->nextTask = 0; + task->stack = stack; +} + +void yield() { + Task* last = currentTask; + currentTask = last->nextTask; + if (currentTask == 0x00) { + puts("No more tasks to run, halting . . .\n"); + asm("hlt"); + } + last->nextTask = 0x00; + switchTask(&(last->registers), &(currentTask->registers)); +} + +void schedule(Task* task) { + Task* test = currentTask; + while (test->nextTask != 0x0) { + if (test->nextTask == task) { + return; // don't schedule if the task is already in the queue + } + test = test->nextTask; + } + if (test->nextTask == task) { + return; + } + test->nextTask = task; +} + +void setRunningTask(Task* task) { + currentTask = task; +} + +void yields() { + schedule(currentTask); + yield(); +} + +void destroyCurrentTask() { + freeTaskAllocations(currentTask); + yield(); +} + +Task* getCurrentTask() { + return currentTask; +} + +void sendMessage(Task* task, Message* message) { + Message* currentMessage = task->message; + if (currentMessage == 0) { + task->message = message; + return; + } + while (currentMessage->next != 0) { + currentMessage = currentMessage->next; + } + currentMessage->next = message; +} + +Message* popMessage(Task* task) { + Message* currentMessage = task->message; + if (currentMessage != 0) { + task->message = currentMessage->next; + } + return currentMessage; +} \ No newline at end of file diff --git a/src/kernel/task/task.s b/src/kernel/task/task.s new file mode 100644 index 0000000..88357cd --- /dev/null +++ b/src/kernel/task/task.s @@ -0,0 +1,49 @@ +.section .text +.global switchTask +switchTask: + pusha + pushf + mov %cr3, %eax #Push CR3 + push %eax + mov 44(%esp), %eax #The first argument, where to save + mov %ebx, 4(%eax) + mov %ecx, 8(%eax) + mov %edx, 12(%eax) + mov %esi, 16(%eax) + mov %edi, 20(%eax) + mov 36(%esp), %ebx #EAX + mov 40(%esp), %ecx #IP + mov 20(%esp), %edx #ESP + add $4, %edx #Remove the return value + mov 16(%esp), %esi #EBP + mov 4(%esp), %edi #EFLAGS + mov %ebx, (%eax) + mov %edx, 24(%eax) + mov %esi, 28(%eax) + mov %ecx, 32(%eax) + mov %edi, 36(%eax) + pop %ebx #CR3 + mov %ebx, 40(%eax) + push %ebx #Goodbye again + mov 48(%esp), %eax #Now it is the new object + mov 4(%eax), %ebx #EBX + mov 8(%eax), %ecx #ECX + mov 12(%eax), %edx #EDX + mov 16(%eax), %esi #ESI + mov 20(%eax), %edi #EDI + mov 28(%eax), %ebp #EBP + push %eax + mov 36(%eax), %eax #EFLAGS + push %eax + popf + pop %eax + mov 24(%eax), %esp #ESP + push %eax + mov 40(%eax), %eax #CR3 + mov %eax, %cr3 + pop %eax + push %eax + mov 32(%eax), %eax #EIP + xchg (%esp), %eax + mov (%eax), %eax #EAX + ret diff --git a/src/kernel/textMode/_stdio.c b/src/kernel/textMode/_stdio.c new file mode 100644 index 0000000..fcecf6f --- /dev/null +++ b/src/kernel/textMode/_stdio.c @@ -0,0 +1,199 @@ +#include +#include +#include <_stdio.h> +#include +#include +#include +#include +#include +#include + +uint16_t* framebuffer = (uint16_t*) FRAMEBUFFER_LOCATION; +char format = 0x0F; + +void putCharWithFormatAtOffset(uint16_t c, uint16_t position) { + *(framebuffer + position) = c; +} + +void putCharWithFormatAtPosition(uint8_t x, uint8_t y, uint32_t c) { + putCharWithFormatAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +void putCharAtOffset(char c, uint16_t offset) { + putCharWithFormatAtOffset(c | format << 8, offset); +} + +void putCharAt(char c, uint8_t x, uint8_t y) { + putCharAtOffset(c, (x + y * VIDEO_WIDTH)); +} + +uint16_t getCharWithFormatAt(uint8_t x, uint8_t y) { + return *(framebuffer + x + y * VIDEO_WIDTH); +} + +void putCharsAt(char* string, uint8_t x, uint8_t y) { + uint16_t position = 0; + char c = *string; + while (c != 0x00) { + putCharAt(c, x + position, y); + position++; + c = *(string + position); + } +} + +void shiftUp() { + for (int y = 1; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, y-1, getCharWithFormatAt(x, y)); + } + } + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharWithFormatAtPosition(x, VIDEO_HEIGHT-1, 0x00); + } +} + +void newLine() { + uint16_t offset = getCursorOffset(); + uint8_t x = offset % VIDEO_WIDTH; + uint8_t y = offset / VIDEO_WIDTH; + x = 0; + y++; + if (y >= VIDEO_HEIGHT) { + shiftUp(); + y--; + } + setCursorPosition(x, y); +} + +void putChar(char c) { + if (c == '\n') { + newLine(); + return; + } + uint16_t offset = getCursorOffset(); + putCharAtOffset(c, offset); + setCursorOffset(offset + 1); +} + +void puts(char* string) { + while (*string != 0x00) { + putChar(*string); + string++; + } +} + +char HEX_PREFIX[] = "0x"; +char HEX_CHARS[] = "0123456789ABCDEF"; + +void putHex(char** write, uint32_t x) { + uint8_t alreadyWriting = 0; + for (uint8_t position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + alreadyWriting = 0x01; + } + if (alreadyWriting) { + **write = HEX_CHARS[byte % 256]; + *write++; + **write = HEX_CHARS[byte / 256]; + *write++; + } + } +} + +uint32_t getInsertLength(char insertType, uint32_t x) { + switch (insertType) + { + case 's': + return strlen((char*) x); + case 'x': + for (uint8_t position = 3; position >= 0; position--) { + uint8_t byte = (x >> (position * 8)) & 0xFF; + if (byte != 0x00) { + return 2*position; + } + } + return 0; + } + return 0; +} + +void handleInsert(char** write, char insertType, uint32_t x) { + if (insertType == 's') { + char* string = (char*) x; + uint32_t length = strlen(string); + for (uint32_t position = 0; position < length; position++) { + **write = string[position]; + *write++; + } + return; + } + if (insertType == 'x') { + putHex(write, x); + } +} + +void printf(const char* format, ...) { + uint32_t size = 0; + va_list valist; + va_start(valist, format); + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + size += getInsertLength(format[++i], va_arg(valist, uint32_t)); + continue; + } + size++; + } + va_start(valist, format); + + char* data = malloc(size); + char* write = data; + for (int i = 0; format[i] != 0; i++) { + if (format[i] == '%') { + handleInsert(&write, format[++i], va_arg(valist, uint32_t)); + continue; + } + *write = format[i]; + write++; + } + va_end(valist); + + Message* message = malloc(sizeof(Message)); + + message->data = data; + message->size = size; + message->next = 0x00; + sendMessage(getPrinterTask(), message); + schedule(getPrinterTask()); +} + +void clearScreen() { + setCursorOffset(0); + for (int y = 0; y < VIDEO_HEIGHT; y++) { + for (int x = 0; x < VIDEO_WIDTH; x++) { + putCharAt(' ', x, y); + } + } +} + +void setTextStyle(uint8_t style) { + format = style; +} + +void putChars(char* string, uint32_t length) { + for (uint32_t i = 0; i < length; i++) { + if (string[i] == '\n') { + newLine(); + continue; + } + putChar(string[i]); + } +} + +uint32_t strlen(char* string) { + uint32_t length = 0; + while (string[length] != 0) { + length++; + } + return length; +} \ No newline at end of file diff --git a/src/kernel/textMode/cursor.c b/src/kernel/textMode/cursor.c new file mode 100644 index 0000000..8247c5e --- /dev/null +++ b/src/kernel/textMode/cursor.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include <_stdio.h> + +void setCursorOffset(uint16_t offset) { + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (offset & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((offset >> 8) & 0xFF)); +} + +void setCursorPosition(uint8_t x, uint8_t y) { + setCursorOffset(x + y * VIDEO_WIDTH); +} + +uint16_t getCursorOffset() { + uint16_t result = 0; + outb(0x3D4, 0x0F); + result |= inb(0x3D5); + outb(0x3D4, 0x0E); + result |= ((uint16_t)inb(0x3D5)) << 8; + return result; +} \ No newline at end of file diff --git a/src/kernel/tree-os.c b/src/kernel/tree-os.c deleted file mode 100644 index 913bb93..0000000 --- a/src/kernel/tree-os.c +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include - -const char* logo = "\ - _______ \n\ -|__ __| \n\ - | |_ __ ___ ___ ___ ___ \n\ - | | '__/ _ \\/ _ \\ / _ \\/ __| \n\ - | | | | __/ __/ | (_) \\__ \\ \n\ - |_|_| \\___|\\___| \\___/|___/ \n\n"; - -void drawLogo() { - clearScreen(); - setTextStyle(0x0F); - printf(logo); - printf("TREE-OS v. alpha 0.1 (IN DEVELOPMENT)\n\n"); -} \ No newline at end of file diff --git a/src/kernel/util/ports.c b/src/kernel/util/ports.c new file mode 100644 index 0000000..6cfbb2a --- /dev/null +++ b/src/kernel/util/ports.c @@ -0,0 +1,12 @@ +#include +#include + +void outb(uint16_t port, uint8_t val) { + asm volatile("outb %0, %1" : : "a"(val), "Nd"(port) ); +} + +uint8_t inb(uint16_t port) { + uint8_t result; + __asm__("in %%dx, %%al" : "=a" (result) : "d" (port)); + return result; +} \ No newline at end of file diff --git a/src/kernel/util/tree-os.c b/src/kernel/util/tree-os.c new file mode 100644 index 0000000..681c1e0 --- /dev/null +++ b/src/kernel/util/tree-os.c @@ -0,0 +1,15 @@ +#include +#include <_stdio.h> + +const char* logo = "\ + _______ \n\ +|__ __| \n\ + | |_ __ ___ ___ ___ ___ \n\ + | | '__/ _ \\/ _ \\ / _ \\/ __| \n\ + | | | | __/ __/ | (_) \\__ \\ \n\ + |_|_| \\___|\\___| \\___/|___/ \n\n"; + +void drawLogo() { + printf(logo); + printf("TREE-OS v. alpha 0.1 (IN DEVELOPMENT)\n\n"); +} \ No newline at end of file