Compare commits
86 Commits
767dac7e73
...
DebugLoggi
Author | SHA1 | Date | |
---|---|---|---|
6086b04054 | |||
9c5667c454 | |||
2522492835 | |||
e82392e9d9 | |||
64c87a2a58 | |||
04470edcc6 | |||
2970806705 | |||
e8df6ec628 | |||
5781f730d9 | |||
2d0bb16fad | |||
e6901f0526 | |||
61f1852420 | |||
32b0d990df | |||
745656eb2d | |||
644ff5b1f5 | |||
a77621faf5 | |||
50bf952a49 | |||
ef2bba5c1c | |||
81f7351fe6 | |||
dea8ab7d71 | |||
2bcc79216e | |||
b07b4f0d38 | |||
94a2de3847 | |||
dbb147e110 | |||
37542b736f | |||
490529099b | |||
133c16cae7 | |||
ecab248cd6 | |||
4ce7cc093b | |||
c9a036bfbb | |||
1f90a5d862 | |||
520104a43a | |||
7993a2d172 | |||
27e99fe4f2 | |||
749f2aa492 | |||
891085e151 | |||
364d10d02e | |||
68371475d9 | |||
16e2354019 | |||
a47879f404 | |||
656ca0baa8 | |||
01fcb0aa15 | |||
13e9beea79 | |||
9893a0bd17 | |||
a70ae5ca31 | |||
15443601a6 | |||
c90e90bd84 | |||
a5e7fdd07e | |||
59ba41f3d2 | |||
5051b8903c | |||
0f0fc9f252 | |||
e70f56a005 | |||
560dd64e64 | |||
9436e6e033 | |||
d280aa0584 | |||
7d6c823d79 | |||
bbfea39c23 | |||
3b3e2597a1 | |||
0b0e37b762 | |||
388ac8e7f9 | |||
9172da075a | |||
23c68d9863 | |||
2e2693d1ea | |||
a93bf566c8 | |||
2e59e6593e | |||
b4cff3e667 | |||
7330b81a10 | |||
97606dbf71 | |||
7496299761 | |||
0d8ef065e0 | |||
19b9cfe908 | |||
b8d75dddae | |||
fb2a19e11d | |||
72008b0a7a | |||
2621399349 | |||
88cc1d75bb | |||
5f39f7e7ed | |||
d455735ea2 | |||
9dc7a05da1 | |||
59bcc17668 | |||
5f50f8c013 | |||
595a7d5163 | |||
e84d196b00 | |||
f71a3a8ed6 | |||
63ea825e2e | |||
a094f510d3 |
7
.gdbinit
Normal file
7
.gdbinit
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
target remote localhost:1234
|
||||||
|
|
||||||
|
file root/boot/myos.bin
|
||||||
|
symbol-file kernel.sym
|
||||||
|
|
||||||
|
break prekernel/prekernel.cpp:18
|
||||||
|
continue
|
13
.gitignore
vendored
13
.gitignore
vendored
@ -1,8 +1,15 @@
|
|||||||
build
|
build/
|
||||||
CON
|
bin/
|
||||||
.vscode
|
.vscode/
|
||||||
|
.idea/
|
||||||
isodir/
|
isodir/
|
||||||
root/
|
root/
|
||||||
*.iso
|
*.iso
|
||||||
*.img
|
*.img
|
||||||
|
*.sym
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
|
||||||
|
|
||||||
|
/CoreLib/warnings.log
|
||||||
|
/kernel/warnings.log
|
||||||
|
12
CoreLib/List.h
Normal file
12
CoreLib/List.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
//
|
||||||
|
// Created by nigel on 25/02/23.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
class List {
|
||||||
|
public:
|
||||||
|
List* next;
|
||||||
|
void* data;
|
||||||
|
};
|
||||||
|
|
35
CoreLib/Makefile
Normal file
35
CoreLib/Makefile
Normal file
@ -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)
|
||||||
|
|
107
CoreLib/Memory.cpp
Normal file
107
CoreLib/Memory.cpp
Normal file
@ -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<char*>(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;
|
||||||
|
}
|
16
CoreLib/Memory.h
Normal file
16
CoreLib/Memory.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
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);
|
24
CoreLib/Path.cpp
Normal file
24
CoreLib/Path.cpp
Normal file
@ -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<unsigned int>(i +1), path_length};
|
||||||
|
}
|
||||||
|
|
||||||
|
char* Path::str() {
|
||||||
|
return path.str();
|
||||||
|
}
|
22
CoreLib/Path.h
Normal file
22
CoreLib/Path.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
//
|
||||||
|
// Created by nigel on 19/02/23.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "StringView.h"
|
||||||
|
|
||||||
|
|
||||||
|
class Path{
|
||||||
|
public:
|
||||||
|
explicit Path(String path);
|
||||||
|
|
||||||
|
StringView getbasename();
|
||||||
|
|
||||||
|
char* str();
|
||||||
|
|
||||||
|
private:
|
||||||
|
String path;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
3
CoreLib/Stack.cpp
Normal file
3
CoreLib/Stack.cpp
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
//
|
||||||
|
// Created by nigel on 19/02/23.
|
||||||
|
//
|
73
CoreLib/Stack.h
Normal file
73
CoreLib/Stack.h
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../kernel/memory/KernelHeap.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
39
CoreLib/String.cpp
Normal file
39
CoreLib/String.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#include "String.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
|
18
CoreLib/String.h
Normal file
18
CoreLib/String.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
|
};
|
14
CoreLib/StringView.cpp
Normal file
14
CoreLib/StringView.cpp
Normal file
@ -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
|
||||||
|
}
|
14
CoreLib/StringView.h
Normal file
14
CoreLib/StringView.h
Normal file
@ -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;
|
||||||
|
};
|
141
CoreLib/ctype.cpp
Normal file
141
CoreLib/ctype.cpp
Normal file
@ -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;
|
||||||
|
|
||||||
|
}
|
21
CoreLib/ctype.h
Normal file
21
CoreLib/ctype.h
Normal file
@ -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);
|
||||||
|
|
114
Makefile
114
Makefile
@ -1,114 +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)/PhysicalMemoryManager.o \
|
|
||||||
$(BUILD_DIR)/io.o \
|
|
||||||
$(BUILD_DIR)/PageDirectory.o \
|
|
||||||
$(BUILD_DIR)/gdtc.o \
|
|
||||||
$(BUILD_DIR)/idt.o \
|
|
||||||
$(BUILD_DIR)/pci.o \
|
|
||||||
$(BUILD_DIR)/pic.o \
|
|
||||||
$(BUILD_DIR)/string.o \
|
|
||||||
$(BUILD_DIR)/pcidevice.o \
|
|
||||||
$(BUILD_DIR)/atapiDevice.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 iso
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
clean_iso:
|
|
||||||
if [[ -a isodir/boot ]] ; then rm root/boot -rd ; fi
|
|
||||||
if [ -f build/barinkOS.iso ] ; then rm build/barinkOS.iso ; fi
|
|
||||||
|
|
||||||
iso: clean_iso clean build
|
|
||||||
mkdir -p root/boot/grub
|
|
||||||
cp build/myos.bin root/boot/myos.bin
|
|
||||||
cp src/grub.cfg root/boot/grub/grub.cfg
|
|
||||||
grub-mkrescue -o build/barinkOS.iso root
|
|
||||||
|
|
||||||
test:
|
|
||||||
$(EMULATOR) -kernel $(BUILD_DIR)/myos.bin -serial stdio -vga std -display gtk -m 2G -cpu core2duo
|
|
||||||
|
|
||||||
test_iso:
|
|
||||||
$(EMULATOR) -cdrom $(BUILD_DIR)/barinkOS.iso -serial stdio -vga std -display gtk -m 2G -cpu core2duo
|
|
||||||
|
|
||||||
build_kernel: $(OBJ_LINK_LIST)
|
|
||||||
$(CC) -T $(SRC_DIR)/kernel//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:
|
|
||||||
$(CPP) -c $(SRC_DIR)/kernel/tty/kterm.cpp -o $(BUILD_DIR)/kterm.o $(CFLAGS) -fno-exceptions -fno-rtti
|
|
||||||
|
|
||||||
$(BUILD_DIR)/boot.o:
|
|
||||||
$(AS) $(SRC_DIR)/kernel//boot.S -o $(BUILD_DIR)/boot.o
|
|
||||||
|
|
||||||
$(BUILD_DIR)/crti.o:
|
|
||||||
$(AS) $(SRC_DIR)/kernel/crti.s -o $(BUILD_DIR)/crti.o
|
|
||||||
|
|
||||||
$(BUILD_DIR)/crtn.o:
|
|
||||||
$(AS) $(SRC_DIR)/kernel/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)/PageDirectory.o:
|
|
||||||
$(CPP) -c $(SRC_DIR)/kernel/memory/PageDirectory.cpp -o $(BUILD_DIR)/PageDirectory.o $(CFLAGS) -fno-exceptions -fno-rtti
|
|
||||||
|
|
||||||
$(BUILD_DIR)/idt.o:
|
|
||||||
$(CPP) -c $(SRC_DIR)/kernel/idt/idt.cpp -o $(BUILD_DIR)/idt.o $(CFLAGS) -fno-exceptions -fno-rtti
|
|
||||||
|
|
||||||
$(BUILD_DIR)/gdtc.o:
|
|
||||||
$(CPP) -c $(SRC_DIR)/kernel/gdt/gdtc.cpp -o $(BUILD_DIR)/gdtc.o $(CFLAGS) -fno-exceptions -fno-rtti
|
|
||||||
|
|
||||||
|
|
||||||
$(BUILD_DIR)/pic.o:
|
|
||||||
$(CPP) -c $(SRC_DIR)/kernel/pic/pic.cpp -o $(BUILD_DIR)/pic.o $(CFLAGS) -fno-exceptions -fno-rtti
|
|
||||||
|
|
||||||
$(BUILD_DIR)/string.o:
|
|
||||||
$(CC) -c $(SRC_DIR)/libc/include/string.c -o $(BUILD_DIR)/string.o $(CFLAGS) -std=gnu99
|
|
||||||
|
|
||||||
$(BUILD_DIR)/PhysicalMemoryManager.o:
|
|
||||||
$(CPP) -c $(SRC_DIR)/kernel/memory/PhysicalMemoryManager.cpp -o $(BUILD_DIR)/PhysicalMemoryManager.o $(CFLAGS) -fno-exceptions -fno-rtti
|
|
||||||
|
|
||||||
$(BUILD_DIR)/pci.o:
|
|
||||||
$(CPP) -c $(SRC_DIR)/kernel/pci.cpp -o $(BUILD_DIR)/pci.o $(CFLAGS) -fno-exceptions -fno-rtti
|
|
||||||
|
|
||||||
$(BUILD_DIR)/pcidevice.o:
|
|
||||||
$(CPP) -c $(SRC_DIR)/kernel/pci/pciDevice.cpp -o $(BUILD_DIR)/pcidevice.o $(CFLAGS) -fno-exceptions -fno-rtti
|
|
||||||
|
|
||||||
$(BUILD_DIR)/atapiDevice.o:
|
|
||||||
$(CPP) -c $(SRC_DIR)/kernel/drivers/atapi/atapiDevice.cpp -o $(BUILD_DIR)/atapiDevice.o $(CFLAGS) -fno-exceptions -fno-rtti
|
|
@ -17,16 +17,23 @@ W.I.P - Working on interrupt handling
|
|||||||
 \
