17 Commits

Author SHA1 Message Date
2522492835 Couple of small changes
* Commented out the map page function call to handle page not present
* Mapped the ACPI_RECLAIMABLE_MEMORY
* Set VBE to false when VBE is not initialized by the bootloader
2023-10-28 20:42:28 +02:00
e82392e9d9 FAT Filesystem implementation additions 2023-10-27 18:07:11 +02:00
64c87a2a58 Fixing an issue in the CoreLib 2023-10-27 18:04:09 +02:00
04470edcc6 Adding gdb init and adjusting some of the build automation steps 2023-10-27 18:03:45 +02:00
2970806705 ACPI reading memory when mapped to higher half 2023-09-11 23:23:38 +02:00
e8df6ec628 Updating Build scripts 2023-09-11 23:21:43 +02:00
5781f730d9 Implemented the basis for syscalls
A software interrupt with vector 0x50 will cause a syscall to start executing.
The EAX register will hold the syscall_num.
Other registers and the stack can be used to hold further arguments.
2023-02-27 00:34:30 +01:00
2d0bb16fad Fixed up ACPI Version 1.0 checksum validation code 2023-02-27 00:32:16 +01:00
e6901f0526 We can now open and read files on the harddisk through a messy virtual filesystem
The uri has to contain 8.3 filenames for now as I have not yet figured out
how to convert from that to regular filenaming for the name comparison.

reading files is still limited to 1 sector
2023-02-26 13:44:41 +01:00
61f1852420 Added file reading without cluster chain following 2023-02-25 21:03:10 +01:00
32b0d990df Added ctype std lib functions 2023-02-25 20:41:21 +01:00
745656eb2d Fixup C++ compiler path in makefile of CoreLib
memcpy implementation added
2023-02-25 20:04:34 +01:00
644ff5b1f5 Adding subdir functionality
Added FAT16 driver ability to list subdir entries
Removed structure of FAT32 (we won't be using it anytime soon)
2023-02-24 21:31:20 +01:00
a77621faf5 Shellscript improvement plus FAT driver implementations
- Improved the run bash script to exit when an error occurs in one of the sub tasks
- Wrote basic FAT16 functions that should give enough information to properly implement the rest of the driver
- FAT structure namings are now in accordence with the microsoft spec of March 2005
2023-02-23 23:54:02 +01:00
50bf952a49 Basic idea's are created for the storage solution
- Added boot device info parsing to the kernel
- Added a pointer in the kernel to our pre-kernel BootInfo structure
- Created a layout for the FAT driver
- Created a layout for the virtual filesystem
- Separated IDE driver from the basic atapio driver.
	This will ensure we are not using one or the other
- The create_harddrive shell script will now actually build a harddrive image of
	the kernel
- The virtual filesystem initializes and creates a filesystem structure
	for every FAT16 partition in the master boot record
2023-02-21 21:43:14 +01:00
ef2bba5c1c Started fleshing out the storage API 2023-02-21 14:36:20 +01:00
81f7351fe6 Created a few shell scripts to update and create an build of the Kernel/Operating System.
A python script can be run to run the scripts in the correct order and immediatly try the build.
2023-02-20 01:03:46 +01:00
78 changed files with 1923 additions and 1067 deletions

7
.gdbinit Normal file
View File

@ -0,0 +1,7 @@
target remote localhost:1234
file root/boot/myos.bin
symbol-file kernel.sym
break prekernel/prekernel.cpp:18
continue

2
.gitignore vendored
View File

@ -11,3 +11,5 @@ root/
*.a
/CoreLib/warnings.log
/kernel/warnings.log

12
CoreLib/List.h Normal file
View File

@ -0,0 +1,12 @@
//
// Created by nigel on 25/02/23.
//
#pragma once
class List {
public:
List* next;
void* data;
};

View File

@ -1,19 +1,23 @@
CPP = ${HOME}/opt/cross/bin/i686-elf-g++
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)/memory.o $(OBJ_FOLDER)/path.o $(OBJ_FOLDER)/stack.o $(OBJ_FOLDER)/string.o $(OBJ_FOLDER)/stringview.o
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)

View File

@ -16,22 +16,31 @@ void* memset (void* ptr, int value, size_t num)
int memcmp( const void* ptr1, const void* ptr2, size_t num)
{
const unsigned char * cs = (const unsigned char*) ptr1;
const unsigned char * ct = (const unsigned char*) ptr2;
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 -1;
} else if( *cs > *ct){
return 1;
}
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]){
@ -56,3 +65,43 @@ int strncmp ( const char* str1, const char* str2, size_t num ){
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;
}

View File

@ -7,6 +7,10 @@ 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);

141
CoreLib/ctype.cpp Normal file
View 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
View 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);

View File

@ -27,7 +27,7 @@ Enumerating the PCI bus
Correctly identified our ATAPI device 🎉
![Reading Files from FAT-16](screenshots/ReadingFilesFromFAT16.png) \
Reading a file from a FAT-16 Formatted drive
Reading a FILE from a FAT-16 Formatted drive
________________________

View File

