diff --git a/.gdbinit b/.gdbinit new file mode 100644 index 0000000..283cb0c --- /dev/null +++ b/.gdbinit @@ -0,0 +1,7 @@ +target remote localhost:1234 + +file root/boot/myos.bin +symbol-file kernel.sym + +break prekernel/prekernel.cpp:18 +continue \ No newline at end of file diff --git a/.gitattributes b/.gitattributes index 12b0908..b2a7b41 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,4 @@ *.pdf filter=lfs diff=lfs merge=lfs -text *.png filter=lfs diff=lfs merge=lfs -text *.svg filter=lfs diff=lfs merge=lfs -text +demodisk.img filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore index c795b05..daf06ba 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,15 @@ -build \ No newline at end of file +build/ +bin/ +.vscode/ +.idea/ +isodir/ +root/ +*.iso +*.img +*.sym +*.o +*.a + + +/CoreLib/warnings.log +/kernel/warnings.log diff --git a/CoreLib/List.h b/CoreLib/List.h new file mode 100644 index 0000000..8d11e3b --- /dev/null +++ b/CoreLib/List.h @@ -0,0 +1,12 @@ +// +// Created by nigel on 25/02/23. +// +#pragma once + + +class List { +public: + List* next; + void* data; +}; + diff --git a/CoreLib/Makefile b/CoreLib/Makefile new file mode 100644 index 0000000..19b06ef --- /dev/null +++ b/CoreLib/Makefile @@ -0,0 +1,35 @@ +CPP = /opt/cross/bin/i686-elf-g++ +CFLAGS = -ffreestanding -Og -ggdb -Wall -Wextra + +BUILD_DIR = ../build/CoreLib +OBJ_FOLDER = ../bin/CoreLib +OUTPUTFILE = $(BUILD_DIR)/libCoreLib.a + +OFILES = $(OBJ_FOLDER)/ctype.o $(OBJ_FOLDER)/memory.o $(OBJ_FOLDER)/path.o $(OBJ_FOLDER)/stack.o $(OBJ_FOLDER)/string.o $(OBJ_FOLDER)/stringview.o + +.phony: all +all: $(OUTPUTFILE) + cp *.h $(BUILD_DIR)/include/CoreLib + +$(OUTPUTFILE): $(OFILES) + pwd + ar -rc $(OUTPUTFILE) $(OFILES) + +$(OBJ_FOLDER)/ctype.o: ctype.cpp + $(CPP) -c ctype.cpp -o $(OBJ_FOLDER)/ctype.o $(CFLAGS) + +$(OBJ_FOLDER)/memory.o: Memory.cpp + $(CPP) -c Memory.cpp -o $(OBJ_FOLDER)/memory.o $(CFLAGS) + +$(OBJ_FOLDER)/path.o: Path.cpp + $(CPP) -c Path.cpp -o $(OBJ_FOLDER)/path.o $(CFLAGS) + +$(OBJ_FOLDER)/stack.o: Stack.cpp + $(CPP) -c Stack.cpp -o $(OBJ_FOLDER)/stack.o $(CFLAGS) + +$(OBJ_FOLDER)/string.o: String.cpp + $(CPP) -c String.cpp -o $(OBJ_FOLDER)/string.o $(CFLAGS) + +$(OBJ_FOLDER)/stringview.o: StringView.cpp + $(CPP) -c StringView.cpp -o $(OBJ_FOLDER)/stringview.o $(CFLAGS) + diff --git a/CoreLib/Memory.cpp b/CoreLib/Memory.cpp new file mode 100644 index 0000000..155dba1 --- /dev/null +++ b/CoreLib/Memory.cpp @@ -0,0 +1,107 @@ +// +// Created by nigel on 19/02/23. +// +#include "Memory.h" + +void* memset (void* ptr, int value, size_t num) +{ + for( int i = 0; i < num; i++ ) + { + unsigned char* data = (unsigned char*)ptr+ i; + *data = (unsigned char)value; + } + return ptr; +} + + +int memcmp( const void* ptr1, const void* ptr2, size_t num) +{ + auto* cs = (const unsigned char*) ptr1; + auto* ct = (const unsigned char*) ptr2; + + + for (int i = 0 ; i < num ; i++, cs++, ct++ ){ + if( *cs != *ct) + return *cs - *ct; + + } + + return 0; + +} + +[[maybe_unused]] void memcpy (void* dest, const void* src, size_t count ){ + for( int i = 0; i < count; i++){ + ((char *)dest)[i] = ((const char*)src)[i]; + } +} + + + + + + +size_t strlen(const char* str) { + size_t len = 0; + while(str[len]){ + len++; + } + return len; +} + +int strncmp ( const char* str1, const char* str2, size_t num ){ + for( int i = 0; i < num ; i++){ + + if( str1[i] < str2[i]){ + return -1; + } + + if( str1[i] > str2[i] ){ + return 1; + } + + + } + + return 0; +} + +char* strchr(const char* s , int c){ + while(*s) { + if(*s == c) return const_cast(s); + s++; + } + return NULL; +} +char* strtok(char* str, const char* delim , char**saveptr){ + char *begin; + if(str) { + begin = str; + } + else if (*saveptr) { + begin = *saveptr; + } + else { + return NULL; + } + + while(strchr(delim, begin[0])) { + begin++; + } + + + char *next = NULL; + for(int i = 0; i < strlen(delim); i++) { + char *temp = strchr(begin, delim[i]); + if(temp < next || next == NULL) { + next = temp; + } + } + if(!next) { + *saveptr = NULL; + return begin; + } + *next = 0; + *saveptr=next+1; + return begin; +} \ No newline at end of file diff --git a/CoreLib/Memory.h b/CoreLib/Memory.h new file mode 100644 index 0000000..7482d65 --- /dev/null +++ b/CoreLib/Memory.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include + +void* memset (void* ptr, int value, size_t num); + +int memcmp( const void* ptr1, const void* ptr2, size_t num); + +[[maybe_unused]] void memcpy (void* dest, const void* src, size_t count ); + +size_t strlen(const char* str); + +int strncmp ( const char* str1, const char* str2, size_t num ); + +char* strtok(char* str, const char* delim , char**saveptr); \ No newline at end of file diff --git a/CoreLib/Path.cpp b/CoreLib/Path.cpp new file mode 100644 index 0000000..d23b226 --- /dev/null +++ b/CoreLib/Path.cpp @@ -0,0 +1,24 @@ +// +// Created by nigel on 19/02/23. +// +#include "Path.h" + +Path::Path(String path) +: path(path) +{ + +} + +StringView Path::getbasename() +{ + unsigned int path_length = path.length(); + int i = path_length; + while (path[i] != '/') + i--; + + return {path,static_cast(i +1), path_length}; +} + +char* Path::str() { + return path.str(); +} \ No newline at end of file diff --git a/CoreLib/Path.h b/CoreLib/Path.h new file mode 100644 index 0000000..ec4d955 --- /dev/null +++ b/CoreLib/Path.h @@ -0,0 +1,22 @@ +// +// Created by nigel on 19/02/23. +// +#pragma once +#include +#include "StringView.h" + + +class Path{ +public: + explicit Path(String path); + + StringView getbasename(); + + char* str(); + +private: + String path; + +}; + + diff --git a/CoreLib/Stack.cpp b/CoreLib/Stack.cpp new file mode 100644 index 0000000..af9520e --- /dev/null +++ b/CoreLib/Stack.cpp @@ -0,0 +1,3 @@ +// +// Created by nigel on 19/02/23. +// diff --git a/CoreLib/Stack.h b/CoreLib/Stack.h new file mode 100644 index 0000000..b363fed --- /dev/null +++ b/CoreLib/Stack.h @@ -0,0 +1,73 @@ +#pragma once +#include "../kernel/memory/KernelHeap.h" +#include + +template +class Stack { + public: + inline Stack() { + elements = (T[MAX_STACK_SIZE]) malloc(MAX_STACK_SIZE * sizeof(T)); + num = 0; + + } + + inline void Push(T element){ + num++; + if(num > MAX_STACK_SIZE) + grow(); + + element[num] = element; + } + + + inline T Pop() + { + T temp = elements[num]; + num --; + + return temp; + } + + inline bool isEmpty() + { + return num == 0; + } + + inline bool isFull() + { + return num == MAX_STACK_SIZE; + } + + + inline int count() + { + return num; + } + + inline ~Stack() + { + free(elements); + } + + + private: + unsigned int MAX_STACK_SIZE; + T[MAX_STACK_SIZE] elements; + unsigned int num; + + inline void grow (){ + MAX_STACK_SIZE = MAX_STACK_SIZE + (int)(MAX_STACK_SIZE / 4); + T[] new_elements =(T[MAX_STACK_SIZE]) malloc(MAX_STACK_SIZE * sizeof(T)); + + for ( int i = 0; i < num ; i++){ + new_elements[i] = elements[i]; + } + free(elements); + elements = new_elements; + + } + + + +}; + diff --git a/CoreLib/String.cpp b/CoreLib/String.cpp new file mode 100644 index 0000000..1aaf064 --- /dev/null +++ b/CoreLib/String.cpp @@ -0,0 +1,39 @@ +#include "String.h" +#include +#include + + +String::String(char* characters) +: chars(characters) + { + + } + +char* String::str(){ + return chars; +} + +unsigned int String::length () +{ + int i = 0; + + while ( chars[i] != '\0'){ + i++; + } + + return i; +} + +// Returns a null character if size exceeds limits +char String::operator[] (size_t idx) +{ + if( idx > this->length()) + return '\0'; + + return chars[idx]; +} + +const char String::operator[](size_t idx) const { +return (const char) chars[idx]; +} + diff --git a/CoreLib/String.h b/CoreLib/String.h new file mode 100644 index 0000000..8ff3f05 --- /dev/null +++ b/CoreLib/String.h @@ -0,0 +1,18 @@ +#pragma once +#include + +class String { +public: + String(char* characters); + String(String&) = default; + unsigned int length(); + + char* str (); + char operator[](size_t index) ; + const char operator[](size_t idx) const; + +protected: + char* chars; + + +}; \ No newline at end of file diff --git a/CoreLib/StringView.cpp b/CoreLib/StringView.cpp new file mode 100644 index 0000000..5392c87 --- /dev/null +++ b/CoreLib/StringView.cpp @@ -0,0 +1,14 @@ +// +// Created by nigel on 19/02/23. +// +#include "StringView.h" + +StringView::StringView(String string, unsigned int start, unsigned int end) + : String(string), begin(start), end(end) +{ + +} + +char* StringView::str(){ + //TODO: Not implemented +} \ No newline at end of file diff --git a/CoreLib/StringView.h b/CoreLib/StringView.h new file mode 100644 index 0000000..725284b --- /dev/null +++ b/CoreLib/StringView.h @@ -0,0 +1,14 @@ +// +// Created by nigel on 19/02/23. +// +#pragma once +#include "String.h" + +class StringView : String { +public: + StringView(String string, unsigned int start, unsigned int end ); + char* str (); +private: + unsigned int begin; + unsigned int end; +}; diff --git a/CoreLib/ctype.cpp b/CoreLib/ctype.cpp new file mode 100644 index 0000000..13e9cde --- /dev/null +++ b/CoreLib/ctype.cpp @@ -0,0 +1,141 @@ +// +// Created by nigel on 25/02/23. +// +#include "ctype.h" + +int isupper (int ch){ + if( ch >= 'A' && ch <= 'Z'){ + return 1; + } + return 0; +} +int islower (int ch){ + if(ch >= 'a' && ch <= 'z'){ + return 1; + } + return 0; +} + +int isalpha (int ch) { + if(isupper(ch)){ + return 1; + } + if(islower(ch)){ + return 1; + } + return 0; +} +int isdigit (int ch){ + if(ch >= '0' && ch <= '9'){ + return 1; + } + return 0; +} + +int isxdigit (int ch){ + if(isdigit(ch)){ + return 1; + } + + if( ch >= 'a' && ch <= 'f'){ + return 1; + } + + if( ch >= 'A' && ch <= 'F'){ + return 1; + } + return 0; +} + +int iscntrl (int ch){ + if(ch >= 0x00 && ch <= 0x1f ) + return 1; + if(ch == 0x7f) + return 1; + return 0; +} + + +int isgraph (int ch){ + if(isdigit(ch)) + return 1; + if(isupper(ch)) + return 1; + if(islower(ch)) + return 1; + if(ispunct(ch)) + return 1; + return 0; +} + +int isspace(int ch){ + if (ch == 0x20) + return 1; + if(ch == 0x0c) + return 1; + if(ch == 0x0a) + return 1; + if(ch == 0x0d) + return 1; + if(ch == 0x09) + return 1; + if(ch == 0x0b) + return 1; + + return 0; +} + +int isblank (int ch){ + if( ch == 0x20 || ch == 0x09) + return 1; + return 0; +} + +int ispunct(int ch){ + if(ch >= '!' && ch <= '~') + return 1; + return 0; +} + +int isprint (int ch){ + if (isdigit(ch)) + return 1; + if(isupper(ch)) + return 1; + if(islower(ch)) + return 1; + if(ispunct(ch)) + return 1; + if(isspace(ch)) + return 1; + return 0; +} + + +int tolower(int ch){ + + if(islower(ch)) return ch; + int diff = 'a' - 'A'; + return ch + diff; +} + +int toupper(int ch){ + if(isupper(ch)) return ch; + int diff = 'a' - 'A'; + return ch - diff; +} + + + +int isalnum (int ch){ + if(isdigit(ch)){ + return 1; + } + + if(isalpha(ch)){ + return 1; + } + + return 0; + +} \ No newline at end of file diff --git a/CoreLib/ctype.h b/CoreLib/ctype.h new file mode 100644 index 0000000..43262d6 --- /dev/null +++ b/CoreLib/ctype.h @@ -0,0 +1,21 @@ +// +// Created by nigel on 25/02/23. +// +#pragma once + +//NOTE: Uses default locale +int isupper (int ch); +int islower (int ch); +int isalpha (int ch); +int isdigit (int ch); +int isxdigit (int ch); +int iscntrl (int ch); +int isgraph(int ch); +int isspace(int ch); +int isblank(int ch); +int ispunct(int ch); +int isprint(int ch); +int isalnum (int ch); +int tolower(int ch); +int toupper(int ch); + diff --git a/Makefile b/Makefile deleted file mode 100644 index 4611669..0000000 --- a/Makefile +++ /dev/null @@ -1,59 +0,0 @@ - -EMULATOR = qemu-system-i386 -AS = ${HOME}/opt/cross/bin/i686-elf-as -CC = ${HOME}/opt/cross/bin/i686-elf-gcc -CPP = ${HOME}/opt/cross/bin/i686-elf-g++ -CFLAGS = -ffreestanding -O2 -Wall -Wextra - -OFILES = $(BUILD_DIR)/boot.o $(BUILD_DIR)/kterm.o $(BUILD_DIR)/kernel.o $(BUILD_DIR)/io.o $(BUILD_DIR)/MMU.o - -SRC_DIR = src -BUILD_DIR = build - -CRTBEGIN_OBJ = $(shell $(CC) $(CFLAGS) -print-file-name=crtbegin.o) -CRTEND_OBJ = $(shell $(CC) $(CFLAGS) -print-file-name=crtend.o) - -CRTI_OBJ = $(BUILD_DIR)/crti.o -CRTN_OBJ = $(BUILD_DIR)/crtn.o -OBJ_LINK_LIST = $(CRTI_OBJ) $(CRTBEGIN_OBJ) $(OFILES) $(CRTEND_OBJ) $(CRTN_OBJ) -INTERNAL_OBJS = $(CRTI_OBJ) $(OFILES) $(CRTN_OBJ) - - -all: clean build - -build: build_kernel run - -run: - $(EMULATOR) -kernel $(BUILD_DIR)/myos.bin -serial stdio - -build_kernel: $(OBJ_LINK_LIST) - - $(CC) -T $(SRC_DIR)/kernel/arch/i386/linker.ld -o $(BUILD_DIR)/myos.bin \ - -ffreestanding -O2 -nostdlib $(OBJ_LINK_LIST) -lgcc - -build_x86_64: - $(AS) $(SRC_DIR)/cgc/x86_64/crti.s -o $(BUILD_DIR)/crti_64.o - $(AS) $(SRC_DIR)/cgc/x86_64/crtn.s -o $(BUILD_DIR)/crtn.o - -clean: - rm -f $(BUILD_DIR)/myos.bin $(INTERNAL_OBJS) - -$(BUILD_DIR)/kernel.o: - $(CPP) -c $(SRC_DIR)/kernel/kernel.cpp -o $(BUILD_DIR)/kernel.o $(CFLAGS) -fno-exceptions -fno-rtti - -$(BUILD_DIR)/kterm.o: - $(CC) -c $(SRC_DIR)/kernel/arch/i386/tty/kterm.c -o $(BUILD_DIR)/kterm.o $(CFLAGS) -std=gnu99 - -$(BUILD_DIR)/boot.o: - $(AS) $(SRC_DIR)/kernel/arch/i386/boot.s -o $(BUILD_DIR)/boot.o - -$(BUILD_DIR)/crti.o: - $(AS) $(SRC_DIR)/kernel/arch/i386/crti.s -o $(BUILD_DIR)/crti.o - -$(BUILD_DIR)/crtn.o: - $(AS) $(SRC_DIR)/kernel/arch/i386/crtn.s -o $(BUILD_DIR)/crtn.o - -$(BUILD_DIR)/io.o: - $(CPP) -c $(SRC_DIR)/kernel/io.cpp -o $(BUILD_DIR)/io.o $(CFLAGS) -fno-exceptions -fno-rtti -$(BUILD_DIR)/MMU.o: - $(CPP) -c $(SRC_DIR)/kernel/MMU.cpp -o $(BUILD_DIR)/MMU.o $(CFLAGS) -fno-exceptions -fno-rtti \ No newline at end of file diff --git a/README.md b/README.md index 5383904..9befc1a 100644 --- a/README.md +++ b/README.md @@ -10,14 +10,30 @@ ________________________ The first scrolling boot screen. 😲 +![Interrupt handeling](screenshots/WIP_interruptHandling.png) \ +W.I.P - Working on interrupt handling + + +![Multiboot integration](screenshots/multiboot.png) \ +Multiboot information can be read by the kernel. + +![Page faulting](screenshots/PageFault.png) \ +Enabled paging and am getting page faults! + +![PCI enumeration](screenshots/PCIBusEnumeration.png) \ +Enumerating the PCI bus + +![ATAPI CD-ROM Identification](screenshots/CD-ROM_Identify.png) \ +Correctly identified our ATAPI device 🎉 + +![Reading Files from FAT-16](screenshots/ReadingFilesFromFAT16.png) \ +Reading a FILE from a FAT-16 Formatted drive + ________________________ ### The goal -Writing a hobby operating system to better understand the basic building blocks of any operating system. - - - - +Writing a hobby operating system to better understand the basic building blocks of any operating system.Initially I'd like for my +operating system to be able to run bash. ________________________ ### Operating System Technical specs/details @@ -26,8 +42,8 @@ screen. The terminal/screen has scrolling so the latest messages are visible on ________________________ ### Planning -[See TODO](TODO.md) - +[See TODO](todo.md) \ +[See Features](features.md) ________________________ ### Docs [Intro](docs/Intro.md) \ diff --git a/TODO.md b/TODO.md deleted file mode 100644 index 662bad3..0000000 --- a/TODO.md +++ /dev/null @@ -1,40 +0,0 @@ -# TODO list -## Start planning - Setup Cross-Compiler \ - Multiboot to kernel \ - Printing string to the screen \ - Printing values/numbers to the screen (a.k.k itoa) \ - Extend Multiboot implementation \ - Output to serial port \ - Move to protected mode \ - Enabel CMOS clock \ - Time measurement (PIC &| PIT) \ - Detect CPU speed \ - Interrupt / exception system (API) \ - - Plan your memory map (virtual, and physical) : decide where you want the data to be. \ - The heap: allocating memory at runtime (malloc and free) is almost impossible to go without. \ - Enable SIMD Extensions (SSE) - -## Other features I am thinking of: - PCI support \ - ATA PIO Mode support \ - USTAR Filesystem ( For its simplicity this is very likely the first filesystem the OS is going to support) \ - ACPI support ( Or some other basic way to support shutdown, reboot and possibly hibernation ) \ - ATAPI support \ - Keyboard support ( P/S2 Keyboard) \ - Memory Management (MMU)\ - Preemptive multi tasking - Processes - Threads - Scheduling (SRV2 Unix OR Priority Based Round Robin) \ - System V ABI compliance (partially) - POSIX compliance (partially) - RPC - for interprocess communication \ - Sync primitives - Semaphores, Mutexes, spinlocks et al. \ - Basic Terminal \ - Extend hardware recognition ( CPU codename, memory, ATA harddisk, RAW diskSpace, CPU speed through SMBIOS et al. ) \ - Basic Window server/client \ -## Support for more filesystems if I like the challenge in writing these ... - FAT Filesystem \ - EXT2 Filesystem \ \ No newline at end of file diff --git a/features.md b/features.md new file mode 100644 index 0000000..a6d8e97 --- /dev/null +++ b/features.md @@ -0,0 +1,50 @@ +# TODO list +## Basics + + Setup Cross-Compiler + Multiboot to kernel \ + Printing string to the screen \ + Printing values/numbers to the screen \ + Basic Terminal \ + Extend Multiboot implementation \ + Output to serial port \ + Move to protected mode \ + Enable CMOS clock \ + Time measurement (PIC &| PIT) \ + Detect CPU speed \ + Interrupt / exception system (API) \ + PCI support \ + ATA PIO Mode support \ + FAT Filesystem \ + Virtual filesystem \ + Keyboard support ( P/S2 Keyboard) \ + Physical memory management \ + Paging \ + Virtual memory management \ + The heap: allocating memory at runtime (malloc and free) is almost impossible to go without. \ + Enable SIMD Extensions (SSE) + PCI support \ + ATA PIO Mode support \ + USTAR Filesystem ( For its simplicity this is very likely the first filesystem the OS is going to support) \ + ACPI support ( Or some other basic way to support shutdown, reboot and possibly hibernation ) \ + ATAPI support \ + Memory Management (MMU) + Hardware Management system + Preemptive multi tasking \ + Processes \ + Threads + Scheduling (SRV2 Unix OR Priority Based Round Robin) \ + System V ABI compliance (partially) \ + POSIX compliance (partially) \ + RPC - for interprocess communication \ + Sync primitives - Semaphores, Mutexes, spinlocks et al. \ + + ACPI support \ + ATAPI support \ + + Basic Window server/client \ + EXT2 Filesystem + USTAR Filesystem \ + FAT16 Filesystem \ diff --git a/images/BarinkOS.png b/images/BarinkOS.png deleted file mode 100644 index 3f6e913..0000000 --- a/images/BarinkOS.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c3415fbc124e9a4f621f7aea377c782b56e42f6271bad434b4a3290437571acb -size 23402 diff --git a/images/BarinkOS_logo(standard).svg b/images/BarinkOS_logo(standard).svg deleted file mode 100644 index 700d71b..0000000 --- a/images/BarinkOS_logo(standard).svg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e9b64404160b415896faae7f3a2521a386162386f3c743cfed36633eb721ad75 -size 15322 diff --git a/images/BarinkOS_logo.svg b/images/BarinkOS_logo.svg deleted file mode 100644 index 7c38c24..0000000 --- a/images/BarinkOS_logo.svg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fe3bc435da5cd4c8244caa71c57a7cfde01b0953be196e731f84d92942d5863f -size 18412 diff --git a/kernel/Makefile b/kernel/Makefile new file mode 100644 index 0000000..8fdb8ad --- /dev/null +++ b/kernel/Makefile @@ -0,0 +1,132 @@ +AS = /opt/cross/bin/i686-elf-as +CC = /opt/cross/bin/i686-elf-gcc +CPP = /opt/cross/bin/i686-elf-g++ +CFLAGS = -ffreestanding -Og -ggdb -Wall -Wextra -I ../build/CoreLib/include +BUILD_DIR = ../build/kernel +OBJ_DIR = ../bin/kernel + +CRTBEGIN_OBJ = $(shell $(CC) $(CFLAGS) -print-file-name=crtbegin.o) +CRTEND_OBJ = $(shell $(CC) $(CFLAGS) -print-file-name=crtend.o) + +CRTI_OBJ = $(OBJ_DIR)/crti.o +CRTN_OBJ = $(OBJ_DIR)/crtn.o + +OFILES = $(OBJ_DIR)/boot.o \ + $(OBJ_DIR)/kterm.o \ + $(OBJ_DIR)/kernel.o \ + $(OBJ_DIR)/memory.o \ + $(OBJ_DIR)/paging.o \ + $(OBJ_DIR)/VFS.o \ + $(OBJ_DIR)/pit.o \ + $(OBJ_DIR)/time.o \ + $(OBJ_DIR)/keyboard.o \ + $(OBJ_DIR)/io.o \ + $(OBJ_DIR)/processor.o \ + $(OBJ_DIR)/gdtc.o \ + $(OBJ_DIR)/idt.o \ + $(OBJ_DIR)/pic.o \ + $(OBJ_DIR)/sv-terminal.o \ + $(OBJ_DIR)/prekernel.o \ + $(OBJ_DIR)/KHeap.o \ + $(OBJ_DIR)/pci.o \ + $(OBJ_DIR)/pcidevice.o \ + $(OBJ_DIR)/atapiDevice.o \ + $(OBJ_DIR)/ataDevice.o \ + $(OBJ_DIR)/rsdp.o \ + $(OBJ_DIR)/acpi.o \ + $(OBJ_DIR)/fat.o + +OBJ_LINK_LIST = $(CRTI_OBJ) $(CRTBEGIN_OBJ) $(OFILES) $(CRTEND_OBJ) $(CRTN_OBJ) +INTERNAL_OBJS = $(CRTI_OBJ) $(OFILES) $(CRTN_OBJ) + +all: clean build + +clean: + rm $(OBJ_DIR)/* -r + + +build: $(OBJ_LINK_LIST) + $(CPP) -T linker.ld -o $(BUILD_DIR)/myos.bin -ffreestanding -ggdb -Og -nostdlib $(OBJ_LINK_LIST) -lgcc -L ../build/CoreLib -lCoreLib + +# C++ definition -> Object files +$(OBJ_DIR)/kernel.o: kernel.cpp + $(CPP) -c kernel.cpp -o $(OBJ_DIR)/kernel.o $(CFLAGS) -fno-exceptions -fno-rtti + +$(OBJ_DIR)/kterm.o: + $(CPP) -c terminal/kterm.cpp -o $(OBJ_DIR)/kterm.o $(CFLAGS) -fno-exceptions -fno-rtti + +$(OBJ_DIR)/io.o: + $(CPP) -c io/io.cpp -o $(OBJ_DIR)/io.o $(CFLAGS) -fno-exceptions -fno-rtti + +$(OBJ_DIR)/idt.o: + $(CPP) -c interrupts/idt.cpp -o $(OBJ_DIR)/idt.o $(CFLAGS) -fno-exceptions -fno-rtti + +$(OBJ_DIR)/gdtc.o: + $(CPP) -c memory/gdt/gdtc.cpp -o $(OBJ_DIR)/gdtc.o $(CFLAGS) -fno-exceptions -fno-rtti + +$(OBJ_DIR)/pic.o: + $(CPP) -c drivers/pic/pic.cpp -o $(OBJ_DIR)/pic.o $(CFLAGS) -fno-exceptions -fno-rtti + +$(OBJ_DIR)/PhysicalMemoryManager.o: + $(CPP) -c memory/PhysicalMemoryManager.cpp -o $(OBJ_DIR)/PhysicalMemoryManager.o $(CFLAGS) -fno-exceptions -fno-rtti + +$(OBJ_DIR)/pci.o: + $(CPP) -c pci/pci.cpp -o $(OBJ_DIR)/pci.o $(CFLAGS) -fno-exceptions -fno-rtti + +$(OBJ_DIR)/pcidevice.o: + $(CPP) -c pci/pciDevice.cpp -o $(OBJ_DIR)/pcidevice.o $(CFLAGS) -fno-exceptions -fno-rtti + +$(OBJ_DIR)/atapiDevice.o: + $(CPP) -c storage/atapi/atapiDevice.cpp -o $(OBJ_DIR)/atapiDevice.o $(CFLAGS) -fno-exceptions -fno-rtti + +$(OBJ_DIR)/ataDevice.o: + $(CPP) -c "storage/ata pio/ATAPIO.cpp" -o $(OBJ_DIR)/ataDevice.o $(CFLAGS) -fno-exceptions -fno-rtti + +$(OBJ_DIR)/rsdp.o: + $(CPP) -c acpi/rsdp.cpp -o $(OBJ_DIR)/rsdp.o $(CFLAGS) -fno-exceptions -fno-rtti + +$(OBJ_DIR)/acpi.o: + $(CPP) -c acpi/acpi.cpp -o $(OBJ_DIR)/acpi.o $(CFLAGS) -fno-exceptions -fno-rtti + +$(OBJ_DIR)/pit.o: + $(CPP) -c drivers/pit/pit.cpp -o $(OBJ_DIR)/pit.o $(CFLAGS) -fno-exceptions -fno-rtti + +$(OBJ_DIR)/VFS.o: + $(CPP) -c storage/vfs/vfs.cpp -o $(OBJ_DIR)/VFS.o $(CFLAGS) -fno-exceptions -fno-rtti + +$(OBJ_DIR)/keyboard.o: + $(CPP) -c drivers/ps-2/keyboard.cpp -o $(OBJ_DIR)/keyboard.o $(CFLAGS) -fno-exceptions -fno-rtti + +$(OBJ_DIR)/time.o: + $(CPP) -c time.cpp -o $(OBJ_DIR)/time.o $(CFLAGS) -fno-exceptions -fno-rtti + +$(OBJ_DIR)/sv-terminal.o: + $(CPP) -c supervisorterminal/superVisorTerminal.cpp -o $(OBJ_DIR)/sv-terminal.o $(CFLAGS) -fno-exceptions -fno-rtti + +$(OBJ_DIR)/memory.o: + $(CPP) -c memory/PhysicalMemoryManager.cpp -o $(OBJ_DIR)/memory.o $(CFLAGS) -fno-exceptions -fno-rtti + +$(OBJ_DIR)/paging.o: + $(CPP) -c memory/VirtualMemoryManager.cpp -o $(OBJ_DIR)/paging.o $(CFLAGS) -fno-exceptions -fno-rtti + +$(OBJ_DIR)/KHeap.o: + $(CPP) -c memory/KernelHeap.cpp -o $(OBJ_DIR)/KHeap.o $(CFLAGS) -fno-exceptions -fno-rtti + +$(OBJ_DIR)/prekernel.o: + $(CPP) -c prekernel/prekernel.cpp -o $(OBJ_DIR)/prekernel.o $(CFLAGS) -fno-exceptions -fno-rtti + +$(OBJ_DIR)/processor.o: + $(CPP) -c i386/processor.cpp -o $(OBJ_DIR)/processor.o $(CFLAGS) -fno-exceptions -fno-rtti + +$(OBJ_DIR)/fat.o: + $(CPP) -c storage/filesystems/FAT/FAT.cpp -o $(OBJ_DIR)/fat.o $(CFLAGS) -fno-exceptions -fno-rtti + +# Assembly -> Object files +$(OBJ_DIR)/boot.o: + $(AS) boot/boot.s -o $(OBJ_DIR)/boot.o + +$(OBJ_DIR)/crti.o: + $(AS) crti.s -o $(OBJ_DIR)/crti.o + +$(OBJ_DIR)/crtn.o: + $(AS) crtn.s -o $(OBJ_DIR)/crtn.o diff --git a/kernel/acpi/acpi.cpp b/kernel/acpi/acpi.cpp new file mode 100644 index 0000000..66d4c7a --- /dev/null +++ b/kernel/acpi/acpi.cpp @@ -0,0 +1,76 @@ +#include "acpi.h" +#include "../../CoreLib/Memory.h" +#include "../memory/VirtualMemoryManager.h" + +RSDPDescriptor* ACPI::rsd_ptr; +RSCPDescriptor20* ACPI::rsd2_ptr; +RSDT* ACPI::rsd_table; + +const int KERNEL_OFFSET = 0xC0000000; + +void ACPI::initialize(){ + // Find the Root System Description Pointer + ACPI::rsd_ptr = FindRSD(); + printf("RSD address: 0x%x\n", ACPI::rsd_ptr); + printRSD(rsd_ptr); + + + if( rsd_ptr->Revision == 0 ){ + // Using version 1.0 of the ACPI specification + int sum = rsd_ptr->Checksum; + for (int i =0; i < sizeof(RSDPDescriptor) ; i++) { + sum += ((char*)rsd_ptr)[i]; + } + + printf(" 0x%x sum\n", sum); + if(sum & 0xfff0) + printf("valid rsd!\n"); + else + printf("invalid rsd\n"); + + printf("rsdp: 0x%x\n", rsd_ptr); + + printf("0x%x address\n", (rsd_ptr->RsdtAddress)); + Immediate_Map(rsd_ptr->RsdtAddress + KERNEL_OFFSET, rsd_ptr->RsdtAddress); + + RSDT* rootSystemDescriptionTable = (RSDT*)(rsd_ptr->RsdtAddress + KERNEL_OFFSET); + //printf("0x%x Root System Descriptor address\n", rootSystemDescriptionTable); + // checksum it, but we'll ignore it for now + printf("signature "); + for (int i = 0; i < 4; i++) { + kterm_put( rootSystemDescriptionTable->h.Signature[i]); + } + kterm_put('\n'); + + + int entries = (rootSystemDescriptionTable->h.Length - sizeof (rootSystemDescriptionTable->h)) /4; + printf("%d num entries\n", entries); + for( int i = 0; i < entries; i++){ + ACPISDTHeader* h = (ACPISDTHeader*) rootSystemDescriptionTable->PointerToSDT + i ; + if(strncmp(h->Signature, "FACP", 4)){ + printf("Found FACP Entry!\n"); + } + } + + + } else{ + // parse it as of version2.0 + printf("rsd2_ptr\n"); + ACPI::rsd2_ptr = (RSCPDescriptor20*)rsd_ptr; + } + + + +/* + auto tableHeader = &rootSystemDescriptionTable->h; + + // do checksum + sum = 0; + + for(int i = 0; i < tableHeader->Length; i ++) { + sum += ((char*) tableHeader)[i]; + } + + if( sum != 0) + printf("Table invalid!");*/ +} \ No newline at end of file diff --git a/kernel/acpi/acpi.h b/kernel/acpi/acpi.h new file mode 100644 index 0000000..97ca223 --- /dev/null +++ b/kernel/acpi/acpi.h @@ -0,0 +1,14 @@ +#pragma once +#include "rsdp.h" +class ACPI { + public: + static void initialize(); + + // In the future ACPI might start + // doing more systems initialization + + static RSDPDescriptor* rsd_ptr; + static RSCPDescriptor20* rsd2_ptr; + static RSDT* rsd_table; + private: +}; \ No newline at end of file diff --git a/kernel/acpi/rsdp.cpp b/kernel/acpi/rsdp.cpp new file mode 100644 index 0000000..8882f7f --- /dev/null +++ b/kernel/acpi/rsdp.cpp @@ -0,0 +1,44 @@ +#include "rsdp.h" +#include "../memory/VirtualMemoryManager.h" +#include "../../CoreLib/Memory.h" + + +void printRSD(RSDPDescriptor* rsd){ + printf("Signature: "); + for(int i = 0; i < 8; i++){ + kterm_put(rsd->signature[i]); + } + kterm_put('\n'); + + printf("OEMID: "); + for(int i =0; i < 6 ; i++){ + kterm_put (rsd->OEMID[i]); + } + kterm_put('\n'); + + printf("Revision: %d\n", rsd->Revision); +} + +RSDPDescriptor* FindRSD(){ + char* memory_byte = (char*) 0x000f2e14; + const void* string = "RSD PTR "; + + + for( ; (uint32_t) memory_byte < 0x0100000; memory_byte+=10){ + if( memcmp(memory_byte , string , 8 ) == 0 ) { + printf("RSD PTR found at 0x%x !\n", memory_byte); + return (RSDPDescriptor*) memory_byte; + break; + } + } + + memory_byte = (char*) 0x000E0000; + for ( ;(uint32_t) memory_byte < 0x000FFFFF; memory_byte += 1) + { + if( memcmp(memory_byte , string , 8 ) == 0 ) { + printf("RSD PTR found at 0x%x !\n", memory_byte); + return (RSDPDescriptor*) memory_byte; + break; + } + } +} diff --git a/kernel/acpi/rsdp.h b/kernel/acpi/rsdp.h new file mode 100644 index 0000000..77014fc --- /dev/null +++ b/kernel/acpi/rsdp.h @@ -0,0 +1,45 @@ +#pragma once +#include "../terminal/kterm.h" +#include +#include + + +struct ACPISDTHeader{ + char Signature[4]; + uint32_t Length; + uint8_t Revision; + uint8_t CheckSum; + char OEMID[6]; + char OEMTableID[8]; + uint32_t OEMRevision; + uint32_t CreatorID; + uint32_t CreatorRevision; +}; + +struct RSDT{ + struct ACPISDTHeader h; + uint32_t *PointerToSDT; // Length of array : (header.Length - sizeof(header))/ 4 +}__attribute__((packed)); + + +struct RSDPDescriptor { + char signature[8]; + uint8_t Checksum ; + char OEMID [6]; + uint8_t Revision; + uint32_t RsdtAddress; +}__attribute__((packed)); + +struct RSCPDescriptor20{ + RSDPDescriptor base; + uint32_t Length; + uint64_t XsdtAddress; + uint8_t ExtendedChecksum; + uint8_t reserved[3]; +}__attribute__((packed)); + +RSDPDescriptor* FindRSD(); + +void printRSD(RSDPDescriptor* rsd); + +RSDT* getRSDT(RSDPDescriptor* rsd); \ No newline at end of file diff --git a/kernel/bitmap.h b/kernel/bitmap.h new file mode 100644 index 0000000..fd80075 --- /dev/null +++ b/kernel/bitmap.h @@ -0,0 +1,38 @@ +#pragma once +#include +#include + +inline void bitmap_set( uint32_t* map , int index ) +{ + map[index/32] |= (1 << (index % 32)); +} + +inline void bitmap_unset(uint32_t* map , int index) +{ + map[index/32] &= ~(1 << (index % 32)); +} + +inline uint32_t bitmap_first_unset( uint32_t* map , int map_size) +{ + for ( int i = 0 ; i < map_size ; i ++ ) + { + // a bit or more is set within this byte! + if( (map[i] & 0xFFFFFFFF) > 0 ){ + + // which bit is set? + for(int j = 0 ; j < 32 ; j++){ + if ( (map[i] & (0x00000001 << j)) > 0) + { + return (i*32)+j; + } + } + + + } + + + } + + return -1; + +} diff --git a/kernel/boot/boot.s b/kernel/boot/boot.s new file mode 100644 index 0000000..b45b3a8 --- /dev/null +++ b/kernel/boot/boot.s @@ -0,0 +1,130 @@ +.include "./boot/multiboot.s" +/* +* Allocate initial stack +*/ +.section .bootstrap_stack, "aw", @nobits +stack_bottom: +.skip 16384 # 16 KiB +.globl stack_top +stack_top: + +/* +* Preallocate a couple pages to get us bootstrapped +* Being carefull to not use any address the bootloader might +* be using for its multiboot structures +*/ +.section .bss, "aw", @nobits + .align 4096 +.globl boot_page_directory +boot_page_directory: + .skip 4096 +.globl boot_page_table +boot_page_table: + .skip 4096 +.globl multiboot_page_table +multiboot_page_table: + .skip 4096 +# More page tables may be required + +# Entry point +.section .multiboot.text, "a" +.globl _start +.type _start, @function +_start: + + # Get physical address of the boot_page_table + movl $(boot_page_table - 0xC0000000), %edi + # Map address 0 + movl $0, %esi +1: + cmpl $(kernel_end - 0xC0000000), %esi + jge 3f + + # Map physical address as "present and writable" + movl %esi, %edx + orl $0x003, %edx + movl %edx, (%edi) + +2: # Size of page is 4096 bytes + addl $4096, %esi + # Size of entries in boot_page_table is 4 bytes + addl $4, %edi + # Loop to the next entry if we haven't finished. + loop 1b + +3: # Map VGA video memory to 0xC03FF00 as "present, writable" + movl $(0x000B8000 | 0x003), boot_page_table - 0xC0000000 + 1023 * 4 + + # Map the page table to both virtual addresss 0x00000000 and 0xC0000000 + movl $(boot_page_table - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 0 + movl $(boot_page_table - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 768 * 4 + + # Set cr3 to the address of the boot_page_directory + movl $(boot_page_directory - 0xC0000000), %ecx + movl %ecx, %cr3 + + # Enable paging and the write-protect bit + movl %cr0, %ecx + orl $0x80010000, %ecx + movl %ecx, %cr0 + + # Jump to higher half with an absolute jump + lea 4f, %ecx + jmp *%ecx + +.section .text +4: + # At this point, paging is fully set up and enabled +isPaging: + + # Reload cr3 to force tlb flush + movl %cr3, %ecx + movl %ecx, %cr3 + + /*Setup the stack pointer to point to the beginning of our stack */ + /* I believe its a high address growing down to lower adress for the stack on x86*/ + mov $stack_top, %esp + + /*Reset EFLAGS*/ + pushl $0 + popf + + + /* push the pointer to the Multiboot information structure*/ + pushl %ebx + + /* push the magic value */ + pushl %eax + call prekernelSetup + + # Unmap the identity mapping as it is now unnecessary + # movl $0, boot_page_directory + 0 + + + call kernel + + cli +1: hlt + jmp 1b + + +.include "./memory/gdt/gdt.s" +.include "./irs_table.s" +.include "./irq_table.s" +.include "./interrupts/idt.s" + +.globl jump_usermode +jump_usermode: + mov $((4*8) | 3) , %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + + mov %esp, %eax + push $( (3*8) | 3) + push %eax + pushf + push $( ( 3 * 8) | 3) + push startSuperVisorTerminal + iret diff --git a/kernel/boot/multiboot.s b/kernel/boot/multiboot.s new file mode 100644 index 0000000..041f103 --- /dev/null +++ b/kernel/boot/multiboot.s @@ -0,0 +1,15 @@ +/* + * Multiboot + */ +.set ALIGN, 1<<0 /* align loaded modules on page boundaries */ +.set MEMINFO, 1<<1 /* provide memory map */ +.set FLAGS, ALIGN | MEMINFO /* this is the Multiboot 'flag' field */ +.set MAGIC, 0x1BADB002 /* 'magic number' lets bootloader find the header */ +.set CHECKSUM, -(MAGIC + FLAGS) /* checksum of above, to prove we are multiboot */ + +.section .multiboot.data, "aw" +.align 4 +.long MAGIC +.long FLAGS +.long CHECKSUM + \ No newline at end of file diff --git a/kernel/bootcheck.h b/kernel/bootcheck.h new file mode 100644 index 0000000..e5f2ae8 --- /dev/null +++ b/kernel/bootcheck.h @@ -0,0 +1,91 @@ +#pragma once +#include "prekernel/multiboot.h" +#define CHECK_FLAG(flags, bit) ((flags) & (1 <<(bit))) + +#include "terminal/kterm.h" + + + +void CheckMBT ( multiboot_info_t* mbt ){ + /* Set MBI to the addresss of the multiboot information structure*/ + multiboot_info_t * mbi = (multiboot_info_t *) mbt; + +#ifdef __VERBOSE__ + /* Print out the flags */ + printf("flags = 0x%x\n", (unsigned) mbi->flags); +#endif + /* Are mem_* valid? */ + if ( CHECK_FLAG(mbi->flags,0)){ + // Do nothing + } + + /* is boot device valid ? */ + if (CHECK_FLAG (mbi->flags, 1)) + { +#ifdef __VERBOSE__ + printf("boot_device = 0x0%x\n", (unsigned) mbi->boot_device); +#endif + } + + /* is the command line passed? */ + if (CHECK_FLAG ( mbi->flags,2)) + { +#ifdef __VERBOSE__ + printf("cmdline = %s\n", (char *) mbi->cmdline); +#endif + } + + /* Are mods_* valid? */ + if(CHECK_FLAG ( mbi->flags, 3)){ + multiboot_module_t *mod; + uint32_t i; +#ifdef __VERBOSE__ + printf("mods count = %d, mods_addr = 0x%x\n", (int) mbi->mods_count, (int) mbi->mods_addr); + + for(i = 0, mod = (multiboot_module_t *) mbi->mods_addr; i < mbi->mods_count; i++ , mod++){ + printf(" mod start = 0x%x, mod_end = 0x%x, cmdline = %s\n", (unsigned) mod->mod_start, (unsigned) mod->mod_end, (char*) mod->cmdline); + } +#endif + } + + /* Bits 4 and 5 are mutually exclusive! */ + if (CHECK_FLAG (mbi->flags, 4) && CHECK_FLAG(mbi->flags, 5)) + { +#ifdef __VERBOSE__ + printf("Both bits 4 and 5 are set.\n"); +#endif + return; + } + + /* Is the symbol table of a.out valid? */ + if (CHECK_FLAG(mbi->flags, 4)){ + multiboot_aout_symbol_table_t *multiboot_aout_sym = &(mbi->u.aout_sym); +#ifdef __VERBOSE__ + printf( "multiboot_aout_symbol_table: tabsize = 0x%0x, strsize = 0x%x, addr = 0x%x\n", + (unsigned) multiboot_aout_sym->tabsize, + (unsigned) multiboot_aout_sym->strsize, + (unsigned) multiboot_aout_sym->addr); +#endif + } + + /* Is the section header table of ELF valid? */ + if (CHECK_FLAG(mbi->flags, 5)){ + multiboot_elf_section_header_table_t *multiboot_elf_sec = &(mbi->u.elf_sec); +#ifdef __VERBOSE__ + printf("multiboot_elf_sec: num = %u, size = 0x%x, addr = 0x%x, shnd = 0x%x\n", + + (unsigned) multiboot_elf_sec->num, (unsigned) multiboot_elf_sec->size, + (unsigned) multiboot_elf_sec->addr, (unsigned) multiboot_elf_sec->shndx); +#endif + + } + + /* Draw diagonal blue line */ + if (CHECK_FLAG (mbt->flags, 12)){ +#ifdef __VERBOSE__ + printf("Can draw!\n"); +#endif + } + + +} \ No newline at end of file diff --git a/kernel/bootinfo.h b/kernel/bootinfo.h new file mode 100644 index 0000000..575a048 --- /dev/null +++ b/kernel/bootinfo.h @@ -0,0 +1,9 @@ +#pragma once +#include "memory/memoryinfo.h" + + +struct BootInfo{ + const char* BootStructureID = "BarinkOS"; + MemoryInfo* memory; + +}; \ No newline at end of file diff --git a/src/kernel/arch/i386/crti.s b/kernel/crti.s similarity index 100% rename from src/kernel/arch/i386/crti.s rename to kernel/crti.s diff --git a/src/kernel/arch/i386/crtn.s b/kernel/crtn.s similarity index 100% rename from src/kernel/arch/i386/crtn.s rename to kernel/crtn.s diff --git a/kernel/definitions.h b/kernel/definitions.h new file mode 100644 index 0000000..c29df40 --- /dev/null +++ b/kernel/definitions.h @@ -0,0 +1,9 @@ +#pragma once +/** + * Kernel definitions + */ + +#define __DEBUG__ false +#define KERNEL_VERSION 0.03 + +#define ARCHITECTURE "I386" diff --git a/kernel/devices/BlockDevice.h b/kernel/devices/BlockDevice.h new file mode 100644 index 0000000..ed412fe --- /dev/null +++ b/kernel/devices/BlockDevice.h @@ -0,0 +1,11 @@ +// +// Created by nigel on 21/02/23. +// +#pragma once + +class BlockDevice { + virtual char* Read()=0; + virtual void Write() =0; +}; + + diff --git a/kernel/devices/CharacterDevice.h b/kernel/devices/CharacterDevice.h new file mode 100644 index 0000000..3afc094 --- /dev/null +++ b/kernel/devices/CharacterDevice.h @@ -0,0 +1,11 @@ +// +// Created by nigel on 21/02/23. +// +#pragma once + +class CharacterDevice { + virtual char Read()=0; + virtual void Write()=0; +}; + + diff --git a/kernel/drivers/cmos/cmos.cpp b/kernel/drivers/cmos/cmos.cpp new file mode 100644 index 0000000..17b3ae6 --- /dev/null +++ b/kernel/drivers/cmos/cmos.cpp @@ -0,0 +1,38 @@ +void ReadFromCMOS(unsigned char array[]) +{ + unsigned char tvalue, index; + + for (index = 0; index < 128; index++) + { + asm( + "cli\n\t" // Disable interrupts + "mov al, index\n\t" // Move index address + // since the 0x80 bit of al is not set, NMI is active + "out 0x70,al\n\t" // Copy address to CMOS register + // some kind of real delay here is probably best + "in al,0x71\n\t" // Fetch 1 byte to al + "sti\n\t" // Enable interrupts + "mov tvalue,al\n\t"); + + array[index] = tvalue; + } +} + +void WriteTOCMOS(unsigned char array[]) +{ + unsigned char index; + + for(index = 0; index < 128; index++) + { + unsigned char tvalue = array[index]; + + asm("cli\n\t" // Clear interrupts + "mov al,index\n\t" // move index address + "out 0x70,al\n\t" // copy address to CMOS register + // some kind of real delay here is probably best + "mov al,tvalue\n\t" // move value to al + "out 0x71,al\n\t" // write 1 byte to CMOS + "sti\n\\t" ); // Enable interrupts + + } +} \ No newline at end of file diff --git a/kernel/drivers/pic/pic.cpp b/kernel/drivers/pic/pic.cpp new file mode 100644 index 0000000..5f1967c --- /dev/null +++ b/kernel/drivers/pic/pic.cpp @@ -0,0 +1,62 @@ +#include "pic.h" + +extern "C" void PIC_sendEOI (unsigned char irq){ + if(irq >= 8) + outb(PIC2_COMMAND, PIC_EOI); + outb(PIC1_COMMAND, PIC_EOI); +} + +/* Helper func */ +static uint16_t __pic_get_irq_reg(int ocw3) +{ + /* OCW3 to PIC CMD to get the register values. PIC2 is chained, and + * represents IRQs 8-15. PIC1 is IRQs 0-7, with 2 being the chain */ + outb(PIC1_COMMAND, ocw3); + outb(PIC2_COMMAND, ocw3); + return (inb(PIC2_COMMAND) << 8) | inb(PIC1_COMMAND); +} + +/* Returns the combined value of the cascaded PICs irq request register */ +uint16_t pic_get_irr(void) +{ + return __pic_get_irq_reg(PIC_READ_IRR); +} + +/* Returns the combined value of the cascaded PICs in-service register */ +uint16_t pic_get_isr(void) +{ + return __pic_get_irq_reg(PIC_READ_ISR); +} + + +void PIC_remap (int offset1, int offset2 ){ + unsigned char a1, a2; + + a1 = inb(PIC1_DATA); + a2 = inb(PIC2_DATA); + + + // Start initialization + + outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4); + io_wait(); + outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4); + io_wait(); + outb(PIC1_DATA, offset1); + io_wait(); + outb(PIC2_DATA, offset2); + io_wait(); + outb(PIC1_DATA, 4); + io_wait(); + outb(PIC2_DATA, 2); + io_wait(); + + outb(PIC1_DATA, ICW4_8086); + io_wait(); + outb(PIC2_DATA, ICW4_8086); + io_wait(); + + outb(PIC1_DATA, a1); + outb(PIC2_DATA, a2); + +} \ No newline at end of file diff --git a/kernel/drivers/pic/pic.h b/kernel/drivers/pic/pic.h new file mode 100644 index 0000000..aeb6e30 --- /dev/null +++ b/kernel/drivers/pic/pic.h @@ -0,0 +1,59 @@ +#pragma once + +#include +#include "../../io/io.h" + +#define PIC1 0x20 /* IO base address for master PIC */ +#define PIC2 0xA0 /* IO base address for slave PIC */ +#define PIC1_COMMAND PIC1 +#define PIC1_DATA (PIC1+1) +#define PIC2_COMMAND PIC2 +#define PIC2_DATA (PIC2+1) + + +#define ICW1_ICW4 0x01 /* ICW4 (not) needed */ +#define ICW1_SINGLE 0x02 /* Single (cascade) mode */ +#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */ +#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */ +#define ICW1_INIT 0x10 /* Initialization - required! */ + +#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */ +#define ICW4_AUTO 0x02 /* Auto (normal) EOI */ +#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */ +#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */ +#define ICW4_SFNM 0x10 /* Special fully nested (not) */ + +#define PIC_EOI 0x20 +#define PIC_READ_IRR 0x0a /* OCW3 irq ready next CMD read */ +#define PIC_READ_ISR 0x0b /* OCW3 irq service next CMD read */ + +extern "C"{ + +extern void irq0 (); +extern void irq1 (); +extern void irq2 (); +extern void irq3 (); +extern void irq4 (); +extern void irq5 (); +extern void irq6 (); +extern void irq7 (); +extern void irq8 (); +extern void irq9 (); +extern void irq10 (); +extern void irq11 (); +extern void irq12 (); +extern void irq13 (); +extern void irq14 (); +extern void irq15 (); + +void PIC_sendEOI (unsigned char irq); + +} + + +//static uint16_t __pic_get_irq_reg(int ocw3); +uint16_t pic_get_irr(void); +uint16_t pic_get_isr(void); + + +void PIC_remap (int offset1, int offset2 ); \ No newline at end of file diff --git a/kernel/drivers/pit/pit.cpp b/kernel/drivers/pit/pit.cpp new file mode 100644 index 0000000..93d1b9e --- /dev/null +++ b/kernel/drivers/pit/pit.cpp @@ -0,0 +1,54 @@ +#include "pit.h" +#include "../../terminal/kterm.h" +uint32_t pit_tick = 0; + + +void pit_initialise() +{ + asm volatile("CLI"); + +#ifdef __VERBOSE__ + printf("Init PIT!\n"); +#endif + // clear mask for IRQ 0 + uint8_t value = inb(0x21) & ~(1<< 0); + outb(0x21, value); + + io_wait(); + + const int freq = 500; + + uint32_t divisor = 1193180 / freq; + + outb(PIT_COMMAND, 0x36); + + uint8_t l = (uint8_t) (divisor & 0xFF); + uint8_t h = (uint8_t) ( (divisor>>8) & 0xff); + + outb(PIT_DATA_0, l); + outb(PIT_DATA_0,h); + + + asm volatile("STI"); +} + + +void get_pit_count() +{ + asm volatile ("CLI"); + + outb(PIT_COMMAND, 0); + uint16_t count = inb(PIT_DATA_0); + count |= inb(PIT_DATA_0) << 8; + + printf("PIT count: 0x%x\n", count); + + asm volatile("STI"); + +} + +void set_pit_count() +{ + +} + diff --git a/kernel/drivers/pit/pit.h b/kernel/drivers/pit/pit.h new file mode 100644 index 0000000..cde7444 --- /dev/null +++ b/kernel/drivers/pit/pit.h @@ -0,0 +1,18 @@ +#pragma once +#include +#include "../../io/io.h" +#define PIT_DATA_0 0x40 +#define PIT_DATA_1 0x41 +#define PIT_DATA_2 0x42 +#define PIT_COMMAND 0x43 + + +extern uint32_t pit_tick; + + +void pit_initialise(); + + +void get_pit_count(); + +void set_pit_count(); diff --git a/kernel/drivers/ps-2/keyboard.cpp b/kernel/drivers/ps-2/keyboard.cpp new file mode 100644 index 0000000..d526ecc --- /dev/null +++ b/kernel/drivers/ps-2/keyboard.cpp @@ -0,0 +1,51 @@ +#include "keyboard.h" + +KeyPressInfo keyPress {}; + +void KeyHandled(){ + keyPress.ScanCode= 0x00; + keyPress.PressedModifiers = 0x00; +} + + +char getASCIIKey(){ + char keyPressed; + // Wait until a key is pressed + while(keyPress.ScanCode == 0x00) { + asm volatile ("NOP"); + } + + + // Translate keycode to ascii + // Probably a lookup table might be handy + // Until 0x37 + const char* ASCIILookUp = + "\01234567890-=\0\0QWERTYUIOP[]\0\0ASDFGHJKL;\'`\0\\ZXCVBNM,./\0"; + + uint8_t ASCII_Index = keyPress.ScanCode - 3 ; + //printf("ASCII_INDEX: %x\n", ASCII_Index); + keyPressed = ASCIILookUp[ASCII_Index]; + + KeyHandled(); + + return keyPressed; +} + + + +uint8_t getKey(){ + // Wait until a key is pressed + while(keyPress.ScanCode == 0x00){ + asm volatile ("NOP"); + } + + if( keyPress.ScanCode > 0x37){ + keyPress.ScanCode = 0x00; + return 0; + } + + uint8_t ScanCode = keyPress.ScanCode; + // KeyHandled(); + + return ScanCode ; +} \ No newline at end of file diff --git a/kernel/drivers/ps-2/keyboard.h b/kernel/drivers/ps-2/keyboard.h new file mode 100644 index 0000000..52c53ba --- /dev/null +++ b/kernel/drivers/ps-2/keyboard.h @@ -0,0 +1,34 @@ +#pragma once +#include +#include "../../terminal/kterm.h" +enum ScanCodeSet { + None = 0, + ScanCodeSet1 = 1, + ScanCodeSet2 = 2, + ScanCodeSet3 = 3, +}; + +enum Modifiers { + LSHIFT = 1, + RSHIFT = 2, + + LCTRL = 3, + RCTRL = 4, + + LALT = 5, + RALT = 6 +}; + +struct KeyPressInfo{ + uint8_t PressedModifiers; + uint8_t ScanCode; +}; + + + +extern KeyPressInfo keyPress; + +void KeyHandled(); + +char getASCIIKey(); +uint8_t getKey(); diff --git a/kernel/drivers/ps-2/scancodes/set1.h b/kernel/drivers/ps-2/scancodes/set1.h new file mode 100644 index 0000000..2fe6b17 --- /dev/null +++ b/kernel/drivers/ps-2/scancodes/set1.h @@ -0,0 +1,184 @@ +#pragma once + + + + + + +// ScanCode set 1 +int ScanCodeToKeyCode [0xD8]; + +/* key pressed scancode */ +ScanCodeToKeyCode[0x01] = 4017; // escape pressed +ScanCodeToKeyCode[0x02] = 4018; // 1 pressed +ScanCodeToKeyCode[0x03] = 4019; // 2 pressed +ScanCodeToKeyCode[0x04] = 4020; // 3 pressed +ScanCodeToKeyCode[0x05] ="" // 4 pressed +ScanCodeToKeyCode[0x06] ="" // 5 pressed +ScanCodeToKeyCode[0x07] ="" // 6 pressed +ScanCodeToKeyCode[0x08] ="" // 7 pressed +ScanCodeToKeyCode[0x09] ="" // 8 pressed +ScanCodeToKeyCode[0x0A] ="" // 9 pressed +ScanCodeToKeyCode[0x0B] ="" // 0 (zero) pressed +ScanCodeToKeyCode[0x0C] ="" // - pressed +ScanCodeToKeyCode[0x0D] ="" // = pressed +ScanCodeToKeyCode[0x0E] ="" // backspace pressed +ScanCodeToKeyCode[0x0F] ="" // tab pressed +ScanCodeToKeyCode[0x10] ="" // Q pressed +ScanCodeToKeyCode[0x11] ="" // W pressed +ScanCodeToKeyCode[0x12] ="" // E pressed +ScanCodeToKeyCode[0x13] ="" // R pressed +ScanCodeToKeyCode[0x14] ="" // T pressed +ScanCodeToKeyCode[0x15] ="" // Y pressed +ScanCodeToKeyCode[0x16] ="" // U pressed +ScanCodeToKeyCode[0x17] ="" // I pressed +ScanCodeToKeyCode[0x18] ="" // O pressed +ScanCodeToKeyCode[0x19] ="" // P pressed +ScanCodeToKeyCode[0x1A] ="" // [ pressed +ScanCodeToKeyCode[0x1B] ="" // ] pressed +ScanCodeToKeyCode[0x1C] ="" // enter pressed +ScanCodeToKeyCode[0x1D] ="" // left control pressed +ScanCodeToKeyCode[0x1E] ="" // A pressed +ScanCodeToKeyCode[0x1F] ="" // S pressed +ScanCodeToKeyCode[0x20] ="" // D pressed +ScanCodeToKeyCode[0x21] ="" // F pressed +ScanCodeToKeyCode[0x22] ="" // G pressed +ScanCodeToKeyCode[0x23] ="" // H pressed +ScanCodeToKeyCode[0x24] ="" // J pressed +ScanCodeToKeyCode[0x25] ="" // K pressed +ScanCodeToKeyCode[0x26] ="" // L pressed +ScanCodeToKeyCode[0x27] ="" // ; pressed +ScanCodeToKeyCode[0x28] ="" // ' (single quote) pressed +ScanCodeToKeyCode[0x29] ="" // ` (back tick) pressed +ScanCodeToKeyCode[0x2A] ="" // left shift pressed +ScanCodeToKeyCode[0x2B] ="" // \ pressed +ScanCodeToKeyCode[0x2C] ="" // Z pressed +ScanCodeToKeyCode[0x2D] ="" // X pressed +ScanCodeToKeyCode[0x2E] ="" // C pressed +ScanCodeToKeyCode[0x2F] ="" // V pressed +ScanCodeToKeyCode[0x30] ="" // B pressed +ScanCodeToKeyCode[0x31] ="" // N pressed +ScanCodeToKeyCode[0x32] ="" // M pressed +ScanCodeToKeyCode[0x33] ="" // , pressed +ScanCodeToKeyCode[0x34] ="" // . pressed +ScanCodeToKeyCode[0x35] ="" // / pressed +ScanCodeToKeyCode[0x36] ="" // right shift pressed +ScanCodeToKeyCode[0x37] ="" // (keypad) * pressed +ScanCodeToKeyCode[0x38] ="" // left alt pressed +ScanCodeToKeyCode[0x39] ="" // space pressed +ScanCodeToKeyCode[0x3A] ="" // CapsLock pressed +ScanCodeToKeyCode[0x3B] ="" // F1 pressed +ScanCodeToKeyCode[0x3C] ="" // F2 pressed +ScanCodeToKeyCode[0x3D] ="" // F3 pressed +ScanCodeToKeyCode[0x3E] ="" // F4 pressed +ScanCodeToKeyCode[0x3F] ="" // F5 pressed +ScanCodeToKeyCode[0x40] ="" // F6 pressed +ScanCodeToKeyCode[0x41] ="" // F7 pressed +ScanCodeToKeyCode[0x42] ="" // F8 pressed +ScanCodeToKeyCode[0x43] ="" // F9 pressed +ScanCodeToKeyCode[0x44] ="" // F10 pressed +ScanCodeToKeyCode[0x45] ="" // NumberLock pressed +ScanCodeToKeyCode[0x46] ="" // ScrollLock pressed +ScanCodeToKeyCode[0x47] ="" // (keypad) 7 pressed +ScanCodeToKeyCode[0x48] ="" // (keypad) 8 pressed +ScanCodeToKeyCode[0x49] ="" // (keypad) 9 pressed +ScanCodeToKeyCode[0x4A] ="" // (keypad) - pressed +ScanCodeToKeyCode[0x4B] ="" // (keypad) 4 pressed +ScanCodeToKeyCode[0x4C] ="" // (keypad) 5 pressed +ScanCodeToKeyCode[0x4D] ="" // (keypad) 6 pressed +ScanCodeToKeyCode[0x4E] ="" // (keypad) + pressed +ScanCodeToKeyCode[0x4F] ="" // (keypad) 1 pressed +ScanCodeToKeyCode[0x50] ="" // (keypad) 2 pressed +ScanCodeToKeyCode[0x51] ="" // (keypad) 3 pressed +ScanCodeToKeyCode[0x52] ="" // (keypad) 0 pressed +ScanCodeToKeyCode[0x53] ="" // (keypad) . pressed +ScanCodeToKeyCode[0x57] ="" // F11 pressed +ScanCodeToKeyCode[0x58] ="" // F12 pressed + + +/* key released scanCode.""*/ +ScanCodeToKeyCode[0x81] ="" // escape released +ScanCodeToKeyCode[0x82] ="" // 1 released +ScanCodeToKeyCode[0x83] ="" // 2 released +ScanCodeToKeyCode[0x84] ="" // 3 released +ScanCodeToKeyCode[0x85] ="" // 4 released +ScanCodeToKeyCode[0x86] ="" // 5 released +ScanCodeToKeyCode[0x87] ="" // 6 released +ScanCodeToKeyCode[0x88] ="" // 7 released +ScanCodeToKeyCode[0x89] ="" // 8 released +ScanCodeToKeyCode[0x8A] ="" // 9 released +ScanCodeToKeyCode[0x8B] ="" // 0 (zero) released +ScanCodeToKeyCode[0x8C] ="" // - released +ScanCodeToKeyCode[0x8D] ="" // = released +ScanCodeToKeyCode[0x8E] ="" // backspace released +ScanCodeToKeyCode[0x8F] ="" // tab released +ScanCodeToKeyCode[0x90] ="" // Q released +ScanCodeToKeyCode[0x91] ="" // W released +ScanCodeToKeyCode[0x92] ="" // E released +ScanCodeToKeyCode[0x93] ="" // R released +ScanCodeToKeyCode[0x94] ="" // T released +ScanCodeToKeyCode[0x95] ="" // Y released +ScanCodeToKeyCode[0x96] ="" // U released +ScanCodeToKeyCode[0x97] ="" // I released +ScanCodeToKeyCode[0x98] ="" // O released +ScanCodeToKeyCode[0x99] ="" // P released +ScanCodeToKeyCode[0x9A] ="" // [ released +ScanCodeToKeyCode[0x9B] ="" // ] released +ScanCodeToKeyCode[0x9C] ="" // enter released +ScanCodeToKeyCode[0x9D] ="" // left control released +ScanCodeToKeyCode[0x9E] ="" // A released +ScanCodeToKeyCode[0x9F] ="" // S released +ScanCodeToKeyCode[0xA0] ="" // D released +ScanCodeToKeyCode[0xA1] ="" // F released +ScanCodeToKeyCode[0xA2] ="" // G released +ScanCodeToKeyCode[0xA3] ="" // H released +ScanCodeToKeyCode[0xA4] ="" // J released +ScanCodeToKeyCode[0xA5] ="" // K released +ScanCodeToKeyCode[0xA6] ="" // L released +ScanCodeToKeyCode[0xA7] ="" // ; released +ScanCodeToKeyCode[0xA8] ="" // ' (single quote) released +ScanCodeToKeyCode[0xA9] ="" // ` (back tick) released +ScanCodeToKeyCode[0xAA] ="" // left shift released +ScanCodeToKeyCode[0xAB] ="" // \ released +ScanCodeToKeyCode[0xAC] ="" // Z released +ScanCodeToKeyCode[0xAD] ="" // X released +ScanCodeToKeyCode[0xAE] ="" // C released +ScanCodeToKeyCode[0xAF] ="" // V released +ScanCodeToKeyCode[0xB0] ="" // B released +ScanCodeToKeyCode[0xB1] ="" // N released +ScanCodeToKeyCode[0xB2] ="" // M released +ScanCodeToKeyCode[0xB3] ="" // , released +ScanCodeToKeyCode[0xB4] ="" // . released +ScanCodeToKeyCode[0xB5] ="" // / released +ScanCodeToKeyCode[0xB6] ="" // right shift released +ScanCodeToKeyCode[0xB7] ="" // (keypad) * released +ScanCodeToKeyCode[0xB8] ="" // left alt released +ScanCodeToKeyCode[0xB9] ="" // space released +ScanCodeToKeyCode[0xBA] ="" // CapsLock released +ScanCodeToKeyCode[0xBB] ="" // F1 released +ScanCodeToKeyCode[0xBC] ="" // F2 released +ScanCodeToKeyCode[0xBD] ="" // F3 released +ScanCodeToKeyCode[0xBE] ="" // F4 released +ScanCodeToKeyCode[0xBF] ="" // F5 released +ScanCodeToKeyCode[0xC0] ="" // F6 released +ScanCodeToKeyCode[0xC1] ="" // F7 released +ScanCodeToKeyCode[0xC2] ="" // F8 released +ScanCodeToKeyCode[0xC3] ="" // F9 released +ScanCodeToKeyCode[0xC4] ="" // F10 released +ScanCodeToKeyCode[0xC5] ="" // NumberLock released +ScanCodeToKeyCode[0xC6] ="" // ScrollLock released +ScanCodeToKeyCode[0xC7] ="" // (keypad) 7 released +ScanCodeToKeyCode[0xC8] ="" // (keypad) 8 released +ScanCodeToKeyCode[0xC9] ="" // (keypad) 9 released +ScanCodeToKeyCode[0xCA] ="" // (keypad) - released +ScanCodeToKeyCode[0xCB] ="" // (keypad) 4 released +ScanCodeToKeyCode[0xCC] ="" // (keypad) 5 released +ScanCodeToKeyCode[0xCD] ="" // (keypad) 6 released +ScanCodeToKeyCode[0xCE] ="" // (keypad) + released +ScanCodeToKeyCode[0xCF] ="" // (keypad) 1 released +ScanCodeToKeyCode[0xD0] ="" // (keypad) 2 released +ScanCodeToKeyCode[0xD1] ="" // (keypad) 3 released +ScanCodeToKeyCode[0xD2] ="" // (keypad) 0 released +ScanCodeToKeyCode[0xD3] ="" // (keypad) . released +ScanCodeToKeyCode[0xD7] ="" // F11 released +ScanCodeToKeyCode[0xD8] ="" // F12 released \ No newline at end of file diff --git a/src/kernel/arch/i386/ports/serial.cpp b/kernel/drivers/serial/serial.cpp similarity index 100% rename from src/kernel/arch/i386/ports/serial.cpp rename to kernel/drivers/serial/serial.cpp diff --git a/src/kernel/arch/i386/ports/serial.h b/kernel/drivers/serial/serial.h similarity index 100% rename from src/kernel/arch/i386/ports/serial.h rename to kernel/drivers/serial/serial.h diff --git a/kernel/drivers/vga/VBE.h b/kernel/drivers/vga/VBE.h new file mode 100644 index 0000000..8b63cd4 --- /dev/null +++ b/kernel/drivers/vga/VBE.h @@ -0,0 +1,41 @@ + +#define VBE_DISPI_IOPORT_INDEX 0x01CE +#define VBE_DISPI_IOPORT_DATA 0x01CF + +/* VBE index values*/ +#define VBE_DISPI_INDEX_ID 0x0 +#define VBE_DISPI_INDEX_XRES 0x1 +#define VBE_DISPI_INDEX_YRES 0x2 +#define VBE_DISPI_INDEX_BPP 0x3 +#define VBE_DISPI_INDEX_ENABLE 0x4 +#define VBE_DISPI_INDEX_BANK 0x5 +#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 +#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 +#define VBE_DISPI_INDEX_X_OFFSET 0x8 +#define VBE_DISPI_INDEX_Y_OFFSET 0x9 + +/* BGA Version */ +#define VBE_DISPI_ID5 0xB0C5 +#define VBE_DISPI_ID4 0xB0C3 +#define VBE_DISPI_ID3 0xB0C2 +#define VBE_DISPI_ID2 0xB0C1 +#define VBE_DISPI_ID1 0xB0C0 + + +/* BGA BIT DEPTH */ +#define VBE_DISPI_BPP_4 0x04 +#define VBE_DISPI_BPP_8 0x08 +#define VBE_DISPI_BPP_15 0x0F +#define VBE_DISPI_BPP_16 0x10 +#define VBE_DISPI_BPP_24 0x18 +#define VBE_DISPI_BPP_32 0x20 + + + /*unsigned short BGAReadRegister(unsigned short IndexValue){ + // outpw(VBE_DISPI_IOPORT_INDEX, IndexValue); + // return inpw (VBE_DISPI_IOPORT_DATA); + } + + int BGAIsAvailable (){ + return (BGAReadRegister(VBE_DISPI_INDEX_ID) == VBE_DISPI_ID5); + }*/ diff --git a/src/kernel/arch/i386/vga/colors.h b/kernel/drivers/vga/colors.h similarity index 100% rename from src/kernel/arch/i386/vga/colors.h rename to kernel/drivers/vga/colors.h diff --git a/kernel/grub.cfg b/kernel/grub.cfg new file mode 100644 index 0000000..27391d2 --- /dev/null +++ b/kernel/grub.cfg @@ -0,0 +1,8 @@ +GRUB_DEFAULT=0 +GRUB_TIMEOUT=-1 +GRUB_HIDDEN_TIMEOUT=0 +GRUB_HIDDEN_TIMEOUT_QUITE=true + +menuentry "BarinkOS" { + multiboot /boot/myos.bin +} diff --git a/kernel/i386/README.md b/kernel/i386/README.md new file mode 100644 index 0000000..6de2022 --- /dev/null +++ b/kernel/i386/README.md @@ -0,0 +1,2 @@ +# architecture specific implementations +## This will contain I386 Architecture specific implementations diff --git a/kernel/i386/processor.cpp b/kernel/i386/processor.cpp new file mode 100644 index 0000000..d04bcdb --- /dev/null +++ b/kernel/i386/processor.cpp @@ -0,0 +1,127 @@ +// +// Created by nigel on 17/02/23. +// + +#include "processor.h" + + +uint32_t processor::cap_page; +uint32_t processor::cap_page1; +uint32_t processor::cap_page7 ; + +void processor::initialize() +{ + + asm volatile ("movl $0x80000001, %%eax;" + "CPUID;" + "movl %%edx, %0" + :: "m"(cap_page)); + + asm volatile ("movl $0x01, %%eax; " + "CPUID;" + "movl %%edx, %0" + :: "m"(cap_page1)); + + asm volatile ("movl $0x07, %%eax;" + "movl $0x0, %%ecx;" + "CPUID;" + "movl %%edx, %0" + :: "m"(cap_page7)); + +} + +bool processor::hasAMXExtension() +{ + return (cap_page7 & AMX_TYPE::AMX_BF16) || (cap_page7 & AMX_TYPE::AMX_TILE) || (cap_page7 & AMX_TYPE::AMX_INT8); +} + + +/* + * PSE: page-size extensions for 32-bit paging. + * If CPUID.01H:EDX.PSE [bit 3] = 1, CR4.PSE may be set to 1, enabling support for 4-MByte pages with 32-bit paging + */ +bool processor::has32bitPagingSupport() { + // is the PSE bit set + return cap_page1 & (0x1 << 3); +} + +/* + * PAE: physical-address extension. + * If CPUID.01H:EDX.PAE [bit 6] = 1, CR4.PAE may be set to 1, enabling PAE paging (this setting is also required + * for 4-level paging and 5-level paging). + */ +bool processor::hasPAEExtension(){ + return cap_page1 & (0x1 << 6); +} + +/* + * PGE: global-page support. + * If CPUID.01H:EDX.PGE [bit 13] = 1, CR4.PGE may be set to 1, enabling the global-page feature (see Section + * 4.10.2.4). + */ +bool processor::hasPageSupport(){ + return cap_page1 & (0x1 << 13); +} + +/* + * Page1GB: 1-GByte pages. + * If CPUID.80000001H:EDX.Page1GB [bit 26] = 1, 1-GByte pages may be supported with 4-level paging and 5- + * level paging (see Section 4.5). + */ +bool processor::gigabytePages() { + return cap_page & (0x1 << 26); +} + +void processor::enable_protectedMode() +{ + // Set the protected bit of control register 0 + // this will put the CPU into protected mode + // NOTE: This should really be an assembly procedure + // We cant directly write to control register 0 + // therefor we copy the value of control register 0 into eax + // once we are done manipulating the value we write the value in + // eax back to control register 0 + + asm volatile("mov %cr0, %eax "); + asm volatile("or $1, %eax"); + asm volatile("mov %eax, %cr0"); +} + + + +uint32_t processor::GetEFLAGS() +{ + uint32_t EFLAGS = 0; + asm volatile ("pushfl;" "movl 4(%%esp), %%edx" : "=d"(EFLAGS)); + return EFLAGS; +} + + +uint32_t processor::GetCR0() +{ + uint32_t cr0_value; + asm volatile ("movl %%cr0, %%edx" : "=d"(cr0_value)); + return cr0_value; + +} + + +uint32_t processor::GetCR2(){ + uint32_t cr2_value; + __asm__ volatile("movl %%cr2, %%edx": "=d"(cr2_value)); + return cr2_value; +} + + +uint32_t processor::GetCR3(){ + uint32_t cr3_value; + __asm__ volatile("movl %%cr3, %%edx": "=d"(cr3_value)); + return cr3_value; +} + + +uint32_t processor::GetCR4(){ + uint32_t cr4_value; + __asm__ volatile("movl %%cr4, %%edx": "=d"(cr4_value)); + return cr4_value; +} \ No newline at end of file diff --git a/kernel/i386/processor.h b/kernel/i386/processor.h new file mode 100644 index 0000000..7ff38fe --- /dev/null +++ b/kernel/i386/processor.h @@ -0,0 +1,36 @@ +// +// Created by nigel on 17/02/23. +// +#pragma once +#include "../terminal/kterm.h" +class processor { +public: + static void initialize(); + + // Based on information from https://en.wikichip.org/wiki/x86/amx#Detection + enum AMX_TYPE{ + AMX_BF16 = (0x1 << 22), + AMX_TILE = (0x1 << 24), + AMX_INT8 = (0x1 << 25) + }; + static bool hasAMXExtension(); + static bool has32bitPagingSupport(); + static bool hasPageSupport(); + static bool gigabytePages(); + + static bool hasPAEExtension(); + static void enable_protectedMode(); + + static uint32_t GetEFLAGS(); + static uint32_t GetCR0(); + static uint32_t GetCR2(); + static uint32_t GetCR3(); + static uint32_t GetCR4(); + +private: + static uint32_t cap_page; + static uint32_t cap_page1; + static uint32_t cap_page7; + + +}; diff --git a/kernel/interrupts/idt.cpp b/kernel/interrupts/idt.cpp new file mode 100644 index 0000000..4b20f2e --- /dev/null +++ b/kernel/interrupts/idt.cpp @@ -0,0 +1,427 @@ +#include "idt.h" +#include "../drivers/pit/pit.h" +#include "../drivers/ps-2/keyboard.h" +#include "../i386/processor.h" +#include "../memory/VirtualMemoryManager.h" +#include "../syscalls.h" + + +IDT_entry idt_table[256]; +IDT_ptr idt_ptr; + + +void set_id_entry (uint8_t num , uint32_t base, uint16_t sel, uint8_t flags){ + idt_table[num].offset_1 = base & 0xFFFF; + idt_table[num].selector = sel; + idt_table[num].zero = 0; + idt_table[num].type_attr = flags; + idt_table[num].offset_2 = (base >> 16) & 0xFFFF; + +}; + +void irs_handler (registers* regs) { + uint32_t FaultingAddress; + printf("(IRS) Interrupt number: %d \n EAX: ", regs->int_no, regs->eax); + switch (regs->int_no) + { + case 0: + // Divide Error #DE + printf("#DE\n"); + printf("EIP: 0x%x\n", regs->eip); + printf("EAX: 0x%x\n", regs->eax); + printf("EBP: 0x%x\n", regs->ebp); + break; + + case 1: + // Debug Exception #DB + printf("#DB\n"); + printf("EIP: 0x%x\n", regs->eip); + printf("EAX: 0x%x\n", regs->eax); + printf("EBP: 0x%x\n", regs->ebp); + break; + + case 2: + // NMI Interrupt + printf("#NMI\n"); + break; + + case 3: + // Breakpoint Exception #BP + printf("#BP\n"); + printf("EIP: 0x%x\n", regs->eip); + printf("EAX: 0x%x\n", regs->eax); + printf("EBP: 0x%x\n", regs->ebp); + break; + + case 4: + // Overflow Exception #OF + printf("#OF\n"); + printf("EIP: 0x%x\n", regs->eip); + printf("EAX: 0x%x\n", regs->eax); + printf("EBP: 0x%x\n", regs->ebp); + break; + + case 5: + // BOUND Range Exceeded Exception #BR + printf("#BR\n"); + printf("EIP: 0x%x\n", regs->eip); + printf("EAX: 0x%x\n", regs->eax); + printf("EBP: 0x%x\n", regs->ebp); + break; + + case 6: + // Invalid OpCode Exception #UD + printf("#UD\n"); + printf("EIP: 0x%x\n", regs->eip); + printf("EAX: 0x%x\n", regs->eax); + printf("EBP: 0x%x\n", regs->ebp); + break; + + case 7: + // Device Not Available Exception #NM + printf("#NM\n"); + printf("EIP: 0x%x\n", regs->eip); + printf("EAX: 0x%x\n", regs->eax); + printf("EBP: 0x%x\n", regs->ebp); + break; + + case 8: + // Double Fault Exception #DF + printf("#DF\n"); + printf("EIP: 0x%x\n", regs->eip); + printf("EAX: 0x%x\n", regs->eax); + printf("EBP: 0x%x\n", regs->ebp); + while(true); + break; + + case 9: + // Coprocessor Segment Overrun + printf("Coprocessor Segment overrun!\n"); + break; + + case 10: + // Invalid TSS Exception #TS + printf("#TS\n"); + printf("EIP: 0x%x\n", regs->eip); + printf("EAX: 0x%x\n", regs->eax); + printf("EBP: 0x%x\n", regs->ebp); + __asm__("cli;" "1: hlt;" "jmp 1b;"); + break; + + case 11: + // Segment Not Present #NP + printf("#NP\n"); + printf("EIP: 0x%x\n", regs->eip); + printf("EAX: 0x%x\n", regs->eax); + printf("EBP: 0x%x\n", regs->ebp); + break; + + case 12: + // Stack Fault Exception #SS + printf("#SS\n"); + printf("EIP: 0x%x\n", regs->eip); + printf("EAX: 0x%x\n", regs->eax); + printf("EBP: 0x%x\n", regs->ebp); + break; + + case 13:{ + // General Protection Exception #GP + printf("#GP\n"); + + printf("Accessing memory caused a general protection exception.\n"); + printf("Faulting instruction at addres: 0x%x\n", regs->eip ); + printf("Error code: 0x%x\n", regs->err_code); + + if (regs->err_code != 0){ + printf("Fault due to entry at index: 0x%x (%d)\n", (regs->err_code >> 3 & 0xFFF ) , regs->err_code); + + + uint8_t table = regs->err_code >> 1 & 0x3 ; + + if(table == 0 ){ + printf("* Index references GDT\n"); + } + if(table == 1 ){ + printf("* Index references IDT\n"); + } + + if(table == 2 ){ + printf("* Index references LDT\n"); + } + + if(table == 3 ){ + printf("* Index references IDT\n"); + } + + if( regs->err_code & 0x1) + { + printf("* Originated externally!\n"); + } + } + + __asm__("cli;" "1: hlt;" "jmp 1b;"); + + } + break; + + case 14: + // Page Fault Exception #PF + printf("#PF\n"); + #define ALIGN(addr, align) (((addr) & ~((align) - 1)) + (align)) + FaultingAddress = processor::GetCR2(); + + printf("Accessing the linear address 0x%x resulted in a page fault!\n\n", FaultingAddress); + + // Error code of 32 bits are on the stack + // CR2 register contains the 32-bit linear virtual address that generated the exception + // See Intel Software Developers manual Volume 3A Part 1 page 236 for more info + #define PF_ERR_PRESENT_BIT 0x1 + #define PF_ERR_WRITE_BIT 0x2 + #define PF_ERR_USER_BIT 0x3 + #define PF_ERR_RESERVERD_WRITE_BIT 0x4 + #define PF_ERR_INSTRUCTION_FETCH_BIT 0x5 + #define PF_ERR_PROTECTION_KEY_BIT 0x6 + #define PF_ERR_SHADOW_STACK_BIT 0x7 + #define PF_ERR_SOFTWARE_GUARD_EXTENSION_BIT 0xE + + printf("REASON: \n\n"); + + + if (regs->err_code & PF_ERR_PRESENT_BIT ){ + printf("* Page protection violation!\n"); + } else{ + printf("* Page not-present!\n"); + //Immediate_Map(FaultingAddress, FaultingAddress); + + } + + if(regs->err_code & PF_ERR_WRITE_BIT){ + printf("* Write access violation!\n"); + } else{ + printf("* Read access violation!\n"); + } + + if(regs->err_code & PF_ERR_USER_BIT){ + printf("* Violation from user-space (CPL=3)\n"); + } + + if(regs->err_code & PF_ERR_INSTRUCTION_FETCH_BIT){ + printf("* Caused by an instruction fetch. \n"); + } + + + __asm__("cli;" "1: hlt;" "jmp 1b;"); + + break; + + case 16: + // x87 FPU Floating-point Error #MF + printf("#MF\n"); + printf("EIP: 0x%x\n", regs->eip); + printf("EAX: 0x%x\n", regs->eax); + printf("EBP: 0x%x\n", regs->ebp); + break; + + case 17: + // Alignment Check Exception #AC + printf("#AC\n"); + printf("EIP: 0x%x\n", regs->eip); + printf("EAX: 0x%x\n", regs->eax); + printf("EBP: 0x%x\n", regs->ebp); + break; + + case 18: + // Machine-Check Exception #MC + printf("#MC\n"); + printf("EIP: 0x%x\n", regs->eip); + printf("EAX: 0x%x\n", regs->eax); + printf("EBP: 0x%x\n", regs->ebp); + break; + + case 19: + // SIMD Floating-point Exception #XM + printf("#XM\n"); + printf("EIP: 0x%x\n", regs->eip); + printf("EAX: 0x%x\n", regs->eax); + printf("EBP: 0x%x\n", regs->ebp); + break; + + case 20: + // Virtualization Exception #VE + printf("#VE\n"); + printf("EIP: 0x%x\n", regs->eip); + printf("EAX: 0x%x\n", regs->eax); + printf("EBP: 0x%x\n", regs->ebp); + break; + + case 21: + // Control Protection Exception #CP + printf("#CP\n"); + printf("EIP: 0x%x\n", regs->eip); + printf("EAX: 0x%x\n", regs->eax); + printf("EBP: 0x%x\n", regs->ebp); + break; + + case 50: + printf("SYSTEMCALL\n"); + printf("EAX 0x%x\n", regs->eax); + + switch (regs->eax) { + case 0x0: + printf("test!\n"); + break; + case 0x5: + sys_open(); + break; + case 0x10: + sys_read((FILE*)regs->ebx, (char*)regs->ecx); + break; + case 0x20: + sys_write((FILE*)regs->ebx, (const char*)regs->ecx, regs->edx); + break; + case 0x666: + sys_version(); + break; + + }; + break; + default: + // PANIC!!! + break; + } + + + +} + +void irq_handler (registers regs) { + switch (regs.int_no) { + case 0: + pit_tick++; + break; + case 1: + // Keyboard interrupt !! + + int scan; + int i;/*register*/ + + // Read scancode + scan = inb(0x60); + + // Send ack message! + i = inb(0x61); + outb(0x61, i|0x80); + outb(0x61, i); + + // NOTE: check for special scan codes + // e.g. modifiers etc.. + if( scan < 0x37){ + //printf("Read from IO: 0x%x\n", scan); + keyPress.ScanCode = scan ; + //printf( "[From Interrupt] Scancode: %x\n", keyPress.ScanCode); + + } + + + break; + case 12: + // PS2 Mouse interrupt + printf("Mouse event triggered!"); + //int event = inb(0x60); + break; + + default: + //printf("Interrupt happened!"); + //printf("Received INT: 0x%x\n", regs.int_no); + break; + } + + outb(0x20, 0x20); // send end of interrupt to master + + if ( regs.int_no > 8 && regs.int_no <= 15) { + outb(0xA0, 0x20); // send end of interrupt to slave + } + + + if( regs.int_no == 13){ + printf(" Error code: %d \n", regs.err_code); + + } + +} + +void initidt(){ + // Initialize the IDT pointer + idt_ptr.length = sizeof(IDT_entry) * 255; + idt_ptr.base = (uint32_t)&idt_table; + +#ifdef __VERBOSE__ + printf("Init IDT\n"); +#endif + + // TODO: Set everything to zero first + + set_id_entry(0, (uint32_t) irs0 , 0x08, 0x8F); + set_id_entry(1, (uint32_t) irs1 , 0x08, 0x8E); + set_id_entry(2, (uint32_t) irs2 , 0x08, 0x8E); + set_id_entry(3, (uint32_t) irs3 , 0x08, 0x8E); + set_id_entry(4, (uint32_t) irs4 , 0x08, 0x8E); + set_id_entry(5, (uint32_t) irs5 , 0x08, 0x8E); + set_id_entry(6, (uint32_t) irs6 , 0x08, 0x8E); + set_id_entry(7, (uint32_t) irs7 , 0x08, 0x8E); + set_id_entry(8, (uint32_t) irs8 , 0x08, 0x8E); + set_id_entry(9, (uint32_t) irs9 , 0x08, 0x8E); + set_id_entry(10, (uint32_t) irs10 , 0x08, 0x8E); + set_id_entry(11, (uint32_t) irs11 , 0x08, 0x8E); + set_id_entry(12, (uint32_t) irs12 , 0x08, 0x8E); + set_id_entry(13, (uint32_t) irs13 , 0x08, 0x8E); + set_id_entry(14, (uint32_t) irs14 , 0x08, 0x8E); + set_id_entry(15, (uint32_t) irs15 , 0x08, 0x8E); + set_id_entry(16, (uint32_t) irs16 , 0x08, 0x8E); + set_id_entry(17, (uint32_t) irs17 , 0x08, 0x8E); + set_id_entry(18, (uint32_t) irs18 , 0x08, 0x8E); + set_id_entry(19, (uint32_t) irs19 , 0x08, 0x8E); + set_id_entry(20, (uint32_t) irs20 , 0x08, 0x8E); + set_id_entry(21, (uint32_t) irs21 , 0x08, 0x8E); + set_id_entry(22, (uint32_t) irs22 , 0x08, 0x8E); + set_id_entry(23, (uint32_t) irs23 , 0x08, 0x8E); + set_id_entry(24, (uint32_t) irs24 , 0x08, 0x8E); + set_id_entry(25, (uint32_t) irs25 , 0x08, 0x8E); + set_id_entry(26, (uint32_t) irs26 , 0x08, 0x8E); + set_id_entry(27, (uint32_t) irs27 , 0x08, 0x8E); + set_id_entry(28, (uint32_t) irs28 , 0x08, 0x8E); + set_id_entry(29, (uint32_t) irs29 , 0x08, 0x8E); + set_id_entry(30, (uint32_t) irs30 , 0x08, 0x8E); + set_id_entry(31, (uint32_t) irs31 , 0x08, 0x8E); + + set_id_entry(0x50, (uint32_t) irs50, 0x08, 0x8E); + //print_serial("Remapping PIC\n"); + PIC_remap(0x20, 0x28); + + // clear mask for IRQ 12 + uint8_t value = inb(0x21) & ~(1<< 12); + outb(0x21, value); + + + + // pic IRQ Table + set_id_entry(32, (uint32_t)irq0, 0x08, 0x8E); + set_id_entry(33, (uint32_t)irq1, 0x08, 0x8E); // PS2 Keyboard + set_id_entry(34, (uint32_t)irq2, 0x08, 0x8E); + set_id_entry(35, (uint32_t)irq3, 0x08, 0x8E); + set_id_entry(36, (uint32_t)irq4, 0x08, 0x8E); + set_id_entry(37, (uint32_t)irq5, 0x08, 0x8E); + set_id_entry(38, (uint32_t)irq6, 0x08, 0x8E); + set_id_entry(39, (uint32_t)irq7, 0x08, 0x8E); + set_id_entry(40, (uint32_t)irq8, 0x08, 0x8E); + set_id_entry(41, (uint32_t)irq9, 0x08, 0x8E); + set_id_entry(42, (uint32_t)irq10, 0x08, 0x8E); + set_id_entry(43, (uint32_t)irq11, 0x08, 0x8E); + set_id_entry(44, (uint32_t)irq12, 0x08, 0x8E); // PS2 Mouse + set_id_entry(45, (uint32_t)irq13, 0x08, 0x8E); + set_id_entry(46, (uint32_t)irq14, 0x08, 0x8E); + set_id_entry(47, (uint32_t)irq15, 0x08, 0x8E); + + + idt_flush((uint32_t)&idt_ptr); +} diff --git a/kernel/interrupts/idt.h b/kernel/interrupts/idt.h new file mode 100644 index 0000000..9a4d126 --- /dev/null +++ b/kernel/interrupts/idt.h @@ -0,0 +1,78 @@ +#pragma once + +#include +#include +#include "../drivers/vga/colors.h" +#include "../drivers/pic/pic.h" + +#include "../terminal/kterm.h" + + +extern "C" { + struct __attribute__((__packed__)) IDT_entry { + uint16_t offset_1; + uint16_t selector; + uint8_t zero; + uint8_t type_attr; + uint16_t offset_2; + }; + + struct __attribute__((__packed__)) IDT_ptr { + unsigned short length; + unsigned long base; + }; + + struct registers { + uint32_t ds; // Data segment selector + uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed by pusha. + uint32_t int_no, err_code; // Interrupt number and error code (if applicable) + uint32_t eip, cs, eflags, useresp, ss; + }; + + + extern void idt_flush(uint32_t); + void set_id_entry (uint8_t num , uint32_t base, uint16_t sel, uint8_t flags); + void initidt(); + + void irq_handler (registers regs); + + void irs_handler (registers* regs); + + extern void irs0 (); + extern void irs1 (); + extern void irs2 (); + extern void irs3 (); + extern void irs4 (); + extern void irs5 (); + extern void irs6 (); + extern void irs7 (); + extern void irs8 (); + extern void irs9 (); + extern void irs10 (); + extern void irs11 (); + extern void irs12 (); + extern void irs13 (); + extern void irs14 (); + extern void irs15 (); + extern void irs16 (); + extern void irs17 (); + extern void irs18 (); + extern void irs19 (); + extern void irs20 (); + extern void irs21 (); + extern void irs22 (); + extern void irs23 (); + extern void irs24 (); + extern void irs25 (); + extern void irs26 (); + extern void irs27 (); + extern void irs28 (); + extern void irs29 (); + extern void irs30 (); + extern void irs31 (); + extern void irs50(); + + + + +} diff --git a/kernel/interrupts/idt.s b/kernel/interrupts/idt.s new file mode 100644 index 0000000..5e19912 --- /dev/null +++ b/kernel/interrupts/idt.s @@ -0,0 +1,6 @@ + +.globl idt_flush +idt_flush: + mov 4(%esp), %eax + lidt (%eax) + ret diff --git a/src/kernel/io.cpp b/kernel/io/io.cpp similarity index 55% rename from src/kernel/io.cpp rename to kernel/io/io.cpp index 11dbc3b..e3e259b 100644 --- a/src/kernel/io.cpp +++ b/kernel/io/io.cpp @@ -1,23 +1,29 @@ #include "io.h" unsigned char inb_p(unsigned short ){ - + // TODO: implement me! + return 0; } unsigned short inw(unsigned short ){ - +// TODO: implement me! + return 0; } unsigned short inw_p(unsigned short ){ - +// TODO: implement me! + return 0; } -unsigned int inl(unsigned short ){ - +uint32_t inl( int port ){ + unsigned int data; + asm volatile ("inl %w1, %0": "=a" (data): "d" (port)); + return data; } unsigned int inl_p(unsigned short ){ - +// TODO: implement me! + return 0; } -void outb_p(unsigned char , unsigned short ){ +void b_p(unsigned char , unsigned short ){ } void outw(unsigned short , unsigned short ){ @@ -26,9 +32,12 @@ void outw(unsigned short , unsigned short ){ void outw_p(unsigned short , unsigned short ){ } -void outl(unsigned int , unsigned short ){ +void outl( int port , uint32_t data ){ + asm volatile ("outl %0, %1" :: "a" (data), "dn"(port)); } + + void outl_p(unsigned int , unsigned short ){ } @@ -56,4 +65,12 @@ void outsw(unsigned short , const void *, void outsl(unsigned short , const void *, unsigned long ){ - } \ No newline at end of file + } + +void io_wait(void) +{ + /* TODO: This is probably fragile. */ + asm volatile ( "jmp 1f\n\t" + "1:jmp 2f\n\t" + "2:" ); +} \ No newline at end of file diff --git a/src/kernel/io.h b/kernel/io/io.h similarity index 68% rename from src/kernel/io.h rename to kernel/io/io.h index 8b729f9..094d595 100644 --- a/src/kernel/io.h +++ b/kernel/io/io.h @@ -12,21 +12,17 @@ static inline uint8_t inb(uint16_t port) unsigned char inb_p(unsigned short port); unsigned short inw(unsigned short port); unsigned short inw_p(unsigned short port); -unsigned int inl(unsigned short port); +uint32_t inl( int port ); unsigned int inl_p(unsigned short port); static inline void outb(uint16_t port, uint8_t val) { asm volatile ( "outb %0, %1" : : "a"(val), "Nd"(port) ); - /* There's an outb %al, $imm8 encoding, for compile-time constant port numbers that fit in 8b. (N constraint). - * Wider immediate constants would be truncated at assemble-time (e.g. "i" constraint). - * The outb %al, %dx encoding is the only option for all other cases. - * %1 expands to %dx because port is a uint16_t. %w1 could be used if we had the port number a wider C type */ } void outb_p(unsigned char value, unsigned short port); void outw(unsigned short value, unsigned short port); void outw_p(unsigned short value, unsigned short port); -void outl(unsigned int value, unsigned short port); +void outl( int port , uint32_t data ); void outl_p(unsigned int value, unsigned short port); void insb(unsigned short port, void *addr, @@ -40,4 +36,5 @@ void outsb(unsigned short port, const void *addr, void outsw(unsigned short port, const void *addr, unsigned long count); void outsl(unsigned short port, const void *addr, - unsigned long count); \ No newline at end of file + unsigned long count); +void io_wait(); \ No newline at end of file diff --git a/kernel/irq_table.s b/kernel/irq_table.s new file mode 100644 index 0000000..5b20edd --- /dev/null +++ b/kernel/irq_table.s @@ -0,0 +1,55 @@ +.globl irq0 + +.macro IRQ NAME, VECTOR + .globl irq\NAME + irq\NAME: + cli + push $0 + push \VECTOR + jmp irq_common +.endm + +IRQ 0 $0 +IRQ 1 $1 +IRQ 2 $2 +IRQ 3 $3 +IRQ 4 $4 +IRQ 5 $5 +IRQ 6 $6 +IRQ 7 $7 +IRQ 8 $8 +IRQ 9 $9 +IRQ 10 $10 +IRQ 11 $11 +IRQ 12 $12 +IRQ 13 $13 +IRQ 14 $14 +IRQ 15 $15 + + + +irq_common: + pusha + + mov %ds, %ax + push %eax + + mov $0x10, %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + + call irq_handler + + pop %eax + + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + + popa + add $8, %esp # cleans push error and irs code + sti + iret # pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP diff --git a/kernel/irs_table.s b/kernel/irs_table.s new file mode 100644 index 0000000..6ecbb78 --- /dev/null +++ b/kernel/irs_table.s @@ -0,0 +1,87 @@ +.code32 +/* +* Interupt handlers +*/ + +.macro ISR_NOERRORCODE NAME, VECTOR + .globl irs\NAME + irs\NAME: + cli + push $0 + push \VECTOR + jmp irs_common +.endm + +.macro ISR_ERROCODE NAME, VECTOR + .globl irs\NAME + irs\NAME: + cli + push \VECTOR + jmp irs_common +.endm + + +ISR_NOERRORCODE 0 $0 +ISR_NOERRORCODE 1 $1 +ISR_NOERRORCODE 2 $2 +ISR_NOERRORCODE 3 $3 +ISR_NOERRORCODE 4 $4 +ISR_NOERRORCODE 5 $5 +ISR_NOERRORCODE 6 $6 +ISR_NOERRORCODE 7 $7 +ISR_NOERRORCODE 8 $8 +ISR_NOERRORCODE 9 $9 +ISR_NOERRORCODE 10 $10 +ISR_NOERRORCODE 11 $11 +ISR_NOERRORCODE 12 $12 +ISR_NOERRORCODE 13 $13 +ISR_NOERRORCODE 14 $14 +ISR_NOERRORCODE 15 $15 +ISR_NOERRORCODE 16 $16 +ISR_NOERRORCODE 17 $17 +ISR_NOERRORCODE 18 $18 +ISR_NOERRORCODE 19 $19 +ISR_NOERRORCODE 20 $20 +ISR_NOERRORCODE 21 $21 +ISR_NOERRORCODE 22 $22 +ISR_NOERRORCODE 23 $23 +ISR_NOERRORCODE 24 $24 +ISR_NOERRORCODE 25 $25 +ISR_NOERRORCODE 26 $26 +ISR_NOERRORCODE 27 $27 +ISR_NOERRORCODE 28 $28 +ISR_NOERRORCODE 29 $29 +ISR_NOERRORCODE 30 $30 +ISR_NOERRORCODE 31 $31 +ISR_NOERRORCODE 50 $50 + +irs_common: + pusha # Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax + + mov %ds, %ax + push %eax + + /* load the kernel data segment descriptor*/ + + mov $0x10, %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + + mov %esp, %eax + push %eax + + call irs_handler + + pop %eax // pop stack pointer + pop %ebx // reload ther orignal data segment descriptor + mov %bx, %ds + mov %bx, %es + mov %bx, %fs + mov %bx, %gs + + popa + add $8, %esp # cleans push error and irs code + + iret # pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP diff --git a/kernel/kernel.cpp b/kernel/kernel.cpp new file mode 100644 index 0000000..4375be3 --- /dev/null +++ b/kernel/kernel.cpp @@ -0,0 +1,82 @@ +/* + Copyright © Nigel Barink 2023 +*/ +#include "memory/memory.h" +#include "memory/KernelHeap.h" +#include "memory/gdt/gdtc.h" +#include "memory/TaskStateSegment.h" +#include "supervisorterminal/superVisorTerminal.h" +#include "drivers/vga/VBE.h" +#include "pci/pci.h" +#include "drivers/pit/pit.h" +#include "i386/processor.h" +#include "terminal/kterm.h" +#include "interrupts/idt.h" +#include "serial.h" +#include "storage/vfs/vfs.h" +#include "storage/filesystems/FAT/FAT.h" +#include "acpi/acpi.h" +#include "memory/VirtualMemoryManager.h" + + +extern BootInfoBlock* BIB; +extern "C" void LoadGlobalDescriptorTable(); +extern "C" void jump_usermode(); + +void initBootDrive(){ + printf("Boot device: 0x%x\n", BIB->bootDeviceID); + unsigned int part3 = BIB->bootDeviceID & 0xFF; + unsigned int part2 = (BIB->bootDeviceID & 0xFF00) >> 8; + unsigned int part1 = (BIB->bootDeviceID & 0xFF0000) >> 16; + unsigned int drive = (BIB->bootDeviceID & 0xFF000000) >> 24; + if (drive == 0x80 ) + printf("booted from disk!\n"); + if(drive == 0x00) + printf("booted from floppy disk\n"); + + printf("Part1: %d, Part2: %d, Part3: %d\n", part1, part2 , part3); + ATAPIO::Identify(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER); +} + +extern "C" void kernel () +{ + init_serial(); + kterm_init(); + print_serial("kterm initialized...\n"); + setup_tss(); + initGDT(); + initidt(); + LoadGlobalDescriptorTable(); + flush_tss(); + printf("Memory setup complete!\n"); + print_serial("Memory initialized....\n"); + // Enable interrupts + asm volatile("STI"); + initHeap(); + print_serial("Heap initialized...\n"); + //pit_initialise(); + + + //ACPI::initialize(); + //PCI::Scan(); + processor::initialize(); + processor::enable_protectedMode(); + initBootDrive(); + VirtualFileSystem::initialize(); + + print_serial("Run test!"); +#define VFS_EXAMPLE +#ifdef VFS_EXAMPLE + auto fontFile = VirtualFileSystem::open("/FONT PSF", 0); + printf("Size of font file: %d bytes", fontFile->root->size); // COOL This Works like a charm +#endif + +#ifdef USERMODE_RELEASE + // Lets jump into user mode + jump_usermode(); +#else + startSuperVisorTerminal(); + +#endif + +} \ No newline at end of file diff --git a/kernel/kernel.h b/kernel/kernel.h new file mode 100644 index 0000000..0b861f8 --- /dev/null +++ b/kernel/kernel.h @@ -0,0 +1,8 @@ +#pragma once + +#define CHECK_FLAG(flags, bit) ((flags) & (1 <<(bit))) +#define PANIC(message) {return;} + + + + diff --git a/kernel/linker.ld b/kernel/linker.ld new file mode 100644 index 0000000..666bc28 --- /dev/null +++ b/kernel/linker.ld @@ -0,0 +1,45 @@ +ENTRY(_start) + +/* Tell where the various sections of the object files will be put in the final + kernel image. */ +SECTIONS +{ + . = 0x00100000; /* place code at 1MB mark*/ + + _kernel_start = .; + kernel_begin = .; /* For legacy reasons */ + + .multiboot.data : { + *(.multiboot.data) + } + + .multiboot.text : { + *(multiboot.text) + } + + . += 0xC0000000; /* Addresses in the following code need to be above the 3Gb mark */ + .text ALIGN (4K) : AT (ADDR (.text) - 0xC0000000) + { + *(.text) + } + .rodata ALIGN (4K) : AT (ADDR (.rodata) - 0xC0000000) + { + *(.rodata) + *(.symtab) + } + .data ALIGN (4K) : AT (ADDR (.data) - 0xC0000000) + { + *(.data) + } + .bss ALIGN (4K) : AT (ADDR (.bss) - 0xC0000000) + { + *(COMMON) + *(.bss) + *(.bootstrap_stack) + } + + + _kernel_end = .; + kernel_end = .; /* For legacy reasons */ +} + diff --git a/kernel/memory/KernelHeap.cpp b/kernel/memory/KernelHeap.cpp new file mode 100644 index 0000000..c935fb1 --- /dev/null +++ b/kernel/memory/KernelHeap.cpp @@ -0,0 +1,86 @@ +#include "KernelHeap.h" +#include "VirtualMemoryManager.h" +extern "C" const uint32_t kernel_end; +// Size of heap metadata is 5 bytes +struct heap_block{ + uint8_t Used; + uint32_t Size; +}; + +uint32_t heap_size; +heap_block* start ; + +void* malloc(size_t size) +{ + //printf("Received request for %d bytes of memory\n", size); + heap_block* current = start; + + // look for a free block + while(current < start + heap_size) + { + if(current->Size >= size && current->Used == false ) + { + // We found a spot + // printf("Block found!\n"); + + // Set the spot to in-use + current->Used = true; + + + // split the block + //printf("Split block.\n"); + uint32_t oldSize = current->Size; + current->Size = size; + + heap_block* new_block = current + sizeof(heap_block) + current->Size; + new_block->Size = oldSize - ( sizeof(heap_block) + size); + new_block->Used = false; + + // return the free address + // NOTE: added an offset from the initial address to accomodate for + // meta-data. + return current + sizeof(heap_block); + + } + + current += current->Size + sizeof(heap_block); + } + + // If we are here we need more memory so we should + // probably ask the VMM for more + // TODO: ask for more memory | Extend kernel heap + + printf("ERROR: OUT OF HEAP MEMORY CONDITION IS NOT IMPLEMENTED. HEAP NEEDS TO BE EXTENDED!\n"); +} + +void free(void* addr) +{ + // clear the free boolean that corresponds to this adddress + // This should be fairly simple + heap_block* allocatedBlock = (heap_block*)((uint32_t)addr - sizeof(heap_block)); + allocatedBlock->Used = false; +} + +void initHeap() +{ + void* HEAP_ADDRESS = allocate_block(); + printf("0x%x HEAP Paddr\n", HEAP_ADDRESS); + + Immediate_Map((uint32_t)HEAP_ADDRESS + 0xC0000000, (uint32_t)HEAP_ADDRESS ); + start = (heap_block*) ((uint32_t)HEAP_ADDRESS + 0xC0000000); + heap_size = 4096; + + printf("Clear heap\n"); + // Clear the heap + printf("set at 0x%x %d bytes to zero\n", start , heap_size); + + memset((void*)start, 0x00, heap_size /4); + + + printf("Init first heap block\n"); + // initialzie + start->Size = heap_size - sizeof(heap_block); + + start->Used = false; + +} \ No newline at end of file diff --git a/kernel/memory/KernelHeap.h b/kernel/memory/KernelHeap.h new file mode 100644 index 0000000..c6f87af --- /dev/null +++ b/kernel/memory/KernelHeap.h @@ -0,0 +1,10 @@ +#pragma once +#include +#include +#include "../terminal/kterm.h" + +void initHeap(); + +void* malloc (size_t size ); +void free(void* addr); + diff --git a/kernel/memory/PageDirectory.cpp b/kernel/memory/PageDirectory.cpp new file mode 100644 index 0000000..5e4ab31 --- /dev/null +++ b/kernel/memory/PageDirectory.cpp @@ -0,0 +1,43 @@ +#include "PageDirectory.h" + +void PageDirectory::enable() +{ + + + // https://wiki.osdev.org/Setting_Up_Paging + //set each entry to not present + // int i; + // for(i = 0; i < 1024; i++) + // { + // // This sets the following flags to the pages: + // // Supervisor: Only kernel-mode can access them + // // Write Enabled: It can be both read from and written to + // // Not Present: The page table is not present + // this->page_directory[i] = 0x00000002; + // } + + // // holds the physical address where we want to start mapping these pages to. + // // in this case, we want to map these pages to the very beginning of memory. + + // //we will fill all 1024 entries in the table, mapping 4 megabytes + // for(unsigned int i = 0; i < 1024; i++) + // { + // // As the address is page aligned, it will always leave 12 bits zeroed. + // // Those bits are used by the attributes ;) + // first_page_table[i] = (i * 0x1000) | 3; // attributes: supervisor level, read/write, present. + // } + + // // attributes: supervisor level, read/write, present + // this->page_directory[0] = ((unsigned int)first_page_table) | 3; + + printf("Enable Paging!\n"); + + loadPageDirectory(this->page_directory); + enablePaging(); +} + + +void PageDirectory::MapPhysicalToVirtualAddress ( address_t PAddress , address_t VAddress, uint32_t size ) +{ + +} diff --git a/kernel/memory/PageDirectory.h b/kernel/memory/PageDirectory.h new file mode 100644 index 0000000..c5c5479 --- /dev/null +++ b/kernel/memory/PageDirectory.h @@ -0,0 +1,31 @@ +#pragma once +#include +#include "./memory.h" +#include "./../terminal/kterm.h" +#define KB 1024 + + +typedef uintptr_t address_t; + +static const int MAX_PAGES = 1024 * KB; // 4GB , 4kB/page +static volatile address_t pmem_stack[MAX_PAGES]; +static volatile address_t pmem_stack_top = MAX_PAGES; // top down allocation + +extern "C" void loadPageDirectory (uint32_t* addr ); +extern "C" void enablePaging(); + +struct page_directory_entry {}; +struct page_table_entry{}; + + + +class PageDirectory { + public: + void enable (); + void MapPhysicalToVirtualAddress ( address_t PAddress , address_t VAddress, uint32_t size ); + + private: + uint32_t page_directory[1024] __attribute__((aligned(4096))); // align on 4 kiloByte pages + uint32_t first_page_table[1024] __attribute__((aligned(4096))); // align on 4 kiloByte pages + +}; \ No newline at end of file diff --git a/kernel/memory/PhysicalMemoryManager.cpp b/kernel/memory/PhysicalMemoryManager.cpp new file mode 100644 index 0000000..3d78798 --- /dev/null +++ b/kernel/memory/PhysicalMemoryManager.cpp @@ -0,0 +1,115 @@ +#include "./PhysicalMemoryManager.h" +#define IS_ALIGNED(addr, align) !((addr) & ~((align) - 1)) +#define ALIGN(addr, align) (((addr) & ~((align) - 1 )) + (align)) + +const uint32_t KERNEL_OFFSET = 0xC0000000; + +uint32_t* memoryBitMap; +uint32_t pmmap_size; +uint32_t max_blocks; +int used_blocks; + + +void SetupPhysicalMemoryManager(uint32_t mapAddress, uint32_t memorySize ) +{ + /* + Every byte contains 8 pages + A page is 4096 kib + Every block (1 bit) represent an page + */ + + // Set the maximum number of blocks + max_blocks = (uint32_t)memorySize / BLOCK_SIZE ; + printf("Max Blocks: %d\n", max_blocks); + + // Set size of the bitmap + uint32_t bitmap_size = max_blocks / 32; + printf("Bitmap size: %d bytes\n",bitmap_size); + + // Set blocks used to zero + used_blocks = max_blocks; + + // set the address of the memory bitmap + memoryBitMap = (uint32_t*) mapAddress; + + // Set all places in memory as free + memset(memoryBitMap, 0xFFFFFFFF, max_blocks / 32 ); +} + +// NOTE: This can only give blocks of 4kb at a time! +// We might at some point want to allocate multiple blocks at once. +void* allocate_block() { + uint8_t blocks_available = max_blocks - used_blocks; + // Are there any blocks available? + if( blocks_available <= 0) + { + printf("No blocks available. Blocks Delta: 0x%x\n", blocks_available); + return 0; + } + + // Find 1 free block somewhere + int free_block_index = bitmap_first_unset(memoryBitMap, max_blocks / 8 ); + + if(free_block_index == -1) + { + printf("Could not find a good block!\n"); + // Could not find a block + return (void*)0xFFFF; + } + + if(free_block_index == 0) + printf("Somethings wrong!!!\n"); + + // Set the block to be used! + bitmap_unset(memoryBitMap, free_block_index); + // Increase the used_block count! + used_blocks++; + printf("used blocks: 0x%x\n", used_blocks); + // return the pointer to the physical address + return (void*) (BLOCK_SIZE * free_block_index); +} + +void free_block(void* p) { + // If it is a null pointer we don't need to do anything. + if(p==0) { + return; + } + // calculate the index into the bitmap + int index = ((uint32_t) p) / BLOCK_SIZE; + + // set the block to be free + bitmap_set(memoryBitMap, index); + used_blocks--; + printf("used blocks: 0x%x, after free\n", used_blocks); + +} + +void allocate_region(uint32_t startAddress, uint32_t size) { + // every bit should be 4KiB + // every byte is 8*4KiB = 32KiB + + int NumberOfBlocksToAllocate = ( size / 1024) / 4 / 8 + 1; + int startBlock = (startAddress / 1024) / 4 / 8 ; + + for( int i = 0; i < NumberOfBlocksToAllocate; i++) + { + bitmap_unset(memoryBitMap, startBlock + i);// allocate region causes #PF Exception + used_blocks++; + } +} + +void deallocate_region(uint32_t StartAddress , uint32_t size ) { + // reverse of what happened in allocate_region + int NumberOfBlocks = (size / 1024) / 4 / 8 + 1; + int startBlock = (StartAddress / 1024) / 4 / 8; + + for(int i = 0; i < NumberOfBlocks; i++) + { + bitmap_set(memoryBitMap, startBlock + i); + used_blocks --; + } +} + +int GetUsedBlocks (){ + return used_blocks; +} diff --git a/kernel/memory/PhysicalMemoryManager.h b/kernel/memory/PhysicalMemoryManager.h new file mode 100644 index 0000000..f83fff1 --- /dev/null +++ b/kernel/memory/PhysicalMemoryManager.h @@ -0,0 +1,20 @@ +#pragma once +#include +#include + +#include "../prekernel/bootstructure.h" +#include "../terminal/kterm.h" +#include "../bitmap.h" + +#define BLOCK_SIZE 4092 + + +void SetupPhysicalMemoryManager(uint32_t mapAddress, uint32_t memorySize); + +void* allocate_block(); +void free_block(void* ptr); + +void allocate_region(uint32_t address, uint32_t size); +void deallocate_region(uint32_t address, uint32_t size); + +int GetUsedBlocks(); \ No newline at end of file diff --git a/kernel/memory/TaskStateSegment.h b/kernel/memory/TaskStateSegment.h new file mode 100644 index 0000000..f26b3ec --- /dev/null +++ b/kernel/memory/TaskStateSegment.h @@ -0,0 +1,60 @@ +#pragma once +#include "gdt/gdtc.h" +#include + +struct TaskStateSegment { + uint32_t prev_tss; + uint32_t esp0; + uint32_t ss0; + // everythinge else is unused + uint32_t esp1; + uint32_t ss1; + uint32_t esp2; + uint32_t ss2; + uint32_t cr3; + uint32_t eip; + uint32_t eflags; + uint32_t eax; + uint32_t ecx; + uint32_t edx; + uint32_t ebx; + uint32_t esp; + uint32_t ebp; + uint32_t esi; + uint32_t edi; + uint32_t es; + uint32_t cs; + uint32_t ss; + uint32_t ds; + uint32_t fs; + uint32_t gs; + uint32_t ldt; + uint16_t trap; + uint16_t iomap_base; +}__attribute__((packed)); + + +TaskStateSegment tss0 ={}; + +inline void flush_tss() +{ + asm volatile("mov $0x2B, %ax ; ltr %ax"); +} + +void setup_tss(){ + // ensure the tss is zero'd + memset((void*)&tss0, 0, sizeof(tss0)); + tss0.ss0 = (uint32_t) &GlobalDescriptorTable[KERNEL_DATA_SEGMENT]; + + extern uint32_t stack_top; + tss0.esp0 = (unsigned long)&stack_top; + + // Task Segment Descriptor + + uint32_t address = (unsigned long) &tss0; + uint32_t size = sizeof(tss0); + uint32_t limit = (address + size ); + + add_descriptor(TASK_STATE_SEGMENT, address, limit- 1, 0xE9, 0x0); +} + diff --git a/kernel/memory/VirtualMemoryManager.cpp b/kernel/memory/VirtualMemoryManager.cpp new file mode 100644 index 0000000..a8ec187 --- /dev/null +++ b/kernel/memory/VirtualMemoryManager.cpp @@ -0,0 +1,130 @@ +#include "VirtualMemoryManager.h" +#include "../../CoreLib/Memory.h" + +#define ALIGN(addr, align) (((addr) & ~((align) - 1 )) + (align)) + +extern uint32_t boot_page_directory[1024] ; // points to the wrong location + +extern uint32_t boot_page_table[1024]; + + +void flush_cr3(){ + asm volatile("movl %cr3, %ecx;" + "movl %ecx, %cr3"); +} + + +void AllocatePage(uint32_t vaddr) +{ + //uint32_t page_aligned_address = ALIGN(vaddr, 4096); + + // allocate a page at virtual address + int PageDirectoryEntryIndex = vaddr >> 22; + int PageTableEntryIndex = (vaddr >> 12) & 0x1FFF; + + printf("Allocation happening at PDE: %d PTE: %d\n", PageDirectoryEntryIndex, PageTableEntryIndex); + + // check if the page directory entry is marked as present + if (boot_page_directory[PageDirectoryEntryIndex] & 0x1 ) + { + printf("Directory entry is marked as present\n"); + uint32_t* page_table = (uint32_t*)((boot_page_directory[PageDirectoryEntryIndex]) & 0xFFFFE000) ; + //page_table = (uint32_t*) ((uint32_t)page_table + 0xC0000000); // Add kernel offset + printf("Page table address: 0x%x\n", (uint32_t)&page_table); + + // check if the page table entry is marked as present + if ( page_table[PageTableEntryIndex] & 0x1 ) + { + printf("page already present!\n"); + } else{ + printf("Mapping a physical page.\n"); + // Map the entry to a physical page + page_table[PageTableEntryIndex] = (uint32_t)allocate_block() | 0x3; + } + + } else { + printf("Mapping a new page directory entry with a page table\n"); + // mark the page table as present and allocate a physical block for it + boot_page_directory[PageDirectoryEntryIndex] = (uint32_t)allocate_block() | 0x3; + + } + + asm ("cli; invlpg (%0); sti" :: "r" (vaddr) : "memory" ); + + +} + +void FreePage(uint32_t vaddr ) +{ + // uint32_t page_aligned_address = ALIGN(vaddr, 4096); + + // allocate a page at virtual address + int PageDirectoryEntryIndex = vaddr >> 22; + int PageTableEntryIndex = (vaddr >> 12) & 0x1FFF; + + uint32_t* pageTable = (uint32_t*)(boot_page_directory[PageDirectoryEntryIndex] & (0xFFFFE000 + 0xC0000000)); + + + void* physicalAddressToFree = (void*)(pageTable[PageTableEntryIndex] & (0xFFFFE000 + 0xC0000000)); + free_block(physicalAddressToFree); + + pageTable[PageTableEntryIndex] = 0x0; + + +} + + +void Immediate_Map ( uint32_t vaddr, uint32_t paddr) +{ + printf("map 0x%x to 0x%x\n", paddr, vaddr); + // allocate a page at virtual address + int PageDirectoryEntryIndex = vaddr >> 22; + int PageTableEntryIndex = (vaddr >> 12) & 0x1FFF; + + printf("Map address at PDE 0x%x PTE 0x%x\n", PageDirectoryEntryIndex, PageTableEntryIndex); + printf("boot pagedirectoy address: 0x%x\n", &boot_page_directory); + printf("PDE : 0x%x\n", boot_page_directory[PageTableEntryIndex]); + if (boot_page_directory[PageDirectoryEntryIndex] & 0x1 ) { + printf("Directory entry is marked as present\n"); + + } else { + printf("Mapping a new page directory entry with a page table\n"); + // mark the page table as present and allocate a physical block for it + + void* new_page_dir = allocate_block(); + memset(new_page_dir, 0 , 1024 * sizeof (uint32_t)); + printf("New page directory address 0x%x\n", &new_page_dir); + boot_page_directory[PageDirectoryEntryIndex] = (uint32_t)new_page_dir | 0x3; + } + + printf("PDE found at : 0x%x\n", (uint32_t) &boot_page_directory[PageDirectoryEntryIndex]); + uint32_t* page_table = (uint32_t*)(boot_page_directory[PageDirectoryEntryIndex] & 0xFFFFE000) ; + printf("Page table address: 0x%x\n", (uint32_t)page_table); + + // check if the page table entry is marked as present + if ( page_table[PageTableEntryIndex] & 0x1 ) + { + printf("page already present!\n"); + printf("Entry found at addr: 0x%x\n", &(page_table[PageTableEntryIndex])); + } else{ + printf("Mapping a physical page.\n"); + // Map the entry to a physical page + page_table[PageTableEntryIndex] = (uint32_t)(paddr | 0x3); + } + + + asm ("invlpg (%0)" :: "r" (vaddr) : "memory" ); +} + + +// NOT IMPLEMENTED +void Immediate_Unmap(uint32_t vaddr) +{ + // NOTE: I will implement lazy unmapping for now + //uint32_t page_aligned_address = ALIGN(vaddr, 4096); + + // allocate a page at virtual address + //int PageDirectoryEntryIndex = vaddr >> 22; + //int PageTableEntryIndex = (vaddr >> 12) & 0x1FFF; + +} diff --git a/kernel/memory/VirtualMemoryManager.h b/kernel/memory/VirtualMemoryManager.h new file mode 100644 index 0000000..1298c2b --- /dev/null +++ b/kernel/memory/VirtualMemoryManager.h @@ -0,0 +1,16 @@ +#pragma once +#include "../terminal/kterm.h" +#include "../i386/processor.h" +#include "PhysicalMemoryManager.h" + + +void SetupVMM(); + +void AllocatePage(uint32_t v_addr ); +void FreePage(uint32_t v_addr); + +void Immediate_Map(uint32_t vaddr, uint32_t paddr); +void Immediate_Unmap (uint32_t v_addr); + +// void Demand_map(uint32_t p_addr, uint32_t v_addr); +// void Demand_Unmap (uint32_t v_addr); diff --git a/kernel/memory/gdt/gdt.s b/kernel/memory/gdt/gdt.s new file mode 100644 index 0000000..95859c2 --- /dev/null +++ b/kernel/memory/gdt/gdt.s @@ -0,0 +1,19 @@ +.global LoadGlobalDescriptorTable + + LoadGlobalDescriptorTable: + lgdt gdtDescriptor + + movw $16, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + movw %ax, %ss + + jmp $8,$flush + + flush: + ret + + + diff --git a/kernel/memory/gdt/gdtc.cpp b/kernel/memory/gdt/gdtc.cpp new file mode 100644 index 0000000..a73b776 --- /dev/null +++ b/kernel/memory/gdt/gdtc.cpp @@ -0,0 +1,46 @@ +#include "gdtc.h" +#include "../../terminal/kterm.h" + + +SegmentDescriptor GlobalDescriptorTable[6]; +GlobalDescriptorTableDescriptor gdtDescriptor; + + +void add_descriptor(int which , unsigned long base, unsigned long limit, unsigned char access, unsigned char granularity ){ + GlobalDescriptorTable[which].base_low = (base & 0xFFFF ); + GlobalDescriptorTable[which].base_middle = (base >> 6) & 0xFF; + GlobalDescriptorTable[which].base_high = (base >> 24) & 0xFF; + + GlobalDescriptorTable[which].limit_low = (limit & 0xFFFF); + GlobalDescriptorTable[which].granularity = ((limit >> 16) & 0x0F); + + GlobalDescriptorTable[which].granularity |= (granularity & 0xF0); + GlobalDescriptorTable[which].access = access; + +} + + + + +void initGDT(){ + + // NULL segment + add_descriptor(NULL_SEGMENT, 0,0,0,0); + + // Kernel Code Segment + add_descriptor(KERNEL_CODE_SEGMENT, 0, 0xFFFFFFFF, 0x9A, 0xCF); + + // Kernel Data Segment + add_descriptor(KERNEL_DATA_SEGMENT, 0, 0xFFFFFFFF, 0x92, 0xCF); + + // User Code Segment + add_descriptor(USER_CODE_SEGMENT, 0, 0xFFFFFFFF, 0xFA, 0xCF); + + // User Data Segement + add_descriptor(USER_DATA_SEGMENT, 0, 0xFFFFFFFF, 0xF2, 0xCF); + + // init Gdt Descriptor + gdtDescriptor.limit = ((sizeof(SegmentDescriptor ) * 6 ) - 1); + gdtDescriptor.base = (unsigned int) (&GlobalDescriptorTable); + +} diff --git a/kernel/memory/gdt/gdtc.h b/kernel/memory/gdt/gdtc.h new file mode 100644 index 0000000..bf914a0 --- /dev/null +++ b/kernel/memory/gdt/gdtc.h @@ -0,0 +1,35 @@ +#pragma once +#include + + +#define NULL_SEGMENT 0 +#define KERNEL_CODE_SEGMENT 1 +#define KERNEL_DATA_SEGMENT 2 +#define USER_CODE_SEGMENT 3 +#define USER_DATA_SEGMENT 4 +#define TASK_STATE_SEGMENT 5 + + + +struct SegmentDescriptor { + unsigned short limit_low; + unsigned short base_low; + unsigned char base_middle; + unsigned char access; + unsigned char granularity; + unsigned char base_high; +}__attribute__((packed)); + +extern SegmentDescriptor GlobalDescriptorTable[6]; + +struct GlobalDescriptorTableDescriptor{ + unsigned short limit; + unsigned int base; +}__attribute__((packed)) ; + + + +void add_descriptor(int which , unsigned long base, unsigned long limit, unsigned char access, unsigned char granularity ); + + +void initGDT(); diff --git a/kernel/memory/memory.cpp b/kernel/memory/memory.cpp new file mode 100644 index 0000000..b72e786 --- /dev/null +++ b/kernel/memory/memory.cpp @@ -0,0 +1,142 @@ +#include "./memory.h" +uint32_t* memoryBitMap; +/* + +*/ +void PhysicalMemory::setup( MemoryInfo* memory) { + + // calculate the maximum number of blocks + max_blocks = KB_TO_BLOCKS(memory->TotalMemory); + + used_blocks = 0; + + memoryBitMap = (uint32_t*) 0x00a00000; + + + printf("Maximum Number of blocks: 0x%x, Number of bytes for memMap: 0x%x\n", max_blocks , (max_blocks/8)); + + //Size of memory map + uint32_t memMap_size = (max_blocks / 8 ) ; + + printf("Memory Map size: 0x%x\n", memMap_size ); + printf("size of int in bytes: 0x%x \n" , sizeof(int)); + + // Set all places in memory as free + memset(memoryBitMap, 0xFF, memMap_size ); +} + +// NOTE: this can only give blocks of 4kb at a time! +void* PhysicalMemory::allocate_block() { + uint8_t blocks_available = max_blocks - used_blocks; + // Are there any blocks available? + if( blocks_available <= 0) + { + printf("No blocks available. Blocks Delta: 0x%x\n", blocks_available); + return 0; + } + + // Find 1 free block somewhere + int free_block_index = bitmap_first_unset(memoryBitMap, (max_blocks /8) /*memMap Size*/ ); + + + + if(free_block_index == -1) + { + printf("Could not find a good block!\n"); + // Could not find a block + return (void*)0xFFFF; + } + + if(free_block_index == 0) + printf("Somethings wrong!!!\n"); + + // Set the block to be used! + bitmap_unset(memoryBitMap, free_block_index); + // Increase the used_block count! + used_blocks++; + printf("used blocks: 0x%x\n", used_blocks); + // return the pointer to the physical address + return (void*) (BLOCK_SIZE * free_block_index); +} + + +void PhysicalMemory::free_block(void* p) { + // If it is a null pointer we don't need to do anything. + if(p==0) { + return; + } + // calculate the index into the bitmap + int index = ((uint32_t) p) / BLOCK_SIZE; + + // set the block to be free + bitmap_set(memoryBitMap, index); + used_blocks--; + printf("used blocks: 0x%x, after free\n", used_blocks); + +} + + + +void PhysicalMemory::allocate_region(uint32_t startAddress, uint32_t size) { + // every bit should be 4KiB + // every byte is 8*4KiB = 32KiB + + int NumberOfBlocksToAllocate = ( size / 1024) / 4 / 8 + 1; + int startBlock = (startAddress / 1024) / 4 / 8 ; + + // printf("NumberOfBlocksToAllocate: 0x%x\n", NumberOfBlocksToAllocate); + //printf( "start block: 0x%x\n" , startBlock); + for( int i = 0; i < NumberOfBlocksToAllocate; i++) + { + + //printf("ALLOCATE BLOCK: 0x%x\n" , startBlock + i ); + bitmap_unset(memoryBitMap, startBlock+ i); + used_blocks++; + } + + +} +void PhysicalMemory::deallocate_region(uint32_t StartAddress , uint32_t size ) { + // NOT IMPLEMENTED YET +} + + +void mapMultibootMemoryMap( MemoryInfo* memInfo , multiboot_info_t *mbt) { + printf("mmap_addr = 0x%x, mmap_length = 0x%x\n", + (unsigned) mbt->mmap_addr, (unsigned) mbt->mmap_length); + multiboot_memory_map_t *mmap = (multiboot_memory_map_t*) mbt->mmap_addr; + + for (; (unsigned long) mmap < mbt->mmap_addr + mbt->mmap_length; mmap = (multiboot_memory_map_t *) ((unsigned long) mmap + mmap->size + sizeof(mmap->size))){ + + if ( mmap->type == MULTIBOOT_MEMORY_AVAILABLE){ + + memInfo->TotalMemory += mmap->len; + } else { + memInfo->ReservedMemory += mmap->len; + } + + print_Multiboot_memory_Map(mmap); + + } + +} + + +/** + * @brief Debug Verbose functions + * + * @param mmap + */ + +void print_Multiboot_memory_Map(multiboot_memory_map_t* mmap) { + printf( + "size = 0x%x, base_addr = 0x%x%08x, length = 0x%x%08x, type = 0x%x\n", + (unsigned) mmap->size, + (unsigned) (mmap->addr >> 32), + (unsigned) (mmap->addr & 0xffffffff), + (unsigned) (mmap->len >> 32), + (unsigned) (mmap->len & 0xffffffff), + (unsigned) mmap->type + ); +} + diff --git a/kernel/memory/memory.h b/kernel/memory/memory.h new file mode 100644 index 0000000..1f2df61 --- /dev/null +++ b/kernel/memory/memory.h @@ -0,0 +1,46 @@ +#pragma once +#include +#include + +#include "memoryinfo.h" +#include "../prekernel/multiboot.h" +#include "../terminal/kterm.h" +#include + +#include "../bitmap.h" + +#define BLOCK_SIZE 4092 +#define BLOCKS_PER_WORD 32 // A word is 16 bit in x86 machines according to my google search results! + +#define KB_TO_BLOCKS(x) (x / BLOCK_SIZE) +#define IS_ALIGNED(addr, align) !((addr) & ~((align) - 1)) +#define ALIGN(addr, align) (((addr) & ~((align) - 1 )) + (align)) + +void initialise_available_regions(uint32_t memoryMapAddr, uint32_t memoryMapLastAddr, uint32_t* memoryBitMap, int* used_blocks); + +extern uint32_t* memoryBitMap; + +class PhysicalMemory +{ + public: + void setup(MemoryInfo* memory); + void destroy(); + void free_block(void* ptr); + void* allocate_block(); + void allocate_region(uint32_t, uint32_t); + void deallocate_region(uint32_t , uint32_t ); + + private: + size_t pmmap_size; + size_t max_blocks; + int used_blocks; +}; + +void mapMultibootMemoryMap( MemoryInfo* memInfo , multiboot_info_t *mbt); + +/** + * @brief Debug Verbose Functions + * + * @param mmap + */ +void print_Multiboot_memory_Map(multiboot_memory_map_t* mmap); diff --git a/kernel/memory/memoryinfo.h b/kernel/memory/memoryinfo.h new file mode 100644 index 0000000..9bbb626 --- /dev/null +++ b/kernel/memory/memoryinfo.h @@ -0,0 +1,20 @@ +#pragma once +#include +#include + +struct MemoryArea{ + void* StartAddress; + size_t Size; + unsigned int type; + MemoryArea* Next; + +}__attribute__((packed)); + +struct MemoryInfo { + uint32_t TotalMemory; + uint32_t ReservedMemory; + MemoryArea* MemoryRegionList; +}__attribute__((packed)); + + + diff --git a/kernel/memory/paging.s b/kernel/memory/paging.s new file mode 100644 index 0000000..fa25003 --- /dev/null +++ b/kernel/memory/paging.s @@ -0,0 +1,20 @@ +.globl enablePaging +enablePaging: + push %ebp + mov %esp, %ebp + mov %cr0, %eax + or $0x80000000, %eax + mov %eax, %cr0 + mov %ebp, %esp + pop %ebp + ret + +.globl loadPageDirectory +loadPageDirectory: + push %ebp + mov %esp, %ebp + mov 8(%esp), %eax + mov %eax, %cr3 + mov %ebp, %esp + pop %ebp + ret diff --git a/kernel/pci/pci.cpp b/kernel/pci/pci.cpp new file mode 100644 index 0000000..ba0fade --- /dev/null +++ b/kernel/pci/pci.cpp @@ -0,0 +1,164 @@ +#include "pci.h" + +void PCI::Scan(){ + + int devicesFound = 0; + + printf("Start finding devices, Found: %d devices"); + // loop through all possible busses, devices and their functions; + for( int bus = 0 ; bus < 256 ; bus++) + { + + for(int device = 0; device < 32 ; device ++) + { + int function = 0; + + uint64_t DeviceIdentify = PCI::ConfigReadWord(bus, device, function,0x0); + uint32_t DeviceID = GetDevice(bus, device, function) >> 16; + + if( DeviceID != 0xFFFF){ + PCIBusAddress busAddress = + PCIBusAddress{bus, device, function }; + + PrintPCIDevice(busAddress); + + // iterate over the functions if it is a multi function device! + if( PCI::IsMultiFunctionDevice(busAddress) ){ + printf("Multi function device! \n"); + printf("Check remaining Functions\n"); + for ( function = 1 ; function < 8; function++) + { + uint32_t DeviceID = GetDevice(bus, device, function) >> 16; + + if( DeviceID != 0xFFFF){ + PCIBusAddress busAddress2 = PCIBusAddress{bus, device, function}; + PrintPCIDevice(busAddress2); + devicesFound++; + } + } + + } + + + devicesFound++; + } + } + + } + + printf("Found %d PCI devices!\n", devicesFound); +} + +const char* PCI::getClassName (uint8_t ClassCode){ + bool isKnown = (ClassCode < PCI::KnownClassCodes); + return isKnown ? PCI::ClassCodeNames[ClassCode].name : "Unknown ClassCode"; +} + +const char* PCI::getVendor( uint32_t VendorID){ + switch (VendorID) + { + case 0x8086: + return "Intel Corporation"; + break; + + case 0x10DE: + return "NVIDIA Corporation"; + break; + + case 0x1022: + return "Advanced Micro Devices, Inc.[AMD]"; + break; + + case 0x1002: + return "Advanced Micor Devices, Inc.[AMD/ATI]"; + break; + + case 0xbeef: + return "VirtualBox Graphics Adapter"; + break; + + case 0xcafe: + return "VirtualBox Guest Service"; + break; + + default: + return "Vendor Unkown"; + break; + } + +} + +uint64_t PCI::GetDevice (int bus, int device, int function ){ + return PCI::ConfigReadWord(bus, device, function,0x0); +} + +bool PCI::IsMultiFunctionDevice(PCIBusAddress& PCIDeviceAddress) +{ + uint32_t header_information = ConfigReadWord(PCIDeviceAddress, 0xC); + return (((header_information>>16) + & 0x80) + >> 7 ); +} + +uint16_t PCI::GetClassCodes( PCIBusAddress& PCIDeviceAddress ){ + return (uint16_t)(ConfigReadWord(PCIDeviceAddress, 0x8) >> 16); +} + +uint8_t PCI::GetHeaderType( PCIBusAddress& PCIDeviceAddress ){ + uint32_t header_information = ConfigReadWord(PCIDeviceAddress , 0xC); + return (uint8_t) ( + ((header_information >> 16) //Get higher half + & 0x00FF) // Select the last two bytes + & 0x7F ); // Mask bit 7 as it indicates if the device is a mulit function device! +} + +uint32_t PCI::ConfigReadWord (uint8_t bus, uint8_t device, uint8_t func, uint8_t offset){ + uint32_t address; + + address = (uint32_t) ( + ((uint32_t) 1 << PCI_ENABLE_ADDR_SHIFT) | + ((uint32_t)bus << PCI_BUS_ADDR_SHIFT) | + ((uint32_t)device << PCI_DEVICE_ADDR_SHIFT) | + ((uint32_t)func << PCI_FUNCTION_ADDR_SHIFT) | + offset ); + + outl(CONFIG_ADDRESS, address); + + + return inl(CONFIG_DATA); +} + +uint8_t PCI::GetProgIF (PCIBusAddress& PCIDeviceAddress){ + uint32_t data = ConfigReadWord(PCIDeviceAddress, 0x8); + return ((data >> 8) & 0xFF); +} + +uint32_t PCI::ConfigReadWord ( PCIBusAddress& PCIDeviceAddress , uint8_t offset){ + outl(CONFIG_ADDRESS , PCIDeviceAddress.getAddress() | offset ); + return inl(CONFIG_DATA); +} + + +uint32_t PCI::ReadBAR ( PCIBusAddress& PCIDeviceAddress, int bar_number){ + int offsetToBar = 0x10 + (bar_number* 0x4); + return ConfigReadWord(PCIDeviceAddress, offsetToBar); +} + +void PCI::PrintPCIDevice (PCIBusAddress& PCIDeviceAddress) +{ + uint32_t DeviceID = (PCI::GetDevice(PCIDeviceAddress.bus, PCIDeviceAddress.device, PCIDeviceAddress.function) >> 16); + uint32_t VendorID = PCI::GetDevice(PCIDeviceAddress.bus, PCIDeviceAddress.device, PCIDeviceAddress.function) & 0xFFFF; + printf("Device found!\n"); + printf("Bus: %d, Device: %d, function: %d \n", PCIDeviceAddress.bus, PCIDeviceAddress.device, PCIDeviceAddress.function); + printf("DeviceID: 0x%x, Vendor: %s\n", + DeviceID + , PCI::getVendor(VendorID) ); + + uint8_t header_type = PCI::GetHeaderType(PCIDeviceAddress); + printf( "Header type: 0x%x\n", header_type); + + uint16_t deviceClasses = PCI::GetClassCodes(PCIDeviceAddress); + + printf("class: %s, subClass: %d\n\n", PCI::getClassName((deviceClasses >> 8)), deviceClasses & 0xFF); + +} \ No newline at end of file diff --git a/kernel/pci/pci.h b/kernel/pci/pci.h new file mode 100644 index 0000000..d09138f --- /dev/null +++ b/kernel/pci/pci.h @@ -0,0 +1,61 @@ +#pragma once +#include +#include "../io/io.h" +#include "../terminal/kterm.h" +#include "pciDevice.h" + +// Configuration Space Access Mechanism #1 +#define CONFIG_ADDRESS 0xCF8 // Configuration adress that is to be accessed +#define CONFIG_DATA 0xCFC // Will do the actual configuration operation +#define PCI_BUS_ADDR_SHIFT 16 +#define PCI_DEVICE_ADDR_SHIFT 11 +#define PCI_FUNCTION_ADDR_SHIFT 8 +#define PCI_ENABLE_ADDR_SHIFT 31 + +class PCI { +public: + static void Scan(); + static uint32_t ConfigReadWord ( PCIBusAddress& PCIDeviceAddress , uint8_t offset); + static uint8_t GetProgIF (PCIBusAddress& PCIDeviceAddress); + static uint32_t ReadBAR ( PCIBusAddress& PCIDeviceAddress, int bar_number); + static uint32_t ConfigReadWord (uint8_t bus, uint8_t device, uint8_t func, uint8_t offset); + static uint8_t GetHeaderType( PCIBusAddress& PCIDeviceAddress ); + static uint16_t GetClassCodes( PCIBusAddress& PCIDeviceAddress ); + static bool IsMultiFunctionDevice(PCIBusAddress& PCIDeviceAddress); + static uint64_t GetDevice (int bus, int device, int function ); + + + static const char* getClassName (uint8_t ClassCode); + static const char* getVendor( uint32_t VendorID); + static void PrintPCIDevice(PCIBusAddress& PCIDevice); + +private: + struct ClassCode { + const char* name; + uint8_t code; + }; + static constexpr ClassCode ClassCodeNames []= { + {"Unclassified", 0x0}, + {"MassStorage Controller", 0x1}, + {"Network Controller", 0x2}, + {"Display Controller", 0x3}, + {"Multimedia Controller", 0x4}, + {"Memory Controller", 0x5}, + {"Bridge", 0x6}, + {"Simple Communication Controller", 0x7}, + {"Base System Peripheral", 0x8}, + {"Input Device Controller", 0x9}, + {"Docking Station", 0xA}, + {"Processor", 0xB}, + {"Serial Bus Controller", 0xC}, + { "Wireless Controller", 0xD}, + {"Intelligent Controller", 0xE}, + {"Satellite Communication Controller", 0xF}, + {"Encryption Controller", 0x10}, + {"Signal Processing Controller", 0x11}, + { "Processing Accelerator", 0x12}, + { "Non-Essential Instrumentation", 0x13} + }; + static const uint8_t KnownClassCodes = sizeof(ClassCodeNames) / sizeof(ClassCode); +}; + diff --git a/kernel/pci/pciDevice.cpp b/kernel/pci/pciDevice.cpp new file mode 100644 index 0000000..e4507fb --- /dev/null +++ b/kernel/pci/pciDevice.cpp @@ -0,0 +1,7 @@ + #include "pciDevice.h" + +// NOTE: we would really like to return a pointer +// to the newly created PCIBusAddress struct; + PCIBusAddress const PCIDevice::PCIAddress(){ + return PCIBusAddress{bus ,device, function}; + } \ No newline at end of file diff --git a/kernel/pci/pciDevice.h b/kernel/pci/pciDevice.h new file mode 100644 index 0000000..9ef88f2 --- /dev/null +++ b/kernel/pci/pciDevice.h @@ -0,0 +1,54 @@ +#pragma once +#include +/* +* PCI devices API +*/ +struct PCIBusAddress{ + + int bus ; + int device ; + int function; + + + uint32_t getAddress( ){ + return ((uint32_t) 1 << 31) | + ((uint32_t) bus << 16) | + ((uint32_t) device << 11)| + ((uint32_t) function << 8) | + 0x0000; + + }; +}; + +class PCIDevice { + public : + PCIDevice (PCIBusAddress* , int ); + ~PCIDevice(); + PCIBusAddress const PCIAddress(); + + + inline const char* getDeviceString(){ + return "Not implemented"; //GetClassCodeName(deviceclass); + } + + inline const char* getVendorString(){ + return "Not implemented"; // getVendor(VendorID); + } + + inline void setVendorID (uint16_t id) { + this->VendorID = id; + } + + private: + int bus; + int device; + int function; + + uint16_t VendorID; + uint16_t DeviceID; + uint8_t deviceclass; + uint8_t devicesubclass; + + int headerType; + +}; diff --git a/kernel/prekernel/bootstructure.h b/kernel/prekernel/bootstructure.h new file mode 100644 index 0000000..48fd40d --- /dev/null +++ b/kernel/prekernel/bootstructure.h @@ -0,0 +1,30 @@ +#pragma once +#include +#include + +extern "C" const uint32_t kernel_begin; +extern "C" const uint32_t kernel_end; + +#define IS_AVAILABLE_MEM(MEM_TYPE) MEM_TYPE & 0x1 +#define IS_ACPI_MEM(MEM_TYPE) MEM_TYPE & 0x2 +#define IS_RESERVED_MEM(MEM_TYPE) MEM_TYPE & 0x4 +#define IS_NVS_MEMORY(MEM_TYPE) MEM_TYPE & 0x8 +#define IS_BADRAM_MEMORY(MEM_TYPE) MEM_TYPE & 0x10 + + +struct BootInfoBlock { + bool MapIsInvalid; + uint32_t bootDeviceID ; + + uint32_t GrubModuleCount; + + bool ValidSymbolTable; + uint32_t SymbolTableAddr; + uint32_t SymbolTabSize; + uint32_t SymbolStrSize; + + bool ValidELFHeader; + + bool EnabledVBE; + +}; diff --git a/kernel/prekernel/multiboot.h b/kernel/prekernel/multiboot.h new file mode 100644 index 0000000..269cf9b --- /dev/null +++ b/kernel/prekernel/multiboot.h @@ -0,0 +1,274 @@ +/* multiboot.h - Multiboot header file. */ +/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY + * DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef MULTIBOOT_HEADER +#define MULTIBOOT_HEADER 1 + +/* How many bytes from the start of the file we search for the header. */ +#define MULTIBOOT_SEARCH 8192 +#define MULTIBOOT_HEADER_ALIGN 4 + +/* The magic field should contain this. */ +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 + +/* This should be in %eax. */ +#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 + +/* Alignment of multiboot modules. */ +#define MULTIBOOT_MOD_ALIGN 0x00001000 + +/* Alignment of the multiboot info structure. */ +#define MULTIBOOT_INFO_ALIGN 0x00000004 + +/* Flags set in the ’flags’ member of the multiboot header. */ + +/* Align all boot modules on i386 page (4KB) boundaries. */ +#define MULTIBOOT_PAGE_ALIGN 0x00000001 + +/* Must pass memory information to OS. */ +#define MULTIBOOT_MEMORY_INFO 0x00000002 + +/* Must pass video information to OS. */ +#define MULTIBOOT_VIDEO_MODE 0x00000004 + +/* This flag indicates the use of the address fields in the header. */ +#define MULTIBOOT_AOUT_KLUDGE 0x00010000 + +/* Flags to be set in the ’flags’ member of the multiboot info structure. */ + +/* is there basic lower/upper memory information? */ +#define MULTIBOOT_INFO_MEMORY 0x00000001 +/* is there a boot device set? */ +#define MULTIBOOT_INFO_BOOTDEV 0x00000002 +/* is the command-line defined? */ +#define MULTIBOOT_INFO_CMDLINE 0x00000004 +/* are there modules to do something with? */ +#define MULTIBOOT_INFO_MODS 0x00000008 + +/* These next two are mutually exclusive */ + +/* is there a symbol table loaded? */ +#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010 +/* is there an ELF section header table? */ +#define MULTIBOOT_INFO_ELF_SHDR 0X00000020 + +/* is there a full memory map? */ +#define MULTIBOOT_INFO_MEM_MAP 0x00000040 + +/* Is there drive info? */ +#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080 + +/* Is there a config table? */ +#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100 + +/* Is there a boot loader name? */ +#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200 + +/* Is there a APM table? */ +#define MULTIBOOT_INFO_APM_TABLE 0x00000400 + +/* Is there video information? */ +#define MULTIBOOT_INFO_VBE_INFO 0x00000800 +#define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000 + +#ifndef ASM_FILE + +typedef unsigned char multiboot_uint8_t; +typedef unsigned short multiboot_uint16_t; +typedef unsigned int multiboot_uint32_t; +typedef unsigned long long multiboot_uint64_t; + +struct multiboot_header +{ + /* Must be MULTIBOOT_MAGIC - see above. */ + multiboot_uint32_t magic; + + /* Feature flags. */ + multiboot_uint32_t flags; + + /* The above fields plus this one must equal 0 mod 2^32. */ + multiboot_uint32_t checksum; + + /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */ + multiboot_uint32_t header_addr; + multiboot_uint32_t load_addr; + multiboot_uint32_t load_end_addr; + multiboot_uint32_t bss_end_addr; + multiboot_uint32_t entry_addr; + + /* These are only valid if MULTIBOOT_VIDEO_MODE is set. */ + multiboot_uint32_t mode_type; + multiboot_uint32_t width; + multiboot_uint32_t height; + multiboot_uint32_t depth; +}; + +/* The symbol table for a.out. */ +struct multiboot_aout_symbol_table +{ + multiboot_uint32_t tabsize; + multiboot_uint32_t strsize; + multiboot_uint32_t addr; + multiboot_uint32_t reserved; +}; +typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t; + +/* The section header table for ELF. */ +struct multiboot_elf_section_header_table +{ + multiboot_uint32_t num; + multiboot_uint32_t size; + multiboot_uint32_t addr; + multiboot_uint32_t shndx; +}; +typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t; + +struct multiboot_info +{ + /* Multiboot info version number */ + multiboot_uint32_t flags; + + /* Available memory from BIOS */ + multiboot_uint32_t mem_lower; + multiboot_uint32_t mem_upper; + + /* "root" partition */ + multiboot_uint32_t boot_device; + + /* Kernel command line */ + multiboot_uint32_t cmdline; + + /* Boot-Module list */ + multiboot_uint32_t mods_count; + multiboot_uint32_t mods_addr; + + union + { + multiboot_aout_symbol_table_t aout_sym; + multiboot_elf_section_header_table_t elf_sec; + } u; + + /* Memory Mapping buffer */ + multiboot_uint32_t mmap_length; + multiboot_uint32_t mmap_addr; + + /* Drive Info buffer */ + multiboot_uint32_t drives_length; + multiboot_uint32_t drives_addr; + + /* ROM configuration table */ + multiboot_uint32_t config_table; + + /* Boot Loader Name */ + multiboot_uint32_t boot_loader_name; + + /* APM table */ + multiboot_uint32_t apm_table; + + /* Video */ + multiboot_uint32_t vbe_control_info; + multiboot_uint32_t vbe_mode_info; + multiboot_uint16_t vbe_mode; + multiboot_uint16_t vbe_interface_seg; + multiboot_uint16_t vbe_interface_off; + multiboot_uint16_t vbe_interface_len; + + multiboot_uint64_t framebuffer_addr; + multiboot_uint32_t framebuffer_pitch; + multiboot_uint32_t framebuffer_width; + multiboot_uint32_t framebuffer_height; + multiboot_uint8_t framebuffer_bpp; +#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0 +#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1 +#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2 + multiboot_uint8_t framebuffer_type; + union + { + struct + { + multiboot_uint32_t framebuffer_palette_addr; + multiboot_uint16_t framebuffer_palette_num_colors; + }; + struct + { + multiboot_uint8_t framebuffer_red_field_position; + multiboot_uint8_t framebuffer_red_mask_size; + multiboot_uint8_t framebuffer_green_field_position; + multiboot_uint8_t framebuffer_green_mask_size; + multiboot_uint8_t framebuffer_blue_field_position; + multiboot_uint8_t framebuffer_blue_mask_size; + }; + }; +}; +typedef struct multiboot_info multiboot_info_t; + +struct multiboot_color +{ + multiboot_uint8_t red; + multiboot_uint8_t green; + multiboot_uint8_t blue; +}; + +struct multiboot_mmap_entry +{ + multiboot_uint32_t size; + multiboot_uint64_t addr; + multiboot_uint64_t len; +#define MULTIBOOT_MEMORY_AVAILABLE 1 +#define MULTIBOOT_MEMORY_RESERVED 2 +#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3 +#define MULTIBOOT_MEMORY_NVS 4 +#define MULTIBOOT_MEMORY_BADRAM 5 + multiboot_uint32_t type; +} __attribute__((packed)); +typedef struct multiboot_mmap_entry multiboot_memory_map_t; + +struct multiboot_mod_list +{ + /* the memory used goes from bytes ’mod_start’ to ’mod_end-1’ inclusive */ + multiboot_uint32_t mod_start; + multiboot_uint32_t mod_end; + + /* Module command line */ + multiboot_uint32_t cmdline; + + /* padding to take it to 16 bytes (must be zero) */ + multiboot_uint32_t pad; +}; +typedef struct multiboot_mod_list multiboot_module_t; + +/* APM BIOS info. */ +struct multiboot_apm_info +{ + multiboot_uint16_t version; + multiboot_uint16_t cseg; + multiboot_uint32_t offset; + multiboot_uint16_t cseg_16; + multiboot_uint16_t dseg; + multiboot_uint16_t flags; + multiboot_uint16_t cseg_len; + multiboot_uint16_t cseg_16_len; + multiboot_uint16_t dseg_len; +}; + +#endif /* ! ASM_FILE */ + +#endif /* ! MULTIBOOT_HEADER */ diff --git a/kernel/prekernel/prekernel.cpp b/kernel/prekernel/prekernel.cpp new file mode 100644 index 0000000..5e4f059 --- /dev/null +++ b/kernel/prekernel/prekernel.cpp @@ -0,0 +1,136 @@ +#include +#include +#include "multiboot.h" +#include "../memory/PhysicalMemoryManager.h" +#include "../memory/VirtualMemoryManager.h" +#include "../acpi/acpi.h" + +#define CHECK_FLAG(flags, bit) ((flags) & (1 <<(bit))) +#define VADDR_TO_PADDR(vaddr) (vaddr - 0xC0000000) +#define PADDR_TO_VADDR(paddr) (paddr + 0xC0000000) +BootInfoBlock* BIB; + +extern "C" void prekernelSetup ( unsigned long magic, multiboot_info_t* mbi) +{ + /* + * Check Multiboot magic number + */ + if (magic != MULTIBOOT_BOOTLOADER_MAGIC) + { + // PANIC!! + return; + } + + mbi = PADDR_TO_VADDR(mbi); + /* + If we got a memory map from our bootloader we + should be parsing it to find out the memory regions available. + */ + if (CHECK_FLAG(mbi->flags, 6)) + { + + // Calculate total memory size + uint32_t RAM_size = 0; + for( + multiboot_memory_map_t* mmap = (multiboot_memory_map_t*) mbi->mmap_addr; + (unsigned long)mmap < mbi->mmap_addr + mbi->mmap_length; + mmap += mmap->size +sizeof(mmap->size) + ){ + RAM_size += mmap->len; + } + + // Call SetupPhysicalMemoryManager at its physical address + SetupPhysicalMemoryManager ( (uint32_t)VADDR_TO_PADDR(&kernel_end), RAM_size); + + for( + multiboot_memory_map_t* mmap = (multiboot_memory_map_t*) mbi->mmap_addr; + (unsigned long)mmap < mbi->mmap_addr + mbi->mmap_length; + mmap += mmap->size +sizeof(mmap->size) + ){ + + if(mmap->type == MULTIBOOT_MEMORY_AVAILABLE) + deallocate_region(mmap->addr, mmap->len); + if(mmap->type == MULTIBOOT_MEMORY_ACPI_RECLAIMABLE) + allocate_region(mmap->addr, mmap->len); + // memory map + Immediate_Map(mmap->addr , mmap->addr); + if(mmap->type == MULTIBOOT_MEMORY_RESERVED) + allocate_region(mmap->addr, mmap->len); + if(mmap->type == MULTIBOOT_MEMORY_NVS) + allocate_region(mmap->addr, mmap->len); + if(mmap->type == MULTIBOOT_MEMORY_BADRAM) + allocate_region(mmap->addr, mmap->len); + + } + + + // Allocate the kernel + allocate_region( (uint32_t)&kernel_begin, ( (uint32_t)&kernel_end - (uint32_t)&kernel_begin)- 0xC0000000 ); + + // Allocate the memory region below 1MB + allocate_region(0x0000000, 0x00100000); + + } + else + { + // We didn't get a memory map from our bootloader. + // PANIC!!!! + return; + } + + // allocate a full block for the other boot info! + BIB = (BootInfoBlock*) allocate_block(); + + + /* is boot device valid ? */ + if (CHECK_FLAG (mbi->flags, 1)) + { + BIB->bootDeviceID = mbi->boot_device; + + } else{ + BIB->bootDeviceID = 0x11111111; + } + + /* Are mods_* valid? */ + if(CHECK_FLAG ( mbi->flags, 3)){ + multiboot_module_t *mod; + uint32_t i; + + BIB->GrubModuleCount = mbi->mods_count; + for(i = 0, mod = (multiboot_module_t *) mbi->mods_addr; i < mbi->mods_count; i++ , mod++){ + + } + } + + /* Is the symbol table of a.out valid? */ + if (CHECK_FLAG(mbi->flags, 4)) + { + // NOTE: Do something with it.. (Store it , process it etc...) + // printf("- Valid Symbol Table available at 0x%x.\n Tab Size: %d, str Size: %d\n", BootInfo->SymbolTableAddr, BootInfo->SymbolTabSize, BootInfo->SymbolStrSize); + BIB->ValidSymbolTable = true; + multiboot_aout_symbol_table_t *multiboot_aout_sym = &(mbi->u.aout_sym); + + } else{ + BIB->ValidSymbolTable = false; + } + + /* Is the section header table of ELF valid? */ + if (CHECK_FLAG(mbi->flags, 5)) + { + // NOTE: Do something with it.. (Store it , process it etc...) + BIB->ValidELFHeader = true; + multiboot_elf_section_header_table_t *multiboot_elf_sec = &(mbi->u.elf_sec); + + }else{ + BIB->ValidELFHeader = false; + } + + /* Draw diagonal blue line */ + if (CHECK_FLAG (mbi->flags, 12)){ + BIB->EnabledVBE = true; + + // NOTE: Do something with it.. (Store it , process it etc...) + } else{ + BIB->EnabledVBE = false; + } +} diff --git a/kernel/serial.h b/kernel/serial.h new file mode 100644 index 0000000..1ede93e --- /dev/null +++ b/kernel/serial.h @@ -0,0 +1,58 @@ +#pragma once + +#include "terminal/kterm.h" +#include "io/io.h" +#define PORT 0x3f8 +static int init_serial() { + +#ifdef __VERBOSE__ + printf("Init Serial\n"); +#endif + + outb(PORT + 1, 0x00); // Disable all interrupts + outb(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor) + outb(PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud + outb(PORT + 1, 0x00); // (hi byte) + outb(PORT + 3, 0x03); // 8 bits, no parity, one stop bit + outb(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold + outb(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set + outb(PORT + 4, 0x1E); // Set in loopback mode, test the serial chip + outb(PORT + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte) + + // Check if serial is faulty (i.e: not same byte as sent) + if(inb(PORT + 0) != 0xAE) { + return 1; + } + + // If serial is not faulty set it in normal operation mode + // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled) + outb(PORT + 4, 0x0F); + return 0; +} + +inline int is_transmit_empty() { + return inb(PORT + 5) & 0x20; +} + +inline void write_serial(char a) { + while (is_transmit_empty() == 0); + + outb(PORT,a); +} + +inline int serial_received() { + return inb(PORT + 5) & 1; +} + +inline char read_serial() { + while (serial_received() == 0); + + return inb(PORT); +} + +inline void print_serial(const char* string ){ + for(size_t i = 0; i < strlen(string); i ++){ + write_serial(string[i]); + } +} + diff --git a/kernel/storage/ata pio/ATAPIO.cpp b/kernel/storage/ata pio/ATAPIO.cpp new file mode 100644 index 0000000..57647f5 --- /dev/null +++ b/kernel/storage/ata pio/ATAPIO.cpp @@ -0,0 +1,199 @@ +#include "ATAPIO.h" +#include "../../io/io.h" + +#define IS_BIT_SET(x, bit) ((x >> bit & 0x1) == 1) + +void ATAPIO::Read(uint16_t DEVICE_CHANNEL, DEVICE_DRIVE drive, uint32_t LBA, uint16_t* buffer) { + /* + Assume you have a sectorcount byte and a 28 bit LBA value. A sectorcount of 0 means 256 sectors = 128K. + + Notes: - When you send a command byte and the RDY bit of the Status Registers is clear, you may have to wait (technically up to 30 seconds) for the drive to spin up, before DRQ sets. You may also need to ignore ERR and DF the first four times that you read the Status, if you are polling. + - for polling PIO drivers: After transferring the last uint16_t of a PIO data block to the data IO port, give the drive a 400ns delay to reset its DRQ bit (and possibly set BSY again, while emptying/filling its buffer to/from the drive). + - on the "magic bits" sent to port 0x1f6: Bit 6 (value = 0x40) is the LBA bit. This must be set for either LBA28 or LBA48 transfers. It must be clear for CHS transfers. Bits 7 and 5 are obsolete for current ATA drives, but must be set for backwards compatibility with very old (ATA1) drives. + + An example of a 28 bit LBA PIO mode read on the Primary bus: + + */ + + const int sectorCount = 1; + + // Floating bus check + uint8_t floatingBus = inb(DEVICE_CHANNEL | 7); + if (floatingBus == 0xFF){ + printf("Floating bus!!"); + return ; + } + + //printf("Read LBA: 0x%x\n", LBA); + // Send 0xE0 for the "master" or 0xF0 for the "slave", ORed with the highest 4 bits of the LBA to port 0x1F6: outb(0x1F6, 0xE0 | (slavebit << 4) | ((LBA >> 24) & 0x0F)) + outb(DEVICE_CHANNEL | 6 , ( 0xE0 | (LBA >>28) ) ); + // Send a NULL byte to port 0x1F1, if you like (it is ignored and wastes lots of CPU time): outb(0x1F1, 0x00) + outb(DEVICE_CHANNEL | 1, 0x0000 ); + //Send the sectorcount to port 0x1F2: outb(0x1F2, (unsigned char) count) + outb(DEVICE_CHANNEL | 2, sectorCount); + //Send the low 8 bits of the LBA to port 0x1F3: outb(0x1F3, (unsigned char) LBA)) + outb(DEVICE_CHANNEL | 3, LBA); + //Send the next 8 bits of the LBA to port 0x1F4: outb(0x1F4, (unsigned char)(LBA >> 8)) + outb(DEVICE_CHANNEL | 4, (LBA >> 8)); + //Send the next 8 bits of the LBA to port 0x1F5: outb(0x1F5, (unsigned char)(LBA >> 16)) + outb(DEVICE_CHANNEL | 5, (LBA >> 16)); + //Send the "READ SECTORS" command (0x20) to port 0x1F7: outb(0x1F7, 0x20) + outb(DEVICE_CHANNEL | 7, 0x20); + + volatile int i,j; + for(i=0;i<2000;i++) + for(j=0;j<25000;j++) + asm("NOP"); + + //Wait for an IRQ or poll. + uint8_t status = inb(DEVICE_CHANNEL | 7); + if( status == 0x00){ + printf("No drive\n"); + return; + } + + //printf("Status: %x\n", status); + // Check if busy! + while((status & 0x80) == 0x80){ + printf("Reading....\r"); + status = inb(DEVICE_CHANNEL | 7); + } + + + if ((status & 0x01) == 0x01){ + printf("Error occured during read!\n"); + return; + } + + //Transfer 256 16-bit values, a uint16_t at a time, into your buffer from I/O port 0x1F0. + if( status & 0x01){ + printf("Error!\n"); + printf("Status: 0x%x\n", status); + uint16_t error_register = inb(DEVICE_CHANNEL | 1); + printf("Error register 0x%x\n",error_register ); + return ; + } + for ( int i = 0; i < 256; i++){ + uint16_t data; + asm volatile ("inw %1, %0" : "=a"(data): "Nd"(DEVICE_CHANNEL)); + // printf (" %x ", data); + + buffer[i] = data; + } + + //Then loop back to waiting for the next IRQ (or poll again -- see next note) for each successive sector. + +} + +void ATAPIO::Write(uint16_t data, DEVICE_DRIVE dev){ + + printf("Not implemented\n"); + +} + +bool ATAPIO::Identify(ATAPIO_PORT DEVICE_CHANNEL, DEVICE_DRIVE drive ){ + // lets ignore which port we actually want to check for now ! + + /* + THE STEPS INVOLVED + + 1. Select the target drive by sending master (0x0A) or slave (0x0B) to the + drive select IO port + + 2. Set the Sectorcount, LBAlo, LBAmid and LBAhi IO ports to 0 + + 3. Send the identify command (0xEC) to the command IO port + + 4. Read the status port + 4.2 If the value is 0x0 the drive does not exist + 4.3 If it has any other value continue + 5. poll the status port until bit 7 is clear. + 6. Check if the LBAmid and LBAhi ports are non-zero + 6.2. If non-zero stop polling this is not an ATA device + 6.3 If zero continue + + 7. poll status port until bit 3 is set or bit 0 is set + + 8. if err is clear, read the data from the data port + + + */ + + + //printf("channel selected: 0x%x", DEVICE_CHANNEL); + // Assuming Master here + // Select the target drive + outb(DEVICE_CHANNEL | 6, drive); // on the primary bus select the master drive + outb(DEVICE_CHANNEL | 6 , 0x0); // write 0 to the controlport for some reason + outb(DEVICE_CHANNEL | 6, drive); + uint8_t status = inb(DEVICE_CHANNEL | 7 ); + if(status == 0x00){ + printf("No drive\n"); + return false; + } + // send the identify command; + outb(DEVICE_CHANNEL | 7, 0xEC); + + + // set the sectorCount, LBAlo, LBAmid, LBA,hi IO ports to 0 + outb(DEVICE_CHANNEL | 2, 0); + + outb(DEVICE_CHANNEL | 3, 0); + + outb(DEVICE_CHANNEL | 4, 0); + + outb(DEVICE_CHANNEL | 5, 0); + + // send the identify command ; + //printf("command sent!\n"); + outb(DEVICE_CHANNEL | 7 , 0xEC); + + // read the status port + uint8_t status2 = inb(DEVICE_CHANNEL | 7); + if( status2 == 0x00){ + printf("No drive\n"); + return false; + } + + //printf("Waiting until ready...\n"); + while(((status2 & 0x80 == 0x80) + && (status2 & 0x01) != 0x01) + ) status2 = inb(DEVICE_CHANNEL | 7); + + if( status2 & 0x01){ + printf("Error!\n"); + return false; + } + + uint16_t deviceIdentify [256] = {0}; + + for ( int i = 0; i < 256; i++){ + uint16_t data; + asm volatile ("inw %1, %0" : "=a"(data): "Nd"(DEVICE_CHANNEL)); + + deviceIdentify[i] = data; + } + + + printf("Model-label (ASCII hex): "); + for(int i = 27; i < 47; i++){ + kterm_put((char)(deviceIdentify[i] >> 8)); + kterm_put((char)(deviceIdentify[i] & 0x00FF)); + } + kterm_put('\n'); + return true; +} + +void ATAPIO::Soft_Reset(ATAPIO_PORT DEVICE_CHANNEL, DEVICE_DRIVE drive){ + printf("Soft reseting drive...\n"); + outb(DEVICE_CHANNEL + 7 , 0x4); + // wait a bit.. + for(int i = 0 ; i < 1000000; i++){ + asm volatile("NOP"); + } + outb(DEVICE_CHANNEL + 7 , 0x0); + +} + + + diff --git a/kernel/storage/ata pio/ATAPIO.h b/kernel/storage/ata pio/ATAPIO.h new file mode 100644 index 0000000..5f3dab8 --- /dev/null +++ b/kernel/storage/ata pio/ATAPIO.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include "../ide/ideCommands.h" +#include "../ide/sampleIDE.definitions.h" +#include "../../devices/BlockDevice.h" +#include "../../terminal/kterm.h" + +/* +* This first driver wil make use of IO ports. +* Doing so means reading or writing from disk is going +* to be very cpu intensive. +*/ + +enum DEVICE_DRIVE{ + MASTER = 0xA0, + SLAVE = 0xB0 +}; + + +enum ATAPIO_PORT { + Primary = 0x1f0, + Secondary = 0x170 +}; + + + +class ATAPIO +{ +public: + static bool Identify(ATAPIO_PORT, DEVICE_DRIVE); + static void Read (uint16_t, DEVICE_DRIVE, uint32_t, uint16_t*); + static void Write(uint16_t, DEVICE_DRIVE); + static void Soft_Reset(ATAPIO_PORT , DEVICE_DRIVE ); +}; + + diff --git a/kernel/storage/atapi/atapiDevice.cpp b/kernel/storage/atapi/atapiDevice.cpp new file mode 100644 index 0000000..e619680 --- /dev/null +++ b/kernel/storage/atapi/atapiDevice.cpp @@ -0,0 +1,145 @@ +#include "atapiDevice.h" +#define IS_BIT_SET(x, bit) ((x >> bit & 0x1) == 1) + +bool isPacketDevice(){ + + uint8_t LBAmid = inb(0x174); + uint8_t LBAhi = inb(0x175); + + printf(" LBAmid: 0x%x, LBAhi: 0x%x"); + return LBAmid == 0x14 && LBAhi == 0xEB; + +} + + +void ATAPI_DEVICE::Identify(uint8_t DEVICE_CHANNEL,DEVICE_DRIVE drive ){ + // lets ignore which port we actually want to check for now ! + + /* THE STEPS INVOLVED + + 1. Select the target drive by sending master (0x0A) or slave (0x0B) to the + drive select IO port + + 2. Set the Sectorcount, LBAlo, LBAmid and LBAhi IO ports to 0 + + 3. Send the identify command (0xEC) to the command IO port + + 4. Read the status port + 4.2 If the value is 0x0 the drive does not exist + 4.3 If it has any other value continue + 5. poll the status port until bit 7 is clear. + 6. Check if the LBAmid and LBAhi ports are non-zero + 6.2. If non-zero stop polling this is not an ATA device + 6.3 If zero continue + + 7. poll status port until bit 3 is set or bit 0 is set + + 8. if err is clear, read the data from the data port + + + */ + + // Select the target drive + outb(0x176, 0xA0); // on the secondary bus select the master drive + outb(0x170 + 0x206 , 0x0); // write 0 to the controlport for some reason + + outb(0x176, 0xA0); + // read the status port + uint8_t status = inb(0x177); + printf("status after drive select: 0x%x\n",status); + if( status == 0x00){ + printf("No drive\n"); + return; + } + + outb(0x176, 0xA0); + + + // Set the Sectorcount, LBAlo, LBAmid and LBAhi IO ports to 0 + outb(0x172, 0); + + outb(0x173, 0); + + outb(0x174, 0); + + outb(0x175, 0); + + // send the identify command; + printf("command sent!\n"); + outb(0x177, 0xA1); + + // read the status port + uint8_t status2 = inb(0x177); + if( status2 == 0x00){ + printf("No drive\n"); + return; + } + + + printf("Waiting until ready...\n"); + + while(((status2 & 0x80 == 0x80) + && (status2 & 0x01) != 0x01) + ) status2 = inb(0x177); + + + if(status2 & 0x01){ + printf("Error!"); + return; + } + + + // READ DATA + + uint16_t deviceIdentify [256] ={0}; + + for (int i= 0; i < 256; i++){ + uint16_t data; + asm volatile ( "in %1, %0" + : "=a"(data) + : "Nd"(0x170) ); + + + deviceIdentify[i] = data ; + + + } + + printf("Model-label (ASCII hex):\n"); + for(int i = 27; i < 47; i++){ + printf(" %x ",deviceIdentify[i]); + } + + printf("\nSerial number (ASCII hex):\n"); + for (int i = 10; i < 19; i++){ + printf(" %x ", deviceIdentify[i]); + } + + printf("\nFirmware revision (ASCII hex):\n"); + for (int i = 23; i < 26; i++){ + printf(" %x ", deviceIdentify[i]); + } + + printf("\nConfiguration: %x\n", deviceIdentify[0]); + + + + printf("\nData received!\n"); + + + + + + +} + + +void ATAPI_DEVICE::Read(uint8_t DEVICE_CHANNEL, DEVICE_DRIVE drive) { + printf("Not implemented"); +} + +void ATAPI_DEVICE::Write(uint8_t DEVICE_CHANNEL, DEVICE_DRIVE drive) { + printf("Not implemented"); +} + + diff --git a/kernel/storage/atapi/atapiDevice.h b/kernel/storage/atapi/atapiDevice.h new file mode 100644 index 0000000..0a3dd14 --- /dev/null +++ b/kernel/storage/atapi/atapiDevice.h @@ -0,0 +1,29 @@ +#pragma once +#include +#include "../../io/io.h" +#include "../ide/ideCommands.h" +#include "../ide/sampleIDE.definitions.h" + +#include "../../terminal/kterm.h" + +/* +* This first driver wil make use of IO ports. +* Doing so means reading or writing from disk is going +* to be very cpu intensive. +* +*/ + +enum DEVICE_DRIVE{ + MASTER = 0xA0, + SLAVE = 0xB0 +}; + + +namespace ATAPI_DEVICE +{ + bool isPacketDevice(); + void Identify ( uint8_t, DEVICE_DRIVE ); + void Read ( uint8_t, DEVICE_DRIVE ); + void Write ( uint8_t, DEVICE_DRIVE ); + +}; diff --git a/kernel/storage/filesystems/EXT2/SuperBlock.h b/kernel/storage/filesystems/EXT2/SuperBlock.h new file mode 100644 index 0000000..35a5a94 --- /dev/null +++ b/kernel/storage/filesystems/EXT2/SuperBlock.h @@ -0,0 +1,29 @@ +#pragma once +#include +struct SuperBlock { + uint32_t NumberOfInodes; + uint32_t NumberOfBlocks; + uint32_t NumberOfReservedBlocks; + uint32_t NumberOfUnallocatedBlocks; + uint32_t NumberOfUnallocatedInodes; + uint32_t BlockNumberOfSuperBlock; + uint32_t BlockSize;// Something about a shift left + uint32_t FragmentSize; + uint32_t NumberOfBlocksInGroup; + uint32_t NumberOfFragmentsInBlockGroup; + uint32_t NumberOfInodesInBlockGroup; + uint32_t LastMountTime; // POSIX + uint32_t LastWrittenTime; // POSIX + uint16_t TimesMountedSinceCheck; + uint16_t TimesMountedUntilCheck; + uint16_t EXT_SIG ; // 0xef53 + uint16_t FS_STATE; + uint16_t ON_ERR; + uint16_t VERSION_MINOR; + uint32_t TimeLastCheck; // POSIX + uint32_t CheckInterval; //POSIX + uint32_t OS_ID; // OS the FS was created with + uint32_t VERSION_MAJOR; + uint16_t UIDReservedBlocks; + uint16_t GIDReservedBlocks; +}__attribute__((packed)); \ No newline at end of file diff --git a/kernel/storage/filesystems/FAT/FAT.cpp b/kernel/storage/filesystems/FAT/FAT.cpp new file mode 100644 index 0000000..e181f7e --- /dev/null +++ b/kernel/storage/filesystems/FAT/FAT.cpp @@ -0,0 +1,404 @@ +// +// Created by nigel on 21/02/23. +// +#include "FAT.h" +#include "../../ata pio/ATAPIO.h" +#include "../../../memory/KernelHeap.h" +#include "../../partitiontables/mbr/MasterBootRecord.h" +#include "../../../../CoreLib/ctype.h" +#include "../../../../CoreLib/Memory.h" +#include +#include + +// exposed driver API +FS_SUPER* FAT::Mount(filesystem *fs, const char* name , vfsmount *mnt) +{ + + if( strncmp (fs->name, "fat", 3 ) != 0 ) + { + printf("Can't mount filesystem with none fat type!\n"); + return nullptr; + } + auto* bpb = GetBiosParameterBlock(); + auto fat_type = DetermineFATType(bpb); + + if(fat_type != FAT_TYPE::FAT16) + return nullptr; + + FS_SUPER* sb = (FS_SUPER*) malloc(sizeof(FS_SUPER)); + DirectoryNode* root = (DirectoryNode*) malloc(sizeof (DirectoryNode)); + inode* node = (inode*) malloc(sizeof(inode)); + + root->children = nullptr; + node->internal = (void*)FAT::GetSectorOfRootDirectory(bpb); //sector number; + node->lookup = FAT::Lookup; + root->name = (char*) name; + root->node = node; + root->parent = nullptr; + root->compare = FAT::Compare; + mnt->mnt_count =1; + mnt->mnt_devname = "QEMU HDD"; + mnt->mnt_flags = 0; + mnt->mnt_parent = nullptr; + mnt->root = root; + mnt->sb = sb; + sb->type = fs; + sb->root = root; + sb->fs_info = bpb; + + return sb; +} +FILE FAT::Open(char* filename){ + + return (FILE){nullptr, 0, nullptr, nullptr, 1} ; +} +int FAT::Read(FILE* file, void* buffer , unsigned int length) +{ + + if(file == nullptr) + { + printf("NO FILE!!\n"); + return -1; + } + inode* node = file->root; + + if(node== nullptr) + { + printf("No INODE!\n"); + return -1; + } + + int cluster = (int)node->internal; + auto* bpb = FAT::GetBiosParameterBlock(); + + unsigned int FAT_entry = FAT::GetFATEntry(bpb, cluster); + unsigned int root_dir_sector = FAT::RootDirSize(bpb); + unsigned int fat_size = bpb->FATSz16; + unsigned int first_data_sector = bpb->RsvdSecCnt + (bpb->NumFATs * fat_size) + root_dir_sector; + unsigned int file_data_sector = ((cluster - 2) * bpb->SecPerClus) + first_data_sector; + + ATAPIO::Read(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER, file_data_sector, (uint16_t*)buffer); + + return 0; +} + +int FAT::Write(FILE* file, const void* buffer, unsigned int length) +{ + return 0; +} + +int FAT::Compare (DirectoryNode*, char* filename, char* filename2) +{ + //TODO Implement proper compare method for 8.3 filenames + // printf("COMPARE: %s with %s\n", filename, filename2); + return memcmp(filename, filename2, 11); +} + +int FAT::Create(inode* dir_node, inode** target, const char* component_name){} + +DirectoryNode* FAT::Lookup (inode* currentDir , DirectoryNode* dir) +{ + + uint16_t data[256]; + ATAPIO::Read(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER, (int)currentDir->internal , data); + + List* lastAdded = nullptr; + auto* directory = (DIR*)data; + for(int i = 0; i < sizeof(data) / sizeof (DIR); i++) + { + DIR* entry = (DIR*)((uint32_t)directory + (i * sizeof(DIR))); + + + if( + entry->Name[0] == FAT::FREE_DIR || + entry->ATTR & FAT::ATTRIBUTES::ATTR_VOLUME_ID || + entry->ATTR & FAT::ATTRIBUTES::ATTR_SYSTEM || + entry->ATTR & FAT::ATTRIBUTES::ATTR_HIDDEN + ){ + continue; + } + + + if( entry->ATTR & FAT::ATTRIBUTES::ATTR_DIRECTORY){ + printf("entry in directory\n"); + for(int i = 0; i < 11 ;i ++) + kterm_put(entry->Name[i]); + kterm_put('\n'); + } + + + + + if( entry->Name[0] == FAT::FREE_DIR_2 ) + break; + + auto* dirNode = (DirectoryNode*) malloc(sizeof (DirectoryNode)); + + char* name = (char*)malloc(sizeof(char[11])); + memcpy(name, entry->Name, 11 ); + dirNode->name = name; + dirNode->compare = dir->compare; + dirNode->parent = dir; + + dirNode->node= (inode*) malloc(sizeof (inode)); + dirNode->node->internal = (void*)entry->FstClusLo; + + dirNode->node->read = currentDir->read; + dirNode->node->lookup = currentDir->lookup; + dirNode->node->sb = currentDir->sb; + dirNode->node->size = entry->FileSize; + + List* dirlist = (List*) malloc(sizeof (List)); + dirlist->data = dirNode; + dirlist->next = nullptr; + + lastAdded = dirlist; + auto* temp = dir->children; + dir->children = lastAdded; + lastAdded->next = temp; + + + } + + return (DirectoryNode*)dir; +} + +// internal functions +FAT_TYPE FAT::DetermineFATType(BiosParameterBlock* bpb){ + int RootDirSector = ((bpb->RootEntCnt * 32) + (bpb->BytsPerSec -1)) / bpb->BytsPerSec; + int FATSz = 0; + if(bpb->FATSz16 != 0){ + FATSz = bpb->FATSz16; + } else{ + // FATSz = bpb->FATSz32; + + } + int TotSec = 0; + if(bpb->TotSec16 != 0){ + TotSec= bpb->TotSec16; + }else{ + TotSec = bpb->TotSec32; + } + + int DataSec = TotSec - (bpb->RsvdSecCnt + (bpb->NumFATs * FATSz) + RootDirSector); + int CountofClusters = DataSec / bpb->SecPerClus; + + if(CountofClusters < 4085){ + return FAT_TYPE::FAT12; + } else if (CountofClusters < 65525) { + return FAT_TYPE::FAT16; + } else{ + return FAT_TYPE::FAT32; + } +}; +BiosParameterBlock* FAT::GetBiosParameterBlock(bool DEBUG ){ + BiosParameterBlock* bpb = (BiosParameterBlock*) malloc(sizeof(BiosParameterBlock)); + uint16_t StartAddress = 0x00 ; + ATAPIO::Read(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER, StartAddress, (uint16_t*) bpb); + + if(DEBUG) + { + printf("OEM ID: %s\n", bpb->OEMName); + printf("Bytes per sector: %d\n", bpb->BytsPerSec); + printf("Sectors per cluster: %d\n", bpb->SecPerClus); + printf("Reserved sectors: %d\n", bpb->RsvdSecCnt); + printf("Number of FAT: %d\n", bpb->NumFATs); + printf("Number of Dir entries: %d\n", bpb->RootEntCnt); + printf("Total Sectors in volume: %d\n", bpb->TotSec16 == 0 ? bpb->TotSec32 : bpb->TotSec16); + printf("Sectors per FAT: %d\n", bpb->FATSz16 ); + } + + return bpb; +} +uint16_t FAT::GetFATEntry (BiosParameterBlock* bpb, unsigned int cluster){ + int FATSz = bpb->FATSz16; + int FATOffset = 0; + FAT_TYPE type = FAT::DetermineFATType(bpb); + if( type == FAT_TYPE::FAT16){ + FATOffset = cluster *2; + } else if( type == FAT_TYPE::FAT32){ + FATOffset = cluster * 4; + } + int thisFATSecNum = bpb->RsvdSecCnt + (FATOffset / bpb->BytsPerSec); // Sector number containing the entry for the cluster + + // For any other FAT other than the default + // SectorNumber = (FATNumber * FATSz) + ThisFATSecNum + + uint16_t buff[bpb->BytsPerSec]; + ATAPIO::Read(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER, thisFATSecNum, buff ); + int thisFATEntOffset = FATOffset % bpb->BytsPerSec; // offset for the entry in the sector containing the entry for the cluster + uint16_t ClusterEntryValue = 0; + // Get the FATEntry + if(type == FAT_TYPE::FAT16){ + return *((uint16_t*) &buff[thisFATEntOffset]); + + } + else{ + // FAT32 logic + return 0; + } + +} +uint16_t FAT::DetermineFreeSpace() +{ + // Loop through all FAT entries in all FAT's + // to construct a list of free/available clusters + // Free clusters are recorded with all 0's except on FAT32 where + // the highest order 4 bits should be ignored. + +/* + * The number of sectors reserved for each FAT (count of sectors in the BPB_FATSz16 or +BPB_FATSz32 fields) may be bigger than the actual number of sectors required for +containing the entire FAT. Therefore, there may be totally unused FAT sectors at the end of +each FAT in the FAT region of the volume. Each implementation must determine the value +for the last valid sector in the FAT using CountOfClusters (the last valid sector in the FAT +is the one containing the FAT entry numbered CountOfClusters + 1). +All sectors reserved for the FAT beyond the last valid sector (defined as the one containing +the FAT entry for the last cluster) must be set to 0x0 during volume initialization/format. + */ + + +} +int FAT::GetSectorOfRootDirectory (BiosParameterBlock* bpb) +{ + return (bpb->RsvdSecCnt + (bpb->NumFATs * bpb->FATSz16)); +} +unsigned int FAT::RootDirSize(BiosParameterBlock* bpb) +{ + return ((bpb->RootEntCnt * 32) + (bpb->BytsPerSec -1)) /bpb->BytsPerSec; + +} +void FAT::OpenSubdir(DIR* directory, BiosParameterBlock* bpb ){ + + unsigned int cluster = directory->FstClusLo; + printf("Listing contents of " ); + + for(unsigned char n : directory->Name){ + if(n == 0x20) + continue; + kterm_put(n); + } + kterm_put('\n'); + printf("FsCluHi: 0x%x , FsCluLo: 0x%x\n", directory->FstClusHi, directory->FstClusLo); + printf("Cluster: 0x%x\n", cluster); + unsigned int FATEntry = FAT::GetFATEntry(bpb, cluster); + printf("FAT_Entry: 0x%x\n", FATEntry); + + unsigned int root_dir_sectors = FAT::RootDirSize(bpb); + unsigned int fat_size = bpb->FATSz16; + unsigned int first_data_sector = bpb->RsvdSecCnt + ( bpb->NumFATs * fat_size) + root_dir_sectors; + unsigned int first_directory_sector = ((cluster - 2) * bpb->SecPerClus) + first_data_sector; + printf("Directory first sector 0x%x\n" , first_directory_sector); + uint16_t data[256]; + ATAPIO::Read(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER, first_directory_sector, data); + + auto* directoryContents = (DIR*) data; + for(int i = 0; i < sizeof(data) / sizeof(DIR); i++){ + DIR* entry = (DIR*)((uint32_t)directoryContents + (i * sizeof(DIR))); + + if(entry->Name[0] == FAT::FREE_DIR || entry->Name[0] == FAT::FREE_DIR_2 || entry->Name[0] == 0xE5) + continue; + + if(entry->ATTR & FAT::ATTRIBUTES::ATTR_HIDDEN){ + continue; + } + + if(entry->ATTR & FAT::ATTRIBUTES::ATTR_SYSTEM) + continue; + + + if(entry->ATTR & FAT::ATTRIBUTES::ATTR_VOLUME_ID){ + continue; + } + + if (!(entry->ATTR & FAT::ATTRIBUTES::ATTR_LONG_NAME)){ + for(char n : entry->Name){ + if(n == 0x20) + continue; + kterm_put(n); + } + kterm_put('\n'); + }else{ + printf("LFN\n"); + } + + } + +} +void FAT::ReadFileContents(DIR* fileEntry , BiosParameterBlock* bpb){ + unsigned int cluster = fileEntry->FstClusLo; + printf("cluster NR: %x\n", cluster); + unsigned int FATEntry = FAT::GetFATEntry(bpb, cluster); + unsigned int root_dir_sectors = FAT::RootDirSize(bpb); + unsigned int fat_size = bpb->FATSz16; + unsigned int first_data_sector = bpb->RsvdSecCnt + (bpb->NumFATs * fat_size) + root_dir_sectors; + unsigned int file_data_sector = ((cluster -2) * bpb->SecPerClus) + first_data_sector; + printf("FAT entry = %x\n", FATEntry); + uint16_t data[256]; + ATAPIO::Read(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER, file_data_sector, data); + + for (unsigned short n : data) + { + kterm_put(n & 0x00ff); + kterm_put(n >> 8); + } + kterm_put('\n'); + +} +void FAT::ListRootDirectoryContents(BiosParameterBlock* bpb){ + int total_sectors = bpb->TotSec32; + int fat_size = bpb->FATSz16; + int root_dir_sectors = FAT::RootDirSize(bpb); + int first_data_sector = bpb->RsvdSecCnt + (bpb->NumFATs * fat_size) + root_dir_sectors ; + int data_sectors = bpb->TotSec32 - (bpb->RsvdSecCnt + (bpb->NumFATs * fat_size) + root_dir_sectors); + int total_clusters = data_sectors / bpb->SecPerClus; + + + int first_root_dir_sector = first_data_sector - root_dir_sectors; + //int first_sector_of_cluster = ((cluster - 2) * bpb->SecPerClus) + first_data_sector; + uint16_t data[256]; + ATAPIO::Read(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER, first_root_dir_sector, data); + + auto* RootDirectory = (DIR*)data; + for(int i = 0; i < sizeof(data) / sizeof (DIR); i++) + { + DIR* entry = (DIR*)((uint32_t)RootDirectory + (i * sizeof(DIR))); + + + if(entry->Name[0] == FAT::FREE_DIR || entry->Name[0] == FAT::FREE_DIR_2 || entry->Name[0] == 0xE5){ + continue; + } + + + if(entry->ATTR & FAT::ATTRIBUTES::ATTR_HIDDEN){ + continue; + } + + if(entry->ATTR & FAT::ATTRIBUTES::ATTR_SYSTEM) + continue; + + + if(entry->ATTR & FAT::ATTRIBUTES::ATTR_VOLUME_ID){ + continue; + } + if (!(entry->ATTR & FAT::ATTRIBUTES::ATTR_LONG_NAME)){ + for(char n : entry->Name){ + if(n == 0x20) + continue; + kterm_put(n); + } + }else{ + printf("Long file name detected!"); + } + + printf(" [Size: %d bytes, Attributes: %d]\n", entry->ATTR, entry->FileSize); + if(entry->ATTR & FAT::ATTRIBUTES::ATTR_DIRECTORY ){ + FAT::OpenSubdir(entry, bpb); + } else { + FAT::ReadFileContents(entry, bpb); + } + + } +} + + diff --git a/kernel/storage/filesystems/FAT/FAT.h b/kernel/storage/filesystems/FAT/FAT.h new file mode 100644 index 0000000..3a29bc1 --- /dev/null +++ b/kernel/storage/filesystems/FAT/FAT.h @@ -0,0 +1,119 @@ +// +// Created by nigel on 21/02/23. +// +#pragma once +#include "../../vfs/vfs_types.h" +#include "../../vfs/vfs_types.h" +#include "../../partitiontables/mbr/MasterBootRecord.h" + +struct ExtendedBootRecord_FAT16{ + uint8_t DrvNum; + uint8_t Reserved1; + uint8_t BootSig; + const uint32_t VolID; + uint8_t VolLab [11]; + uint8_t FilSysType [8]; + uint8_t bootCode [448]; + uint16_t Signature_word; + uint8_t SecRmndr[512]; +}__attribute__((packed)); + +struct BiosParameterBlock { + uint8_t jmpBoot[3]; + uint8_t OEMName [8]; + uint16_t BytsPerSec ; // I suspect would be 512 + uint8_t SecPerClus ; + uint16_t RsvdSecCnt; + uint8_t NumFATs; // Probably equals 2 + uint16_t RootEntCnt; // Root directory must contain entire sectors + uint16_t TotSec16 ; // 0 means >65535 sectors in volume , actual count can be found in LargeSectorCount + uint8_t Media ; // Indication the media descriptor type + uint16_t FATSz16;// only in FAT12 / FAT 16 + uint16_t SecPerTrk; + uint16_t NumHeads; + uint32_t HiddSec; + uint32_t TotSec32; + ExtendedBootRecord_FAT16 ebpb; +}__attribute__((packed)); + +struct DIR { + uint8_t Name [11]; + uint8_t ATTR ; + uint8_t NTRes; + uint8_t CrtTimeTenth; // File Creation time component - count of tenths of a second (between 0 and 199) + uint16_t CrtTime; // Creation time. Granularity is 2 seconds + uint16_t CrtDate; // Creation date. + uint16_t LstAccDate; // Last Access Date (Last read or write date) + uint16_t FstClusHi; // High Word of first data cluster for file/directory described + uint16_t WrtTime; // Last Modification time | Must equal CrtTime + uint16_t WrtDate; // Last Modification date | Must equal CrtDate + uint16_t FstClusLo; // Low word of first data cluster for file/directory described + uint32_t FileSize; // size in bytes of file/directory described +}__attribute__((packed)); + + +enum struct FAT_TYPE{ + FAT12, + FAT16, + FAT32, + VFAT, + UNKOWN +}; + +class FAT { +public: + + // Wanted API for vfs + static FILE Open(char* filename); + static int close(FILE* file); + static int Read(FILE* file, void* buffer , unsigned int length); + static int Write(FILE* file, const void* buffer, unsigned int length); + static int Create(inode* dir_node, inode** target, const char* component_name); + static DirectoryNode* Lookup(inode* , DirectoryNode*); + static int Compare(DirectoryNode* , char *filename, char *filename2); + static FS_SUPER* Mount(filesystem* fs, const char* name , vfsmount* mount); + + static const int FREE = 0x0000; + static const int ALLOCATED = 0x0002; + static const int BAD = 0xFFF7; + static const int EOF = 0xFFFF; + + static const int ClnShutBitMask = 0x8000; + static const int HrdErrBitMask = 0x4000; + + static const char DOS_TRAILING_SPACE = 0x20; + static const char FREE_DIR = 0xE5; // If KANJI charset 0x05 + static const char FREE_DIR_2 = 0x00; // All directories after this are free including this one + static void ListRootDirectoryContents(BiosParameterBlock* bpb ); + static BiosParameterBlock* GetBiosParameterBlock(bool DEBUG =false ); + + + enum ATTRIBUTES { + ATTR_READ_ONLY = 0x01, + ATTR_HIDDEN = 0x02, + ATTR_SYSTEM = 0x04, + ATTR_VOLUME_ID = 0x08, + ATTR_DIRECTORY = 0x10, + ATTR_ARCHIVE = 0x20, + ATTR_LONG_NAME = (ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID) + }; + +private: + + static FAT_TYPE DetermineFATType(BiosParameterBlock* bpb); + static uint16_t GetFATEntry(BiosParameterBlock*, unsigned int); + static uint16_t DetermineFreeSpace(); + static int GetSectorOfRootDirectory(BiosParameterBlock*); + static unsigned int RootDirSize(BiosParameterBlock*); + static void OpenSubdir (DIR*, BiosParameterBlock*); + static void ReadFileContents(DIR *fileEntry, BiosParameterBlock *bpb); + + enum ENTRY_SIZE { + FAT12 = 12, + FAT16 = 16, + FAT32 = 32 + }; + + + +}; diff --git a/kernel/storage/filesystems/FAT/msdosDate.h b/kernel/storage/filesystems/FAT/msdosDate.h new file mode 100644 index 0000000..8eb2cc4 --- /dev/null +++ b/kernel/storage/filesystems/FAT/msdosDate.h @@ -0,0 +1,42 @@ +// +// Created by nigel on 23/02/23. +// + +#pragma once + +#include "../../../terminal/kterm.h" +#include "../../../memory/KernelHeap.h" +#include "../../../../CoreLib/Memory.h" + +// Date Format +// [0..4] Day +// [5..8] Month +// [9..15] Year +class MSDOSDATE { + static void ParseDate(unsigned int date){ + printf("Date (hex) 0x%x\n", date); + unsigned int year = (date >> 9 )+ 1980; + unsigned int month = (date & 0xf0 ) >> 4; + unsigned int day = date & 0xf ; + printf("Date: (D,M,Y) %d, %d ,%d\n", day , month, year ); + } +}; + + + +// Time Format +// [0..4] Seconds +// [5..10] Minute +// [11..15] Hour +class MSDOSTIME { + static void ParseTime(unsigned int time) + { + printf("Time (hex) 0x%x\n", time); + unsigned int seconds = ( time & 0x0f) * 2; + unsigned int minutes = (time & 0xf0); + unsigned int hours = (time & 0xf00); + printf("Time (H:M:S) %d:%d:%d\n", hours, minutes, seconds); + } +}; + + diff --git a/kernel/storage/ide/ide.h b/kernel/storage/ide/ide.h new file mode 100644 index 0000000..1248f44 --- /dev/null +++ b/kernel/storage/ide/ide.h @@ -0,0 +1,98 @@ +#pragma once +#include +#include "../../terminal/kterm.h" +#include "ideCommands.h" +#include "sampleIDE.h" +#include "../../pci/pciDevice.h" +#include "../../pci/pci.h" + +#define IS_BIT_SET(x, bit) ((x >> bit & 0x1) == 1) + +IDEChannelRegisters channels[2]; +IDE_DEVICE ide_devices[4]; + +inline void CheckProgIF(uint8_t ProgIF){ + if( IS_BIT_SET(ProgIF, 0) ) // Is the 0th bit set + { + printf ("Primary Channel is in PCI native mode\n"); + } else{ + printf("Primary Channel is in Compatibility mode\n"); + } + + if( IS_BIT_SET(ProgIF, 1)){ + printf("Bit 0 can be modified\n"); + }else{ + printf("Bit 0 cannot be modified\n"); + } + + if( IS_BIT_SET(ProgIF, 2)){ + printf("Secondary channel is in PCI native mode\n"); + }else{ + printf("Secondary channel is in Compatibility mode\n"); + } + + if( IS_BIT_SET(ProgIF, 3)){ + printf("Bit 2 can be modified\n"); + }else{ + printf("Bit 2 cannot be modified\n"); + } + + + if( IS_BIT_SET(ProgIF , 7)){ + printf("This is a bus master IDE Controller\n"); + } else{ + printf("This controller doesn't support DMA!\n"); + } + +} + +inline void TestIDEController(){ + // Do stuff + printf("Testing IDE controllers\n"); + + // NOTE: Testing done with a hard coded known PCI addres + // Of an intel PIIX3 IDE Controller + int bus = 0; + int device =1 , function = 1; + PCIBusAddress IDEControllerPCIAddress = PCIBusAddress{bus,device, function}; + + uint8_t ProgIF = PCI::GetProgIF(IDEControllerPCIAddress); + printf( "ProgIF: 0x%x\n" ,ProgIF); + + //CheckProgIF(ProgIF); + + // For this test will just assume all bits are set + // the CheckProgIF can check but on the test machine all bits are set anyways + + uint32_t BAR0,BAR1,BAR2,BAR3, BAR4; + + BAR0 = PCI::ReadBAR(IDEControllerPCIAddress, 0); + + BAR1 = PCI::ReadBAR(IDEControllerPCIAddress, 1); + + BAR2 = PCI::ReadBAR(IDEControllerPCIAddress, 2); + + BAR3 = PCI::ReadBAR(IDEControllerPCIAddress, 3); + + BAR4 = PCI::ReadBAR(IDEControllerPCIAddress, 4); + + // All bars are return 0xffffff for some as of yet mysterious reason! + printf( "BAR 0: 0x%x\n", BAR0); + + printf( "BAR 1: 0x%x\n", BAR1); + + printf( "BAR 2: 0x%x\n", BAR2); + + printf( "BAR 3: 0x%x\n", BAR3); + + printf( "BAR 4: 0x%x\n", BAR4); + + init_IDE(BAR0, BAR1, BAR2, BAR3, BAR4); + + // Read Something from disc + unsigned int maxByteCount = 20 ; + void* MDA_buffer = (void*)0xC0000000; + + + +} diff --git a/kernel/storage/ide/ideCommands.h b/kernel/storage/ide/ideCommands.h new file mode 100644 index 0000000..584756e --- /dev/null +++ b/kernel/storage/ide/ideCommands.h @@ -0,0 +1,86 @@ +#pragma once + +// Commands +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_CACHE_FLUSH 0xE7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_IDENTIFY 0xEC + +#define ATAPI_CMD_READ 0xA8 +#define ATAPI_CMD_EJECT 0x1B + +#define ATA_IDENT_DEVICETYPE 0 +#define ATA_IDENT_CYLINDERS 2 +#define ATA_IDENT_HEADS 6 +#define ATA_IDENT_SECTORS 12 +#define ATA_IDENT_SERIAL 20 +#define ATA_IDENT_MODEL 54 +#define ATA_IDENT_CAPABILITIES 98 +#define ATA_IDENT_FIELDVALID 106 +#define ATA_IDENT_MAX_LBA 120 +#define ATA_IDENT_COMMANDSETS 164 +#define ATA_IDENT_MAX_LBA_EXT 200 + +#define IDE_ATA 0x00 +#define IDE_ATAPI 0x01 + +#define ATA_MASTER 0x00 +#define ATA_SLAVE 0x01 + + +#define ATA_REG_DATA 0x00 +#define ATA_REG_ERROR 0x01 +#define ATA_REG_FEATURES 0x01 +#define ATA_REG_SECCOUNT0 0x02 +#define ATA_REG_LBA0 0x03 +#define ATA_REG_LBA1 0x04 +#define ATA_REG_LBA2 0x05 +#define ATA_REG_HDDEVSEL 0x06 +#define ATA_REG_COMMAND 0x07 +#define ATA_REG_STATUS 0x07 +#define ATA_REG_SECCOUNT1 0x08 +#define ATA_REG_LBA3 0x09 +#define ATA_REG_LBA4 0x0A +#define ATA_REG_LBA5 0x0B +#define ATA_REG_CONTROL 0x0C +#define ATA_REG_ALTSTATUS 0x0C +#define ATA_REG_DEVADDRESS 0x0D + +// Channels: +#define ATA_PRIMARY 0x00 +#define ATA_SECONDARY 0x01 + +// Directions: +#define ATA_READ 0x00 +#define ATA_WRITE 0x01 + + +// Status +#define ATA_SR_BSY 0x80 // Busy +#define ATA_SR_DRDY 0x40 // Drive ready +#define ATA_SR_DF 0x20 // Drive write fault +#define ATA_SR_DSC 0x10 // Drive seek complete +#define ATA_SR_DRQ 0x08 // Data request ready +#define ATA_SR_CORR 0x04 // Corrected data +#define ATA_SR_IDX 0x02 // Index +#define ATA_SR_ERR 0x01 // Error + + +// Errors +#define ATA_ER_BBK 0x80 // Bad block +#define ATA_ER_UNC 0x40 // Uncorrectable data +#define ATA_ER_MC 0x20 // Media changed +#define ATA_ER_IDNF 0x10 // ID mark not found +#define ATA_ER_MCR 0x08 // Media change request +#define ATA_ER_ABRT 0x04 // Command aborted +#define ATA_ER_TK0NF 0x02 // Track 0 not found +#define ATA_ER_AMNF 0x01 // No address mark \ No newline at end of file diff --git a/kernel/storage/ide/sampleIDE.definitions.h b/kernel/storage/ide/sampleIDE.definitions.h new file mode 100644 index 0000000..957dc60 --- /dev/null +++ b/kernel/storage/ide/sampleIDE.definitions.h @@ -0,0 +1,29 @@ +#pragma once + +struct IDEChannelRegisters{ + unsigned short base; // I/O Base. + unsigned short ctrl; // Control Base + unsigned short bmide; // Bus Master IDE + unsigned char nIEN; // IEN (no interrupt) +}; + + +struct IDE_DEVICE { + unsigned char Reserved; // 0 (Empty) or 1 (This device exists). + unsigned char Channel; // 0 (Primary Channel) or 1 (Secondary Channel). + unsigned char Drive; // 0 (Master Drive) or 1 (Slave Drive). + unsigned short Type; // 0 ATA, 1:ATAPI + unsigned short Signature; // Drive Signature + unsigned short Capabilities; // Features. + unsigned int CommandSets; // Command Sets Supported. + unsigned int Size; // Size in Sectors (NOTE: Seems unused nowadays as i've only seen the value be zero + unsigned char Model[41]; // Model in string. +} ; + + + +extern IDEChannelRegisters channels[2]; +extern IDE_DEVICE ide_devices[4]; +extern unsigned char ide_buf[2048]; +extern unsigned char ide_irq_invoked; +extern unsigned char atapi_packet[12]; diff --git a/kernel/storage/ide/sampleIDE.h b/kernel/storage/ide/sampleIDE.h new file mode 100644 index 0000000..7322ccd --- /dev/null +++ b/kernel/storage/ide/sampleIDE.h @@ -0,0 +1,258 @@ +#pragma once +#include +#include "../../terminal/kterm.h" +#include "sampleIDE.definitions.h" +#include "ideCommands.h" + +void Detect_IO_Ports(uint32_t BAR0, uint32_t BAR1,uint32_t BAR2, uint32_t BAR3, uint32_t BAR4); +void DetectDevices(); + +unsigned char ide_buf[2048] = {0}; +unsigned char ide_irq_invoked = 0; +unsigned char atapi_packet[12] = {0xA8,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +void wait(int t){ + volatile int i,j; + for(i=0;i 0x07 && reg < 0x0C) + ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN); + if (reg < 0x08) + outb(channels[channel].base + reg - 0x00, data); + else if (reg < 0x0C) + outb(channels[channel].base + reg - 0x06, data); + else if (reg < 0x0E) + outb(channels[channel].ctrl + reg - 0x0A, data); + else if (reg < 0x16) + outb(channels[channel].bmide + reg - 0x0E, data); + if (reg > 0x07 && reg < 0x0C) + ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN); +} + +unsigned char ide_read(unsigned char channel, unsigned char reg){ + unsigned char result; + if( reg > 0x07 && reg < 0x0C) + ide_write(channel,ATA_REG_CONTROL, 0x80 | channels[channel].nIEN); + if( reg < 0x08) + result = inb(channels[channel].base + reg - 0x00); + else if (reg < 0x0C) + result = inb(channels[channel].base + reg - 0x06); + else if (reg < 0x0E) + result = inb(channels[channel].ctrl + reg - 0x0A); + else if (reg < 0x16) + result = inb(channels[channel].bmide + reg - 0x0E); + if (reg > 0x07 && reg < 0x0C) + ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN); + return result; +} + +void ide_read_buffer(unsigned char channel, unsigned char reg, unsigned int buffer, unsigned int quads){ + if (reg > 0x07 && reg < 0x0C) + ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN); + if (reg < 0x08) + insl(channels[channel].base + reg - 0x00, (void *)buffer, quads); + else if (reg < 0x0C) + insl(channels[channel].base + reg - 0x06, (void *)buffer, quads); + else if (reg < 0x0E) + insl(channels[channel].ctrl + reg - 0x0A, (void *)buffer, quads); + else if (reg < 0x16) + insl(channels[channel].bmide + reg - 0x0E, (void *)buffer, quads); + if (reg > 0x07 && reg < 0x0C) + ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN); +} + +unsigned char ide_polling(unsigned char channel, unsigned int advanced_check) { + + // (I) Delay 400 nanosecond for BSY to be set: + // ------------------------------------------------- + for(int i = 0; i < 4; i++) + ide_read(channel, ATA_REG_ALTSTATUS); // Reading the Alternate Status port wastes 100ns; loop four times. + + // (II) Wait for BSY to be cleared: + // ------------------------------------------------- + while (ide_read(channel, ATA_REG_STATUS) & ATA_SR_BSY) + ; // Wait for BSY to be zero. + + if (advanced_check) { + unsigned char state = ide_read(channel, ATA_REG_STATUS); // Read Status Register. + + // (III) Check For Errors: + // ------------------------------------------------- + if (state & ATA_SR_ERR) + return 2; // Error. + + // (IV) Check If Device fault: + // ------------------------------------------------- + if (state & ATA_SR_DF) + return 1; // Device Fault. + + // (V) Check DRQ: + // ------------------------------------------------- + // BSY = 0; DF = 0; ERR = 0 so we should check for DRQ now. + if ((state & ATA_SR_DRQ) == 0) + return 3; // DRQ should be set + + } + + return 0; // No Error. + +} + +unsigned char ide_print_error(unsigned int drive, unsigned char err) { + if (err == 0) + return err; + + printf("IDE:"); + if (err == 1) {printf("- Device Fault\n "); err = 19;} + else if (err == 2) { + unsigned char st = ide_read(ide_devices[drive].Channel, ATA_REG_ERROR); + if (st & ATA_ER_AMNF) {printf("- No Address Mark Found\n "); err = 7;} + if (st & ATA_ER_TK0NF) {printf("- No Media or Media Error\n "); err = 3;} + if (st & ATA_ER_ABRT) {printf("- Command Aborted\n "); err = 20;} + if (st & ATA_ER_MCR) {printf("- No Media or Media Error\n "); err = 3;} + if (st & ATA_ER_IDNF) {printf("- ID mark not Found\n "); err = 21;} + if (st & ATA_ER_MC) {printf("- No Media or Media Error\n "); err = 3;} + if (st & ATA_ER_UNC) {printf("- Uncorrectable Data Error\n "); err = 22;} + if (st & ATA_ER_BBK) {printf("- Bad Sectors\n "); err = 13;} + } else if (err == 3) {printf("- Reads Nothing\n "); err = 23;} + else if (err == 4) {printf("- Write Protected\n "); err = 8;} + printf("- [%s %s] %s\n", + (const char *[]){"Primary", "Secondary"}[ide_devices[drive].Channel], // Use the channel as an index into the array + (const char *[]){"Master", "Slave"}[ide_devices[drive].Drive], // Same as above, using the drive + ide_devices[drive].Model); + + return err; +} + + +inline void init_IDE( uint32_t BAR0, uint32_t BAR1,uint32_t BAR2, uint32_t BAR3, uint32_t BAR4) +{ + Detect_IO_Ports( BAR0, BAR1, BAR2, BAR3, BAR4); + + printf("ATA Primary port, base: 0x%x, ctrl: 0x%x\n", channels[ATA_PRIMARY].base , channels[ATA_PRIMARY].ctrl); + printf("ATA Secondary port, base: 0x%x, ctrl: 0x%x\n", channels[ATA_SECONDARY].base , channels[ATA_SECONDARY].ctrl); + + // 2- Disable IRQs: + ide_write(ATA_PRIMARY , ATA_REG_CONTROL, 2); + ide_write(ATA_SECONDARY, ATA_REG_CONTROL, 2); + + DetectDevices(); + + return; + // 4- Print Summary: + for (int i = 0; i < 4; i++) + if (ide_devices[i].Reserved == 1) { + printf(" Found %s Drive %d bytes - %x\n", + (const char *[]){"ATA", "ATAPI"}[ide_devices[i].Type], /* Type */ + ide_devices[i].Size / 2, /* Size */ + ide_devices[i].Model); + } +} + + +// 3- Detect ATA-ATAPI Devices: +inline void DetectDevices(){ + int i, j, k, count = 0; + + for (i = 0; i < 2; i++) + for (j = 0; j < 2; j++) { + + unsigned char err = 0, type = IDE_ATA, status; + ide_devices[count].Reserved = 0; // Assuming that no drive here. + + // (I) Select Drive: + ide_write(i, ATA_REG_HDDEVSEL, 0xA0 | (j << 4)); // Select Drive. + wait(1000); // Wait 1ms for drive select to work. + + // (II) Send ATA Identify Command: + ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY); + wait(1000); + + // (III) Polling: + if (ide_read(i, ATA_REG_STATUS) == 0) continue; // If Status = 0, No Device. + + while(1) { + status = ide_read(i, ATA_REG_STATUS); + if ((status & ATA_SR_ERR)) {err = 1; break;} // If Err, Device is not ATA. + if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRQ)) break; // Everything is right. + } + + // (IV) Probe for ATAPI Devices: + if (err != 0) { + unsigned char cl = ide_read(i, ATA_REG_LBA1); + unsigned char ch = ide_read(i, ATA_REG_LBA2); + + if (cl == 0x14 && ch ==0xEB) + type = IDE_ATAPI; + else if (cl == 0x69 && ch == 0x96) + type = IDE_ATAPI; + else + continue; // Unknown Type (may not be a device). + + ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY_PACKET); + wait(1000); + } + + // (V) Read Identification Space of the Device: + ide_read_buffer(i, ATA_REG_DATA, (unsigned int) ide_buf, 128); + + // (VI) Read Device Parameters: + ide_devices[count].Reserved = 1; + ide_devices[count].Type = type; + ide_devices[count].Channel = i; + ide_devices[count].Drive = j; + ide_devices[count].Signature = *((unsigned short *)(ide_buf + ATA_IDENT_DEVICETYPE)); + ide_devices[count].Capabilities = *((unsigned short *)(ide_buf + ATA_IDENT_CAPABILITIES)); + ide_devices[count].CommandSets = *((unsigned int *)(ide_buf + ATA_IDENT_COMMANDSETS)); + + // (VII) Get Size: + if (ide_devices[count].CommandSets & (1 << 26)) + // Device uses 48-Bit Addressing: + ide_devices[count].Size = *((unsigned int *)(ide_buf + ATA_IDENT_MAX_LBA_EXT)); + else + // Device uses CHS or 28-bit Addressing: + ide_devices[count].Size = *((unsigned int *)(ide_buf + ATA_IDENT_MAX_LBA)); + + // (VIII) String indicates model of device (like Western Digital HDD and SONY DVD-RW...): + for(k = 0; k < 40; k += 2) { + ide_devices[count].Model[k] = ide_buf[ATA_IDENT_MODEL + k + 1]; + ide_devices[count].Model[k + 1] = ide_buf[ATA_IDENT_MODEL + k];} + ide_devices[count].Model[40] = 0; // Terminate String. + + count++; + } +} + + +inline void Detect_IO_Ports(uint32_t BAR0, uint32_t BAR1,uint32_t BAR2, uint32_t BAR3, uint32_t BAR4){ + // 1 Detect I/O Ports which interface an IDE Controller + + // Based on the implementation within serenity + channels[ATA_PRIMARY].base = (BAR0 == 0x1 || BAR0 == 0x0) ? 0x1F0 : BAR0 & (~1); + channels[ATA_PRIMARY ].ctrl = (BAR1 == 0x1 || BAR1 == 0x0) ? 0x3F6 : BAR1 & (~1); + channels[ATA_SECONDARY].base = (BAR2 == 0x1 || BAR2 == 0x0) ? 0x170 : BAR2 & (~1); + channels[ATA_SECONDARY].ctrl = (BAR3 == 0x1 || BAR3 == 0x0) ? 0x376 : BAR3 & (~1); + channels[ATA_PRIMARY ].bmide = (BAR4 & (~1)) + 0; // Bus Master IDE + channels[ATA_SECONDARY].bmide = (BAR4 & (~1)) + 8; // Bus Master IDE + +} + + +bool driveAvailable(){ + int devNumber = 0; + for ( auto device : ide_devices){ + if(!device.Reserved) + continue; + devNumber++; + } + + + // FIXME: If no drive is connected we continue trying to read from + // a not connected drive! + //ATAPIO::Identify((uint16_t) BUS_PORT::Primary, DEVICE_DRIVE::MASTER); + return true; +} \ No newline at end of file diff --git a/kernel/storage/partitions/partitionManager.cpp b/kernel/storage/partitions/partitionManager.cpp new file mode 100644 index 0000000..ef62452 --- /dev/null +++ b/kernel/storage/partitions/partitionManager.cpp @@ -0,0 +1,18 @@ +// +// Created by nigel on 23/02/23. +// + +#include "partitionManager.h" + +bool partitionManager::Validate( ) +{ + + //auto* bootParams = getBPB(this, true); + + //if(bootParams->OEM_id) { + // return true; + //} + + return true; + +} diff --git a/kernel/storage/partitions/partitionManager.h b/kernel/storage/partitions/partitionManager.h new file mode 100644 index 0000000..56cbee9 --- /dev/null +++ b/kernel/storage/partitions/partitionManager.h @@ -0,0 +1,11 @@ +// +// Created by nigel on 23/02/23. +// +#pragma once + +class partitionManager { +public: + static bool Validate(); + +}; + diff --git a/kernel/storage/partitiontables/mbr/MasterBootRecord.h b/kernel/storage/partitiontables/mbr/MasterBootRecord.h new file mode 100644 index 0000000..4f83ceb --- /dev/null +++ b/kernel/storage/partitiontables/mbr/MasterBootRecord.h @@ -0,0 +1,43 @@ +#pragma once +#include +#include "PartitionTableEntry.h" +#include "../../../memory/KernelHeap.h" +#include "../../ata pio/ATAPIO.h" + +struct MBR { + uint8_t code [440]; + uint32_t uniqueID; + uint16_t Reserved; + struct PartitionTableEntry TableEntries[4]; + uint16_t ValidBootsector; +}__attribute__((packed)); + + +inline MBR* GetPartitions(bool DEBUG = false){ + const int C = 0; + const int H = 0; + const int HPC = 16; + const int SPT = 63; + + int S =1; + uint32_t LBA = (C*HPC+H) * SPT + (S-1); + + uint16_t* mbr =(uint16_t*) malloc(sizeof (MBR)); + + ATAPIO::Read(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER, LBA, mbr ); + auto bootRecord = (MBR*)(mbr); + + printf("MBR (In Memory) Address 0x%x, Size = %d\n", bootRecord, sizeof (MBR)); + if(DEBUG){ + printf("BootSector: 0x%x\n", bootRecord->ValidBootsector ); + for( int i = 0 ; i < 4 ; i ++){ + PartitionTableEntry PT = bootRecord->TableEntries[i]; + + printf("Partition %d [ %d sectors, PartitionType: 0x%x, 0x%x, \nLBA Start: 0x%x ]\n" , + i, PT.Number_sectors_inPartition, PT.PartitionType, bootRecord->uniqueID, PT.LBA_partition_start ); + } + + } + + return bootRecord; +} diff --git a/kernel/storage/partitiontables/mbr/PartitionTableEntry.h b/kernel/storage/partitiontables/mbr/PartitionTableEntry.h new file mode 100644 index 0000000..e1bd4d6 --- /dev/null +++ b/kernel/storage/partitiontables/mbr/PartitionTableEntry.h @@ -0,0 +1,11 @@ +#pragma once +#include + +struct PartitionTableEntry{ + uint8_t driveAttribute; + uint8_t CHS_start_address [3]; + uint8_t PartitionType; + uint8_t CHS_lastSector_Address[3]; + uint32_t LBA_partition_start; + uint32_t Number_sectors_inPartition; +}__attribute__((packed)); \ No newline at end of file diff --git a/kernel/storage/vfs/vfs.cpp b/kernel/storage/vfs/vfs.cpp new file mode 100644 index 0000000..0eb140e --- /dev/null +++ b/kernel/storage/vfs/vfs.cpp @@ -0,0 +1,201 @@ +#include "vfs.h" +#include +#include "../../memory/KernelHeap.h" +#include "../ata pio/ATAPIO.h" +#include "../partitiontables/mbr/MasterBootRecord.h" +#include "../filesystems/FAT/FAT.h" +#include "vfs_types.h" +#include "../../../CoreLib/Memory.h" +#include + +vfsmount* VirtualFileSystem::rootfs; +int VirtualFileSystem::mount_number = 0; +int VirtualFileSystem::superblock_number =0; +int VirtualFileSystem::filesystem_number =0; + +filesystem* VirtualFileSystem::filesystems[4]; +FS_SUPER* VirtualFileSystem::superblocks[8]; +vfsmount* VirtualFileSystem::mounts[12]; + +void VirtualFileSystem::Mount(filesystem* fs, const char* name) +{ + + vfsmount* mnt_point = (vfsmount*) malloc(sizeof(vfsmount)); + FS_SUPER* sb = fs->mount(fs, name, mnt_point); + if( sb == nullptr){ + printf("mount failed!\n"); + return; + } + mounts[mount_number++] = mnt_point; + superblocks[superblock_number++] = sb; + mnt_point->mnt_count = 1; + rootfs = mnt_point; +} + +void VirtualFileSystem::initialize() +{ + // TODO: setup memory pools etc to speed things up + // a bit + // TODO: Add a devfs, procfs etc... + + filesystem* fat_fs = (filesystem*) malloc(sizeof (filesystem)); + fat_fs->name = "fat"; + fat_fs->mount = FAT::Mount; + //register_filesystem(fat_fs); + + + // Mount the bootdrive + // NOTE: for now will hardcode this + Mount(fat_fs, "/"); +}; + + +int VirtualFileSystem::register_filesystem(struct filesystem* fs) { + // register the filesystem to the kernel. + filesystems[filesystem_number] = fs; + filesystem_number++; + + +} + +FILE* VirtualFileSystem::open(const char* pathname, int flags){ + // 1. Lookup pathname from the root node + // 2. Create a new file descriptor for this inode if found. + // 3. Create a new file if O_CREATE is specified in the flags. + FILE* file = (FILE*) malloc(sizeof (FILE)) ; + auto* rootentry = rootfs->root; + char* tokstate = nullptr; + auto nextdir = strtok ((char*)pathname, "/", &tokstate ); + + // look up children if not filled + if(rootentry->children == nullptr) + { + rootentry = rootentry->node->lookup(rootentry->node, rootentry); + } + + if(rootentry->children == nullptr) + { + file->flags =1; + return file; + } + + // let's just loop through the folder first + printf("looking for: "); + for(int i = 0; i < 5; i++) + kterm_put(nextdir[i]); + kterm_put('\n'); + auto* child = rootentry->children; + while(child->next != nullptr){ + auto* directory = (DirectoryNode*)child->data; + + for(int i = 0; i < 11 ; i++) + kterm_put(directory->name[i]); + kterm_put('\n'); + + if( directory->compare(directory, directory->name, nextdir) == 0){ + nextdir = strtok(nullptr, "/", &tokstate); + printf("Found dir!\n"); + if(nextdir == NULL){ + file->root = directory->node; + file->flags =0; + file->read = FAT::Read; + return file; + } + printf("continue searching next directory!\n"); + if(directory->children == nullptr) + directory->node->lookup(directory->node, directory); + + + child = directory->children; + + }else{ + child = child->next; + } + } + + + + file->flags = 1; + return file; +} + +int VirtualFileSystem::close (struct FILE* file){ + // 1. release the file descriptor +} +int VirtualFileSystem::write(struct FILE* file, const void* buf, unsigned int len){ + // 1. Write len bytes from buf to the opened file. + // 2. return written size or error code if an error occurs +} +int VirtualFileSystem::read (struct FILE* file, void* buf, unsigned int len){ + // 1. read min(len, readable file data size) bytes ro buf from the opened file. + // 2. return read size or error code if an error occurs +} + +/* + +void fs_discovery(){ + + + // Mount the boot disk + // NOTE: we assume for now that it is the only disk in the system + // This information could possibly be had from the bootloader (GRUB) + // We als assume it is the primary device on the Master port. + ATAPIO::Soft_Reset(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER); + bool isAvailable = ATAPIO::Identify(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER); + if(!isAvailable){ + // PANIC!!! + printf("Failed to mount root filesystem!\n"); + return; + } + + auto masterbootrecord = GetPartitions(false); + + for (auto partition : masterbootrecord->TableEntries) + { + if(partition.PartitionType == 0x0) continue; // Consider marked as free + + PTR_PARTITION found_partition = (PARTITION*) malloc(sizeof(PARTITION)); + found_partition->Disk = ATAPIO_PORT::Primary | ( DEVICE_DRIVE::MASTER << 16); + printf("Disk Identifier: 0x%x\n", found_partition->Disk); + found_partition->Attributes = partition.driveAttribute; + found_partition->StartAddress = partition.LBA_partition_start; + found_partition->Sectors = partition.Number_sectors_inPartition; + found_partition->Fs_hint = partition.PartitionType; + + + } + + printf("Found %d partitions on disk!\n", num_partitions); + + for (int i = 0; i < num_partitions; i++) + { + auto* partition = _partitions[i]; + // Check the fs_hint for a proper driver + if ( partition->Fs_hint != 0x06){ + printf("Assumed Unkown filesystem!\n"); + continue; + } + // Check if filesystem OK + + printf("Partition Start Address (LBA): 0x%x\n", partition->StartAddress); + bool valid = FAT::Validate(partition); + if(!valid) + { + printf("Not a valid FAT fs!\n"); + continue; + } + + // setup FileSystem Description before mounting + PFS FS_FAT = (PFS)malloc(sizeof(FILESYSTEM)); + + FAT::Info(partition, FS_FAT); + + // Mount the partition/filesystem + } + + +} + + + +*/ \ No newline at end of file diff --git a/kernel/storage/vfs/vfs.h b/kernel/storage/vfs/vfs.h new file mode 100644 index 0000000..821853d --- /dev/null +++ b/kernel/storage/vfs/vfs.h @@ -0,0 +1,32 @@ +#pragma once +#include +#include "../../../CoreLib/Path.h" +#include "vfs_types.h" +#include "vfs_types.h" + class VirtualFileSystem + { + public: + static void initialize(); + static void Mount(filesystem* fs, const char* name); + + static int register_filesystem(struct filesystem* fs); + + static FILE* open(const char* pathname, int flags); + static int close(struct FILE* file); + static int write(struct FILE* file, const void* buf, unsigned int len); + static int read(struct FILE* file, void* buf, unsigned int len); + + private: + static vfsmount* rootfs; + + + static int mount_number; + static int superblock_number; + static int filesystem_number; + + static filesystem* filesystems[]; + static FS_SUPER* superblocks[]; + static vfsmount* mounts[]; + + }; + diff --git a/kernel/storage/vfs/vfs_types.h b/kernel/storage/vfs/vfs_types.h new file mode 100644 index 0000000..73744ca --- /dev/null +++ b/kernel/storage/vfs/vfs_types.h @@ -0,0 +1,110 @@ +// +// Created by nigel on 21/02/23. +// +#pragma once +// grasslab.github.io/osdi/en/labs/lab7.html +#include +#include +#include "../../../CoreLib/List.h" + +struct inode_operations; +struct vfsmount; +struct FS_SUPER; +struct inode; +struct dentry_operations; +struct DirectoryNode; +struct filesystem; +struct FS_SUPER; +struct FILE; + + +// Describes a mount +struct vfsmount { + vfsmount* mnt_parent; // fs we are mounted on + DirectoryNode* mountpoint; // dentry of mount point + DirectoryNode* root; // root of the mounted tree + FS_SUPER* sb; // pointer to the superblock + unsigned int mnt_count; // keep track of users of this structure + int mnt_flags; + char* mnt_devname; // name of device eg /dev/dsk/hda1 + +}; +struct FS_SUPER; +// Represents a filesystem object (i.e. a file or directory or device) +struct inode { + unsigned long mode; // access permissions + unsigned long uid; // user id owner + unsigned long gid; // group id owner + unsigned int flags; + // operations possible on inode + int (*create)(inode*, DirectoryNode*, const char* ); + DirectoryNode* (*lookup)(inode* , DirectoryNode*); + int (*link)(DirectoryNode*, inode* , DirectoryNode*); + int (*unlink)(inode*, DirectoryNode*); + int (*symlink)(inode*, DirectoryNode*); + int (*mkdir)(inode*, DirectoryNode*, const char*); + int (*rmdir)(inode*, DirectoryNode*); + int (*rename)(inode*, DirectoryNode*, inode*, DirectoryNode*); + void (*truncate)(inode*); + int (*permission)(inode*, int); + int (*setattr)(DirectoryNode, unsigned long*); + int (*getattr)(vfsmount* mnt, DirectoryNode*, unsigned long*); + + FS_SUPER* sb; + unsigned long ino; // unique number of this inode + unsigned int links; // number of hard links + void* device; + unsigned long size; // size of inode contents in bytes + unsigned long atime; // Access time + unsigned long mtime; // Modify time + unsigned long ctime; // Creation time + unsigned short bytes; // bytes consumed + // File operations possible on Inode; + int(*write) (FILE* file, const void* buf, unsigned int len); + int(*read) (FILE* file, void* buf, unsigned int len); + void* internal; // point to underlying representation of this virtual node (e.g. FAT entry or Directory Entry) +}; + +// Represents the name of files in the filesystem +// it identifies the file that an inode represents +struct DirectoryNode { + char* name; // name of the file on the disk + DirectoryNode* parent; // parent of the file + inode* node; // node belongs to... + int (*compare)(DirectoryNode*, char*, char* ); + int (*o_delete)(DirectoryNode*); + void (*release)(DirectoryNode*); + void (*iput)(DirectoryNode*, inode*); + List* children; +}; +// Represents a filesystem type +struct filesystem { + const char* name; + FS_SUPER* (*mount)(filesystem* self, const char* name, vfsmount* mnt); +}; + +// Represents a mounted filesystem +struct FS_SUPER { + + void* device; // device associated with the filesystem + unsigned long blocksize; + unsigned long maxbytes; + filesystem* type; + unsigned long magic; // IDK + DirectoryNode* root; // Root dentry + int count; // IDK + void* fs_info; // pointer to raw filesystem info + dentry_operations* d_op; + inode* inodes[]; +}; + +// Represents an opened file +struct FILE { + inode* root; + unsigned int f_pos; // The next read/write position of this file descriptor; + int(*write) (FILE* file, const void* buf, unsigned int len); + int(*read) (FILE* file, void* buf, unsigned int len); + int flags; +}; + + diff --git a/kernel/supervisorterminal/superVisorTerminal.cpp b/kernel/supervisorterminal/superVisorTerminal.cpp new file mode 100644 index 0000000..2034e65 --- /dev/null +++ b/kernel/supervisorterminal/superVisorTerminal.cpp @@ -0,0 +1,100 @@ +#include "superVisorTerminal.h" +#include "../storage/ata pio/ATAPIO.h" +#include "../storage/partitiontables/mbr/MasterBootRecord.h" +#include "../storage/filesystems/FAT/FAT.h" + +bool isRunning = true; +extern "C" void startSuperVisorTerminal() +{ + + + /* + * Show a little banner for cuteness + */ + printf("|=== BarinkOS ===|\n"); + + while (isRunning){ + + printf("SUPERVISOR:>$ " ); + int characterCount = 0; + char command[10] = ""; + + // NOTE: lets just show a kernel prompt + uint8_t ScanCode = getKey(); + while( ScanCode != 0x1C ) + { + char character = getASCIIKey(); + kterm_put(character ); + // wHAT THE HELL + + if( characterCount < 10 ){ + command[characterCount] = character; + characterCount++; + } + + ScanCode = getKey(); + } + printf("\n"); + KeyHandled(); + + + if ( strncmp("DATE", command , characterCount ) == 0 ) + { + read_rtc(); + printf("======= Time & Date ==========\n"); + printf(" - Date: %02d-%02d-%02d\n",day, month, year); + printf(" - Time: %02d:%02d:%02d\n" , hour, minute, second); + printf(" - Ticks: %09d\n", pit_tick); + } + if( strncmp ("MEMORY" , command , characterCount) == 0 ) + { + // Show memory layout + printf("========= Memory (very inaccurate) ==========\n"); + printf("Kernel MemoryMap:\n"); + printf("kernel: 0x%x - 0x%x\n", &kernel_begin , &kernel_end); + printf("Frames used: %d blocks of 4 KiB\n", GetUsedBlocks()); + + } + if(strncmp("TEST", command, characterCount) == 0) + { + // TEST #DE exception + asm volatile ("MOV $4, %AX ; MOV $0, %BX ; DIV %BX"); // IRS 0 + } + if (strncmp("VERSION", command , characterCount) == 0) + { + // Show version information + printf("========= Version ========\n"); + + asm volatile ("movl $0x666, %eax; int $0x50"); + + } + if(strncmp("CLEAR", command, characterCount) == 0) + { + kterm_init(); + printf("|=== BarinkOS ===|\n"); + } + if(strncmp("LIST", command, 4) == 0) + { + + // slice off the command part + char args[characterCount - 4]; + for(int i = 5 ; i < characterCount; i++) { + args[i] = command[i]; + } + + printf("=============== DIRECTORY LISTING =================\n"); + printf("Path to show %s\n", args); + } + + if(strncmp("DEVICES", command, characterCount) == 0){ + printf("================ CONNECTED DEVICES ===============\n"); + + } + + + printf("executed command: %s\n", command); + + + delay(1000); + } +} \ No newline at end of file diff --git a/kernel/supervisorterminal/superVisorTerminal.h b/kernel/supervisorterminal/superVisorTerminal.h new file mode 100644 index 0000000..f68456c --- /dev/null +++ b/kernel/supervisorterminal/superVisorTerminal.h @@ -0,0 +1,9 @@ +#pragma once +#include "../terminal/kterm.h" +#include "../time.h" +#include "../drivers/pit/pit.h" +#include "../drivers/ps-2/keyboard.h" +#include "../memory/PhysicalMemoryManager.h" +#include + +extern "C" void startSuperVisorTerminal(); \ No newline at end of file diff --git a/kernel/syscalls.h b/kernel/syscalls.h new file mode 100644 index 0000000..dddb884 --- /dev/null +++ b/kernel/syscalls.h @@ -0,0 +1,52 @@ +// +// Created by nigel on 26/02/23. +// +#pragma once + + +#include "terminal/kterm.h" +#include "storage/vfs/vfs_types.h" + + +void sys_version (){ + printf("KERNEL VERSION v0.4\n"); +} + +void sys_open(){ + +} + +void sys_read(FILE* file, char* data){ + file->read(file, data, 512); +} + +void sys_write(FILE* path, const char* data, size_t size){ + +} + +// NOTE: this should become our standard! +void syscall_handler(int syscall_no , uint32_t* args... ){ + switch(syscall_no){ + case 0x0: + printf("test!\n"); + break; + case 0x5: + // SYS_OPEN + // sys_open(); + break; + case 0x10: + // SYS_READ + // sys_read((FILE*)args[1], (char*) args[2] ); + break; + case 0x20: + // SYS_WRITE + //sys_write((FILE*)args[1], (const char*) args[2], (size_t)args[3]); + break; + case 0x666: + // SYS_VERSION + sys_version(); + break; + } +} + + diff --git a/kernel/terminal/kterm.cpp b/kernel/terminal/kterm.cpp new file mode 100644 index 0000000..263d799 --- /dev/null +++ b/kernel/terminal/kterm.cpp @@ -0,0 +1,235 @@ +#include "kterm.h" + +static const size_t VGA_WIDTH = 80; +static const size_t VGA_HEIGHT = 25; + +size_t kterm_row; +size_t kterm_column; +uint8_t kterm_color; +uint16_t* kterm_buffer; + + +static inline uint8_t vga_entry_color( enum vga_color fg, enum vga_color bg) { + return fg | bg << 4; +} + +static inline uint16_t vga_entry (unsigned char uc, uint8_t color) { + return (uint16_t) uc | (uint16_t) color << 8; +} + +void kterm_init () { + kterm_row = 0; + kterm_column = 0; + kterm_color = vga_entry_color ( VGA_COLOR_LIGHT_GREY , VGA_COLOR_BLACK); + + //Physical address + // 0xB8000 + // Virtual address + // 0xC03FF000 + + //kterm_buffer = ((uint16_t*) 0xB8000); + kterm_buffer = ((uint16_t*) 0xC03FF000 ); + + for (size_t y = 0; y < VGA_HEIGHT; y++ ){ + for( size_t x = 0; x < VGA_WIDTH; x++){ + const size_t index = y * VGA_WIDTH + x; + kterm_buffer[index] = vga_entry(' ', kterm_color); + + } + } +} + +void kterm_resetcolor(){ + kterm_color = vga_entry_color ( VGA_COLOR_LIGHT_GREY , VGA_COLOR_BLACK); +} + +void kterm_setcolor(uint8_t color){ + kterm_color = color; +} + +void kterm_putat (char c, uint8_t color, size_t x, size_t y ) { + const size_t index = y * VGA_WIDTH + x; + kterm_buffer[index] = vga_entry(c, color); +} + +void enable_cursor (uint8_t start_cursor , uint8_t end_cursor ){ + outb(0x3D4, 0x0A); + outb(0x3D5, (inb(0x3D5) & 0xC0) | start_cursor); + + outb(0x3D4, 0x0B); + outb(0x3D5, (inb(0x3D5) & 0xE0) | end_cursor); +} + +void disable_cursor() +{ + outb(0x3D4, 0x0A); + outb(0x3D5, 0x20); +} + +void update_cursor(int x, int y){ + uint16_t pos = y * VGA_WIDTH + x; + + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (pos & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((pos >> 8) & 0xFF)); +} + +uint16_t get_cursor_position(){ + uint16_t pos = 0; + outb(0x3D4, 0x0F); + pos |= inb(0x3D5); + outb(0x3D4, 0x0E); + pos |= ((uint16_t) inb(0x3D5)) << 8; + return pos; +} + +int get_cursor_x (uint16_t cursor_pos) { + return cursor_pos % VGA_WIDTH; +} + +int get_cursor_y (uint16_t cursor_pos ) { + return cursor_pos / VGA_WIDTH; +} + +/** + * With the help from: + * https://whiteheadsoftware.dev/operating-systems-development-for-dummies/ + **/ +void kterm_scrollup(){ + size_t i ; + for(i=0; i < (VGA_WIDTH * VGA_HEIGHT - VGA_WIDTH); i++) + kterm_buffer[i] = kterm_buffer[i+VGA_WIDTH]; + + for( i=0; i< VGA_WIDTH; i++) + kterm_buffer[(VGA_HEIGHT -1) * VGA_WIDTH + i ] = vga_entry(' ', kterm_color); + +} + +void kterm_put (char c) { + if(++kterm_column == VGA_WIDTH || c == '\n' ) { + update_cursor(kterm_column , kterm_row); + kterm_column = 0; + if(kterm_row == VGA_HEIGHT-1 ) { + kterm_scrollup(); + } else { + kterm_row ++; + } + } + if ( c == '\r'){ + kterm_column = 0; + return; + } + + if(c == '\n') return; + kterm_putat ( c, kterm_color, kterm_column, kterm_row); + + +} + +void kterm_write(const char* data, size_t size) { + for(size_t i = 0; i < size; i++){ + kterm_put(data[i]); + } +} + +void kterm_writestring(const char* data ){ + // AS_KERNEL(); + kterm_write(data, strlen(data)); +} + +static void itoa (char *buf, int base, int d) { + char *p = buf; + char *p1, *p2; + unsigned long ud = d; + int divisor = 10; + if ( base == 'd' && d < 0){ + *p++ = '-'; + buf++; + ud = -d; + } else if (base == 'x'){ + divisor = 16; + } + + do { + int remainder = ud % divisor; + + *p++ = (remainder < 10 ) ? remainder + '0' : remainder + 'a' -10; + } while(ud /= divisor); + + /*terminate buf*/ + *p =0; + p1 = buf; + p2 = p -1; + + while (p1 < p2) + { + char tmp = *p1; + *p1 = *p2; + *p2 = tmp; + p1++; + p2--; + + } + +} + +void printf ( const char *format, ...) { + + auto **arg = (unsigned char **)&format; + int c; + char buf[20]; + + arg++; + + while ((c = *(const unsigned char*)format++) != 0){ + if( c != '%') + kterm_put(c); + else{ + char const *p, *p2; + int pad0 = 0, pad = 0; + + c = *(const unsigned char*)format++; + if(c =='0'){ + pad0 = 1; + c = *(const unsigned char*)format++; + } + + if ( c >= '0' && c <= '9'){ + pad = c - '0'; + c = *(const unsigned char*)format++; + } + + switch (c) + { + case 'd': + + case 'u': + case 'x': + itoa(buf, c, *((int *) arg++)); + + p = buf; + goto string; + break; + + case 's': + p = (char const *)*arg++; + if(!p) + p = "(null)"; + + string: + for (p2 = p; *p2; p2++); + for (; p2 < p + pad; p2++) + kterm_put(pad0 ? '0': ' '); + while (*p) + kterm_put(*p++); + break; + + + default: + kterm_put(*(int *) arg++); // NOLINT(cppcoreguidelines-narrowing-conversions) + break; + } + } + } +} \ No newline at end of file diff --git a/kernel/terminal/kterm.h b/kernel/terminal/kterm.h new file mode 100644 index 0000000..5d5a7a0 --- /dev/null +++ b/kernel/terminal/kterm.h @@ -0,0 +1,34 @@ +#pragma once +#include +#include +#include + +#include "../drivers/vga/colors.h" +#include "../io/io.h" +#include + +void kterm_init(); + +/* Kernel terminal - Colour functions*/ +void kterm_resetcolor(); +void kterm_setcolor(uint8_t); + +/* Kernel terminal - Printing function */ +void kterm_putat(char, uint8_t, size_t, size_t); +void kterm_put(char); +void kterm_write(const char*, size_t); +void kterm_writestring(const char*); +void kterm_scrollup(); + + +/* Kernel terminal - Cursor functions */ +void enable_cursor (uint8_t start_cursor , uint8_t end_cursor ); +void disable_cursor(); +void update_cursor(int x, int y); +uint16_t get_cursor_position(); +int get_cursor_x (uint16_t cursor_pos); +int get_cursor_y (uint16_t cursor_pos); + + +void printf ( const char *format, ...); + diff --git a/kernel/time.cpp b/kernel/time.cpp new file mode 100644 index 0000000..325aece --- /dev/null +++ b/kernel/time.cpp @@ -0,0 +1,111 @@ +#include "time.h" + +// Set by ACPI table parsing code if possible +int century_register = 0x00; +unsigned char second; +unsigned char minute; +unsigned char hour; +unsigned char day; +unsigned char month; +unsigned int year; + + +int get_update_in_progress_flag() { + outb(cmos_address, 0x0A); + return (inb(cmos_data) & 0x80); +} + +unsigned char get_RTC_register(int reg) { + outb(cmos_address, reg); + return inb(cmos_data); +} + +void read_rtc() { + unsigned char century; + unsigned char last_second; + unsigned char last_minute; + unsigned char last_hour; + unsigned char last_day; + unsigned char last_month; + unsigned char last_year; + unsigned char last_century; + unsigned char registerB; + + // Note: This uses the "read registers until you get the same values twice in a row" technique + // to avoid getting dodgy/inconsistent values due to RTC updates + + while (get_update_in_progress_flag()); // Make sure an update isn't in progress + second = get_RTC_register(0x00); + minute = get_RTC_register(0x02); + hour = get_RTC_register(0x04); + day = get_RTC_register(0x07); + month = get_RTC_register(0x08); + year = get_RTC_register(0x09); + if(century_register != 0) { + century = get_RTC_register(century_register); + } else { + century = 21; + } + + do { + last_second = second; + last_minute = minute; + last_hour = hour; + last_day = day; + last_month = month; + last_year = year; + last_century = century; + + while (get_update_in_progress_flag()); // Make sure an update isn't in progress + second = get_RTC_register(0x00); + minute = get_RTC_register(0x02); + hour = get_RTC_register(0x04); + day = get_RTC_register(0x07); + month = get_RTC_register(0x08); + year = get_RTC_register(0x09); + if(century_register != 0) { + century = get_RTC_register(century_register); + } + } while( (last_second != second) || (last_minute != minute) || (last_hour != hour) || + (last_day != day) || (last_month != month) || (last_year != year) || + (last_century != century) ); + + registerB = get_RTC_register(0x0B); + + // Convert BCD to binary values if necessary + + if (!(registerB & 0x04)) { + second = (second & 0x0F) + ((second / 16) * 10); + minute = (minute & 0x0F) + ((minute / 16) * 10); + hour = ( (hour & 0x0F) + (((hour & 0x70) / 16) * 10) ) | (hour & 0x80); + day = (day & 0x0F) + ((day / 16) * 10); + month = (month & 0x0F) + ((month / 16) * 10); + year = (year & 0x0F) + ((year / 16) * 10); + if(century_register != 0) { + century = (century & 0x0F) + ((century / 16) * 10); + } + } + + // Convert 12 hour clock to 24 hour clock if necessary + + if (!(registerB & 0x02) && (hour & 0x80)) { + hour = ((hour & 0x7F) + 12) % 24; + } + + // Calculate the full (4-digit) year + + if(century_register != 0) { + year += century * 100; + } else { + year += (CURRENT_YEAR / 100) * 100; + if(year < CURRENT_YEAR) year += 100; + } +} + + +void delay(int t){ + volatile int i,j; + for(i=0;i> 8) & 0xFF); + + outb(0x40, low); + outb(0x40, high); + + +} \ No newline at end of file diff --git a/kernel/timer.h b/kernel/timer.h new file mode 100644 index 0000000..9b877e1 --- /dev/null +++ b/kernel/timer.h @@ -0,0 +1,6 @@ +#pragma once + +#include +#include + +void init_timer (uint32_t frequency); \ No newline at end of file diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..20cebe8 --- /dev/null +++ b/run.sh @@ -0,0 +1,27 @@ +#!/bin/bash +PROC=$$ + +# Build the Corelib static library +(cd CoreLib +if ! make 2> warnings.log 1> /dev/null ; then + echo "Build Corelib failed!" + kill -10 $PROC +fi) + +# Build the kernel image +(cd kernel +# make clean +if ! make 2> warnings.log 1> /dev/null ; then + echo "Build kernel failed!" + kill -10 $PROC +fi) + +./scripts/update_harddrive.sh +./scripts/create_symbol_lookup.sh + +args=""; +if [[ $1 == "-d" ]] +then + args="debug" +fi +./scripts/run_qemu.sh $args diff --git a/screenshots/.blank b/screenshots/.blank deleted file mode 100644 index e69de29..0000000 diff --git a/screenshots/CD-ROM_Identify.png b/screenshots/CD-ROM_Identify.png new file mode 100644 index 0000000..586d2ee --- /dev/null +++ b/screenshots/CD-ROM_Identify.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a49af346df5f591fd139ebda79fbb80e9d79b1db2697bc8e037ccc6955e69959 +size 58517 diff --git a/screenshots/PCIBusEnumeration.png b/screenshots/PCIBusEnumeration.png new file mode 100644 index 0000000..cafbf48 --- /dev/null +++ b/screenshots/PCIBusEnumeration.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3873ae8e4e291661ae99310cf26ed6b51462a3434142423b55652e63efd96c79 +size 17146 diff --git a/screenshots/PageFault.png b/screenshots/PageFault.png new file mode 100644 index 0000000..adc5332 --- /dev/null +++ b/screenshots/PageFault.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:edf3a8ff640f0a3fbf58756d10526ee3bc03068d0cea4d81d64a897d52e29c85 +size 10406 diff --git a/screenshots/ReadingFilesFromFAT16.png b/screenshots/ReadingFilesFromFAT16.png new file mode 100644 index 0000000..f203823 --- /dev/null +++ b/screenshots/ReadingFilesFromFAT16.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ab26fe8f7b0d9fca81e8481a67796e93bbc2fb7369accac03a9aaecf415cd4de +size 27813 diff --git a/screenshots/Screenshot from 2021-06-21 14-26-39.png b/screenshots/Screenshot from 2021-06-21 14-26-39.png new file mode 100644 index 0000000..30c104f --- /dev/null +++ b/screenshots/Screenshot from 2021-06-21 14-26-39.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:73b9d3ed540e1bc0b6d55114a00f9aa688006b38a542c1bf048d90b791a748ce +size 141605 diff --git a/screenshots/WIP_interruptHandling.png b/screenshots/WIP_interruptHandling.png new file mode 100644 index 0000000..6c22b50 --- /dev/null +++ b/screenshots/WIP_interruptHandling.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bfbde3cc43610681eca3f38e56d8af1d0e5d0ad2f465cb743a5b8ea5c3adbe47 +size 16282 diff --git a/screenshots/multiboot.png b/screenshots/multiboot.png new file mode 100644 index 0000000..25cf7ff --- /dev/null +++ b/screenshots/multiboot.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:13bb64394a1c4df50f254a7adfeda213a085b5338c44d6f61bbe2221c32e1929 +size 21530 diff --git a/screenshots/must frustrating bug ever.png b/screenshots/must frustrating bug ever.png new file mode 100644 index 0000000..5b908d8 --- /dev/null +++ b/screenshots/must frustrating bug ever.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a55e6e0d5beb8d3d390c6877c9eabc7f8e7aa539d124e24f433ae4eda4cf4c21 +size 10397 diff --git a/scripts/build.py b/scripts/build.py new file mode 100755 index 0000000..8183b1a --- /dev/null +++ b/scripts/build.py @@ -0,0 +1,24 @@ +#!/usr/bin/python3 +import os +import subprocess + +print("Give BarinkOS A Test Run") + +# list and run build scripts +print("Running build-scripts") +os.chdir("scripts") +scripts=os.listdir() +currentScript=os.path.basename(__file__) + +os.chdir("../CoreLib") +print("Building CoreLib") +subprocess.call("make") + +os.chdir("../kernel") +print("Building kernel") +subprocess.call("make") + +os.chdir("..") +subprocess.call("scripts/update_harddrive.sh", cwd=os.getcwd()) +subprocess.call("scripts/create_symbol_lookup.sh", cwd=os.getcwd()) +subprocess.call("scripts/run_qemu.sh", cwd=os.getcwd()) \ No newline at end of file diff --git a/scripts/create_harddrive.sh b/scripts/create_harddrive.sh new file mode 100755 index 0000000..4e0926d --- /dev/null +++ b/scripts/create_harddrive.sh @@ -0,0 +1,61 @@ +#!/bin/bash +# +# How to build a boot image +# NOTE: This script cant run properly yet +# Things described here should be done manually for now +# +# COPYRIGHT © Nigel Barink 2023 +# + +echo "Building a FAT16 filesystem" + +dd if=/dev/zero of=disk.img bs=512 count=131072 +fdisk disk.img +# Use the following options in fdisk (Format Disk Tool) +# We want to create a MBR (NOT GPT) Partition table containing 1 logical disk +# with a primary FAT16 partition marked bootable + +#OPTIONs + +# Create new DOS disklabel +# o +# Create new partition +# n +# Choose Primary as partition type +# p +# hit enter to choose default for the other options + +# Mark partition 1 as bootable +# a + +# Change partition type to FAT16 +# t +# Choose Partition 1 +# 1 +# Choose HEX 6 for FAT16 +# 6 + +# Sync and write changes to disk +# w + +# Create a "block" device from the disk.img +losetup /dev/loop9 disk.img + +# Format the partition on the disk as FAT16 +mkdosfs -F16 /dev/loop9 + +# Mount the disk to a folder on our dev machine +mount /dev/loop9 /mnt + +# Install the grub bootloader onto the disk +grub-install --no-floppy --modules="normal multiboot" /dev/loop9 --target=i386-pc --boot-directory=/mnt/boot --force + +# copy the necessary OS files +cp root/boot/myos.bin /mnt/boot/myos.bin +cp root/boot/grub/grub.cfg /mnt/boot/grub/grub.cfg + +# Unmount the device +umount /mnt + +# Destroy the loop device +losetup -d /dev/loop9 diff --git a/scripts/create_iso.sh b/scripts/create_iso.sh new file mode 100755 index 0000000..356fdf3 --- /dev/null +++ b/scripts/create_iso.sh @@ -0,0 +1,5 @@ +#!/bin/bash +mkdir -p root/boot/grub +cp build/kernel/myos.bin root/boot/myos.bin +cp kernel/grub.cfg root/boot/grub/grub.cfg +grub-mkrescue -o barinkOS.iso root \ No newline at end of file diff --git a/scripts/create_symbol_lookup.sh b/scripts/create_symbol_lookup.sh new file mode 100755 index 0000000..5d6dd6c --- /dev/null +++ b/scripts/create_symbol_lookup.sh @@ -0,0 +1,4 @@ +#!/bin/bash +echo "creating symbols file" +echo $(pwd) +objcopy --only-keep-debug root/boot/myos.bin kernel.sym \ No newline at end of file diff --git a/scripts/dev-setup/install.sh b/scripts/dev-setup/install.sh new file mode 100644 index 0000000..9da7639 --- /dev/null +++ b/scripts/dev-setup/install.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +cmake -DLLVM_ENABLE_PROJECTS="clang-tools-extra" -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles" ../llvm \ No newline at end of file diff --git a/scripts/hooks/pre-commit.hook.sh b/scripts/hooks/pre-commit.hook.sh new file mode 100644 index 0000000..5bad261 --- /dev/null +++ b/scripts/hooks/pre-commit.hook.sh @@ -0,0 +1,2 @@ +#!/bin/bash +# Run clang-tidy diff --git a/scripts/run_qemu.sh b/scripts/run_qemu.sh new file mode 100755 index 0000000..bf9cac3 --- /dev/null +++ b/scripts/run_qemu.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +if [[ $1 == "debug" ]] +then + qemu-system-i386 -s -boot d -drive format=raw,file=disk.img -serial stdio -vga std -display gtk -m 2G -cpu core2duo -d int -no-shutdown -no-reboot +else + qemu-system-i386 -s -boot d -drive format=raw,file=disk.img -serial stdio -vga std -display gtk -m 2G -cpu core2duo +fi +# Run from harddisk +#qemu-system-i386 -boot d -drive format=raw,file=disk.img -serial stdio -vga std -display gtk -m 2G -cpu core2duo -d int -no-shutdown -no-reboot + +# Run disk version +# qemu-system-i386 -cdrom barinkOS.iso -serial stdio -vga std -display gtk -m 2G -cpu core2duo -s -d int -no-shutdown -no-reboot + +# Run the raw kernel image +# qemu-system-i386 -kernel build/kernel/myos.bin -serial stdio -vga std -display gtk -m 2G -cpu core2duo -d int -no-shutdown -no-reboot + + diff --git a/scripts/run_virtualbox.sh b/scripts/run_virtualbox.sh new file mode 100755 index 0000000..db37ed2 --- /dev/null +++ b/scripts/run_virtualbox.sh @@ -0,0 +1,2 @@ +#!/bin/bash +virtualboxvm --startvm "BarinkOS_test" \ No newline at end of file diff --git a/scripts/update_harddrive.sh b/scripts/update_harddrive.sh new file mode 100755 index 0000000..cc342c2 --- /dev/null +++ b/scripts/update_harddrive.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +echo "running in cwd : " + echo $(pwd) +echo "Mount harddrive image as block device" +sudo losetup /dev/loop9 disk.img +sudo mount /dev/loop9 /mnt + +echo "Copy over kernel binary" +sudo cp build/kernel/myos.bin /mnt/boot/myos.bin + +echo "unmount image" +sudo umount /mnt +sudo losetup -d /dev/loop9 \ No newline at end of file diff --git a/src/kernel/MMU.cpp b/src/kernel/MMU.cpp deleted file mode 100644 index 96867f4..0000000 --- a/src/kernel/MMU.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "MMU.h" - - - -void MMU::enable(){ - - //set each entry to not present - int i; - for(i = 0; i < 1024; i++) - { - // This sets the following flags to the pages: - // Supervisor: Only kernel-mode can access them - // Write Enabled: It can be both read from and written to - // Not Present: The page table is not present - this->page_directory[i] = 0x00000002; - } - - // holds the physical address where we want to start mapping these pages to. - // in this case, we want to map these pages to the very beginning of memory. - - //we will fill all 1024 entries in the table, mapping 4 megabytes - for(unsigned int i = 0; i < 1024; i++) - { - // As the address is page aligned, it will always leave 12 bits zeroed. - // Those bits are used by the attributes ;) - first_page_table[i] = (i * 0x1000) | 3; // attributes: supervisor level, read/write, present. - } - - // attributes: supervisor level, read/write, present - this->page_directory[0] = ((unsigned int)first_page_table) | 3; - - - loadPageDirectory(this->page_directory); - enablePaging(); -} \ No newline at end of file diff --git a/src/kernel/MMU.h b/src/kernel/MMU.h deleted file mode 100644 index cb3b7f8..0000000 --- a/src/kernel/MMU.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include - -extern "C" void loadPageDirectory (long unsigned int* addr ); -extern "C" void enablePaging(); - -class MMU { - public: - void enable (); - - private: - uint32_t page_directory[1024] __attribute__((aligned(4096))); - uint32_t first_page_table[1024] __attribute__((aligned(4096))); -}; \ No newline at end of file diff --git a/src/kernel/arch/i386/boot.s b/src/kernel/arch/i386/boot.s deleted file mode 100644 index 99fa270..0000000 --- a/src/kernel/arch/i386/boot.s +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Multiboot - */ -.set ALIGN, 1<<0 /* align loaded modules on page boundaries */ -.set MEMINFO, 1<<1 /* provide memory map */ -.set FLAGS, ALIGN | MEMINFO /* this is the Multiboot 'flag' field */ -.set MAGIC, 0x1BADB002 /* 'magic number' lets bootloader find the header */ -.set CHECKSUM, -(MAGIC + FLAGS) /* checksum of above, to prove we are multiboot */ - -.section .multiboot -.align 4 -.long MAGIC -.long FLAGS -.long CHECKSUM - - -.section .bss -.align 16 -stack_bottom: -.skip 16384 # 16 KiB -stack_top: - - - - -.text -.globl enablePaging -enablePaging: - push %ebp - mov %esp, %ebp - mov %cr0, %eax - or $0x80000000, %eax - mov %eax, %cr0 - mov %ebp, %esp - pop %ebp - ret - -.text -.globl loadPageDirectory -loadPageDirectory: - push %ebp - mov %esp, %ebp - mov 8(%esp), %eax - mov %eax, %cr3 - mov %ebp, %esp - pop %ebp - ret - - -.section .text -.global _start -.type _start, @function -_start: - - - - mov $stack_top, %esp - - - - call _init - call kernel_main - - - cli -1: hlt - jmp 1b - - -.size _start, . - _start \ No newline at end of file diff --git a/src/kernel/arch/i386/linker.ld b/src/kernel/arch/i386/linker.ld deleted file mode 100644 index 7292df5..0000000 --- a/src/kernel/arch/i386/linker.ld +++ /dev/null @@ -1,43 +0,0 @@ -/* The bootloader will look at this image and start execution at the symbol - designated as the entry point. */ -ENTRY(_start) - -/* Tell where the various sections of the object files will be put in the final - kernel image. */ -SECTIONS -{ - /* Begin putting sections at 1 MiB, a conventional place for kernels to be - loaded at by the bootloader. */ - . = 1M; - - /* First put the multiboot header, as it is required to be put very early - early in the image or the bootloader won't recognize the file format. - Next we'll put the .text section. */ - .text BLOCK(4K) : ALIGN(4K) - { - *(.multiboot) - *(.text) - } - - /* Read-only data. */ - .rodata BLOCK(4K) : ALIGN(4K) - { - *(.rodata) - } - - /* Read-write data (initialized) */ - .data BLOCK(4K) : ALIGN(4K) - { - *(.data) - } - - /* Read-write data (uninitialized) and stack */ - .bss BLOCK(4K) : ALIGN(4K) - { - *(COMMON) - *(.bss) - } - - /* The compiler may produce other sections, by default it will put them in - a segment with the same name. Simply add stuff here as needed. */ -} \ No newline at end of file diff --git a/src/kernel/arch/i386/tty/kterm.c b/src/kernel/arch/i386/tty/kterm.c deleted file mode 100644 index 2021e22..0000000 --- a/src/kernel/arch/i386/tty/kterm.c +++ /dev/null @@ -1,92 +0,0 @@ -#include "kterm.h" -static const size_t VGA_WIDTH = 80; -static const size_t VGA_HEIGHT = 25; - -size_t kterm_row; -size_t kterm_column; -uint8_t kterm_color; -uint16_t* kterm_buffer; - - -static inline uint8_t vga_entry_color( enum vga_color fg, enum vga_color bg) { - return fg | bg << 4; -} - -static inline uint16_t vga_entry (unsigned char uc, uint8_t color) { - return (uint16_t) uc | (uint16_t) color << 8; -} - -void kterm_init () { - kterm_row = 0; - kterm_column = 0; - kterm_color = vga_entry_color ( VGA_COLOR_LIGHT_GREY , VGA_COLOR_BLACK); - kterm_buffer = (uint16_t*) 0xB8000; - for (size_t y = 0; y < VGA_HEIGHT; y++ ){ - for( size_t x = 0; x < VGA_WIDTH; x++){ - const size_t index = y * VGA_WIDTH + x; - kterm_buffer[index] = vga_entry(' ', kterm_color); - - } - } -} - - -void kterm_resetcolor(){ - kterm_color = vga_entry_color ( VGA_COLOR_LIGHT_GREY , VGA_COLOR_BLACK); -} - -void kterm_setcolor(uint8_t color){ - kterm_color = color; -} - -void kterm_putat (char c, uint8_t color, size_t x, size_t y ) { - const size_t index = y * VGA_WIDTH + x; - - kterm_buffer[index] = vga_entry(c, color); - -} - - -/** - * With the help from: - * https://whiteheadsoftware.dev/operating-systems-development-for-dummies/ - **/ -void kterm_scrollup(){ - size_t i ; - for(i=0; i < (VGA_WIDTH * VGA_HEIGHT - VGA_WIDTH); i++) - kterm_buffer[i] = kterm_buffer[i+VGA_WIDTH]; - - for( i=0; i< VGA_WIDTH; i++) - kterm_buffer[(VGA_HEIGHT -1) * VGA_WIDTH + i ] = vga_entry(' ', kterm_color); - -} - -void kterm_put (char c) { - - if(++kterm_column == VGA_WIDTH || c == '\n' ) { - kterm_column = 0; - if(kterm_row == VGA_HEIGHT-1) { - kterm_scrollup(); - } else { - kterm_row ++; - } - - } - - if(c == '\n') return; - kterm_putat ( c, kterm_color, kterm_column, kterm_row); - - -} - -void kterm_write(const char* data, size_t size) { - for(size_t i = 0; i < size; i++){ - kterm_put(data[i]); - } -} - -void kterm_writestring(const char* data ){ - AS_KERNEL(); - kterm_write(data, strlen(data)); -} - diff --git a/src/kernel/arch/i386/tty/kterm.h b/src/kernel/arch/i386/tty/kterm.h deleted file mode 100644 index 6cf784e..0000000 --- a/src/kernel/arch/i386/tty/kterm.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once -#include -#include -#include -#include - -#include "../vga/colors.h" - -void kterm_init(); - -void kterm_resetcolor(); -void kterm_setcolor(uint8_t); - -void kterm_putat(char, uint8_t, size_t, size_t); -void kterm_put(char); -void kterm_write(const char*, size_t); -void kterm_writestring(const char*); -void kterm_scrollup(); - -#define KernelTag "[Kernel]: " -#define AS_KERNEL() ( kterm_setcolor(VGA_COLOR_LIGHT_BLUE),\ - kterm_write(KernelTag, 10 ), \ - kterm_resetcolor()) \ No newline at end of file diff --git a/src/kernel/kernel.cpp b/src/kernel/kernel.cpp deleted file mode 100644 index 14f0321..0000000 --- a/src/kernel/kernel.cpp +++ /dev/null @@ -1,136 +0,0 @@ -#include "kernel.h" -/** - * simple delay function - **/ -void delay(int t){ - volatile int i,j; - for(i=0;i -size_t strlen(const char* str){ - size_t len = 0; - while(str[len]){ - len++; - } - return len; -} \ No newline at end of file diff --git a/todo.md b/todo.md new file mode 100644 index 0000000..b5556ea --- /dev/null +++ b/todo.md @@ -0,0 +1,21 @@ +# TODO list + +![Todo image](https://camo.githubusercontent.com/c43d969d9d071c8342e9a69cdd6acb433c541f431127738974ce22290c46f2b8/68747470733a2f2f692e696d6775722e636f6d2f4f764d5a4273392e6a7067) + + +This list keeps me focused and organised so I don't forget what +needs to be done. It is a expansion on the features markdown FILE which describes the features. Here I put things I need to remember +to do on a more in depth level. + +## -- +[x] Setup paging \ +[ ] HELP command +[x] Setup a proper HEAP \ +[ ] Setup a proper Stack \ +[x] Setup KMalloc and KFree \ +[x] Merge Functioning Feature branches into sandboxKernelDev \ +[ ] Remove merged feature branches \ +[ ] Merge sandboxKernelDev with dev \ +[x] Remove sandboxKernelDev branch \ +[ ] Implement proper virtual filesystem +