Compare commits
27 Commits
c9a036bfbb
...
dev
Author | SHA1 | Date | |
---|---|---|---|
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 |
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
|
11
.gitignore
vendored
11
.gitignore
vendored
@ -1,10 +1,15 @@
|
||||
build
|
||||
CON
|
||||
.vscode
|
||||
build/
|
||||
bin/
|
||||
.vscode/
|
||||
.idea/
|
||||
isodir/
|
||||
root/
|
||||
*.iso
|
||||
*.img
|
||||
*.sym
|
||||
*.o
|
||||
*.a
|
||||
|
||||
|
||||
/CoreLib/warnings.log
|
||||
/kernel/warnings.log
|
||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +0,0 @@
|
||||
[submodule "mlibc"]
|
||||
path = mlibc
|
||||
url = https://github.com/managarm/mlibc.git
|
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.
|
||||
//
|
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "../../kernel/memory/KernelHeap.h"
|
||||
#include "../kernel/memory/KernelHeap.h"
|
||||
#include <stdint.h>
|
||||
|
||||
template <typename T>
|
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);
|
||||
|
141
Makefile
141
Makefile
@ -1,141 +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 -Og -ggdb -Wall -Wextra
|
||||
|
||||
OFILES =$(BUILD_DIR)/boot.o $(BUILD_DIR)/kterm.o $(BUILD_DIR)/kernel.o $(BUILD_DIR)/memory.o $(BUILD_DIR)/paging.o $(BUILD_DIR)/pit.o $(BUILD_DIR)/time.o $(BUILD_DIR)/keyboard.o $(BUILD_DIR)/io.o $(BUILD_DIR)/gdtc.o $(BUILD_DIR)/idt.o $(BUILD_DIR)/pic.o $(BUILD_DIR)/sv-terminal.o $(BUILD_DIR)/string.o $(BUILD_DIR)/prekernel.o $(BUILD_DIR)/cpu.o $(BUILD_DIR)/KHeap.o $(BUILD_DIR)/pci.o $(BUILD_DIR)/pcidevice.o $(BUILD_DIR)/atapiDevice.o $(BUILD_DIR)/ataDevice.o $(BUILD_DIR)/rsdp.o $(BUILD_DIR)/acpi.o
|
||||
|
||||
SRC_DIR = source
|
||||
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 source/grub.cfg root/boot/grub/grub.cfg
|
||||
grub-mkrescue -o build/barinkOS.iso root
|
||||
run: all
|
||||
virtualboxvm --startvm "BarinkOS_test"
|
||||
debug: all
|
||||
objcopy --only-keep-debug build/myos.bin kernel.sym
|
||||
$(EMULATOR) -cdrom build/barinkOS.iso -serial stdio -vga std -display gtk -m 2G -cpu core2duo -s -d int -no-shutdown -no-reboot
|
||||
test:
|
||||
$(EMULATOR) -kernel $(BUILD_DIR)/myos.bin -serial stdio -vga std -display gtk -m 2G -cpu core2duo -d int -no-shutdown -no-reboot
|
||||
|
||||
test_iso:
|
||||
$(EMULATOR) -boot d -cdrom $(BUILD_DIR)/barinkOS.iso -serial stdio -vga std -display gtk -m 2G -cpu core2duo -d int -no-reboot -no-shutdown
|
||||
test_disk:
|
||||
$(EMULATOR) -boot d -drive format=raw,file=build/disk.img -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 -ggdb -Og -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)
|
||||
|
||||
# C++ definition -> Object files
|
||||
$(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/terminal/kterm.cpp -o $(BUILD_DIR)/kterm.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(BUILD_DIR)/io.o:
|
||||
$(CPP) -c $(SRC_DIR)/kernel/drivers/io/io.cpp -o $(BUILD_DIR)/io.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(BUILD_DIR)/idt.o:
|
||||
$(CPP) -c $(SRC_DIR)/kernel/interrupts/idt.cpp -o $(BUILD_DIR)/idt.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(BUILD_DIR)/gdtc.o:
|
||||
$(CPP) -c $(SRC_DIR)/kernel/memory/gdt/gdtc.cpp -o $(BUILD_DIR)/gdtc.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(BUILD_DIR)/pic.o:
|
||||
$(CPP) -c $(SRC_DIR)/kernel/drivers/pic/pic.cpp -o $(BUILD_DIR)/pic.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(BUILD_DIR)/string.o:
|
||||
$(CC) -c $(SRC_DIR)/lib/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/drivers/pci/pci.cpp -o $(BUILD_DIR)/pci.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(BUILD_DIR)/pcidevice.o:
|
||||
$(CPP) -c $(SRC_DIR)/kernel/drivers/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
|
||||
|
||||
$(BUILD_DIR)/ataDevice.o:
|
||||
$(CPP) -c $(SRC_DIR)/kernel/drivers/ata/ataDevice.cpp -o $(BUILD_DIR)/ataDevice.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(BUILD_DIR)/rsdp.o:
|
||||
$(CPP) -c $(SRC_DIR)/kernel/drivers/acpi/rsdp.cpp -o $(BUILD_DIR)/rsdp.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(BUILD_DIR)/acpi.o:
|
||||
$(CPP) -c $(SRC_DIR)/kernel/drivers/acpi/acpi.cpp -o $(BUILD_DIR)/acpi.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(BUILD_DIR)/pit.o:
|
||||
$(CPP) -c $(SRC_DIR)/kernel/drivers/pit/pit.cpp -o $(BUILD_DIR)/pit.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
|
||||
$(BUILD_DIR)/keyboard.o:
|
||||
$(CPP) -c $(SRC_DIR)/kernel/drivers/ps-2/keyboard.cpp -o $(BUILD_DIR)/keyboard.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(BUILD_DIR)/time.o:
|
||||
$(CPP) -c $(SRC_DIR)/kernel/time.cpp -o $(BUILD_DIR)/time.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(BUILD_DIR)/sv-terminal.o:
|
||||
$(CPP) -c $(SRC_DIR)/kernel/supervisorterminal/superVisorTerminal.cpp -o $(BUILD_DIR)/sv-terminal.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(BUILD_DIR)/memory.o:
|
||||
$(CPP) -c $(SRC_DIR)/kernel/memory/PhysicalMemoryManager.cpp -o $(BUILD_DIR)/memory.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(BUILD_DIR)/paging.o:
|
||||
$(CPP) -c $(SRC_DIR)/kernel/memory/VirtualMemoryManager.cpp -o $(BUILD_DIR)/paging.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(BUILD_DIR)/KHeap.o:
|
||||
$(CPP) -c $(SRC_DIR)/kernel/memory/KernelHeap.cpp -o $(BUILD_DIR)/KHeap.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(BUILD_DIR)/prekernel.o:
|
||||
$(CPP) -c $(SRC_DIR)/kernel/prekernel/prekernel.cpp -o $(BUILD_DIR)/prekernel.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(BUILD_DIR)/cpu.o:
|
||||
$(CPP) -c $(SRC_DIR)/kernel/cpu.cpp -o $(BUILD_DIR)/cpu.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
|
||||
|
||||
# Assembly -> Object files
|
||||
$(BUILD_DIR)/boot.o:
|
||||
$(AS) $(SRC_DIR)/kernel/boot/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
|
@ -27,7 +27,7 @@ Enumerating the PCI bus
|
||||
Correctly identified our ATAPI device 🎉
|
||||
|
||||
 \
|
||||
Reading a file from a FAT-16 Formatted drive
|
||||
Reading a FILE from a FAT-16 Formatted drive
|
||||
|
||||
________________________
|
||||
|
||||
|
17
features.md
17
features.md
@ -1,14 +1,17 @@
|
||||
# TODO list
|
||||
## Basics
|
||||
<input type="checkbox" checked/> Setup Cross-Compiler \
|
||||
<input type="checkbox" checked/> Multiboot to kernel \
|
||||
<input type="checkbox" checked/> Printing string to the screen \
|
||||
|
||||
<label>
|
||||
<input type="checkbox" checked/>
|
||||
</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/> Output to serial port \
|
||||
<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" checked/> Time measurement (PIC &| PIT) \
|
||||
<input type="checkbox" /> Detect CPU speed \
|
||||
<input type="checkbox" checked/> Interrupt / exception system (API) \
|
||||
@ -22,16 +25,13 @@
|
||||
<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)
|
||||
|
||||
## Other features I am thinking of:
|
||||
<input type="checkbox" checked/> PCI support \
|
||||
<input type="checkbox" /> ATA PIO Mode 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" /> ACPI support ( Or some other basic way to support shutdown, reboot and possibly hibernation ) \
|
||||
<input type="checkbox" /> ATAPI support \
|
||||
<input type="checkbox" checked/> Memory Management (MMU)
|
||||
<input type="checkbox" /> Hardware Management system
|
||||
|
||||
<input type="checkbox" /> Preemptive multi tasking \
|
||||
<input type="checkbox" /> Processes \
|
||||
<input type="checkbox" /> Threads
|
||||
@ -44,7 +44,6 @@
|
||||
<input type="checkbox" /> ACPI support \
|
||||
<input type="checkbox" /> ATAPI support \
|
||||
|
||||
## Optional
|
||||
<input type="checkbox" /> Basic Window server/client \
|
||||
<input type="checkbox" /> EXT2 Filesystem
|
||||
<input type="checkbox" /> USTAR Filesystem \
|
||||
|
132
kernel/Makefile
Normal file
132
kernel/Makefile
Normal file
@ -0,0 +1,132 @@
|
||||
AS = /opt/cross/bin/i686-elf-as
|
||||
CC = /opt/cross/bin/i686-elf-gcc
|
||||
CPP = /opt/cross/bin/i686-elf-g++
|
||||
CFLAGS = -ffreestanding -Og -ggdb -Wall -Wextra -I ../build/CoreLib/include
|
||||
BUILD_DIR = ../build/kernel
|
||||
OBJ_DIR = ../bin/kernel
|
||||
|
||||
CRTBEGIN_OBJ = $(shell $(CC) $(CFLAGS) -print-file-name=crtbegin.o)
|
||||
CRTEND_OBJ = $(shell $(CC) $(CFLAGS) -print-file-name=crtend.o)
|
||||
|
||||
CRTI_OBJ = $(OBJ_DIR)/crti.o
|
||||
CRTN_OBJ = $(OBJ_DIR)/crtn.o
|
||||
|
||||
OFILES = $(OBJ_DIR)/boot.o \
|
||||
$(OBJ_DIR)/kterm.o \
|
||||
$(OBJ_DIR)/kernel.o \
|
||||
$(OBJ_DIR)/memory.o \
|
||||
$(OBJ_DIR)/paging.o \
|
||||
$(OBJ_DIR)/VFS.o \
|
||||
$(OBJ_DIR)/pit.o \
|
||||
$(OBJ_DIR)/time.o \
|
||||
$(OBJ_DIR)/keyboard.o \
|
||||
$(OBJ_DIR)/io.o \
|
||||
$(OBJ_DIR)/processor.o \
|
||||
$(OBJ_DIR)/gdtc.o \
|
||||
$(OBJ_DIR)/idt.o \
|
||||
$(OBJ_DIR)/pic.o \
|
||||
$(OBJ_DIR)/sv-terminal.o \
|
||||
$(OBJ_DIR)/prekernel.o \
|
||||
$(OBJ_DIR)/KHeap.o \
|
||||
$(OBJ_DIR)/pci.o \
|
||||
$(OBJ_DIR)/pcidevice.o \
|
||||
$(OBJ_DIR)/atapiDevice.o \
|
||||
$(OBJ_DIR)/ataDevice.o \
|
||||
$(OBJ_DIR)/rsdp.o \
|
||||
$(OBJ_DIR)/acpi.o \
|
||||
$(OBJ_DIR)/fat.o
|
||||
|
||||
OBJ_LINK_LIST = $(CRTI_OBJ) $(CRTBEGIN_OBJ) $(OFILES) $(CRTEND_OBJ) $(CRTN_OBJ)
|
||||
INTERNAL_OBJS = $(CRTI_OBJ) $(OFILES) $(CRTN_OBJ)
|
||||
|
||||
all: clean build
|
||||
|
||||
clean:
|
||||
rm $(OBJ_DIR)/* -r
|
||||
|
||||
|
||||
build: $(OBJ_LINK_LIST)
|
||||
$(CPP) -T linker.ld -o $(BUILD_DIR)/myos.bin -ffreestanding -ggdb -Og -nostdlib $(OBJ_LINK_LIST) -lgcc -L ../build/CoreLib -lCoreLib
|
||||
|
||||
# C++ definition -> Object files
|
||||
$(OBJ_DIR)/kernel.o: kernel.cpp
|
||||
$(CPP) -c kernel.cpp -o $(OBJ_DIR)/kernel.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(OBJ_DIR)/kterm.o:
|
||||
$(CPP) -c terminal/kterm.cpp -o $(OBJ_DIR)/kterm.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(OBJ_DIR)/io.o:
|
||||
$(CPP) -c io/io.cpp -o $(OBJ_DIR)/io.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(OBJ_DIR)/idt.o:
|
||||
$(CPP) -c interrupts/idt.cpp -o $(OBJ_DIR)/idt.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(OBJ_DIR)/gdtc.o:
|
||||
$(CPP) -c memory/gdt/gdtc.cpp -o $(OBJ_DIR)/gdtc.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(OBJ_DIR)/pic.o:
|
||||
$(CPP) -c drivers/pic/pic.cpp -o $(OBJ_DIR)/pic.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(OBJ_DIR)/PhysicalMemoryManager.o:
|
||||
$(CPP) -c memory/PhysicalMemoryManager.cpp -o $(OBJ_DIR)/PhysicalMemoryManager.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(OBJ_DIR)/pci.o:
|
||||
$(CPP) -c pci/pci.cpp -o $(OBJ_DIR)/pci.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(OBJ_DIR)/pcidevice.o:
|
||||
$(CPP) -c pci/pciDevice.cpp -o $(OBJ_DIR)/pcidevice.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(OBJ_DIR)/atapiDevice.o:
|
||||
$(CPP) -c storage/atapi/atapiDevice.cpp -o $(OBJ_DIR)/atapiDevice.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(OBJ_DIR)/ataDevice.o:
|
||||
$(CPP) -c "storage/ata pio/ATAPIO.cpp" -o $(OBJ_DIR)/ataDevice.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(OBJ_DIR)/rsdp.o:
|
||||
$(CPP) -c acpi/rsdp.cpp -o $(OBJ_DIR)/rsdp.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(OBJ_DIR)/acpi.o:
|
||||
$(CPP) -c acpi/acpi.cpp -o $(OBJ_DIR)/acpi.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(OBJ_DIR)/pit.o:
|
||||
$(CPP) -c drivers/pit/pit.cpp -o $(OBJ_DIR)/pit.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(OBJ_DIR)/VFS.o:
|
||||
$(CPP) -c storage/vfs/vfs.cpp -o $(OBJ_DIR)/VFS.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(OBJ_DIR)/keyboard.o:
|
||||
$(CPP) -c drivers/ps-2/keyboard.cpp -o $(OBJ_DIR)/keyboard.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(OBJ_DIR)/time.o:
|
||||
$(CPP) -c time.cpp -o $(OBJ_DIR)/time.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(OBJ_DIR)/sv-terminal.o:
|
||||
$(CPP) -c supervisorterminal/superVisorTerminal.cpp -o $(OBJ_DIR)/sv-terminal.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(OBJ_DIR)/memory.o:
|
||||
$(CPP) -c memory/PhysicalMemoryManager.cpp -o $(OBJ_DIR)/memory.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(OBJ_DIR)/paging.o:
|
||||
$(CPP) -c memory/VirtualMemoryManager.cpp -o $(OBJ_DIR)/paging.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(OBJ_DIR)/KHeap.o:
|
||||
$(CPP) -c memory/KernelHeap.cpp -o $(OBJ_DIR)/KHeap.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(OBJ_DIR)/prekernel.o:
|
||||
$(CPP) -c prekernel/prekernel.cpp -o $(OBJ_DIR)/prekernel.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(OBJ_DIR)/processor.o:
|
||||
$(CPP) -c i386/processor.cpp -o $(OBJ_DIR)/processor.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
$(OBJ_DIR)/fat.o:
|
||||
$(CPP) -c storage/filesystems/FAT/FAT.cpp -o $(OBJ_DIR)/fat.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
# Assembly -> Object files
|
||||
$(OBJ_DIR)/boot.o:
|
||||
$(AS) boot/boot.s -o $(OBJ_DIR)/boot.o
|
||||
|
||||
$(OBJ_DIR)/crti.o:
|
||||
$(AS) crti.s -o $(OBJ_DIR)/crti.o
|
||||
|
||||
$(OBJ_DIR)/crtn.o:
|
||||
$(AS) crtn.s -o $(OBJ_DIR)/crtn.o
|
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!");*/
|
||||
}
|
@ -7,7 +7,8 @@ class ACPI {
|
||||
// In the future ACPI might start
|
||||
// doing more systems initialization
|
||||
|
||||
static RSDPDescriptor* rsd_ptr;
|
||||
static RSCPDescriptor20* rsd2_ptr;
|
||||
static RSDT* rsd_table;
|
||||
private:
|
||||
static RSDPTR* rsd_ptr;
|
||||
static RSDT* rsd_table;
|
||||
};
|
@ -1,6 +1,9 @@
|
||||
#include "rsdp.h"
|
||||
#include "../memory/VirtualMemoryManager.h"
|
||||
#include "../../CoreLib/Memory.h"
|
||||
|
||||
void printRSD(RSDPTR* rsd){
|
||||
|
||||
void printRSD(RSDPDescriptor* rsd){
|
||||
printf("Signature: ");
|
||||
for(int i = 0; i < 8; i++){
|
||||
kterm_put(rsd->signature[i]);
|
||||
@ -14,33 +17,28 @@ void printRSD(RSDPTR* rsd){
|
||||
kterm_put('\n');
|
||||
|
||||
printf("Revision: %d\n", rsd->Revision);
|
||||
printf("RSDT Address: 0x%x\n", rsd->RsdtAddress );
|
||||
}
|
||||
|
||||
RSDPTR* FindRSD(){
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
printRSD((RSDPTR*) memory_byte);
|
||||
return (RSDPTR*) memory_byte;
|
||||
}
|
||||
|
||||
|
||||
RSDT* getRSDT(RSDPTR* rsd){
|
||||
|
||||
RSDT* rsdt = (RSDT*) rsd->RsdtAddress;
|
||||
|
||||
printf("OEMID: ");
|
||||
for(int i = 0; i < 6; i++){
|
||||
kterm_put(rsdt->header.OEMID[i]);
|
||||
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;
|
||||
}
|
||||
kterm_put('\n');
|
||||
return rsdt;
|
||||
}
|
||||
}
|
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);
|
@ -1,4 +1,4 @@
|
||||
.include "./source/kernel/boot/multiboot.s"
|
||||
.include "./boot/multiboot.s"
|
||||
/*
|
||||
* Allocate initial stack
|
||||
*/
|
||||
@ -101,18 +101,30 @@ isPaging:
|
||||
# movl $0, boot_page_directory + 0
|
||||
|
||||
|
||||
|
||||
|
||||
call early_main
|
||||
call kernel
|
||||
|
||||
cli
|
||||
1: hlt
|
||||
jmp 1b
|
||||
|
||||
|
||||
.include "./source/kernel/memory/gdt/gdt.s"
|
||||
.include "./source/kernel/irs_table.s"
|
||||
.include "./source/kernel/irq_table.s"
|
||||
.include "./source/kernel/interrupts/idt.s"
|
||||
.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
|
@ -4,6 +4,6 @@
|
||||
*/
|
||||
|
||||
#define __DEBUG__ false
|
||||
#define KERNEL_VERSION 0
|
||||
#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;
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
#include "../io/io.h"
|
||||
|
||||
#include <stdint-gcc.h>
|
||||
#include "../../io/io.h"
|
||||
|
||||
#define PIC1 0x20 /* IO base address for master PIC */
|
||||
#define PIC2 0xA0 /* IO base address for slave PIC */
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include "../io/io.h"
|
||||
#include <stdint-gcc.h>
|
||||
#include "../../io/io.h"
|
||||
#define PIT_DATA_0 0x40
|
||||
#define PIT_DATA_1 0x41
|
||||
#define PIT_DATA_2 0x42
|
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;
|
||||
|
||||
|
||||
};
|
@ -1,8 +1,11 @@
|
||||
#include "idt.h"
|
||||
#include "../drivers/pit/pit.h"
|
||||
#include "../drivers/ps-2/keyboard.h"
|
||||
#include "../cpu.h"
|
||||
#include "../i386/processor.h"
|
||||
#include "../memory/VirtualMemoryManager.h"
|
||||
#include "../syscalls.h"
|
||||
|
||||
|
||||
IDT_entry idt_table[256];
|
||||
IDT_ptr idt_ptr;
|
||||
|
||||
@ -18,7 +21,7 @@ void set_id_entry (uint8_t num , uint32_t base, uint16_t sel, uint8_t flags){
|
||||
|
||||
void irs_handler (registers* regs) {
|
||||
uint32_t FaultingAddress;
|
||||
//printf("(IRS) Interrupt number: %d \r", regs.int_no);
|
||||
printf("(IRS) Interrupt number: %d \n EAX: ", regs->int_no, regs->eax);
|
||||
switch (regs->int_no)
|
||||
{
|
||||
case 0:
|
||||
@ -165,7 +168,7 @@ void irs_handler (registers* regs) {
|
||||
// Page Fault Exception #PF
|
||||
printf("#PF\n");
|
||||
#define ALIGN(addr, align) (((addr) & ~((align) - 1)) + (align))
|
||||
FaultingAddress = GetCR2();
|
||||
FaultingAddress = processor::GetCR2();
|
||||
|
||||
printf("Accessing the linear address 0x%x resulted in a page fault!\n\n", FaultingAddress);
|
||||
|
||||
@ -188,7 +191,7 @@ void irs_handler (registers* regs) {
|
||||
printf("* Page protection violation!\n");
|
||||
} else{
|
||||
printf("* Page not-present!\n");
|
||||
Immediate_Map(FaultingAddress, FaultingAddress - 0xC0000000);
|
||||
//Immediate_Map(FaultingAddress, FaultingAddress);
|
||||
|
||||
}
|
||||
|
||||
@ -259,6 +262,29 @@ void irs_handler (registers* regs) {
|
||||
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;
|
||||
@ -269,9 +295,6 @@ void irs_handler (registers* regs) {
|
||||
}
|
||||
|
||||
void irq_handler (registers regs) {
|
||||
|
||||
|
||||
|
||||
switch (regs.int_no) {
|
||||
case 0:
|
||||
pit_tick++;
|
||||
@ -308,8 +331,8 @@ void irq_handler (registers regs) {
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Interrupt happened!");
|
||||
printf("Received INT: 0x%x\n", regs.int_no);
|
||||
//printf("Interrupt happened!");
|
||||
//printf("Received INT: 0x%x\n", regs.int_no);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -328,7 +351,7 @@ void irq_handler (registers regs) {
|
||||
}
|
||||
|
||||
void initidt(){
|
||||
// Initialise the IDT pointer
|
||||
// Initialize the IDT pointer
|
||||
idt_ptr.length = sizeof(IDT_entry) * 255;
|
||||
idt_ptr.base = (uint32_t)&idt_table;
|
||||
|
||||
@ -371,7 +394,7 @@ void initidt(){
|
||||
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);
|
||||
|
@ -70,6 +70,7 @@ extern "C" {
|
||||
extern void irs29 ();
|
||||
extern void irs30 ();
|
||||
extern void irs31 ();
|
||||
extern void irs50();
|
||||
|
||||
|
||||
|
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
|
@ -53,7 +53,7 @@ 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
|
||||
@ -74,7 +74,7 @@ irs_common:
|
||||
|
||||
call irs_handler
|
||||
|
||||
pop %eax
|
||||
pop %eax // pop stack pointer
|
||||
pop %ebx // reload ther orignal data segment descriptor
|
||||
mov %bx, %ds
|
||||
mov %bx, %es
|
||||
@ -82,6 +82,6 @@ irs_common:
|
||||
mov %bx, %gs
|
||||
|
||||
popa
|
||||
add $12, %esp # cleans push error and irs code
|
||||
add $8, %esp # cleans push error and irs code
|
||||
|
||||
iret # pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
|
82
kernel/kernel.cpp
Normal file
82
kernel/kernel.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
Copyright © Nigel Barink 2023
|
||||
*/
|
||||
#include "memory/memory.h"
|
||||
#include "memory/KernelHeap.h"
|
||||
#include "memory/gdt/gdtc.h"
|
||||
#include "memory/TaskStateSegment.h"
|
||||
#include "supervisorterminal/superVisorTerminal.h"
|
||||
#include "drivers/vga/VBE.h"
|
||||
#include "pci/pci.h"
|
||||
#include "drivers/pit/pit.h"
|
||||
#include "i386/processor.h"
|
||||
#include "terminal/kterm.h"
|
||||
#include "interrupts/idt.h"
|
||||
#include "serial.h"
|
||||
#include "storage/vfs/vfs.h"
|
||||
#include "storage/filesystems/FAT/FAT.h"
|
||||
#include "acpi/acpi.h"
|
||||
#include "memory/VirtualMemoryManager.h"
|
||||
|
||||
|
||||
extern BootInfoBlock* BIB;
|
||||
extern "C" void LoadGlobalDescriptorTable();
|
||||
extern "C" void jump_usermode();
|
||||
|
||||
void initBootDrive(){
|
||||
printf("Boot device: 0x%x\n", BIB->bootDeviceID);
|
||||
unsigned int part3 = BIB->bootDeviceID & 0xFF;
|
||||
unsigned int part2 = (BIB->bootDeviceID & 0xFF00) >> 8;
|
||||
unsigned int part1 = (BIB->bootDeviceID & 0xFF0000) >> 16;
|
||||
unsigned int drive = (BIB->bootDeviceID & 0xFF000000) >> 24;
|
||||
if (drive == 0x80 )
|
||||
printf("booted from disk!\n");
|
||||
if(drive == 0x00)
|
||||
printf("booted from floppy disk\n");
|
||||
|
||||
printf("Part1: %d, Part2: %d, Part3: %d\n", part1, part2 , part3);
|
||||
ATAPIO::Identify(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER);
|
||||
}
|
||||
|
||||
extern "C" void kernel ()
|
||||
{
|
||||
init_serial();
|
||||
kterm_init();
|
||||
print_serial("kterm initialized...\n");
|
||||
setup_tss();
|
||||
initGDT();
|
||||
initidt();
|
||||
LoadGlobalDescriptorTable();
|
||||
flush_tss();
|
||||
printf("Memory setup complete!\n");
|
||||
print_serial("Memory initialized....\n");
|
||||
// Enable interrupts
|
||||
asm volatile("STI");
|
||||
initHeap();
|
||||
print_serial("Heap initialized...\n");
|
||||
//pit_initialise();
|
||||
|
||||
|
||||
//ACPI::initialize();
|
||||
//PCI::Scan();
|
||||
processor::initialize();
|
||||
processor::enable_protectedMode();
|
||||
initBootDrive();
|
||||
VirtualFileSystem::initialize();
|
||||
|
||||
print_serial("Run test!");
|
||||
#define VFS_EXAMPLE
|
||||
#ifdef VFS_EXAMPLE
|
||||
auto fontFile = VirtualFileSystem::open("/FONT PSF", 0);
|
||||
printf("Size of font file: %d bytes", fontFile->root->size); // COOL This Works like a charm
|
||||
#endif
|
||||
|
||||
#ifdef USERMODE_RELEASE
|
||||
// Lets jump into user mode
|
||||
jump_usermode();
|
||||
#else
|
||||
startSuperVisorTerminal();
|
||||
|
||||
#endif
|
||||
|
||||
}
|
@ -25,6 +25,7 @@ SECTIONS
|
||||
.rodata ALIGN (4K) : AT (ADDR (.rodata) - 0xC0000000)
|
||||
{
|
||||
*(.rodata)
|
||||
*(.symtab)
|
||||
}
|
||||
.data ALIGN (4K) : AT (ADDR (.data) - 0xC0000000)
|
||||
{
|
||||
@ -36,6 +37,8 @@ SECTIONS
|
||||
*(.bss)
|
||||
*(.bootstrap_stack)
|
||||
}
|
||||
|
||||
|
||||
_kernel_end = .;
|
||||
kernel_end = .; /* For legacy reasons */
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
#include "KernelHeap.h"
|
||||
#include "VirtualMemoryManager.h"
|
||||
extern "C" const uint32_t kernel_end;
|
||||
// Size of heap meta data is 5 bytes
|
||||
// Size of heap metadata is 5 bytes
|
||||
struct heap_block{
|
||||
uint8_t Used;
|
||||
uint32_t Size;
|
||||
@ -12,7 +12,7 @@ heap_block* start ;
|
||||
|
||||
void* malloc(size_t size)
|
||||
{
|
||||
printf("Received request for %d bytes of memory\n", size);
|
||||
//printf("Received request for %d bytes of memory\n", size);
|
||||
heap_block* current = start;
|
||||
|
||||
// look for a free block
|
||||
@ -21,14 +21,14 @@ void* malloc(size_t size)
|
||||
if(current->Size >= size && current->Used == false )
|
||||
{
|
||||
// We found a spot
|
||||
printf("Block found!\n");
|
||||
// printf("Block found!\n");
|
||||
|
||||
// Set the spot to in-use
|
||||
current->Used = true;
|
||||
|
||||
|
||||
// split the block
|
||||
printf("Split block.\n");
|
||||
//printf("Split block.\n");
|
||||
uint32_t oldSize = current->Size;
|
||||
current->Size = size;
|
||||
|
||||
@ -57,7 +57,7 @@ void free(void* addr)
|
||||
{
|
||||
// clear the free boolean that corresponds to this adddress
|
||||
// This should be fairly simple
|
||||
heap_block* allocatedBlock = (heap_block*)(addr - sizeof(heap_block));
|
||||
heap_block* allocatedBlock = (heap_block*)((uint32_t)addr - sizeof(heap_block));
|
||||
allocatedBlock->Used = false;
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
#pragma once
|
||||
#include <stddef.h>
|
||||
#include <CoreLib/Memory.h>
|
||||
|
||||
#include "../prekernel/bootstructure.h"
|
||||
#include "../terminal/kterm.h"
|
||||
#include "../../lib/include/mem.h"
|
||||
#include "../bitmap.h"
|
||||
|
||||
#define BLOCK_SIZE 4092
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "gdt/gdtc.h"
|
||||
#include "../../lib/include/string.h"
|
||||
#include <CoreLib/Memory.h>
|
||||
|
||||
struct TaskStateSegment {
|
||||
uint32_t prev_tss;
|
@ -1,4 +1,6 @@
|
||||
#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
|
||||
@ -14,7 +16,7 @@ void flush_cr3(){
|
||||
|
||||
void AllocatePage(uint32_t vaddr)
|
||||
{
|
||||
uint32_t page_aligned_address = ALIGN(vaddr, 4096);
|
||||
//uint32_t page_aligned_address = ALIGN(vaddr, 4096);
|
||||
|
||||
// allocate a page at virtual address
|
||||
int PageDirectoryEntryIndex = vaddr >> 22;
|
||||
@ -54,16 +56,16 @@ void AllocatePage(uint32_t vaddr)
|
||||
|
||||
void FreePage(uint32_t vaddr )
|
||||
{
|
||||
uint32_t page_aligned_address = ALIGN(vaddr, 4096);
|
||||
// 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);
|
||||
uint32_t* pageTable = (uint32_t*)(boot_page_directory[PageDirectoryEntryIndex] & (0xFFFFE000 + 0xC0000000));
|
||||
|
||||
|
||||
void* physicalAddressToFree = (void*)(pageTable[PageTableEntryIndex] & 0xFFFFE000 + 0xC0000000);
|
||||
void* physicalAddressToFree = (void*)(pageTable[PageTableEntryIndex] & (0xFFFFE000 + 0xC0000000));
|
||||
free_block(physicalAddressToFree);
|
||||
|
||||
pageTable[PageTableEntryIndex] = 0x0;
|
||||
@ -80,9 +82,9 @@ void Immediate_Map ( uint32_t vaddr, uint32_t paddr)
|
||||
int PageTableEntryIndex = (vaddr >> 12) & 0x1FFF;
|
||||
|
||||
printf("Map address at PDE 0x%x PTE 0x%x\n", PageDirectoryEntryIndex, PageTableEntryIndex);
|
||||
|
||||
if ((boot_page_directory - 0xC0000000)[PageDirectoryEntryIndex] & 0x1 )
|
||||
{
|
||||
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 {
|
||||
@ -90,37 +92,39 @@ void Immediate_Map ( uint32_t vaddr, uint32_t paddr)
|
||||
// mark the page table as present and allocate a physical block for it
|
||||
|
||||
void* new_page_dir = allocate_block();
|
||||
printf("New page directory address 0x%x\n", new_page_dir);
|
||||
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) ;
|
||||
//page_table = (uint32_t*) ((uint32_t)page_table - 0xC0000000); // remove kernel offset
|
||||
printf("Page table address: 0x%x\n", (uint32_t)page_table);
|
||||
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);
|
||||
}
|
||||
// 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 ("cli; invlpg (%0); sti" :: "r" (vaddr) : "memory" );
|
||||
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);
|
||||
//uint32_t page_aligned_address = ALIGN(vaddr, 4096);
|
||||
|
||||
// allocate a page at virtual address
|
||||
int PageDirectoryEntryIndex = vaddr >> 22;
|
||||
int PageTableEntryIndex = (vaddr >> 12) & 0x1FFF;
|
||||
//int PageDirectoryEntryIndex = vaddr >> 22;
|
||||
//int PageTableEntryIndex = (vaddr >> 12) & 0x1FFF;
|
||||
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "../terminal/kterm.h"
|
||||
#include "../cpu.h"
|
||||
#include "../i386/processor.h"
|
||||
#include "PhysicalMemoryManager.h"
|
||||
|
||||
|
@ -5,7 +5,8 @@
|
||||
#include "memoryinfo.h"
|
||||
#include "../prekernel/multiboot.h"
|
||||
#include "../terminal/kterm.h"
|
||||
#include "../../lib/include/mem.h"
|
||||
#include <CoreLib/Memory.h>
|
||||
|
||||
#include "../bitmap.h"
|
||||
|
||||
#define BLOCK_SIZE 4092
|
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);
|
||||
};
|
||||
|
@ -2,15 +2,16 @@
|
||||
#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
|
||||
*/
|
||||
@ -21,12 +22,6 @@ extern "C" void prekernelSetup ( unsigned long magic, multiboot_info_t* mbi)
|
||||
}
|
||||
|
||||
mbi = PADDR_TO_VADDR(mbi);
|
||||
|
||||
|
||||
// Setup the physical memory manager immmediatly
|
||||
// Doing so saves the complications of doing it later when
|
||||
// paging is enabled
|
||||
|
||||
/*
|
||||
If we got a memory map from our bootloader we
|
||||
should be parsing it to find out the memory regions available.
|
||||
@ -57,6 +52,8 @@ extern "C" void prekernelSetup ( unsigned long magic, multiboot_info_t* mbi)
|
||||
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)
|
||||
@ -82,13 +79,14 @@ extern "C" void prekernelSetup ( unsigned long magic, multiboot_info_t* mbi)
|
||||
}
|
||||
|
||||
// allocate a full block for the other boot info!
|
||||
BootInfoBlock* BIB = (BootInfoBlock*) allocate_block();
|
||||
BIB = (BootInfoBlock*) allocate_block();
|
||||
|
||||
|
||||
/* is boot device valid ? */
|
||||
if (CHECK_FLAG (mbi->flags, 1))
|
||||
{
|
||||
BIB->bootDeviceID = mbi->boot_device;
|
||||
|
||||
} else{
|
||||
BIB->bootDeviceID = 0x11111111;
|
||||
}
|
||||
@ -99,8 +97,6 @@ extern "C" void prekernelSetup ( unsigned long magic, multiboot_info_t* mbi)
|
||||
uint32_t i;
|
||||
|
||||
BIB->GrubModuleCount = mbi->mods_count;
|
||||
|
||||
|
||||
for(i = 0, mod = (multiboot_module_t *) mbi->mods_addr; i < mbi->mods_count; i++ , mod++){
|
||||
|
||||
}
|
||||
@ -135,6 +131,6 @@ extern "C" void prekernelSetup ( unsigned long magic, multiboot_info_t* mbi)
|
||||
|
||||
// NOTE: Do something with it.. (Store it , process it etc...)
|
||||
} else{
|
||||
BIB->EnabledVBE;
|
||||
BIB->EnabledVBE = false;
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "terminal/kterm.h"
|
||||
#include "drivers/io/io.h"
|
||||
#include "io/io.h"
|
||||
#define PORT 0x3f8
|
||||
static int init_serial() {
|
||||
|
@ -1,19 +1,97 @@
|
||||
#include "ataDevice.h"
|
||||
#include "ATAPIO.h"
|
||||
#include "../../io/io.h"
|
||||
|
||||
#define IS_BIT_SET(x, bit) ((x >> bit & 0x1) == 1)
|
||||
|
||||
void ATA_DEVICE::Soft_Reset(uint8_t DEVICE_CHANNEL,DEVICE_DRIVE drive){
|
||||
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) {
|
||||
/*
|
||||
Assume you have a sectorcount byte and a 28 bit LBA value. A sectorcount of 0 means 256 sectors = 128K.
|
||||
|
||||
Notes: - When you send a command byte and the RDY bit of the Status Registers is clear, you may have to wait (technically up to 30 seconds) for the drive to spin up, before DRQ sets. You may also need to ignore ERR and DF the first four times that you read the Status, if you are polling.
|
||||
- for polling PIO drivers: After transferring the last uint16_t of a PIO data block to the data IO port, give the drive a 400ns delay to reset its DRQ bit (and possibly set BSY again, while emptying/filling its buffer to/from the drive).
|
||||
- on the "magic bits" sent to port 0x1f6: Bit 6 (value = 0x40) is the LBA bit. This must be set for either LBA28 or LBA48 transfers. It must be clear for CHS transfers. Bits 7 and 5 are obsolete for current ATA drives, but must be set for backwards compatibility with very old (ATA1) drives.
|
||||
|
||||
An example of a 28 bit LBA PIO mode read on the Primary bus:
|
||||
|
||||
*/
|
||||
|
||||
const int sectorCount = 1;
|
||||
|
||||
// Floating bus check
|
||||
uint8_t floatingBus = inb(DEVICE_CHANNEL | 7);
|
||||
if (floatingBus == 0xFF){
|
||||
printf("Floating bus!!");
|
||||
return ;
|
||||
}
|
||||
|
||||
//printf("Read LBA: 0x%x\n", LBA);
|
||||
// Send 0xE0 for the "master" or 0xF0 for the "slave", ORed with the highest 4 bits of the LBA to port 0x1F6: outb(0x1F6, 0xE0 | (slavebit << 4) | ((LBA >> 24) & 0x0F))
|
||||
outb(DEVICE_CHANNEL | 6 , ( 0xE0 | (LBA >>28) ) );
|
||||
// Send a NULL byte to port 0x1F1, if you like (it is ignored and wastes lots of CPU time): outb(0x1F1, 0x00)
|
||||
outb(DEVICE_CHANNEL | 1, 0x0000 );
|
||||
//Send the sectorcount to port 0x1F2: outb(0x1F2, (unsigned char) count)
|
||||
outb(DEVICE_CHANNEL | 2, sectorCount);
|
||||
//Send the low 8 bits of the LBA to port 0x1F3: outb(0x1F3, (unsigned char) LBA))
|
||||
outb(DEVICE_CHANNEL | 3, LBA);
|
||||
//Send the next 8 bits of the LBA to port 0x1F4: outb(0x1F4, (unsigned char)(LBA >> 8))
|
||||
outb(DEVICE_CHANNEL | 4, (LBA >> 8));
|
||||
//Send the next 8 bits of the LBA to port 0x1F5: outb(0x1F5, (unsigned char)(LBA >> 16))
|
||||
outb(DEVICE_CHANNEL | 5, (LBA >> 16));
|
||||
//Send the "READ SECTORS" command (0x20) to port 0x1F7: outb(0x1F7, 0x20)
|
||||
outb(DEVICE_CHANNEL | 7, 0x20);
|
||||
|
||||
volatile int i,j;
|
||||
for(i=0;i<2000;i++)
|
||||
for(j=0;j<25000;j++)
|
||||
asm("NOP");
|
||||
|
||||
//Wait for an IRQ or poll.
|
||||
uint8_t status = inb(DEVICE_CHANNEL | 7);
|
||||
if( status == 0x00){
|
||||
printf("No drive\n");
|
||||
return;
|
||||
}
|
||||
|
||||
//printf("Status: %x\n", status);
|
||||
// Check if busy!
|
||||
while((status & 0x80) == 0x80){
|
||||
printf("Reading....\r");
|
||||
status = inb(DEVICE_CHANNEL | 7);
|
||||
}
|
||||
|
||||
|
||||
if ((status & 0x01) == 0x01){
|
||||
printf("Error occured during read!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
//Transfer 256 16-bit values, a uint16_t at a time, into your buffer from I/O port 0x1F0.
|
||||
if( status & 0x01){
|
||||
printf("Error!\n");
|
||||
printf("Status: 0x%x\n", status);
|
||||
uint16_t error_register = inb(DEVICE_CHANNEL | 1);
|
||||
printf("Error register 0x%x\n",error_register );
|
||||
return ;
|
||||
}
|
||||
for ( int i = 0; i < 256; i++){
|
||||
uint16_t data;
|
||||
asm volatile ("inw %1, %0" : "=a"(data): "Nd"(DEVICE_CHANNEL));
|
||||
// printf (" %x ", data);
|
||||
|
||||
buffer[i] = data;
|
||||
}
|
||||
|
||||
//Then loop back to waiting for the next IRQ (or poll again -- see next note) for each successive sector.
|
||||
|
||||
}
|
||||
|
||||
void ATAPIO::Write(uint16_t data, DEVICE_DRIVE dev){
|
||||
|
||||
void ATA_DEVICE::Identify(uint16_t DEVICE_CHANNEL,DEVICE_DRIVE drive ){
|
||||
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 !
|
||||
|
||||
/*
|
||||
@ -47,46 +125,45 @@ void ATA_DEVICE::Identify(uint16_t DEVICE_CHANNEL,DEVICE_DRIVE drive ){
|
||||
// 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;
|
||||
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);
|
||||
// set the sectorCount, LBAlo, LBAmid, LBA,hi IO ports to 0
|
||||
outb(DEVICE_CHANNEL | 2, 0);
|
||||
|
||||
outb(DEVICE_CHANNEL | 3, 0);
|
||||
outb(DEVICE_CHANNEL | 3, 0);
|
||||
|
||||
outb(DEVICE_CHANNEL | 4, 0);
|
||||
outb(DEVICE_CHANNEL | 4, 0);
|
||||
|
||||
outb(DEVICE_CHANNEL | 5, 0);
|
||||
outb(DEVICE_CHANNEL | 5, 0);
|
||||
|
||||
// send the identify command ;
|
||||
//printf("command sent!\n");
|
||||
outb(DEVICE_CHANNEL | 7 , 0xEC);
|
||||
// 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;
|
||||
}
|
||||
// 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);
|
||||
//printf("Waiting until ready...\n");
|
||||
while(((status2 & 0x80 == 0x80)
|
||||
&& (status2 & 0x01) != 0x01)
|
||||
) status2 = inb(DEVICE_CHANNEL | 7);
|
||||
|
||||
if( status2 & 0x01){
|
||||
printf("Error!\n");
|
||||
return ;
|
||||
}
|
||||
if( status2 & 0x01){
|
||||
printf("Error!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t deviceIdentify [256] = {0};
|
||||
|
||||
@ -104,91 +181,19 @@ void ATA_DEVICE::Identify(uint16_t DEVICE_CHANNEL,DEVICE_DRIVE drive ){
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
Notes: - When you send a command byte and the RDY bit of the Status Registers is clear, you may have to wait (technically up to 30 seconds) for the drive to spin up, before DRQ sets. You may also need to ignore ERR and DF the first four times that you read the Status, if you are polling.
|
||||
- for polling PIO drivers: After transferring the last uint16_t of a PIO data block to the data IO port, give the drive a 400ns delay to reset its DRQ bit (and possibly set BSY again, while emptying/filling its buffer to/from the drive).
|
||||
- on the "magic bits" sent to port 0x1f6: Bit 6 (value = 0x40) is the LBA bit. This must be set for either LBA28 or LBA48 transfers. It must be clear for CHS transfers. Bits 7 and 5 are obsolete for current ATA drives, but must be set for backwards compatibility with very old (ATA1) drives.
|
||||
|
||||
An example of a 28 bit LBA PIO mode read on the Primary bus:
|
||||
|
||||
*/
|
||||
|
||||
const int sectorCount = 1;
|
||||
|
||||
// Floating bus check
|
||||
uint8_t floatingBus = inb(DEVICE_CHANNEL | 7);
|
||||
if (floatingBus == 0xFF){
|
||||
printf("Floating bus!!");
|
||||
return ;
|
||||
}
|
||||
|
||||
printf("Read LBA: 0x%x\n", LBA);
|
||||
// Send 0xE0 for the "master" or 0xF0 for the "slave", ORed with the highest 4 bits of the LBA to port 0x1F6: outb(0x1F6, 0xE0 | (slavebit << 4) | ((LBA >> 24) & 0x0F))
|
||||
outb(DEVICE_CHANNEL | 6 , ( 0xE0 | (LBA >>28) ) );
|
||||
// Send a NULL byte to port 0x1F1, if you like (it is ignored and wastes lots of CPU time): outb(0x1F1, 0x00)
|
||||
outb(DEVICE_CHANNEL | 1, 0x0000 );
|
||||
//Send the sectorcount to port 0x1F2: outb(0x1F2, (unsigned char) count)
|
||||
outb(DEVICE_CHANNEL | 2, sectorCount);
|
||||
//Send the low 8 bits of the LBA to port 0x1F3: outb(0x1F3, (unsigned char) LBA))
|
||||
outb(DEVICE_CHANNEL | 3, LBA);
|
||||
//Send the next 8 bits of the LBA to port 0x1F4: outb(0x1F4, (unsigned char)(LBA >> 8))
|
||||
outb(DEVICE_CHANNEL | 4, (LBA >> 8));
|
||||
//Send the next 8 bits of the LBA to port 0x1F5: outb(0x1F5, (unsigned char)(LBA >> 16))
|
||||
outb(DEVICE_CHANNEL | 5, (LBA >> 16));
|
||||
//Send the "READ SECTORS" command (0x20) to port 0x1F7: outb(0x1F7, 0x20)
|
||||
outb(DEVICE_CHANNEL | 7, 0x20);
|
||||
|
||||
volatile int i,j;
|
||||
for(i=0;i<2000;i++)
|
||||
for(j=0;j<25000;j++)
|
||||
asm("NOP");
|
||||
|
||||
//Wait for an IRQ or poll.
|
||||
uint8_t status = inb(DEVICE_CHANNEL | 7);
|
||||
if( status == 0x00){
|
||||
printf("No drive\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Status: %x\n", status);
|
||||
// Check if busy!
|
||||
while((status & 0x80) == 0x80){
|
||||
printf("Reading....\r");
|
||||
status = inb(DEVICE_CHANNEL | 7);
|
||||
}
|
||||
|
||||
|
||||
if ((status & 0x01) == 0x01){
|
||||
printf("Error occured during read!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
//Transfer 256 16-bit values, a uint16_t at a time, into your buffer from I/O port 0x1F0.
|
||||
if( status & 0x01){
|
||||
printf("Error!\n");
|
||||
printf("Status: 0x%x\n", status);
|
||||
uint16_t error_register = inb(DEVICE_CHANNEL | 1);
|
||||
printf("Error register 0x%x\n",error_register );
|
||||
return ;
|
||||
}
|
||||
for ( int i = 0; i < 256; i++){
|
||||
uint16_t data;
|
||||
asm volatile ("inw %1, %0" : "=a"(data): "Nd"(DEVICE_CHANNEL));
|
||||
// printf (" %x ", data);
|
||||
|
||||
buffer[i] = data;
|
||||
}
|
||||
|
||||
//Then loop back to waiting for the next IRQ (or poll again -- see next note) for each successive sector.
|
||||
|
||||
}
|
||||
|
||||
void ATA_DEVICE::Write(uint16_t DEVICE_CHANNEL, DEVICE_DRIVE drive) {
|
||||
printf("Not implemented\n");
|
||||
}
|
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,6 +1,6 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include "../io/io.h"
|
||||
#include "../../io/io.h"
|
||||
#include "../ide/ideCommands.h"
|
||||
#include "../ide/sampleIDE.definitions.h"
|
||||
|
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,10 +1,10 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include "../pci/pciDevice.h"
|
||||
#include "../pci/pci.h"
|
||||
#include <stdint-gcc.h>
|
||||
#include "../../terminal/kterm.h"
|
||||
#include "ideCommands.h"
|
||||
#include "sampleIDE.h"
|
||||
#include "../../pci/pciDevice.h"
|
||||
#include "../../pci/pci.h"
|
||||
|
||||
#define IS_BIT_SET(x, bit) ((x >> bit & 0x1) == 1)
|
||||
|
||||
@ -56,7 +56,7 @@ inline void TestIDEController(){
|
||||
int device =1 , function = 1;
|
||||
PCIBusAddress IDEControllerPCIAddress = PCIBusAddress{bus,device, function};
|
||||
|
||||
uint8_t ProgIF = GetProgIF(IDEControllerPCIAddress);
|
||||
uint8_t ProgIF = PCI::GetProgIF(IDEControllerPCIAddress);
|
||||
printf( "ProgIF: 0x%x\n" ,ProgIF);
|
||||
|
||||
//CheckProgIF(ProgIF);
|
||||
@ -66,15 +66,15 @@ inline void TestIDEController(){
|
||||
|
||||
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!
|
||||
printf( "BAR 0: 0x%x\n", BAR0);
|
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <stdint-gcc.h>
|
||||
#include "../../terminal/kterm.h"
|
||||
#include "sampleIDE.definitions.h"
|
||||
#include "ideCommands.h"
|
||||
@ -240,3 +240,19 @@ inline void Detect_IO_Ports(uint32_t BAR0, uint32_t BAR1,uint32_t BAR2, uint32_t
|
||||
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;
|
||||
}
|
18
kernel/storage/partitions/partitionManager.cpp
Normal file
18
kernel/storage/partitions/partitionManager.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
//
|
||||
// Created by nigel on 23/02/23.
|
||||
//
|
||||
|
||||
#include "partitionManager.h"
|
||||
|
||||
bool partitionManager::Validate( )
|
||||
{
|
||||
|
||||
//auto* bootParams = getBPB(this, true);
|
||||
|
||||
//if(bootParams->OEM_id) {
|
||||
// return true;
|
||||
//}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
11
kernel/storage/partitions/partitionManager.h
Normal file
11
kernel/storage/partitions/partitionManager.h
Normal file
@ -0,0 +1,11 @@
|
||||
//
|
||||
// Created by nigel on 23/02/23.
|
||||
//
|
||||
#pragma once
|
||||
|
||||
class partitionManager {
|
||||
public:
|
||||
static bool Validate();
|
||||
|
||||
};
|
||||
|
43
kernel/storage/partitiontables/mbr/MasterBootRecord.h
Normal file
43
kernel/storage/partitiontables/mbr/MasterBootRecord.h
Normal file
@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
#include <stdint-gcc.h>
|
||||
#include "PartitionTableEntry.h"
|
||||
#include "../../../memory/KernelHeap.h"
|
||||
#include "../../ata pio/ATAPIO.h"
|
||||
|
||||
struct MBR {
|
||||
uint8_t code [440];
|
||||
uint32_t uniqueID;
|
||||
uint16_t Reserved;
|
||||
struct PartitionTableEntry TableEntries[4];
|
||||
uint16_t ValidBootsector;
|
||||
}__attribute__((packed));
|
||||
|
||||
|
||||
inline MBR* GetPartitions(bool DEBUG = false){
|
||||
const int C = 0;
|
||||
const int H = 0;
|
||||
const int HPC = 16;
|
||||
const int SPT = 63;
|
||||
|
||||
int S =1;
|
||||
uint32_t LBA = (C*HPC+H) * SPT + (S-1);
|
||||
|
||||
uint16_t* mbr =(uint16_t*) malloc(sizeof (MBR));
|
||||
|
||||
ATAPIO::Read(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER, LBA, mbr );
|
||||
auto bootRecord = (MBR*)(mbr);
|
||||
|
||||
printf("MBR (In Memory) Address 0x%x, Size = %d\n", bootRecord, sizeof (MBR));
|
||||
if(DEBUG){
|
||||
printf("BootSector: 0x%x\n", bootRecord->ValidBootsector );
|
||||
for( int i = 0 ; i < 4 ; i ++){
|
||||
PartitionTableEntry PT = bootRecord->TableEntries[i];
|
||||
|
||||
printf("Partition %d [ %d sectors, PartitionType: 0x%x, 0x%x, \nLBA Start: 0x%x ]\n" ,
|
||||
i, PT.Number_sectors_inPartition, PT.PartitionType, bootRecord->uniqueID, PT.LBA_partition_start );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return bootRecord;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user