@ -1,7 +1,6 @@
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++
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
@ -34,25 +33,30 @@ OFILES = $(OBJ_DIR)/boot.o \
$(OBJ_DIR)/atapiDevice.o \
$(OBJ_DIR)/ataDevice.o \
$(OBJ_DIR)/rsdp.o \
$(OBJ_DIR)/acpi.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: build
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:
$(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 drivers/io/io.cpp -o $(OBJ_DIR)/io.o $(CFLAGS) -fno-exceptions -fno-rtti
$(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
@ -67,28 +71,28 @@ $(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 drivers/pci/pci.cpp -o $(OBJ_DIR)/pci.o $(CFLAGS) -fno-exceptions -fno-rtti
$(CPP) -c pci/pci.cpp -o $(OBJ_DIR)/pci.o $(CFLAGS) -fno-exceptions -fno-rtti
$(OBJ_DIR)/pcidevice.o:
$(CPP) -c drivers/pci/pciDevice.cpp -o $(OBJ_DIR)/pcidevice.o $(CFLAGS) -fno-exceptions -fno-rtti
$(CPP) -c pci/pciDevice.cpp -o $(OBJ_DIR)/pcidevice.o $(CFLAGS) -fno-exceptions -fno-rtti
$(OBJ_DIR)/atapiDevice.o:
$(CPP) -c drivers/atapi/atapiDevice.cpp -o $(OBJ_DIR)/atapiDevice.o $(CFLAGS) -fno-exceptions -fno-rtti
$(CPP) -c storage/atapi/atapiDevice.cpp -o $(OBJ_DIR)/atapiDevice.o $(CFLAGS) -fno-exceptions -fno-rtti
$(OBJ_DIR)/ataDevice.o:
$(CPP) -c drivers/ata/ataDevice.cpp -o $(OBJ_DIR)/ataDevice.o $(CFLAGS) -fno-exceptions -fno-rtti
$(CPP) -c "storage/ata pio/ATAPIO.cpp" -o $(OBJ_DIR)/ataDevice.o $(CFLAGS) -fno-exceptions -fno-rtti
$(OBJ_DIR)/rsdp.o:
$(CPP) -c drivers/acpi/rsdp.cpp -o $(OBJ_DIR)/rsdp.o $(CFLAGS) -fno-exceptions -fno-rtti
$(CPP) -c acpi/rsdp.cpp -o $(OBJ_DIR)/rsdp.o $(CFLAGS) -fno-exceptions -fno-rtti
$(OBJ_DIR)/acpi.o:
$(CPP) -c drivers/acpi/acpi.cpp -o $(OBJ_DIR)/acpi.o $(CFLAGS) -fno-exceptions -fno-rtti
$(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 vfs/VFS.cpp -o $(OBJ_DIR)/VFS.o $(CFLAGS) -fno-exceptions -fno-rtti
$(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
@ -114,6 +118,9 @@ $(OBJ_DIR)/prekernel.o:
$(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

76
kernel/acpi/acpi.cpp Normal file
View 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!");*/
}

View File

@ -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;
};

44
kernel/acpi/rsdp.cpp Normal file
View File

@ -0,0 +1,44 @@
#include "rsdp.h"
#include "../memory/VirtualMemoryManager.h"
#include "../../CoreLib/Memory.h"
void printRSD(RSDPDescriptor* rsd){
printf("Signature: ");
for(int i = 0; i < 8; i++){
kterm_put(rsd->signature[i]);
}
kterm_put('\n');
printf("OEMID: ");
for(int i =0; i < 6 ; i++){
kterm_put (rsd->OEMID[i]);
}
kterm_put('\n');
printf("Revision: %d\n", rsd->Revision);
}
RSDPDescriptor* FindRSD(){
char* memory_byte = (char*) 0x000f2e14;
const void* string = "RSD PTR ";
for( ; (uint32_t) memory_byte < 0x0100000; memory_byte+=10){
if( memcmp(memory_byte , string , 8 ) == 0 ) {
printf("RSD PTR found at 0x%x !\n", memory_byte);
return (RSDPDescriptor*) memory_byte;
break;
}
}
memory_byte = (char*) 0x000E0000;
for ( ;(uint32_t) memory_byte < 0x000FFFFF; memory_byte += 1)
{
if( memcmp(memory_byte , string , 8 ) == 0 ) {
printf("RSD PTR found at 0x%x !\n", memory_byte);
return (RSDPDescriptor*) memory_byte;
break;
}
}
}

View File

@ -1,9 +1,28 @@
#pragma once
#include <stdint.h>
#include "./../../terminal/kterm.h"
#include "../terminal/kterm.h"
#include <CoreLib/Memory.h>
#include <stdint-gcc.h>
struct RSDPTR {
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];
@ -11,25 +30,16 @@ struct RSDPTR {
uint32_t RsdtAddress;
}__attribute__((packed));
struct ACPISDTHeader{
char Signature[4];
uint32_t Length;
uint8_t CheckSum;
char OEMID[6];
char OEMTableID[8];
uint32_t OEMRevision;
uint32_t CreatorID;
uint32_t CreatorRevision;
struct RSCPDescriptor20{
RSDPDescriptor base;
uint32_t Length;
uint64_t XsdtAddress;
uint8_t ExtendedChecksum;
uint8_t reserved[3];
}__attribute__((packed));
RSDPDescriptor* FindRSD();
struct RSDT{
struct ACPISDTHeader header;
uint32_t PointerToSDT[]; // Length of array : (header.Length - sizeof(header))/ 4
}__attribute__((packed));
void printRSD(RSDPDescriptor* rsd);
RSDPTR* FindRSD();
void printRSD(RSDPTR* rsd);
RSDT* getRSDT(RSDPTR* rsd);
RSDT* getRSDT(RSDPDescriptor* rsd);

View File

@ -0,0 +1,11 @@
//
// Created by nigel on 21/02/23.
//
#pragma once
class BlockDevice {
virtual char* Read()=0;
virtual void Write() =0;
};

View File

@ -0,0 +1,11 @@
//
// Created by nigel on 21/02/23.
//
#pragma once
class CharacterDevice {
virtual char Read()=0;
virtual void Write()=0;
};

View File

@ -1,15 +0,0 @@
#include "acpi.h"
RSDPTR* ACPI::rsd_ptr;
RSDT* ACPI::rsd_table;
void ACPI::initialize(){
// Find the Root System Description Pointer
ACPI::rsd_ptr = FindRSD();
printRSD(rsd_ptr);
// Get the Root System Description Table
ACPI::rsd_table = getRSDT((RSDPTR*)((uint32_t)rsd_ptr + 0xC00000000));
}

View File

@ -1,45 +0,0 @@
#include "rsdp.h"
void printRSD(RSDPTR* rsd){
printf("Signature: ");
for(int i = 0; i < 8; i++){
kterm_put(rsd->signature[i]);
}
kterm_put('\n');
printf("OEMID: ");
for(int i =0; i < 6 ; i++){
kterm_put (rsd->OEMID[i]);
}
kterm_put('\n');
printf("Revision: %d\n", rsd->Revision);
printf("RSDT Address: 0x%x\n", rsd->RsdtAddress );
}
RSDPTR* FindRSD(){
char* memory_byte = (char*) 0xC00f2e14;
const void* string = "RSD PTR ";
for( ; (uint32_t) memory_byte < 0xC0100000; memory_byte+=10){
if( memcmp(memory_byte , string , 8 ) == 0 ) {
printf("RSD PTR found at 0x%x !\n", memory_byte);
break;
}
}
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]);
}
kterm_put('\n');
return rsdt;
}

View File

@ -1,27 +0,0 @@
#pragma once
#include <stdint.h>
#include "../io/io.h"
#include "../ide/ideCommands.h"
#include "../ide/sampleIDE.definitions.h"
#include "../../terminal/kterm.h"
/*
* This first driver wil make use of IO ports.
* Doing so means reading or writing from disk is going
* to be very cpu intensive.
*/
enum DEVICE_DRIVE{
MASTER = 0xA0,
SLAVE = 0xB0
};
namespace ATA_DEVICE{
void Identify(uint16_t, DEVICE_DRIVE);
void Read (uint16_t, DEVICE_DRIVE, uint32_t, uint16_t*);
void Write(uint16_t, DEVICE_DRIVE);
void Soft_Reset(uint8_t ,DEVICE_DRIVE );
};

View File

@ -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 */

View File

@ -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

View File

@ -1,21 +0,0 @@
#pragma once
#include <stdint.h>
#include "./ExtendBootRecord.h"
struct BiosParameterBlock {
uint8_t BootLoaderCodeSection [3];
uint8_t OEM_id [8];
uint16_t BytesPerSector ; // I suspect would be 512
uint8_t SectorsPerCluster ;
uint16_t ReservedSectors;
uint8_t NumberOfFileAllocationTables; // Probably equals 2
uint16_t NumberOfDirectoryEntries; // Root directory must contain entire sectors
uint16_t TotalSectorsInLogicalVolume ; // 0 means >65535 sectors in volume , actual count can be found in LargeSectorCount
uint8_t MediaDescriptor ; // Indication the media descriptor type
uint16_t NumberOfSectorsPerFAT;// only in FAT12 / FAT 16
uint16_t NumberOfSectorsPerTrack;
uint16_t NumberOfHeadsOnMedia;
uint32_t NumberOfHiddenSectors;
uint32_t LargeSectorCount;
ExtendedBootRecord_FAT16 ebpb;
}__attribute__((packed));

View File

@ -1,19 +0,0 @@
#pragma once
#include <stdint.h>
struct DirectoryEntry {
uint8_t filename [8];
uint8_t Extension [3];
uint8_t attribute;
uint8_t Reserved;
uint8_t creation;
uint16_t CreationTime;
uint16_t CreationDate;
uint16_t LastAccessDate;
uint16_t ReservedFAT32;
uint16_t LastWriteTime;
uint16_t LastWriteDate;
uint16_t StartingCluster;
uint32_t FilesizeInBytes;
}__attribute__((packed));

View File

@ -1,32 +0,0 @@
#pragma once
#include <stdint.h>
struct ExtendedBootRecord_FAT16{
uint8_t DriveNumber;
uint8_t Reserved;
uint8_t Signature;
const uint32_t VOLUME_ID_SERIAL_NUMBER;
uint8_t volume_label [11];
uint8_t Identifier_string [8];
uint8_t bootCode [448];
uint16_t partitionSignature;
}__attribute__((packed));
struct ExtendedBootRecord_FAT32{
uint32_t SectorsPerFAT;
uint16_t Flags;
const uint16_t FAT_VERSION_NUMBER;
uint32_t rootDirectory_clusterNumber;// Often set to 2;
uint16_t FSInfo_SectorNumber;
uint16_t backup_bpb_sectorNumber;
uint8_t Reserved [12];
uint8_t DriveNumber;
uint8_t Reserved2;
uint8_t Signature; // must be 0x28 or 0x29
uint32_t VOLUME_ID_SERIAL;
uint8_t volume_label[11];
uint8_t SystemIdentifierString [8]; // ALWAYS "FAT32 " but spec says do not trust
uint8_t BootCode [420]; // NICE
uint16_t PartitionSignature; // 0xAA55
}__attribute__((packed));

View File

@ -3,6 +3,9 @@
#include "../drivers/ps-2/keyboard.h"
#include "../i386/processor.h"
#include "../memory/VirtualMemoryManager.h"
#include "../syscalls.h"
IDT_entry idt_table[256];
IDT_ptr idt_ptr;
@ -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:
@ -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++;
@ -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);

View File

@ -70,6 +70,7 @@ extern "C" {
extern void irs29 ();
extern void irs30 ();
extern void irs31 ();
extern void irs50();

View File

@ -1,115 +1,32 @@
.globl irq0
irq0:
cli
push $0
push $0
jmp irq_common
.globl irq1
irq1:
cli
push $0
push $1
jmp irq_common
.macro IRQ NAME, VECTOR
.globl irq\NAME
irq\NAME:
cli
push $0
push \VECTOR
jmp irq_common
.endm
.globl irq2
irq2:
cli
push $0
push $2
jmp irq_common
.globl irq3
irq3:
cli
push $0
push $3
jmp irq_common
.globl irq4
irq4:
cli
push $0
push $4
jmp irq_common
.globl irq5
irq5:
cli
push $0
push $5
jmp irq_common
.globl irq6
irq6:
cli
push $0
push $6
jmp irq_common
.globl irq7
irq7:
cli
push $0
push $7
jmp irq_common
.globl irq8
irq8:
cli
push $0
push $8
jmp irq_common
.globl irq9
irq9:
cli
push $0
push $9
jmp irq_common
.globl irq10
irq10:
cli
push $0
push $10
jmp irq_common
.globl irq11
irq11:
cli
push $0
push $11
jmp irq_common
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
.globl irq12
irq12:
cli
push $0
push $12
jmp irq_common
.globl irq13
irq13:
cli
push $0
push $13
jmp irq_common
.globl irq14
irq14:
cli
push $0
push $14
jmp irq_common
.globl irq15
irq15:
cli
push $0
push $15
jmp irq_common
irq_common:
pusha

View File

@ -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

View File

@ -7,53 +7,76 @@
#include "memory/TaskStateSegment.h"
#include "supervisorterminal/superVisorTerminal.h"
#include "drivers/vga/VBE.h"
#include "drivers/pci/pci.h"
#include "pci/pci.h"
#include "drivers/pit/pit.h"
#include "drivers/acpi/acpi.h"
#include "i386/processor.h"
#include "terminal/kterm.h"
#include "interrupts/idt.h"
#include "serial.h"
#include "vfs/VFS.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();
pit_initialise();
// ACPI::initialize(); // FIXME: improper reading of bios memory
PCI::Scan();
print_serial("Heap initialized...\n");
//pit_initialise();
//ACPI::initialize();
//PCI::Scan();
processor::initialize();
processor::enable_protectedMode();
initBootDrive();
VirtualFileSystem::initialize();
FileSystem::initialize();
// Testing my path resolution functions
Path test = Path("/boot/myos.bin");
FileSystem::ResolvePath(test);
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
}

View File

@ -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 */
}

