Files
kern/src/kernel.c
T

373 lines
12 KiB
C

#include "screen.h"
#include "idt.h"
#include "isrs.h"
#include "irq.h"
#include "keyboard.h"
#include "timer.h"
#include "system.h"
#include "disk.h"
#include "string.h"
#include "graphics.h"
#include "physicalMemManager.h" // TODO: Name this better
#define PROMPT "#> "
char* filetable = (char*)0x7000; // Pretty sure we don't have to care about the bootloader at 0x7c00
uint32_t memmapAddr = 0x30000;
// Function declarations
void printFiletable(char* ft);
void printPhysicalMemmap();
__attribute__ ((section ("entry"))) // Make sure that main() is at the start of kernel.bin
void main() {
// Interrupts
setupIdt();
setupIsrs();
setupIrqs();
sti();
setupKeyboard();
setupTimer();
timerPhase(1000); // 1 tick per ~1ms
// Memory manager setup
uint32_t smapEntryCount = *(uint32_t*)0x8500;
smapEntry_t* smapEntries = (smapEntry_t*)0x8504;
uint32_t totalMemory = smapEntries[smapEntryCount - 1].baseAddress + smapEntries[smapEntryCount - 1].length - 1;
setupMemoryManager(memmapAddr, totalMemory);
for (uint32_t i = 0; i < smapEntryCount; i++) {
if (smapEntries[i].type == 1) {
initMemoryRegion(smapEntries[i].baseAddress, smapEntries[i].length);
}
}
deinitMemoryRegion(0x1000, 0x9000); // Reserve kernel memory (under 0xa000)
deinitMemoryRegion(memmapAddr, maxBlocks / BLOCKS_PER_BYTE);
// Screen setup
// TODO: Find font in filetable
diskRead(36, 4, (char*)0x6000); // Read font from disk
// loadFont((char*)0x6000);
clear();
print("kern.\n\n");
diskRead(5, 1, filetable); // Read the filetable and store it in memory
// Run Interactive Shell Program
// TODO: Make it in another file
while (1) {
print(PROMPT);
char* input = read('\n');
if (input[0] == '\n') continue;
char* args;
if ((args = strchr(input, ' ')) == NULL) {
args = strchr(input, '\n');
}
*args++ = '\0'; // Separate command from args
if (strcmp(input, "clear") == 0) {
clear();
} else if (strcmp(input, "disk") == 0) {
char buf[512] = { 0 };
if (*args == '\0') {
print("disk: ");
print("No arguments given\n");
print("Usage: disk <r/w> <sector> [data]\n");
continue;
}
while (isSpace(*args)) { args++; } // Skip whitespace
char mode = *args++;
while (isSpace(*args)) { args++; }
if (mode == 'r') {
if (*args == '\0') {
print("disk: ");
print("Sector not specified\n");
print("Usage: disk <r/w> <sector> [data]\n");
continue;
}
uint32_t sector = atoi(args);
print("Reading...\n");
diskRead(sector, 1, buf);
print("Contents:\n");
for (size_t i = 0; i < 512; i++) {
if (buf[i] != '\0') {
putc(buf[i]);
}
}
putc('\n');
} else if (mode == 'w') {
char* data;
if ((data = strchr(args, ' ')) == NULL) {
print("disk: ");
print("No data given\n");
print("Usage: disk <r/w> <sector> [data]\n");
continue;
}
*data++ = '\0';
uint32_t sector = atoi(args);
while (isSpace(*args)) { args++; } // Skip whitespace
strcpy(buf, data);
print("Writing...\n");
diskWrite(sector, 1, buf);
} else {
print("disk: ");
print("Invalid access mode. Use r(ead) or w(rite)\n");
print("Usage: disk <r/w> <sector> [data]\n");
continue;
}
} else if (strcmp(input, "echo") == 0) {
print(args);
} else if (strcmp(input, "exit") == 0) {
break;
} else if (strcmp(input, "gfx") == 0) {
clear();
// Draw some stuff :)
for (size_t i = 0; i < 120; i++) {
for (size_t j = 0; j < 120; j++) {
drawPixel(200 + i, 200 + j, GREEN);
}
}
fillRect(200, 200, 320, 320, GREEN);
drawLine(200, 200, 320, 320, RED);
drawLine(320, 200, 200, 320, RED);
drawLine(800, 300, 900, 400, BLUE);
drawLine(900, 400, 1000, 300, BLUE);
drawLine(1000, 300, 900, 200, BLUE);
drawLine(900, 200, 800, 300, BLUE);
drawLine(400, 350, 420, 100, rgb(0xee, 0x9f, 0x00));
drawTriangle(200, 400, 400, 600, 200, 600, MAGENTA);
fillTriangle(750, 400, 800, 450, 700, 450, CYAN);
drawTriangle(960, 400, 1000, 500, 990, 580, YELLOW);
drawRect(100, 650, 800, 900, rgb(0xe0, 0x0a, 0x3a));
drawCircle(1500, 600, 300, WHITE);
fillCircle(950, 750, 75, rgb(0xa2, 0xd6, 0xf9));
read('q'); // Wait until we get a 'q'
clear();
} else if (strcmp(input, "help") == 0) {
print("Available Commands:\n");
print(" clear | Clears the screen\n");
print(" disk | Reads/Writes data from/to the disk\n");
print(" echo | Prints a message to stdout\n");
print(" exit | Exits shell\n");
print(" gfx | Does a graphics test\n");
print(" help | Prints this message\n");
print(" ls | Lists all available files\n");
print(" memmap | Prints the memory map and info\n");
print(" reboot | Reboots the system\n");
print(" test | Performs tests\n");
} else if (strcmp(input, "ls") == 0) {
printFiletable(filetable);
} else if (strcmp(input, "memmap") == 0) {
printPhysicalMemmap();
} else if (strcmp(input, "reboot") == 0) {
outb(0x64, 0xFE);
} else if (strcmp(input, "test") == 0) {
print("Running Tests...\n");
uint8_t buf[512];
print("Read Test .......... ");
diskRead(0, 1, (char*)buf);
if (buf[510] == 0x55 && buf[511] == 0xaa) {
print("[ DONE ]\n");
} else {
print("[ FAIL ]\n");
}
print("Write Test ......... ");
buf[510] = 0x55; buf[511] = 0xaa;
diskWrite(0, 1, (char*)buf);
diskRead(0, 1, (char*)buf); // Idk how else to test if the right data was written (also could break the bootloader if it fails)
if (buf[510] == 0x55 && buf[511] == 0xaa) {
print("[ DONE ]\n");
} else {
print("[ FAIL ]\n");
}
print("Tests Finished!\n");
} else {
char* ft = filetable;
uint8_t found = 0;
while (*ft != '\0') {
char filename[15] = { 0 };
uint8_t offset = 0;
for (uint8_t i = 0; i < 14; i++) {
if (i == 9) {
filename[offset++] = '.';
continue;
}
if (*ft != '\0') { filename[offset++] = *ft; }
ft++;
}
if (strcmp(input, filename) == 0) {
ft++; // RESERVED
uint8_t sector = *ft++;
uint8_t size = *ft++;
found++; // Set found to 1
char* fileType = strchr(filename, '.') + 1;
uint32_t neededBlocks = (size * 512) / BLOCK_SIZE + 1;
/* Debug printing
print("Allocating ");
print(itoa(neededBlocks, 10));
print(" Block");
if (neededBlocks > 1) putc('s');
*/
char* address = allocBlocks(neededBlocks);
if (address == NULL) {
print("\nNot enough memory to allocate!\n");
break;
}
/* Debug printing
print("\nAllocated to address 0x");
print(itoa((uint32_t)address, 16));
print("!\n");
*/
diskRead(sector, size, address);
if (strcmp(fileType, "bin") == 0) {
clear();
((void(*)(void))address)(); // Call program
clear();
} else if (strcmp(fileType, "tab") == 0) {
printFiletable(address);
} else {
for (size_t i = 0; i < size * 512; i++) {
if (address[i] != '\0') {
putc(address[i]);
}
}
putc('\n');
}
// Debug printing
// print("Freeing allocated memory...\n");
freeBlocks(address, neededBlocks);
// print("Done!\n");
break;
}
ft += 3;
}
if (!found) {
print("Command not found: ");
print(input);
putc('\n');
}
}
}
}
void printFiletable(char* ft) {
while (*ft != '\0') {
char filename[15] = { 0 };
uint8_t offset = 0;
for (uint8_t i = 0; i < 14; i++) {
if (i == 9) {
filename[offset++] = '.';
continue;
}
if (*ft != '\0') { filename[offset++] = *ft; }
ft++;
}
ft++; // RESERVED
uint8_t sector = *ft++;
uint8_t size = *ft++;
if (sector < 10) putc('0');
if (sector == 0) putc('0');
else print(itoa(sector, 10));
print(": ");
print(filename);
for (uint8_t i = 14 - strlen(filename); i > 0; i--) {
putc(' ');
}
print(" | ");
if (size >> 1) {
print(itoa(size >> 1, 10));
if (size & 0x01) { print(".5"); }
print("kB\n");
} else {
print(itoa(size*512, 10));
print("B\n");
}
}
}
void printPhysicalMemmap() {
uint32_t entryCount = *(uint32_t*)SMAP_ADDRESS;
smapEntry_t* smapEntry = (smapEntry_t*)(SMAP_ADDRESS+4);
for (uint32_t i = 0; i < entryCount; i++) {
print("Region ");
print(itoa(i, 10));
print(" - base: 0x");
print(itoa(smapEntry->baseAddress, 16));
print(" length: 0x");
print(itoa(smapEntry->length, 16));
print(" type: ");
print(itoa(smapEntry->type, 10));
switch (smapEntry->type) {
case 1: print(" (Available)"); break;
case 2: print(" (Reserved)"); break;
case 3: print(" (ACPI Reclaim)"); break;
case 4: print(" (ACPI NVS)"); break;
default: print(" (Reserved)"); break;
}
putc('\n');
smapEntry++;
}
smapEntry--; // We incremented it after the last entry
print("\nTotal memory: 0x");
print(itoa(smapEntry->baseAddress + smapEntry->length - 1, 16));
print(" Bytes\n");
print("Total 4kB Blocks: ");
print(itoa(maxBlocks, 10));
print("\nUsed or reserved blocks: ");
print(itoa(usedBlocks, 10));
print("\nFree blocks: ");
print(itoa(maxBlocks - usedBlocks, 10));
print("\n\n");
}