|
 \
|
||||||
Multiboot information can be read by the kernel.
|
Multiboot information can be read by the kernel.
|
||||||
|
|
||||||
|
 \
|
||||||
|
Enabled paging and am getting page faults!
|
||||||
|
|
||||||
 \
|
 \
|
||||||
Enumerating the PCI bus
|
Enumerating the PCI bus
|
||||||
|
|
||||||
 \
|
 \
|
||||||
Correctly identified our ATAPI device 🎉
|
Correctly identified our ATAPI device 🎉
|
||||||
|
|
||||||
|
 \
|
||||||
|
Reading a FILE from a FAT-16 Formatted drive
|
||||||
|
|
||||||
________________________
|
________________________
|
||||||
|
|
||||||
### The goal
|
### 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
|
### Operating System Technical specs/details
|
||||||
|
48
features.md
48
features.md
@ -1,29 +1,37 @@
|
|||||||
# TODO list
|
# TODO list
|
||||||
## Start planning
|
## Basics
|
||||||
<input type="checkbox" checked/> Setup Cross-Compiler \
|
|
||||||
<input type="checkbox" checked/> Multiboot to kernel \
|
<label>
|
||||||
<input type="checkbox" checked/> Printing string to the screen \
|
<input type="checkbox" checked/>
|
||||||
<input type="checkbox" checked/> Printing values/numbers to the screen (a.k.k itoa) \
|
</label> Setup Cross-Compiler
|
||||||
|
<input type="checkbox" checked> Multiboot to kernel \
|
||||||
|
<input type="checkbox" checked/> Printing string to the screen \
|
||||||
|
<input type="checkbox" checked/> Printing values/numbers to the screen \
|
||||||
|
<input type="checkbox" checked/> Basic Terminal \
|
||||||
<input type="checkbox" checked/> Extend Multiboot implementation \
|
<input type="checkbox" checked/> Extend Multiboot implementation \
|
||||||
<input type="checkbox" checked/> Output to serial port \
|
<input type="checkbox" checked/> Output to serial port \
|
||||||
<input type="checkbox" checked/> Move to protected mode \
|
<input type="checkbox" checked/> Move to protected mode \
|
||||||
<input type="checkbox" checked/> Enabel CMOS clock \
|
<input type="checkbox" checked/> Enable CMOS clock \
|
||||||
<input type="checkbox" /> Time measurement (PIC &| PIT) \
|
<input type="checkbox" checked/> Time measurement (PIC &| PIT) \
|
||||||
<input type="checkbox" /> Detect CPU speed \
|
<input type="checkbox" /> Detect CPU speed \
|
||||||
<input type="checkbox" checked/> Interrupt / exception system (API) \
|
<input type="checkbox" checked/> Interrupt / exception system (API) \
|
||||||
|
|
||||||
<input type="checkbox" checked/> Plan your memory map (virtual, and physical) : decide where you want the data to be. \
|
|
||||||
<input type="checkbox" /> The heap: allocating memory at runtime (malloc and free) is almost impossible to go without. \
|
|
||||||
<input type="checkbox" /> Enable SIMD Extensions (SSE)
|
|
||||||
|
|
||||||
## Other features I am thinking of:
|
|
||||||
<input type="checkbox" checked/> PCI support \
|
<input type="checkbox" checked/> PCI support \
|
||||||
<input type="checkbox" /> ATA PIO Mode support \
|
<input type="checkbox" checked/> ATA PIO Mode support \
|
||||||
|
<input type="checkbox" checked/> FAT Filesystem \
|
||||||
|
<input type="checkbox" /> Virtual filesystem \
|
||||||
|
<input type="checkbox" checked/> Keyboard support ( P/S2 Keyboard) \
|
||||||
|
<input type="checkbox" checked/> Physical memory management \
|
||||||
|
<input type="checkbox" checked/> Paging \
|
||||||
|
<input type="checkbox" checked/> Virtual memory management \
|
||||||
|
<input type="checkbox" checked/> The heap: allocating memory at runtime (malloc and free) is almost impossible to go without. \
|
||||||
|
<input type="checkbox" /> Enable SIMD Extensions (SSE)
|
||||||
|
<input type="checkbox" checked/> PCI support \
|
||||||
|
<input type="checkbox" checked/> ATA PIO Mode support \
|
||||||
<input type="checkbox" /> USTAR Filesystem ( For its simplicity this is very likely the first filesystem the OS is going to support) \
|
<input type="checkbox" /> USTAR Filesystem ( For its simplicity this is very likely the first filesystem the OS is going to support) \
|
||||||
<input type="checkbox" /> ACPI support ( Or some other basic way to support shutdown, reboot and possibly hibernation ) \
|
<input type="checkbox" /> ACPI support ( Or some other basic way to support shutdown, reboot and possibly hibernation ) \
|
||||||
<input type="checkbox" /> ATAPI support \
|
<input type="checkbox" /> ATAPI support \
|
||||||
<input type="checkbox" /> Keyboard support ( P/S2 Keyboard) \
|
|
||||||
<input type="checkbox" checked/> Memory Management (MMU)
|
<input type="checkbox" checked/> Memory Management (MMU)
|
||||||
|
<input type="checkbox" /> Hardware Management system
|
||||||
<input type="checkbox" /> Preemptive multi tasking \
|
<input type="checkbox" /> Preemptive multi tasking \
|
||||||
<input type="checkbox" /> Processes \
|
<input type="checkbox" /> Processes \
|
||||||
<input type="checkbox" /> Threads
|
<input type="checkbox" /> Threads
|
||||||
@ -32,9 +40,11 @@
|
|||||||
<input type="checkbox" /> POSIX compliance (partially) \
|
<input type="checkbox" /> POSIX compliance (partially) \
|
||||||
<input type="checkbox" /> RPC - for interprocess communication \
|
<input type="checkbox" /> RPC - for interprocess communication \
|
||||||
<input type="checkbox" /> Sync primitives - Semaphores, Mutexes, spinlocks et al. \
|
<input type="checkbox" /> Sync primitives - Semaphores, Mutexes, spinlocks et al. \
|
||||||
<input type="checkbox" /> Basic Terminal \
|
|
||||||
<input type="checkbox" /> Extend hardware recognition ( CPU codename, memory, ATA harddisk, RAW diskSpace, CPU speed through SMBIOS et al. ) \
|
<input type="checkbox" /> ACPI support \
|
||||||
|
<input type="checkbox" /> ATAPI support \
|
||||||
|
|
||||||
<input type="checkbox" /> Basic Window server/client \
|
<input type="checkbox" /> Basic Window server/client \
|
||||||
## Support for more filesystems if I like the challenge in writing these ...
|
|
||||||
<input type="checkbox" /> FAT Filesystem \
|
|
||||||
<input type="checkbox" /> EXT2 Filesystem
|
<input type="checkbox" /> EXT2 Filesystem
|
||||||
|
<input type="checkbox" /> USTAR Filesystem \
|
||||||
|
<input type="checkbox" /> FAT16 Filesystem \
|
||||||
|
BIN
images/BarinkOS.png
(Stored with Git LFS)
BIN
images/BarinkOS.png
(Stored with Git LFS)
Binary file not shown.
BIN
images/BarinkOS_logo(standard).svg
(Stored with Git LFS)
BIN
images/BarinkOS_logo(standard).svg
(Stored with Git LFS)
Binary file not shown.
BIN
images/BarinkOS_logo.svg
(Stored with Git LFS)
BIN
images/BarinkOS_logo.svg
(Stored with Git LFS)
Binary file not shown.
140
kernel/Makefile
Normal file
140
kernel/Makefile
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
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_DIR)/serial.o \
|
||||||
|
$(OBJ_DIR)/klog.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
|
||||||
|
|
||||||
|
$(OBJ_DIR)/serial.o:
|
||||||
|
$(CPP) -c drivers/serial/serial.cpp -o $(OBJ_DIR)/serial.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||||
|
|
||||||
|
$(OBJ_DIR)/klog.o:
|
||||||
|
$(CPP) -c klog.cpp -o $(OBJ_DIR)/klog.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
|
76
kernel/acpi/acpi.cpp
Normal file
76
kernel/acpi/acpi.cpp
Normal file
@ -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!");*/
|
||||||
|
}
|
14
kernel/acpi/acpi.h
Normal file
14
kernel/acpi/acpi.h
Normal file
@ -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:
|
||||||
|
};
|
44
kernel/acpi/rsdp.cpp
Normal file
44
kernel/acpi/rsdp.cpp
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
45
kernel/acpi/rsdp.h
Normal file
45
kernel/acpi/rsdp.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../terminal/kterm.h"
|
||||||
|
#include <CoreLib/Memory.h>
|
||||||
|
#include <stdint-gcc.h>
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
38
kernel/bitmap.h
Normal file
38
kernel/bitmap.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
}
|
130
kernel/boot/boot.s
Normal file
130
kernel/boot/boot.s
Normal file
@ -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
|
15
kernel/boot/multiboot.s
Normal file
15
kernel/boot/multiboot.s
Normal file
@ -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
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "bootloader/multiboot.h"
|
#include "prekernel/multiboot.h"
|
||||||
#define CHECK_FLAG(flags, bit) ((flags) & (1 <<(bit)))
|
#define CHECK_FLAG(flags, bit) ((flags) & (1 <<(bit)))
|
||||||
|
|
||||||
#include "tty/kterm.h"
|
#include "terminal/kterm.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -10,66 +10,81 @@ void CheckMBT ( multiboot_info_t* mbt ){
|
|||||||
/* Set MBI to the addresss of the multiboot information structure*/
|
/* Set MBI to the addresss of the multiboot information structure*/
|
||||||
multiboot_info_t * mbi = (multiboot_info_t *) mbt;
|
multiboot_info_t * mbi = (multiboot_info_t *) mbt;
|
||||||
|
|
||||||
|
#ifdef __VERBOSE__
|
||||||
/* Print out the flags */
|
/* Print out the flags */
|
||||||
printf("flags = 0x%x\n", (unsigned) mbi->flags);
|
printf("flags = 0x%x\n", (unsigned) mbi->flags);
|
||||||
|
#endif
|
||||||
/* Are mem_* valid? */
|
/* Are mem_* valid? */
|
||||||
if ( CHECK_FLAG(mbi->flags,0)){
|
if ( CHECK_FLAG(mbi->flags,0)){
|
||||||
printf("mem_lower = %uKB, mem_upper = %uKB\n");
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
/* is boot device valid ? */
|
/* is boot device valid ? */
|
||||||
if (CHECK_FLAG (mbi->flags, 1)){
|
if (CHECK_FLAG (mbi->flags, 1))
|
||||||
|
{
|
||||||
|
#ifdef __VERBOSE__
|
||||||
printf("boot_device = 0x0%x\n", (unsigned) mbi->boot_device);
|
printf("boot_device = 0x0%x\n", (unsigned) mbi->boot_device);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* is the command line passed? */
|
/* is the command line passed? */
|
||||||
if (CHECK_FLAG ( mbi->flags,2)){
|
if (CHECK_FLAG ( mbi->flags,2))
|
||||||
|
{
|
||||||
|
#ifdef __VERBOSE__
|
||||||
printf("cmdline = %s\n", (char *) mbi->cmdline);
|
printf("cmdline = %s\n", (char *) mbi->cmdline);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Are mods_* valid? */
|
/* Are mods_* valid? */
|
||||||
if(CHECK_FLAG ( mbi->flags, 3)){
|
if(CHECK_FLAG ( mbi->flags, 3)){
|
||||||
multiboot_module_t *mod;
|
multiboot_module_t *mod;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
#ifdef __VERBOSE__
|
||||||
printf("mods count = %d, mods_addr = 0x%x\n", (int) mbi->mods_count, (int) mbi->mods_addr);
|
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++){
|
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);
|
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! */
|
/* Bits 4 and 5 are mutually exclusive! */
|
||||||
if (CHECK_FLAG (mbi->flags, 4) && CHECK_FLAG(mbi->flags, 5)){
|
if (CHECK_FLAG (mbi->flags, 4) && CHECK_FLAG(mbi->flags, 5))
|
||||||
|
{
|
||||||
|
#ifdef __VERBOSE__
|
||||||
printf("Both bits 4 and 5 are set.\n");
|
printf("Both bits 4 and 5 are set.\n");
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is the symbol table of a.out valid? */
|
/* Is the symbol table of a.out valid? */
|
||||||
if (CHECK_FLAG(mbi->flags, 4)){
|
if (CHECK_FLAG(mbi->flags, 4)){
|
||||||
multiboot_aout_symbol_table_t *multiboot_aout_sym = &(mbi->u.aout_sym);
|
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",
|
printf( "multiboot_aout_symbol_table: tabsize = 0x%0x, strsize = 0x%x, addr = 0x%x\n",
|
||||||
(unsigned) multiboot_aout_sym->tabsize,
|
(unsigned) multiboot_aout_sym->tabsize,
|
||||||
(unsigned) multiboot_aout_sym->strsize,
|
(unsigned) multiboot_aout_sym->strsize,
|
||||||
(unsigned) multiboot_aout_sym->addr);
|
(unsigned) multiboot_aout_sym->addr);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is the section header table of ELF valid? */
|
/* Is the section header table of ELF valid? */
|
||||||
if (CHECK_FLAG(mbi->flags, 5)){
|
if (CHECK_FLAG(mbi->flags, 5)){
|
||||||
multiboot_elf_section_header_table_t *multiboot_elf_sec = &(mbi->u.elf_sec);
|
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",
|
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->num, (unsigned) multiboot_elf_sec->size,
|
||||||
(unsigned) multiboot_elf_sec->addr, (unsigned) multiboot_elf_sec->shndx);
|
(unsigned) multiboot_elf_sec->addr, (unsigned) multiboot_elf_sec->shndx);
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Draw diagonal blue line */
|
/* Draw diagonal blue line */
|
||||||
if (CHECK_FLAG (mbt->flags, 12)){
|
if (CHECK_FLAG (mbt->flags, 12)){
|
||||||
printf("Can draw!");
|
#ifdef __VERBOSE__
|
||||||
|
printf("Can draw!\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
9
kernel/bootinfo.h
Normal file
9
kernel/bootinfo.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "memory/memoryinfo.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct BootInfo{
|
||||||
|
const char* BootStructureID = "BarinkOS";
|
||||||
|
MemoryInfo* memory;
|
||||||
|
|
||||||
|
};
|
9
kernel/definitions.h
Normal file
9
kernel/definitions.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
/**
|
||||||
|
* Kernel definitions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define __DEBUG__ false
|
||||||
|
#define KERNEL_VERSION 0.03
|
||||||
|
|
||||||
|
#define ARCHITECTURE "I386"
|
11
kernel/devices/BlockDevice.h
Normal file
11
kernel/devices/BlockDevice.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
//
|
||||||
|
// Created by nigel on 21/02/23.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class BlockDevice {
|
||||||
|
virtual char* Read()=0;
|
||||||
|
virtual void Write() =0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
11
kernel/devices/CharacterDevice.h
Normal file
11
kernel/devices/CharacterDevice.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
//
|
||||||
|
// Created by nigel on 21/02/23.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class CharacterDevice {
|
||||||
|
virtual char Read()=0;
|
||||||
|
virtual void Write()=0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
38
kernel/drivers/cmos/cmos.cpp
Normal file
38
kernel/drivers/cmos/cmos.cpp
Normal file
@ -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
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "../io.h"
|
|
||||||
|
#include <stdint-gcc.h>
|
||||||
|
#include "../../io/io.h"
|
||||||
|
|
||||||
#define PIC1 0x20 /* IO base address for master PIC */
|
#define PIC1 0x20 /* IO base address for master PIC */
|
||||||
#define PIC2 0xA0 /* IO base address for slave PIC */
|
#define PIC2 0xA0 /* IO base address for slave PIC */
|
54
kernel/drivers/pit/pit.cpp
Normal file
54
kernel/drivers/pit/pit.cpp
Normal file
@ -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()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
18
kernel/drivers/pit/pit.h
Normal file
18
kernel/drivers/pit/pit.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint-gcc.h>
|
||||||
|
#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();
|
51
kernel/drivers/ps-2/keyboard.cpp
Normal file
51
kernel/drivers/ps-2/keyboard.cpp
Normal file
@ -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 ;
|
||||||
|
}
|
34
kernel/drivers/ps-2/keyboard.h
Normal file
34
kernel/drivers/ps-2/keyboard.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
#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();
|
52
kernel/drivers/serial/serial.cpp
Normal file
52
kernel/drivers/serial/serial.cpp
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#include "serial.h"
|
||||||
|
#include "../../io/io.h"
|
||||||
|
|
||||||
|
// Initializes communication according to the spec given
|
||||||
|
Serial::Serial(SerialConfig config) {
|
||||||
|
port = config.port;
|
||||||
|
// Disable interrupts
|
||||||
|
outb(config.port + 1, 0x00);
|
||||||
|
|
||||||
|
// Enable DLAB
|
||||||
|
outb(config.port + 3, 0x80);
|
||||||
|
|
||||||
|
// set the baudrate
|
||||||
|
outb(config.port + 0, 0x03);
|
||||||
|
outb(config.port + 1, 0x00);
|
||||||
|
|
||||||
|
// configure for 8bits, no parity, one stop bit
|
||||||
|
outb(config.port + 3, 0x03);
|
||||||
|
|
||||||
|
// Enable FIFO, clear them, with 14-byte threshhold
|
||||||
|
outb(config.port + 2, 0xC7);
|
||||||
|
// Enable IRQ's, RTS/DSR set
|
||||||
|
outb(config.port + 4, 0x0B );
|
||||||
|
// Set in loopback mode, test the serial chip.
|
||||||
|
outb(config.port + 4, 0x1E);
|
||||||
|
|
||||||
|
// TEST
|
||||||
|
outb(config.port + 0 , 0xAE);
|
||||||
|
|
||||||
|
if(inb(config.port + 0) != 0xAE)
|
||||||
|
return ; // FAIL
|
||||||
|
|
||||||
|
outb(config.port + 4, 0x0F);
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Serial::write(void* data, int len) {
|
||||||
|
while (is_transmit_empty() == 0); // Wait for transmit queue to be free
|
||||||
|
for (int i = 0; i < len ; i++){
|
||||||
|
outb(port, ((uint8_t*)data)[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char Serial::read() {
|
||||||
|
return inb(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Serial::is_transmit_empty() {
|
||||||
|
return inb(port + 5) & 0x20;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
29
kernel/drivers/serial/serial.h
Normal file
29
kernel/drivers/serial/serial.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
// For now these are the standard
|
||||||
|
// serial ports we can talk to
|
||||||
|
enum SERIALPORT {
|
||||||
|
COM1 = 0x3F8,
|
||||||
|
COM2 = 0x2F8,
|
||||||
|
COM3 = 0x3E8,
|
||||||
|
COM4 = 0x2E8
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SerialConfig {
|
||||||
|
SERIALPORT port;
|
||||||
|
char baud_rate_lo ;
|
||||||
|
char baud_rate_hi;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Serial {
|
||||||
|
|
||||||
|
public:
|
||||||
|
Serial (SerialConfig config );
|
||||||
|
|
||||||
|
char read();
|
||||||
|
void write(void* data, int length);
|
||||||
|
|
||||||
|
private:
|
||||||
|
SERIALPORT port;
|
||||||
|
int is_transmit_empty();
|
||||||
|
};
|
8
kernel/grub.cfg
Normal file
8
kernel/grub.cfg
Normal file
@ -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
|
||||||
|
}
|
2
kernel/i386/README.md
Normal file
2
kernel/i386/README.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# architecture specific implementations
|
||||||
|
## This will contain I386 Architecture specific implementations
|
127
kernel/i386/processor.cpp
Normal file
127
kernel/i386/processor.cpp
Normal file
@ -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;
|
||||||
|
}
|
36
kernel/i386/processor.h
Normal file
36
kernel/i386/processor.h
Normal file
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
};
|
427
kernel/interrupts/idt.cpp
Normal file
427
kernel/interrupts/idt.cpp
Normal file
@ -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);
|
||||||
|
}
|
@ -1,11 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "stdint.h"
|
#include <stdint.h>
|
||||||
#include "stddef.h"
|
#include <stddef.h>
|
||||||
#include "../vga/colors.h"
|
#include "../drivers/vga/colors.h"
|
||||||
#include "../pic/pic.h"
|
#include "../drivers/pic/pic.h"
|
||||||
|
|
||||||
#include "../tty/kterm.h"
|
#include "../terminal/kterm.h"
|
||||||
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -32,11 +32,11 @@ extern "C" {
|
|||||||
|
|
||||||
extern void idt_flush(uint32_t);
|
extern void idt_flush(uint32_t);
|
||||||
void set_id_entry (uint8_t num , uint32_t base, uint16_t sel, uint8_t flags);
|
void set_id_entry (uint8_t num , uint32_t base, uint16_t sel, uint8_t flags);
|
||||||
void init_idt();
|
void initidt();
|
||||||
|
|
||||||
void irq_handler (registers regs);
|
void irq_handler (registers regs);
|
||||||
|
|
||||||
void irs_handler (registers regs);
|
void irs_handler (registers* regs);
|
||||||
|
|
||||||
extern void irs0 ();
|
extern void irs0 ();
|
||||||
extern void irs1 ();
|
extern void irs1 ();
|
||||||
@ -70,6 +70,7 @@ extern "C" {
|
|||||||
extern void irs29 ();
|
extern void irs29 ();
|
||||||
extern void irs30 ();
|
extern void irs30 ();
|
||||||
extern void irs31 ();
|
extern void irs31 ();
|
||||||
|
extern void irs50();
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -23,7 +23,7 @@ unsigned int inl_p(unsigned short ){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void outb_p(unsigned char , unsigned short ){
|
void b_p(unsigned char , unsigned short ){
|
||||||
|
|
||||||
}
|
}
|
||||||
void outw(unsigned short , unsigned short ){
|
void outw(unsigned short , unsigned short ){
|
55
kernel/irq_table.s
Normal file
55
kernel/irq_table.s
Normal file
@ -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
|
87
kernel/irs_table.s
Normal file
87
kernel/irs_table.s
Normal file
@ -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
|
88
kernel/kernel.cpp
Normal file
88
kernel/kernel.cpp
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
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 "storage/vfs/vfs.h"
|
||||||
|
#include "storage/filesystems/FAT/FAT.h"
|
||||||
|
#include "acpi/acpi.h"
|
||||||
|
#include "memory/VirtualMemoryManager.h"
|
||||||
|
#include "klog.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 ()
|
||||||
|
{
|
||||||
|
kterm_init();
|
||||||
|
setup_tss();
|
||||||
|
initGDT();
|
||||||
|
initidt();
|
||||||
|
LoadGlobalDescriptorTable();
|
||||||
|
flush_tss();
|
||||||
|
|
||||||
|
|
||||||
|
print_info("Memory setup complete!\n");
|
||||||
|
// Enable interrupts
|
||||||
|
asm volatile("STI");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
initHeap();
|
||||||
|
//pit_initialise();
|
||||||
|
|
||||||
|
|
||||||
|
//ACPI::initialize();
|
||||||
|
//PCI::Scan();
|
||||||
|
processor::initialize();
|
||||||
|
processor::enable_protectedMode();
|
||||||
|
initBootDrive();
|
||||||
|
VirtualFileSystem::initialize();
|
||||||
|
|
||||||
|
print_dbg("Hello debug!\n");
|
||||||
|
print_info("Hello info!\n");
|
||||||
|
print_err("Hello error!\n");
|
||||||
|
|
||||||
|
#define VFS_EXAMPLE
|
||||||
|
#ifdef VFS_EXAMPLE
|
||||||
|
auto fontFile = VirtualFileSystem::open("/FONT PSF", 0);
|
||||||
|
printf("Size of font file: %d bytes\n", fontFile->root->size); // COOL This Works like a charm
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USERMODE_RELEASE
|
||||||
|
// Lets jump into user mode
|
||||||
|
jump_usermode();
|
||||||
|
#else
|
||||||
|
startSuperVisorTerminal();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
8
kernel/kernel.h
Normal file
8
kernel/kernel.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define CHECK_FLAG(flags, bit) ((flags) & (1 <<(bit)))
|
||||||
|
#define PANIC(message) {return;}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
58
kernel/klog.cpp
Normal file
58
kernel/klog.cpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
//
|
||||||
|
// Created by nigel on 10/28/23.
|
||||||
|
//
|
||||||
|
#include "klog.h"
|
||||||
|
#include "terminal/kterm.h"
|
||||||
|
#include <CoreLib/Memory.h>
|
||||||
|
|
||||||
|
const char* ForeGroundColourReset = "\e[39m";
|
||||||
|
void print_dbg(const char* message, ...){
|
||||||
|
auto **arg = (unsigned char**)&message;
|
||||||
|
// Send it to the VGA
|
||||||
|
printf(message, arg);
|
||||||
|
|
||||||
|
// Now send the message to the serial
|
||||||
|
Serial com1= Serial({
|
||||||
|
COM1,
|
||||||
|
0x03,
|
||||||
|
0x00
|
||||||
|
});
|
||||||
|
|
||||||
|
const char* ForeGroundColour = "\e[32m";
|
||||||
|
com1.write((void*)ForeGroundColour, strlen(ForeGroundColour));
|
||||||
|
com1.write((void*)message, strlen(message));
|
||||||
|
com1.write((void*)ForeGroundColourReset, strlen(ForeGroundColourReset));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void print_info(const char* message, ...){
|
||||||
|
auto **arg = (unsigned char**)&message;
|
||||||
|
// Send it to the VGA
|
||||||
|
printf(message, arg);
|
||||||
|
|
||||||
|
Serial com1 = Serial({
|
||||||
|
COM1,
|
||||||
|
0x03,
|
||||||
|
0x00
|
||||||
|
});
|
||||||
|
|
||||||
|
const char* ForeGroundColour = "\e[34m";
|
||||||
|
com1.write((void*)ForeGroundColour, strlen(ForeGroundColour));
|
||||||
|
com1.write((void*)message, strlen(message));
|
||||||
|
com1.write((void*)ForeGroundColourReset, strlen(ForeGroundColourReset));
|
||||||
|
}
|
||||||
|
void print_err(const char* message, ...){
|
||||||
|
auto **arg = (unsigned char**)&message;
|
||||||
|
// Send it to the VGA
|
||||||
|
printf(message, arg);
|
||||||
|
Serial com1 = Serial({
|
||||||
|
COM1,
|
||||||
|
0x03,
|
||||||
|
0x00
|
||||||
|
});
|
||||||
|
const char* ForeGroundColour = "\e[31m";
|
||||||
|
com1.write((void*)ForeGroundColour, strlen(ForeGroundColour));
|
||||||
|
com1.write((void*)message, strlen(message));
|
||||||
|
com1.write((void*)ForeGroundColourReset, strlen(ForeGroundColourReset));
|
||||||
|
}
|
12
kernel/klog.h
Normal file
12
kernel/klog.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
//
|
||||||
|
// Created by nigel on 10/28/23.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "drivers/serial/serial.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void print_dbg(const char* message, ...);
|
||||||
|
void print_info(const char* message, ...);
|
||||||
|
void print_err(const char* message, ...);
|
45
kernel/linker.ld
Normal file
45
kernel/linker.ld
Normal file
@ -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 */
|
||||||
|
}
|
||||||
|
|
86
kernel/memory/KernelHeap.cpp
Normal file
86
kernel/memory/KernelHeap.cpp
Normal file
@ -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;
|
||||||
|
|
||||||
|
}
|
10
kernel/memory/KernelHeap.h
Normal file
10
kernel/memory/KernelHeap.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "../terminal/kterm.h"
|
||||||
|
|
||||||
|
void initHeap();
|
||||||
|
|
||||||
|
void* malloc (size_t size );
|
||||||
|
void free(void* addr);
|
||||||
|
|
43
kernel/memory/PageDirectory.cpp
Normal file
43
kernel/memory/PageDirectory.cpp
Normal file
@ -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 )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
@ -1,17 +1,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "./memory.h"
|
||||||
extern "C" void loadPageDirectory (uint32_t* addr );
|
#include "./../terminal/kterm.h"
|
||||||
extern "C" void enablePaging();
|
|
||||||
typedef uintptr_t address_t;
|
|
||||||
|
|
||||||
|
|
||||||
#define KB 1024
|
#define KB 1024
|
||||||
|
|
||||||
|
|
||||||
|
typedef uintptr_t address_t;
|
||||||
|
|
||||||
static const int MAX_PAGES = 1024 * KB; // 4GB , 4kB/page
|
static const int MAX_PAGES = 1024 * KB; // 4GB , 4kB/page
|
||||||
static volatile address_t pmem_stack[MAX_PAGES];
|
static volatile address_t pmem_stack[MAX_PAGES];
|
||||||
static volatile address_t pmem_stack_top = MAX_PAGES; // top down allocation
|
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_directory_entry {};
|
||||||
struct page_table_entry{};
|
struct page_table_entry{};
|
||||||
@ -21,8 +22,10 @@ struct page_table_entry{};
|
|||||||
class PageDirectory {
|
class PageDirectory {
|
||||||
public:
|
public:
|
||||||
void enable ();
|
void enable ();
|
||||||
|
void MapPhysicalToVirtualAddress ( address_t PAddress , address_t VAddress, uint32_t size );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t page_directory[1024] __attribute__((aligned(4096)));
|
uint32_t page_directory[1024] __attribute__((aligned(4096))); // align on 4 kiloByte pages
|
||||||
uint32_t first_page_table[1024] __attribute__((aligned(4096)));
|
uint32_t first_page_table[1024] __attribute__((aligned(4096))); // align on 4 kiloByte pages
|
||||||
|
|
||||||
};
|
};
|
115
kernel/memory/PhysicalMemoryManager.cpp
Normal file
115
kernel/memory/PhysicalMemoryManager.cpp
Normal file
@ -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;
|
||||||
|
}
|
20
kernel/memory/PhysicalMemoryManager.h
Normal file
20
kernel/memory/PhysicalMemoryManager.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <CoreLib/Memory.h>
|
||||||
|
|
||||||
|
#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();
|
60
kernel/memory/TaskStateSegment.h
Normal file
60
kernel/memory/TaskStateSegment.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "gdt/gdtc.h"
|
||||||
|
#include <CoreLib/Memory.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
130
kernel/memory/VirtualMemoryManager.cpp
Normal file
130
kernel/memory/VirtualMemoryManager.cpp
Normal file
@ -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;
|
||||||
|
|
||||||
|
}
|
16
kernel/memory/VirtualMemoryManager.h
Normal file
16
kernel/memory/VirtualMemoryManager.h
Normal file
@ -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);
|
@ -1,15 +1,11 @@
|
|||||||
#include "gdtc.h"
|
#include "gdtc.h"
|
||||||
#include "../tty/kterm.h"
|
#include "../../terminal/kterm.h"
|
||||||
|
|
||||||
#define NULL_SEGMENT 0
|
|
||||||
#define KERNEL_CODE_SEGMENT 1
|
|
||||||
#define KERNEL_DATA_SEGMENT 2
|
|
||||||
#define USER_CODE_SEGMENT 3
|
|
||||||
#define USER_DATA_SEGMENT 4
|
|
||||||
|
|
||||||
SegmentDescriptor GlobalDescriptorTable[5];
|
SegmentDescriptor GlobalDescriptorTable[6];
|
||||||
GlobalDescriptorTableDescriptor gdtDescriptor;
|
GlobalDescriptorTableDescriptor gdtDescriptor;
|
||||||
|
|
||||||
|
|
||||||
void add_descriptor(int which , unsigned long base, unsigned long limit, unsigned char access, unsigned char granularity ){
|
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_low = (base & 0xFFFF );
|
||||||
GlobalDescriptorTable[which].base_middle = (base >> 6) & 0xFF;
|
GlobalDescriptorTable[which].base_middle = (base >> 6) & 0xFF;
|
||||||
@ -21,7 +17,6 @@ void add_descriptor(int which , unsigned long base, unsigned long limit, unsigne
|
|||||||
GlobalDescriptorTable[which].granularity |= (granularity & 0xF0);
|
GlobalDescriptorTable[which].granularity |= (granularity & 0xF0);
|
||||||
GlobalDescriptorTable[which].access = access;
|
GlobalDescriptorTable[which].access = access;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -39,19 +34,13 @@ void initGDT(){
|
|||||||
add_descriptor(KERNEL_DATA_SEGMENT, 0, 0xFFFFFFFF, 0x92, 0xCF);
|
add_descriptor(KERNEL_DATA_SEGMENT, 0, 0xFFFFFFFF, 0x92, 0xCF);
|
||||||
|
|
||||||
// User Code Segment
|
// User Code Segment
|
||||||
// TODO:
|
add_descriptor(USER_CODE_SEGMENT, 0, 0xFFFFFFFF, 0xFA, 0xCF);
|
||||||
|
|
||||||
// User Data Segement
|
// User Data Segement
|
||||||
// TODO:
|
add_descriptor(USER_DATA_SEGMENT, 0, 0xFFFFFFFF, 0xF2, 0xCF);
|
||||||
|
|
||||||
// init Gdt Descriptor
|
// init Gdt Descriptor
|
||||||
gdtDescriptor.limit = ((sizeof(SegmentDescriptor ) * 5 ) - 1);
|
gdtDescriptor.limit = ((sizeof(SegmentDescriptor ) * 6 ) - 1);
|
||||||
gdtDescriptor.base = (unsigned int) &GlobalDescriptorTable;
|
gdtDescriptor.base = (unsigned int) (&GlobalDescriptorTable);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
LoadGlobalDescriptorTable();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,6 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
#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 {
|
struct SegmentDescriptor {
|
||||||
unsigned short limit_low;
|
unsigned short limit_low;
|
||||||
unsigned short base_low;
|
unsigned short base_low;
|
||||||
@ -10,18 +20,16 @@ struct SegmentDescriptor {
|
|||||||
unsigned char base_high;
|
unsigned char base_high;
|
||||||
}__attribute__((packed));
|
}__attribute__((packed));
|
||||||
|
|
||||||
|
extern SegmentDescriptor GlobalDescriptorTable[6];
|
||||||
|
|
||||||
struct GlobalDescriptorTableDescriptor{
|
struct GlobalDescriptorTableDescriptor{
|
||||||
unsigned short limit;
|
unsigned short limit;
|
||||||
unsigned int base;
|
unsigned int base;
|
||||||
}__attribute__((packed));
|
}__attribute__((packed)) ;
|
||||||
|
|
||||||
extern SegmentDescriptor GlobalDescriptorTable[];
|
|
||||||
extern GlobalDescriptorTableDescriptor gdtDescriptor;
|
|
||||||
|
|
||||||
|
|
||||||
void add_descriptor(int which , unsigned long base, unsigned long limit, unsigned char access, unsigned char granularity );
|
void add_descriptor(int which , unsigned long base, unsigned long limit, unsigned char access, unsigned char granularity );
|
||||||
|
|
||||||
|
|
||||||
extern "C" void LoadGlobalDescriptorTable();
|
|
||||||
void initGDT();
|
void initGDT();
|
142
kernel/memory/memory.cpp
Normal file
142
kernel/memory/memory.cpp
Normal file
@ -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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
46
kernel/memory/memory.h
Normal file
46
kernel/memory/memory.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "memoryinfo.h"
|
||||||
|
#include "../prekernel/multiboot.h"
|
||||||
|
#include "../terminal/kterm.h"
|
||||||
|
#include <CoreLib/Memory.h>
|
||||||
|
|
||||||
|
#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);
|
20
kernel/memory/memoryinfo.h
Normal file
20
kernel/memory/memoryinfo.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
|
||||||
|
|
164
kernel/pci/pci.cpp
Normal file
164
kernel/pci/pci.cpp
Normal file
@ -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);
|
||||||
|
|
||||||
|
}
|
61
kernel/pci/pci.h
Normal file
61
kernel/pci/pci.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
#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);
|
||||||
|
};
|
||||||
|
|
30
kernel/prekernel/bootstructure.h
Normal file
30
kernel/prekernel/bootstructure.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
};
|
136
kernel/prekernel/prekernel.cpp
Normal file
136
kernel/prekernel/prekernel.cpp
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
@ -1,113 +1,9 @@
|
|||||||
#include "ataDevice.h"
|
#include "ATAPIO.h"
|
||||||
#define IS_BIT_SET(x, bit) ((x >> bit & 0x1) == 1)
|
#include "../../io/io.h"
|
||||||
|
|
||||||
void ATA_DEVICE::Soft_Reset(uint8_t DEVICE_CHANNEL,DEVICE_DRIVE drive){
|
#define IS_BIT_SET(x, bit) ((x >> bit & 0x1) == 1)
|
||||||
printf("Soft reseting drive...\n");
|
|
||||||
outb(channels[DEVICE_CHANNEL].base + 7 , 0x4);
|
|
||||||
// wait a bit..
|
|
||||||
for(int i = 0 ; i < 1000000; i++){
|
|
||||||
asm volatile("NOP");
|
|
||||||
}
|
|
||||||
outb(channels[DEVICE_CHANNEL].base + 7 , 0x0);
|
|
||||||
|
|
||||||
}
|
void ATAPIO::Read(uint16_t DEVICE_CHANNEL, DEVICE_DRIVE drive, uint32_t LBA, uint16_t* buffer) {
|
||||||
|
|
||||||
|
|
||||||
void ATA_DEVICE::Identify(uint16_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
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
//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;
|
|
||||||
}
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
//printf("Waiting until ready...\n");
|
|
||||||
while(((status2 & 0x80 == 0x80)
|
|
||||||
&& (status2 & 0x01) != 0x01)
|
|
||||||
) status2 = inb(DEVICE_CHANNEL | 7);
|
|
||||||
|
|
||||||
if( status2 & 0x01){
|
|
||||||
printf("Error!\n");
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
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');
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ATA_DEVICE::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.
|
Assume you have a sectorcount byte and a 28 bit LBA value. A sectorcount of 0 means 256 sectors = 128K.
|
||||||
|
|
||||||
@ -128,7 +24,7 @@ void ATA_DEVICE::Read(uint16_t DEVICE_CHANNEL, DEVICE_DRIVE drive, uint32_t LBA
|
|||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Read LBA: 0x%x\n", LBA);
|
//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))
|
// 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) ) );
|
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)
|
// Send a NULL byte to port 0x1F1, if you like (it is ignored and wastes lots of CPU time): outb(0x1F1, 0x00)
|
||||||
@ -156,7 +52,7 @@ void ATA_DEVICE::Read(uint16_t DEVICE_CHANNEL, DEVICE_DRIVE drive, uint32_t LBA
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Status: %x\n", status);
|
//printf("Status: %x\n", status);
|
||||||
// Check if busy!
|
// Check if busy!
|
||||||
while((status & 0x80) == 0x80){
|
while((status & 0x80) == 0x80){
|
||||||
printf("Reading....\r");
|
printf("Reading....\r");
|
||||||
@ -180,7 +76,8 @@ void ATA_DEVICE::Read(uint16_t DEVICE_CHANNEL, DEVICE_DRIVE drive, uint32_t LBA
|
|||||||
for ( int i = 0; i < 256; i++){
|
for ( int i = 0; i < 256; i++){
|
||||||
uint16_t data;
|
uint16_t data;
|
||||||
asm volatile ("inw %1, %0" : "=a"(data): "Nd"(DEVICE_CHANNEL));
|
asm volatile ("inw %1, %0" : "=a"(data): "Nd"(DEVICE_CHANNEL));
|
||||||
printf (" %x ", data);
|
// printf (" %x ", data);
|
||||||
|
|
||||||
buffer[i] = data;
|
buffer[i] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,6 +85,115 @@ void ATA_DEVICE::Read(uint16_t DEVICE_CHANNEL, DEVICE_DRIVE drive, uint32_t LBA
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ATA_DEVICE::Write(uint16_t DEVICE_CHANNEL, DEVICE_DRIVE drive) {
|
void ATAPIO::Write(uint16_t data, DEVICE_DRIVE dev){
|
||||||
|
|
||||||
printf("Not implemented\n");
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
36
kernel/storage/ata pio/ATAPIO.h
Normal file
36
kernel/storage/ata pio/ATAPIO.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint-gcc.h>
|
||||||
|
#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 );
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "../../io.h"
|
#include "../../io/io.h"
|
||||||
#include "../../ide/ideCommands.h"
|
#include "../ide/ideCommands.h"
|
||||||
#include "../../ide/sampleIDE.definitions.h"
|
#include "../ide/sampleIDE.definitions.h"
|
||||||
|
|
||||||
#include "../../tty/kterm.h"
|
#include "../../terminal/kterm.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This first driver wil make use of IO ports.
|
* This first driver wil make use of IO ports.
|
404
kernel/storage/filesystems/FAT/FAT.cpp
Normal file
404
kernel/storage/filesystems/FAT/FAT.cpp
Normal file
@ -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 <CoreLib/Memory.h>
|
||||||
|
#include <CoreLib/ctype.h>
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
119
kernel/storage/filesystems/FAT/FAT.h
Normal file
119
kernel/storage/filesystems/FAT/FAT.h
Normal file
@ -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
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
42
kernel/storage/filesystems/FAT/msdosDate.h
Normal file
42
kernel/storage/filesystems/FAT/msdosDate.h
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <stdint.h>
|
#include <stdint-gcc.h>
|
||||||
#include "../pci/pciDevice.h"
|
#include "../../terminal/kterm.h"
|
||||||
#include "../tty/kterm.h"
|
|
||||||
#include "ideCommands.h"
|
#include "ideCommands.h"
|
||||||
#include "sampleIDE.h"
|
#include "sampleIDE.h"
|
||||||
|
#include "../../pci/pciDevice.h"
|
||||||
|
#include "../../pci/pci.h"
|
||||||
|
|
||||||
#define IS_BIT_SET(x, bit) ((x >> bit & 0x1) == 1)
|
#define IS_BIT_SET(x, bit) ((x >> bit & 0x1) == 1)
|
||||||
|
|
||||||
@ -55,7 +56,7 @@ inline void TestIDEController(){
|
|||||||
int device =1 , function = 1;
|
int device =1 , function = 1;
|
||||||
PCIBusAddress IDEControllerPCIAddress = PCIBusAddress{bus,device, function};
|
PCIBusAddress IDEControllerPCIAddress = PCIBusAddress{bus,device, function};
|
||||||
|
|
||||||
uint8_t ProgIF = GetProgIF(IDEControllerPCIAddress);
|
uint8_t ProgIF = PCI::GetProgIF(IDEControllerPCIAddress);
|
||||||
printf( "ProgIF: 0x%x\n" ,ProgIF);
|
printf( "ProgIF: 0x%x\n" ,ProgIF);
|
||||||
|
|
||||||
//CheckProgIF(ProgIF);
|
//CheckProgIF(ProgIF);
|
||||||
@ -65,15 +66,15 @@ inline void TestIDEController(){
|
|||||||
|
|
||||||
uint32_t BAR0,BAR1,BAR2,BAR3, BAR4;
|
uint32_t BAR0,BAR1,BAR2,BAR3, BAR4;
|
||||||
|
|
||||||
BAR0 = ReadBAR(IDEControllerPCIAddress, 0);
|
BAR0 = PCI::ReadBAR(IDEControllerPCIAddress, 0);
|
||||||
|
|
||||||
BAR1 = ReadBAR(IDEControllerPCIAddress, 1);
|
BAR1 = PCI::ReadBAR(IDEControllerPCIAddress, 1);
|
||||||
|
|
||||||
BAR2 = ReadBAR(IDEControllerPCIAddress, 2);
|
BAR2 = PCI::ReadBAR(IDEControllerPCIAddress, 2);
|
||||||
|
|
||||||
BAR3 = ReadBAR(IDEControllerPCIAddress, 3);
|
BAR3 = PCI::ReadBAR(IDEControllerPCIAddress, 3);
|
||||||
|
|
||||||
BAR4 = ReadBAR(IDEControllerPCIAddress, 4);
|
BAR4 = PCI::ReadBAR(IDEControllerPCIAddress, 4);
|
||||||
|
|
||||||
// All bars are return 0xffffff for some as of yet mysterious reason!
|
// All bars are return 0xffffff for some as of yet mysterious reason!
|
||||||
printf( "BAR 0: 0x%x\n", BAR0);
|
printf( "BAR 0: 0x%x\n", BAR0);
|
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <stdint.h>
|
#include <stdint-gcc.h>
|
||||||
#include "../tty/kterm.h"
|
#include "../../terminal/kterm.h"
|
||||||
#include "sampleIDE.definitions.h"
|
#include "sampleIDE.definitions.h"
|
||||||
#include "ideCommands.h"
|
#include "ideCommands.h"
|
||||||
|
|
||||||
@ -155,7 +155,7 @@ inline void init_IDE( uint32_t BAR0, uint32_t BAR1,uint32_t BAR2, uint32_t BAR3,
|
|||||||
|
|
||||||
|
|
||||||
// 3- Detect ATA-ATAPI Devices:
|
// 3- Detect ATA-ATAPI Devices:
|
||||||
void DetectDevices(){
|
inline void DetectDevices(){
|
||||||
int i, j, k, count = 0;
|
int i, j, k, count = 0;
|
||||||
|
|
||||||
for (i = 0; i < 2; i++)
|
for (i = 0; i < 2; i++)
|
||||||
@ -228,7 +228,7 @@ void DetectDevices(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Detect_IO_Ports(uint32_t BAR0, uint32_t BAR1,uint32_t BAR2, uint32_t BAR3, uint32_t BAR4){
|
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
|
// 1 Detect I/O Ports which interface an IDE Controller
|
||||||
|
|
||||||
// Based on the implementation within serenity
|
// Based on the implementation within serenity
|
||||||
@ -239,4 +239,20 @@ void Detect_IO_Ports(uint32_t BAR0, uint32_t BAR1,uint32_t BAR2, uint32_t BAR3,
|
|||||||
channels[ATA_PRIMARY ].bmide = (BAR4 & (~1)) + 0; // Bus Master IDE
|
channels[ATA_PRIMARY ].bmide = (BAR4 & (~1)) + 0; // Bus Master IDE
|
||||||
channels[ATA_SECONDARY].bmide = (BAR4 & (~1)) + 8; // 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;
|
||||||
}
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user