View File

@ -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;
}

View File

@ -1,11 +0,0 @@
#pragma once
#include <stdint.h>
#include "PartitionTableEntry.h"
struct MBR {
uint8_t code [440];
uint32_t uniqueID;
uint16_t Reserved;
PartitionTableEntry TableEntries[4];
uint16_t ValidBootsector;
}__attribute__((packed));

View File

@ -1,7 +1,7 @@
#pragma once
#include <stdint.h>
#include "../io/io.h"
#include "../../terminal/kterm.h"
#include "../terminal/kterm.h"
#include "pciDevice.h"
// Configuration Space Access Mechanism #1

View File

@ -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;
}
}

View File

@ -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() {

View File

@ -1,112 +1,9 @@
#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 ATA_DEVICE::Identify(uint16_t DEVICE_CHANNEL,DEVICE_DRIVE drive ){
// lets ignore which port we actually want to check for now !
/*
THE STEPS INVOLVED
1. Select the target drive by sending master (0x0A) or slave (0x0B) to the
drive select IO port
2. Set the Sectorcount, LBAlo, LBAmid and LBAhi IO ports to 0
3. Send the identify command (0xEC) to the command IO port
4. Read the status port
4.2 If the value is 0x0 the drive does not exist
4.3 If it has any other value continue
5. poll the status port until bit 7 is clear.
6. Check if the LBAmid and LBAhi ports are non-zero
6.2. If non-zero stop polling this is not an ATA device
6.3 If zero continue
7. poll status port until bit 3 is set or bit 0 is set
8. if err is clear, read the data from the data port
*/
//printf("channel selected: 0x%x", DEVICE_CHANNEL);
// Assuming Master here
// Select the target drive
outb(DEVICE_CHANNEL | 6, drive); // on the primary bus select the master drive
outb(DEVICE_CHANNEL | 6 , 0x0); // write 0 to the controlport for some reason
outb(DEVICE_CHANNEL | 6, drive);
uint8_t status = inb(DEVICE_CHANNEL | 7 );
if(status == 0x00){
printf("No drive\n");
return;
}
// send the identify command;
outb(DEVICE_CHANNEL | 7, 0xEC);
// set the sectorCount, LBAlo, LBAmid, LBA,hi IO ports to 0
outb(DEVICE_CHANNEL | 2, 0);
outb(DEVICE_CHANNEL | 3, 0);
outb(DEVICE_CHANNEL | 4, 0);
outb(DEVICE_CHANNEL | 5, 0);
// send the identify command ;
//printf("command sent!\n");
outb(DEVICE_CHANNEL | 7 , 0xEC);
// read the status port
uint8_t status2 = inb(DEVICE_CHANNEL | 7);
if( status2 == 0x00){
printf("No drive\n");
return;
}
//printf("Waiting until ready...\n");
while(((status2 & 0x80 == 0x80)
&& (status2 & 0x01) != 0x01)
) status2 = inb(DEVICE_CHANNEL | 7);
if( status2 & 0x01){
printf("Error!\n");
return ;
}
uint16_t deviceIdentify [256] = {0};
for ( int i = 0; i < 256; i++){
uint16_t data;
asm volatile ("inw %1, %0" : "=a"(data): "Nd"(DEVICE_CHANNEL));
deviceIdentify[i] = data;
}
printf("Model-label (ASCII hex): ");
for(int i = 27; i < 47; i++){
kterm_put((char)(deviceIdentify[i] >> 8));
kterm_put((char)(deviceIdentify[i] & 0x00FF));
}
kterm_put('\n');
}
void ATA_DEVICE::Read(uint16_t DEVICE_CHANNEL, DEVICE_DRIVE drive, uint32_t LBA, uint16_t* buffer) {
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.
@ -188,6 +85,115 @@ void ATA_DEVICE::Read(uint16_t DEVICE_CHANNEL, DEVICE_DRIVE drive, uint32_t LBA
}
void ATA_DEVICE::Write(uint16_t DEVICE_CHANNEL, DEVICE_DRIVE drive) {
void ATAPIO::Write(uint16_t data, DEVICE_DRIVE dev){
printf("Not implemented\n");
}
bool ATAPIO::Identify(ATAPIO_PORT DEVICE_CHANNEL, DEVICE_DRIVE drive ){
// lets ignore which port we actually want to check for now !
/*
THE STEPS INVOLVED
1. Select the target drive by sending master (0x0A) or slave (0x0B) to the
drive select IO port
2. Set the Sectorcount, LBAlo, LBAmid and LBAhi IO ports to 0
3. Send the identify command (0xEC) to the command IO port
4. Read the status port
4.2 If the value is 0x0 the drive does not exist
4.3 If it has any other value continue
5. poll the status port until bit 7 is clear.
6. Check if the LBAmid and LBAhi ports are non-zero
6.2. If non-zero stop polling this is not an ATA device
6.3 If zero continue
7. poll status port until bit 3 is set or bit 0 is set
8. if err is clear, read the data from the data port
*/
//printf("channel selected: 0x%x", DEVICE_CHANNEL);
// Assuming Master here
// Select the target drive
outb(DEVICE_CHANNEL | 6, drive); // on the primary bus select the master drive
outb(DEVICE_CHANNEL | 6 , 0x0); // write 0 to the controlport for some reason
outb(DEVICE_CHANNEL | 6, drive);
uint8_t status = inb(DEVICE_CHANNEL | 7 );
if(status == 0x00){
printf("No drive\n");
return false;
}
// send the identify command;
outb(DEVICE_CHANNEL | 7, 0xEC);
// set the sectorCount, LBAlo, LBAmid, LBA,hi IO ports to 0
outb(DEVICE_CHANNEL | 2, 0);
outb(DEVICE_CHANNEL | 3, 0);
outb(DEVICE_CHANNEL | 4, 0);
outb(DEVICE_CHANNEL | 5, 0);
// send the identify command ;
//printf("command sent!\n");
outb(DEVICE_CHANNEL | 7 , 0xEC);
// read the status port
uint8_t status2 = inb(DEVICE_CHANNEL | 7);
if( status2 == 0x00){
printf("No drive\n");
return false;
}
//printf("Waiting until ready...\n");
while(((status2 & 0x80 == 0x80)
&& (status2 & 0x01) != 0x01)
) status2 = inb(DEVICE_CHANNEL | 7);
if( status2 & 0x01){
printf("Error!\n");
return false;
}
uint16_t deviceIdentify [256] = {0};
for ( int i = 0; i < 256; i++){
uint16_t data;
asm volatile ("inw %1, %0" : "=a"(data): "Nd"(DEVICE_CHANNEL));
deviceIdentify[i] = data;
}
printf("Model-label (ASCII hex): ");
for(int i = 27; i < 47; i++){
kterm_put((char)(deviceIdentify[i] >> 8));
kterm_put((char)(deviceIdentify[i] & 0x00FF));
}
kterm_put('\n');
return true;
}
void ATAPIO::Soft_Reset(ATAPIO_PORT DEVICE_CHANNEL, DEVICE_DRIVE drive){
printf("Soft reseting drive...\n");
outb(DEVICE_CHANNEL + 7 , 0x4);
// wait a bit..
for(int i = 0 ; i < 1000000; i++){
asm volatile("NOP");
}
outb(DEVICE_CHANNEL + 7 , 0x0);
}

View 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 );
};

View File

@ -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"

View 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);
}
}
}

View 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
};
};

View 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);
}
};

View File

@ -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)

View File

@ -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;
}

View 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;
}

View File

@ -0,0 +1,11 @@
//
// Created by nigel on 23/02/23.
//
#pragma once
class partitionManager {
public:
static bool Validate();
};

View 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;
}

201
kernel/storage/vfs/vfs.cpp Normal file
View File

@ -0,0 +1,201 @@
#include "vfs.h"
#include <stdint-gcc.h>
#include "../../memory/KernelHeap.h"
#include "../ata pio/ATAPIO.h"
#include "../partitiontables/mbr/MasterBootRecord.h"
#include "../filesystems/FAT/FAT.h"
#include "vfs_types.h"
#include "../../../CoreLib/Memory.h"
#include <CoreLib/Memory.h>
vfsmount* VirtualFileSystem::rootfs;
int VirtualFileSystem::mount_number = 0;
int VirtualFileSystem::superblock_number =0;
int VirtualFileSystem::filesystem_number =0;
filesystem* VirtualFileSystem::filesystems[4];
FS_SUPER* VirtualFileSystem::superblocks[8];
vfsmount* VirtualFileSystem::mounts[12];
void VirtualFileSystem::Mount(filesystem* fs, const char* name)
{
vfsmount* mnt_point = (vfsmount*) malloc(sizeof(vfsmount));
FS_SUPER* sb = fs->mount(fs, name, mnt_point);
if( sb == nullptr){
printf("mount failed!\n");
return;
}
mounts[mount_number++] = mnt_point;
superblocks[superblock_number++] = sb;
mnt_point->mnt_count = 1;
rootfs = mnt_point;
}
void VirtualFileSystem::initialize()
{
// TODO: setup memory pools etc to speed things up
// a bit
// TODO: Add a devfs, procfs etc...
filesystem* fat_fs = (filesystem*) malloc(sizeof (filesystem));
fat_fs->name = "fat";
fat_fs->mount = FAT::Mount;
//register_filesystem(fat_fs);
// Mount the bootdrive
// NOTE: for now will hardcode this
Mount(fat_fs, "/");
};
int VirtualFileSystem::register_filesystem(struct filesystem* fs) {
// register the filesystem to the kernel.
filesystems[filesystem_number] = fs;
filesystem_number++;
}
FILE* VirtualFileSystem::open(const char* pathname, int flags){
// 1. Lookup pathname from the root node
// 2. Create a new file descriptor for this inode if found.
// 3. Create a new file if O_CREATE is specified in the flags.
FILE* file = (FILE*) malloc(sizeof (FILE)) ;
auto* rootentry = rootfs->root;
char* tokstate = nullptr;
auto nextdir = strtok ((char*)pathname, "/", &tokstate );
// look up children if not filled
if(rootentry->children == nullptr)
{
rootentry = rootentry->node->lookup(rootentry->node, rootentry);
}
if(rootentry->children == nullptr)
{
file->flags =1;
return file;
}
// let's just loop through the folder first
printf("looking for: ");
for(int i = 0; i < 5; i++)
kterm_put(nextdir[i]);
kterm_put('\n');
auto* child = rootentry->children;
while(child->next != nullptr){
auto* directory = (DirectoryNode*)child->data;
for(int i = 0; i < 11 ; i++)
kterm_put(directory->name[i]);
kterm_put('\n');
if( directory->compare(directory, directory->name, nextdir) == 0){
nextdir = strtok(nullptr, "/", &tokstate);
printf("Found dir!\n");
if(nextdir == NULL){
file->root = directory->node;
file->flags =0;
file->read = FAT::Read;
return file;
}
printf("continue searching next directory!\n");
if(directory->children == nullptr)
directory->node->lookup(directory->node, directory);
child = directory->children;
}else{
child = child->next;
}
}
file->flags = 1;
return file;
}
int VirtualFileSystem::close (struct FILE* file){
// 1. release the file descriptor
}
int VirtualFileSystem::write(struct FILE* file, const void* buf, unsigned int len){
// 1. Write len bytes from buf to the opened file.
// 2. return written size or error code if an error occurs
}
int VirtualFileSystem::read (struct FILE* file, void* buf, unsigned int len){
// 1. read min(len, readable file data size) bytes ro buf from the opened file.
// 2. return read size or error code if an error occurs
}
/*
void fs_discovery(){
// Mount the boot disk
// NOTE: we assume for now that it is the only disk in the system
// This information could possibly be had from the bootloader (GRUB)
// We als assume it is the primary device on the Master port.
ATAPIO::Soft_Reset(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER);
bool isAvailable = ATAPIO::Identify(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER);
if(!isAvailable){
// PANIC!!!
printf("Failed to mount root filesystem!\n");
return;
}
auto masterbootrecord = GetPartitions(false);
for (auto partition : masterbootrecord->TableEntries)
{
if(partition.PartitionType == 0x0) continue; // Consider marked as free
PTR_PARTITION found_partition = (PARTITION*) malloc(sizeof(PARTITION));
found_partition->Disk = ATAPIO_PORT::Primary | ( DEVICE_DRIVE::MASTER << 16);
printf("Disk Identifier: 0x%x\n", found_partition->Disk);
found_partition->Attributes = partition.driveAttribute;
found_partition->StartAddress = partition.LBA_partition_start;
found_partition->Sectors = partition.Number_sectors_inPartition;
found_partition->Fs_hint = partition.PartitionType;
}
printf("Found %d partitions on disk!\n", num_partitions);
for (int i = 0; i < num_partitions; i++)
{
auto* partition = _partitions[i];
// Check the fs_hint for a proper driver
if ( partition->Fs_hint != 0x06){
printf("Assumed Unkown filesystem!\n");
continue;
}
// Check if filesystem OK
printf("Partition Start Address (LBA): 0x%x\n", partition->StartAddress);
bool valid = FAT::Validate(partition);
if(!valid)
{
printf("Not a valid FAT fs!\n");
continue;
}
// setup FileSystem Description before mounting
PFS FS_FAT = (PFS)malloc(sizeof(FILESYSTEM));
FAT::Info(partition, FS_FAT);
// Mount the partition/filesystem
}
}
*/

32
kernel/storage/vfs/vfs.h Normal file
View File

@ -0,0 +1,32 @@
#pragma once
#include <stdint-gcc.h>
#include "../../../CoreLib/Path.h"
#include "vfs_types.h"
#include "vfs_types.h"
class VirtualFileSystem
{
public:
static void initialize();
static void Mount(filesystem* fs, const char* name);
static int register_filesystem(struct filesystem* fs);
static FILE* open(const char* pathname, int flags);
static int close(struct FILE* file);
static int write(struct FILE* file, const void* buf, unsigned int len);
static int read(struct FILE* file, void* buf, unsigned int len);
private:
static vfsmount* rootfs;
static int mount_number;
static int superblock_number;
static int filesystem_number;
static filesystem* filesystems[];
static FS_SUPER* superblocks[];
static vfsmount* mounts[];
};

View File

@ -0,0 +1,110 @@
//
// Created by nigel on 21/02/23.
//
#pragma once
// grasslab.github.io/osdi/en/labs/lab7.html
#include <stddef.h>
#include <stdint.h>
#include "../../../CoreLib/List.h"
struct inode_operations;
struct vfsmount;
struct FS_SUPER;
struct inode;
struct dentry_operations;
struct DirectoryNode;
struct filesystem;
struct FS_SUPER;
struct FILE;
// Describes a mount
struct vfsmount {
vfsmount* mnt_parent; // fs we are mounted on
DirectoryNode* mountpoint; // dentry of mount point
DirectoryNode* root; // root of the mounted tree
FS_SUPER* sb; // pointer to the superblock
unsigned int mnt_count; // keep track of users of this structure
int mnt_flags;
char* mnt_devname; // name of device eg /dev/dsk/hda1
};
struct FS_SUPER;
// Represents a filesystem object (i.e. a file or directory or device)
struct inode {
unsigned long mode; // access permissions
unsigned long uid; // user id owner
unsigned long gid; // group id owner
unsigned int flags;
// operations possible on inode
int (*create)(inode*, DirectoryNode*, const char* );
DirectoryNode* (*lookup)(inode* , DirectoryNode*);
int (*link)(DirectoryNode*, inode* , DirectoryNode*);
int (*unlink)(inode*, DirectoryNode*);
int (*symlink)(inode*, DirectoryNode*);
int (*mkdir)(inode*, DirectoryNode*, const char*);
int (*rmdir)(inode*, DirectoryNode*);
int (*rename)(inode*, DirectoryNode*, inode*, DirectoryNode*);
void (*truncate)(inode*);
int (*permission)(inode*, int);
int (*setattr)(DirectoryNode, unsigned long*);
int (*getattr)(vfsmount* mnt, DirectoryNode*, unsigned long*);
FS_SUPER* sb;
unsigned long ino; // unique number of this inode
unsigned int links; // number of hard links
void* device;
unsigned long size; // size of inode contents in bytes
unsigned long atime; // Access time
unsigned long mtime; // Modify time
unsigned long ctime; // Creation time
unsigned short bytes; // bytes consumed
// File operations possible on Inode;
int(*write) (FILE* file, const void* buf, unsigned int len);
int(*read) (FILE* file, void* buf, unsigned int len);
void* internal; // point to underlying representation of this virtual node (e.g. FAT entry or Directory Entry)
};
// Represents the name of files in the filesystem
// it identifies the file that an inode represents
struct DirectoryNode {
char* name; // name of the file on the disk
DirectoryNode* parent; // parent of the file
inode* node; // node belongs to...
int (*compare)(DirectoryNode*, char*, char* );
int (*o_delete)(DirectoryNode*);
void (*release)(DirectoryNode*);
void (*iput)(DirectoryNode*, inode*);
List* children;
};
// Represents a filesystem type
struct filesystem {
const char* name;
FS_SUPER* (*mount)(filesystem* self, const char* name, vfsmount* mnt);
};
// Represents a mounted filesystem
struct FS_SUPER {
void* device; // device associated with the filesystem
unsigned long blocksize;
unsigned long maxbytes;
filesystem* type;
unsigned long magic; // IDK
DirectoryNode* root; // Root dentry
int count; // IDK
void* fs_info; // pointer to raw filesystem info
dentry_operations* d_op;
inode* inodes[];
};
// Represents an opened file
struct FILE {
inode* root;
unsigned int f_pos; // The next read/write position of this file descriptor;
int(*write) (FILE* file, const void* buf, unsigned int len);
int(*read) (FILE* file, void* buf, unsigned int len);
int flags;
};

View File

@ -1,11 +1,13 @@
#include "superVisorTerminal.h"
#include "../drivers/ata/ataDevice.h"
#include "../partitiontable/mbr/MasterBootRecord.h"
#include "../filesystem/FAT/BiosParameterBlock.h"
#include "../filesystem/FAT/DirectoryEntry.h"
#include "../storage/ata pio/ATAPIO.h"
#include "../storage/partitiontables/mbr/MasterBootRecord.h"
#include "../storage/filesystems/FAT/FAT.h"
bool isRunning = true;
extern "C" void startSuperVisorTerminal()
{
/*
* Show a little banner for cuteness
*/
@ -62,7 +64,8 @@ extern "C" void startSuperVisorTerminal()
{
// Show version information
printf("========= Version ========\n");
printf("Kernel v%d\n", 0);
asm volatile ("movl $0x666, %eax; int $0x50");
}
if(strncmp("CLEAR", command, characterCount) == 0)

52
kernel/syscalls.h Normal file
View File

@ -0,0 +1,52 @@
//
// Created by nigel on 26/02/23.
//
#pragma once
#include "terminal/kterm.h"
#include "storage/vfs/vfs_types.h"
void sys_version (){
printf("KERNEL VERSION v0.4\n");
}
void sys_open(){
}
void sys_read(FILE* file, char* data){
file->read(file, data, 512);
}
void sys_write(FILE* path, const char* data, size_t size){
}
// NOTE: this should become our standard!
void syscall_handler(int syscall_no , uint32_t* args... ){
switch(syscall_no){
case 0x0:
printf("test!\n");
break;
case 0x5:
// SYS_OPEN
// sys_open();
break;
case 0x10:
// SYS_READ
// sys_read((FILE*)args[1], (char*) args[2] );
break;
case 0x20:
// SYS_WRITE
//sys_write((FILE*)args[1], (const char*) args[2], (size_t)args[3]);
break;
case 0x666:
// SYS_VERSION
sys_version();
break;
}
}

View File

@ -21,7 +21,14 @@ void kterm_init () {
kterm_row = 0;
kterm_column = 0;
kterm_color = vga_entry_color ( VGA_COLOR_LIGHT_GREY , VGA_COLOR_BLACK);
kterm_buffer = (uint16_t*) 0xC03FF000;
//Physical address
// 0xB8000
// Virtual address
// 0xC03FF000
//kterm_buffer = ((uint16_t*) 0xB8000);
kterm_buffer = ((uint16_t*) 0xC03FF000 );
for (size_t y = 0; y < VGA_HEIGHT; y++ ){
for( size_t x = 0; x < VGA_WIDTH; x++){
@ -59,7 +66,6 @@ void disable_cursor()
outb(0x3D5, 0x20);
}
void update_cursor(int x, int y){
uint16_t pos = y * VGA_WIDTH + x;
@ -86,8 +92,6 @@ int get_cursor_y (uint16_t cursor_pos ) {
return cursor_pos / VGA_WIDTH;
}
/**
* With the help from:
* https://whiteheadsoftware.dev/operating-systems-development-for-dummies/
@ -134,7 +138,6 @@ void kterm_writestring(const char* data ){
kterm_write(data, strlen(data));
}
static void itoa (char *buf, int base, int d) {
char *p = buf;
char *p1, *p2;
@ -173,28 +176,28 @@ static void itoa (char *buf, int base, int d) {
void printf ( const char *format, ...) {
char **arg = (char **)&format;
auto **arg = (unsigned char **)&format;
int c;
char buf[20];
arg++;
while ((c = *format++) != 0){
while ((c = *(const unsigned char*)format++) != 0){
if( c != '%')
kterm_put(c);
else{
char *p, *p2;
char const *p, *p2;
int pad0 = 0, pad = 0;
c = *format++;
c = *(const unsigned char*)format++;
if(c =='0'){
pad0 = 1;
c = *format++;
c = *(const unsigned char*)format++;
}
if ( c >= '0' && c <= '9'){
pad = c - '0';
c = *format++;
c = *(const unsigned char*)format++;
}
switch (c)
@ -210,7 +213,7 @@ void printf ( const char *format, ...) {
break;
case 's':
p = *arg++;
p = (char const *)*arg++;
if(!p)
p = "(null)";
@ -224,7 +227,7 @@ void printf ( const char *format, ...) {
default:
kterm_put(*((int *)arg++));
kterm_put(*(int *) arg++); // NOLINT(cppcoreguidelines-narrowing-conversions)
break;
}
}

View File

@ -1,10 +1,10 @@
#pragma once
#include <stdint.h>
#include <stdint-gcc.h>
#include <stddef.h>
#include <stdbool.h>
#include "../drivers/vga/colors.h"
#include "../drivers/io/io.h"
#include "../io/io.h"
#include <CoreLib/Memory.h>
void kterm_init();

View File

@ -1,5 +1,5 @@
#pragma once
#include "drivers/io/io.h"
#include "io/io.h"
#define CURRENT_YEAR 2021

View File

@ -1,6 +1,6 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <stdint-gcc.h>
void init_timer (uint32_t frequency);

View File

@ -1,417 +0,0 @@
#include "VFS.h"
#include "../filesystem/FAT/BiosParameterBlock.h"
#include "../drivers/ide/ide.h"
#include "../drivers/ata/ataDevice.h"
#include "../partitiontable/mbr/MasterBootRecord.h"
#include "../memory/KernelHeap.h"
#include "../../CoreLib/Memory.h"
#include "../filesystem/FAT/DirectoryEntry.h"
MOUNT_INFO mountInfo;
PFILESYSTEM _filesystems[DEVICE_MAX];
FILE volOpenFile(const char* fname)
{
if(fname){
unsigned char device = 'a';
char* filename = (char*) fname;
if(fname[1]== ':'){
device = fname[0];
filename += 2; // strip the volume component from the path
}
if(_filesystems[device - 'a']){
FILE file = _filesystems[device-'a']->Open(filename);
file.device = device;
return file;
}
}
FILE file;
file.flags = FS_INVALID;
return file;
}
extern void volReadFile(PFILE file, unsigned char* Buffer, unsigned int length)
{
}
extern void volCloseFile(PFILE file)
{
if( file->device < DEVICE_MAX){
// _filesystems[file->device]->Close(file);
}
}
extern void volRegisterFilesystem(PFILESYSTEM fsys , unsigned int deviceID){
if(deviceID < DEVICE_MAX)
if(fsys)
_filesystems[deviceID] = fsys;
}
extern void volUnregisterFilesystem(PFILESYSTEM){
}
extern void volUnregisterFileSystemByID(unsigned int deviceID){
}
enum BUS_PORT {
Primary = 0x1f0,
Secondary = 0x170
};
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!
ATA_DEVICE::Identify((uint16_t) BUS_PORT::Primary, DEVICE_DRIVE::MASTER);
return true;
}
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);
MBR* mbr =(MBR*) malloc(sizeof (MBR));
ATA_DEVICE::Read(BUS_PORT::Primary, DEVICE_DRIVE::MASTER, LBA, (uint16_t*)mbr);
if(DEBUG){
printf("BootSector: 0x%x\n", mbr->ValidBootsector );
for( int i = 0 ; i < 4 ; i ++){
PartitionTableEntry PT = mbr->TableEntries[i];
printf("Partition %d [ %d sectors, PartitionType: 0x%x, 0x%x, \nLBA Start: 0x%x ]\n" ,
i, PT.Number_sectors_inPartition, PT.PartitionType, mbr->uniqueID, PT.LBA_partition_start );
}
}
return mbr;
}
BiosParameterBlock* getBPB(MBR* mbr, bool DEBUG =false ){
BiosParameterBlock* bpb = (BiosParameterBlock*) malloc(sizeof(BiosParameterBlock));
ATA_DEVICE::Read(BUS_PORT::Primary, DEVICE_DRIVE::MASTER, mbr->TableEntries[0].LBA_partition_start, (uint16_t*) bpb);
if(DEBUG)
{
printf("OEM ID: %s\n", bpb->OEM_id);
printf("Bytes per sector: %d\n", bpb->BytesPerSector);
printf("Sectors per cluster: %d\n", bpb->SectorsPerCluster);
printf("Reserved sectors: %d\n", bpb->ReservedSectors);
printf("Number of FAT: %d\n", bpb->NumberOfFileAllocationTables);
printf("Number of Dir entries: %d\n", bpb->NumberOfDirectoryEntries);
printf("Total Sectors in volume: %d\n", bpb->TotalSectorsInLogicalVolume);
printf("Sectors per FAT: %d\n", bpb->NumberOfSectorsPerFAT);
}
return bpb;
}
uint16_t* ReadFAT (BiosParameterBlock& bpb , MBR& mbr, bool DEBUG = false ) {
uint32_t FATAddress = mbr.TableEntries[0].LBA_partition_start + bpb.ReservedSectors ;
uint16_t* FAT = (uint16_t*)malloc(sizeof (uint16_t) * 256);
ATA_DEVICE::Read(BUS_PORT::Primary, DEVICE_DRIVE::MASTER, FATAddress, FAT );
// Show data in terminal
if(DEBUG){
for( unsigned int i =0 ; i < 256 ; i++) {
printf("0x%x ", (unsigned short)FAT[i]);
}
kterm_put('\n');
}
return FAT;
}
void readFile(uint32_t DataRegion, DirectoryEntry* entry, uint16_t FATentry, BiosParameterBlock& bpb ){
printf("Show contents");
printf("Start cluster of the file: 0x%x\n", entry->StartingCluster);
printf("IS it only 1 cluster? %s\n", FATentry == 0xFFFF ? "Yes" : "No");
uint32_t sector = DataRegion + ((entry->StartingCluster - 0x02) * bpb.SectorsPerCluster);
uint16_t dataBlob[256];
ATA_DEVICE::Read(BUS_PORT::Primary, DEVICE_DRIVE::MASTER, sector, dataBlob);
for (unsigned short n: dataBlob) {
kterm_put(n & 0x00ff);
kterm_put(n >> 8);
}
kterm_put('\n');
}
void listFilesInRoot(MBR& mbr, BiosParameterBlock& bpb ){
auto FATAddress = mbr.TableEntries[0].LBA_partition_start + bpb.ReservedSectors;
uint32_t RootDirectoryRegion = FATAddress + ( bpb.NumberOfFileAllocationTables * bpb.NumberOfSectorsPerFAT );
uint32_t DataRegion = RootDirectoryRegion + ((bpb.NumberOfDirectoryEntries * 32) / bpb.BytesPerSector );
uint16_t* FAT = ReadFAT(bpb, mbr);
uint16_t data2 [256];
ATA_DEVICE::Read(BUS_PORT::Primary, DEVICE_DRIVE::MASTER, RootDirectoryRegion, data2 );
auto* RootDirectory = (DirectoryEntry*) data2;
// List files in root
for(int i= 0; i < sizeof (data2) / sizeof (DirectoryEntry); i++ ) {
auto *entry = (DirectoryEntry * )((uint32_t) RootDirectory + (i * sizeof(DirectoryEntry)));
if (entry->filename[0] == (uint8_t) 0x00)
continue; // There are no more entries in this directory or the entry is free
if ((entry->attribute & 0x01) == 0x01 || (entry->attribute & 0x20) == 0x20)
continue; // Skip listing if hidden or Achieve flag is set
// Print the filename;
for (char n: entry->filename) {
if (n == 0x20)
break;
kterm_put(n);
}
for (unsigned char n: entry->Extension) {
kterm_put(n);
}
kterm_put('\n');
printf("Attribute: %x \n", entry->attribute);
printf("FileSize: %d Bytes\n", entry->FilesizeInBytes);
if (entry->FilesizeInBytes != 0x0 && (entry->attribute == 0x08)) {
readFile(DataRegion,entry, FAT[i], bpb);
}
}
free(FAT);
}
/*
FILE fsysFatDirectory (const char* DirectoryName){
FILE file;
unsigned char* buf;
PDIRECTORY directory;
char DosFileName[11];
ToDosFileName(DirectoryName, DosFileName, 11);
DosFileName[11] =0;
for (int sector=0; sector <14 ; sector++){
ATA_DEVICE::Read(BUS_PORT::Primary, DEVICE_DRIVE::MASTER, mountInfo.rootOffset + sector, (uint16_t*)buf);
directory = (PDIRECTORY) buf;
for (int i =0; i < 16; i++){
char name[11];
memcpy(name, directory->Filename, 11);
name[11]=0;
if(strncmp(DosFileName, name, 11) == 0){
strcpy(file.name, DirectoryName);
file.id = 0;
file.currentCluster = directory->FirstCluster;
file.eof = 0;
file.filelength = directory->FileSize;
if(directory->Attrib == 0x10){
file.flags = FS_DIRECTORY;
} else {
file.flags = FS_FILE;
}
return file;
}
directory++;
}
}
// Can't find file
file.flags = FS_INVALID;
return file;
}
*/
void fsysFATRead(PFILE file, unsigned char* buffer, unsigned int length){
if(file){
unsigned int physSector = 32 + (file->currentCluster - 1);
const unsigned int SECTOR_SIZE = 512;
// read sector
ATA_DEVICE::Read(BUS_PORT::Primary, DEVICE_DRIVE::MASTER, physSector, (uint16_t*) buffer );
unsigned int FAT_Offset = file->currentCluster + (file->currentCluster /2);
unsigned int FAT_Sector = 1 + (FAT_Offset / SECTOR_SIZE);
unsigned int entryOffset =FAT_Offset % SECTOR_SIZE;
uint8_t FAT[SECTOR_SIZE*2];
ATA_DEVICE::Read(BUS_PORT::Primary, DEVICE_DRIVE::MASTER, FAT_Sector,(uint16_t*) FAT); // Read 1st FAT sector
ATA_DEVICE::Read(BUS_PORT::Primary, DEVICE_DRIVE::MASTER, FAT_Sector +1, (uint16_t*)FAT+SECTOR_SIZE);
// read entry for next cluster
uint16_t nextCluster = *(uint16_t*) &FAT[entryOffset];
// test if entry is odd or even
if(file->currentCluster & 0x0001){
nextCluster>>= 4; // grab the high 12 bits
}else{
nextCluster &= 0x0FFF; // grab the low 12 bits
}
// test for end of file
if(nextCluster >= 0xff8){
file->eof -1;
return;
}
// test for file corruption
if(nextCluster == 0){
file->eof =1;
return;
}
// set next cluster
file->currentCluster = nextCluster;
}
}
/*
FILE fsysFatOpenSubDir(FILE kFile, const char* filename){
FILE file;
char DosFileName[11];
ToDosFileName(filename, DosFileName, 11);
DosFileName[11] = 0;
while(!kFile.eof){
//read directory
unsigned char buf[512];
fsysFATRead(&file, buf, 512);
PDIRECTORY pkDir = (PDIRECTORY) buf;
for (unsigned int i = 0; i < 16; i++){
// get current filename
char name[11];
memcpy(name, pkDir->Filename, 11);
name[11] = 0;
if(strncmp(name, DosFileName, 11) == 0){
strcpy(file.name, filename);
file.id = 0;
file.currentCluster = pkDir->FirstCluster;
file.filelength = pkDir->FileSize;
file.eof = 0;
// set file type;
if(pkDir->Attrib == 0x10){
file.flags = FS_DIRECTORY;
} else{
file.flags = FS_FILE;
}
return file;
}
// go to next entry
pkDir++;
}
}
// unable to find file
file.flags = FS_INVALID;
return file;
}
*/
void FileSystem::initialize()
{
MBR* mbr = getPartitions();
BiosParameterBlock* bootsector = getBPB(mbr);
listFilesInRoot(*mbr, *bootsector);
free(mbr);
free(bootsector);
/*
mountInfo.numSectors = bootsector->NumberOfSectorsPerFAT;
mountInfo.fatOffset = 1;
mountInfo.fatSize = bootsector->NumberOfSectorsPerFAT;
mountInfo.fatEntrySize = 8;
mountInfo.numRootEntries = bootsector->NumberOfDirectoryEntries;
mountInfo.rootOffset = (bootsector->NumberOfFileAllocationTables * bootsector->NumberOfSectorsPerFAT) + 1;
mountInfo.rootSize = (bootsector->NumberOfDirectoryEntries * 32) / bootsector->BytesPerSector;
*/
}
char* FindNextEntryName (char* path )
{
int length = strlen(path);
char* name = path;
int i = 0;
if( name[0] == '/')
i++;
while ( name[i] != '/' && i <= length)
i++;
char* s = (char*) malloc(i + 1 * sizeof(char));
for ( int a = 0; a < i; a++)
s[a] = path[a];
s[i + 1] = '\0';
return s;
}
void FileSystem::ResolvePath(Path &path)
{
// See reference material (1) https://man7.org/linux/man-pages/man7/path_resolution.7.html
char* string_path = path.str();
void* cpy = string_path;
bool isAbsolutePath = string_path[0] == '/';
if(isAbsolutePath)
{
// strip the first slash
string_path++;
}
char* entry_name = FindNextEntryName(string_path);
printf("Look for entry with name: %s\n", entry_name);
int skip = strlen(entry_name);
free(entry_name);
entry_name = FindNextEntryName(string_path + skip);
printf("Look for entry with name: %s\n", entry_name);
skip = strlen(entry_name);
free(entry_name);
free(cpy);
}

View File

@ -1,80 +0,0 @@
#pragma once
#include <stdint.h>
#include "../../CoreLib/Path.h"
#define FS_FILE 0
#define FS_DIRECTORY 1
#define FS_INVALID 2
#define DEVICE_MAX 26
typedef struct _FILE {
char name [32];
uint32_t flags;
uint32_t filelength;
uint32_t id;
uint32_t eof;
uint32_t position;
uint32_t currentCluster;
uint32_t device;
}FILE, *PFILE;
typedef struct _FILE_SYSTEM{
char name[8];
FILE (*Directory) (const char* Directoryname);
void (*Mount) ();
void (*Read) (PFILE file, unsigned char* buffer, unsigned int length);
void (Close) (PFILE);
FILE (*Open) (const char* filename);
}FILESYSTEM, *PFILESYSTEM;
typedef struct _MOUNT_INFO{
uint32_t numSectors;
uint32_t fatOffset;
uint32_t numRootEntries;
uint32_t rootOffset;
uint32_t rootSize;
uint32_t fatSize;
uint32_t fatEntrySize;
}MOUNT_INFO, *PMOUNT_INFO;
typedef struct _DIRECTORY{
uint8_t Filename[8];
uint8_t Ext[3];
uint8_t Attrib;
uint8_t Reserved;
uint8_t TimeCreatedMs;
uint16_t TimeCreated;
uint16_t DateCreated;
uint16_t DateLastAccessed;
uint16_t FirstClusterHiBytes;
uint16_t LastModTime;
uint16_t LastModDate;
uint16_t FirstCluster;
uint32_t FileSize;
}DIRECTORY, *PDIRECTORY;
// Date Format
// [0..4] Day
// [5..8] Month
// [9..15] Year
// Time Format
// [0..4] Seconds
// [5..10] Minute
// [11..15] Hour
extern PFILESYSTEM _filesystems[DEVICE_MAX];
FILE volOpenFile(const char* fname);
void volCloseFile(PFILE file);
void volRegisterFilesystem(PFILESYSTEM, unsigned int deviceID);
void volUnregisterFilesystem(PFILESYSTEM);
void volUnregisterFileSystemByID(unsigned int deviceID);
class FileSystem{
public:
static void initialize();
static void ResolvePath(Path& path);
};

27
run.sh Executable file
View File

@ -0,0 +1,27 @@
#!/bin/bash
PROC=$$
# Build the Corelib static library
(cd CoreLib
if ! make 2> warnings.log 1> /dev/null ; then
echo "Build Corelib failed!"
kill -10 $PROC
fi)
# Build the kernel image
(cd kernel
# make clean
if ! make 2> warnings.log 1> /dev/null ; then
echo "Build kernel failed!"
kill -10 $PROC
fi)
./scripts/update_harddrive.sh
./scripts/create_symbol_lookup.sh
args="";
if [[ $1 == "-d" ]]
then
args="debug"
fi
./scripts/run_qemu.sh $args

View File

@ -2,24 +2,23 @@
import os
import subprocess
print("Building BarinkOS")
print("Give BarinkOS A Test Run")
# list and run build scripts
print("Running build-scripts")
os.chdir("scripts")
scripts=os.listdir()
currentScript=os.path.basename(__file__)
if currentScript in scripts:
scripts.remove(currentScript)
os.chdir("../CoreLib")
print("Building CoreLib")
subprocess.call("make")
for script in scripts:
print(os.getcwd())
print("Running:" + script)
subprocess.call(script, cwd=os.getcwd())
os.chdir("../kernel")
print("Building kernel")
subprocess.call("make")
os.chdir("..")
subprocess.call("scripts/update_harddrive.sh", cwd=os.getcwd())
subprocess.call("scripts/create_symbol_lookup.sh", cwd=os.getcwd())
subprocess.call("scripts/run_qemu.sh", cwd=os.getcwd())

View File

@ -9,11 +9,8 @@
echo "Building a FAT16 filesystem"
su
# dd if=/dev/zero of=diks.img bs=512 count=131072
# fdisk disk.img
dd if=/dev/zero of=disk.img bs=512 count=131072
fdisk disk.img
# Use the following options in fdisk (Format Disk Tool)
# We want to create a MBR (NOT GPT) Partition table containing 1 logical disk
# with a primary FAT16 partition marked bootable
@ -42,23 +39,23 @@ su
# w
# Create a "block" device from the disk.img
# losetup /dev/loop9 disk.img
losetup /dev/loop9 disk.img
# Format the partition on the disk as FAT16
# mkdosfs -F16 /dev/loop9
mkdosfs -F16 /dev/loop9
# Mount the disk to a folder on our dev machine
# mount /dev/loop9 /mnt
mount /dev/loop9 /mnt
# Install the grub bootloader onto the disk
# grub-install --no-floppy --modules="normal multiboot" /dev/loop9 --target=i386-pc --boot-directory=/mnt/boot --force
grub-install --no-floppy --modules="normal multiboot" /dev/loop9 --target=i386-pc --boot-directory=/mnt/boot --force
# copy the necessary OS files
# cp root/boot/myos.bin /mnt/boot/myos.bin
# cp root/boot/grub/grub.cfg /mnt/boot/grub/grub.cfg
cp root/boot/myos.bin /mnt/boot/myos.bin
cp root/boot/grub/grub.cfg /mnt/boot/grub/grub.cfg
# Unmount the device
# umount /mnt
umount /mnt
# Destroy the loop device
# losetup -d /dev/loop9
losetup -d /dev/loop9

5
scripts/create_iso.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/bash
mkdir -p root/boot/grub
cp build/kernel/myos.bin root/boot/myos.bin
cp kernel/grub.cfg root/boot/grub/grub.cfg
grub-mkrescue -o barinkOS.iso root

View File

@ -0,0 +1,4 @@
#!/bin/bash
echo "creating symbols file"
echo $(pwd)
objcopy --only-keep-debug root/boot/myos.bin kernel.sym

View File

@ -1,5 +1,2 @@
#!/bin/bash
# Run clang-tidy

18
scripts/run_qemu.sh Executable file
View File

@ -0,0 +1,18 @@
#!/bin/bash
if [[ $1 == "debug" ]]
then
qemu-system-i386 -s -boot d -drive format=raw,file=disk.img -serial stdio -vga std -display gtk -m 2G -cpu core2duo -d int -no-shutdown -no-reboot
else
qemu-system-i386 -s -boot d -drive format=raw,file=disk.img -serial stdio -vga std -display gtk -m 2G -cpu core2duo
fi
# Run from harddisk
#qemu-system-i386 -boot d -drive format=raw,file=disk.img -serial stdio -vga std -display gtk -m 2G -cpu core2duo -d int -no-shutdown -no-reboot
# Run disk version
# qemu-system-i386 -cdrom barinkOS.iso -serial stdio -vga std -display gtk -m 2G -cpu core2duo -s -d int -no-shutdown -no-reboot
# Run the raw kernel image
# qemu-system-i386 -kernel build/kernel/myos.bin -serial stdio -vga std -display gtk -m 2G -cpu core2duo -d int -no-shutdown -no-reboot

2
scripts/run_virtualbox.sh Executable file
View File

@ -0,0 +1,2 @@
#!/bin/bash
virtualboxvm --startvm "BarinkOS_test"

View File

@ -1,5 +0,0 @@
#!/bin/bash
start=`date +%s`
end=`date +%s`
echo That took $((end-start)) seconds
date +"%c" -d195440409

14
scripts/update_harddrive.sh Executable file
View File

@ -0,0 +1,14 @@
#!/bin/bash
echo "running in cwd : "
echo $(pwd)
echo "Mount harddrive image as block device"
sudo losetup /dev/loop9 disk.img
sudo mount /dev/loop9 /mnt
echo "Copy over kernel binary"
sudo cp build/kernel/myos.bin /mnt/boot/myos.bin
echo "unmount image"
sudo umount /mnt
sudo losetup -d /dev/loop9

View File

@ -4,7 +4,7 @@
This list keeps me focused and organised so I don't forget what
needs to be done. It is a expansion on the features markdown file which describes the features. Here I put things I need to remember
needs to be done. It is a expansion on the features markdown FILE which describes the features. Here I put things I need to remember
to do on a more in depth level.
## --