Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Appendix B01-B03 in series of writing os in cpp #37

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion include/drivers/ata.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace myos
{
protected:
bool master;
common::uint16_t bytesPerSector;
hardwarecommunication::Port16Bit dataPort;
hardwarecommunication::Port8Bit errorPort;
hardwarecommunication::Port8Bit sectorCountPort;
Expand All @@ -30,7 +31,7 @@ namespace myos
~AdvancedTechnologyAttachment();

void Identify();
void Read28(common::uint32_t sectorNum, int count = 512);
void Read28(common::uint32_t sectorNum, common::uint8_t* data, common::uint32_t count);
void Write28(common::uint32_t sectorNum, common::uint8_t* data, common::uint32_t count);
void Flush();

Expand Down
69 changes: 69 additions & 0 deletions include/filesystem/fat.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#ifndef __MYOS__FILESYSTEM__FAT_h
#define __MYOS__FILESYSTEM__FAT_h

#include <common/types.h>
#include <drivers/ata.h>

namespace myos
{
namespace filesystem
{
struct BiosParameterBlock32
{
// common biosParameter for fat12/16/32
common::uint8_t jump[3];
common::uint8_t softName[8];
common::uint16_t bytesPerSector;
common::uint8_t sectorPerCluster;
common::uint16_t reservedSectors;
common::uint8_t fatCopies;
common::uint16_t rootDirEntries;
common::uint16_t totalSectors;
common::uint8_t mediaType;
common::uint16_t fatSectorCount;
common::uint16_t sectorPerTrack;
common::uint16_t headCount;
common::uint32_t hiddenSectors;
common::uint32_t totalSectorCount;

// extended biosParameter for fat32 only
common::uint32_t tableSize;
common::uint16_t extFlags;
common::uint16_t fatVersion;
common::uint32_t rootCluster;
common::uint16_t fatInfo;
common::uint16_t backupSector;
common::uint8_t reserved0[12];
common::uint8_t driveNumber;
common::uint8_t reserved;
common::uint8_t bootSignature;
common::uint32_t volumeId;
common::uint8_t volumeLabel[11];
common::uint8_t fatTypeLabel[8];

} __attribute__((packed));


struct DirectoryEntryFat32
{
common::uint8_t name[8];
common::uint8_t ext[3];
common::uint8_t attributes;
common::uint8_t reserved;
common::uint8_t cTimeTenth;
common::uint16_t cTime;
common::uint16_t cDate;
common::uint16_t aTime;
common::uint16_t firstClusterHi;
common::uint16_t wTime;
common::uint16_t wDate;
common::uint16_t firstClusterLow;
common::uint32_t size;

} __attribute__((packed));

void ReadBiosParameterBlock(drivers::AdvancedTechnologyAttachment *hd, common::uint32_t paritionOffset);
}
}

#endif
49 changes: 49 additions & 0 deletions include/filesystem/msdospart.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@

#ifndef __MYOS__FILESYSTEM__MSDOSPART_H
#define __MYOS__FILESYSTEM__MSDOSPART_H

#include <common/types.h>
#include <drivers/ata.h>

namespace myos
{
namespace filesystem
{
struct PartitionTableEntry
{
common::uint8_t bootable;
common::uint8_t start_head;
common::uint8_t start_sector:6;
common::uint16_t start_cylinder:10;

common::uint8_t partition_id;

common::uint8_t end_head;
common::uint8_t end_sector:6;
common::uint16_t end_cylinder:10;

common::uint32_t start_lba;
common::uint32_t length;
} __attribute__((packed));


struct MasterBootRecord
{
common::uint8_t bootloader[440];
common::uint32_t signature;
common::uint16_t unused;

PartitionTableEntry primaryPartition[4];

common::uint16_t magicnumber;
} __attribute__((packed));

class MSDOSPartitionTable
{
public:
static void ReadPartitions(drivers::AdvancedTechnologyAttachment *hd);
};
}
}

#endif
2 changes: 2 additions & 0 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ objects = obj/loader.o \
obj/drivers/mouse.o \
obj/drivers/vga.o \
obj/drivers/ata.o \
obj/filesystem/msdospart.o \
obj/filesystem/fat.o \
obj/gui/widget.o \
obj/gui/window.o \
obj/gui/desktop.o \
Expand Down
33 changes: 18 additions & 15 deletions src/drivers/ata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ AdvancedTechnologyAttachment::AdvancedTechnologyAttachment(bool master, common::
controlPort(portBase + 0x206)
{
this->master = master;
bytesPerSector = 512;
}

AdvancedTechnologyAttachment::~AdvancedTechnologyAttachment()
Expand Down Expand Up @@ -70,7 +71,7 @@ void AdvancedTechnologyAttachment::Identify()
printf("\n");
}

void AdvancedTechnologyAttachment::Read28(common::uint32_t sectorNum, int count)
void AdvancedTechnologyAttachment::Read28(common::uint32_t sectorNum, common::uint8_t* data, common::uint32_t count)
{
if(sectorNum > 0x0FFFFFFF)
return;
Expand Down Expand Up @@ -98,19 +99,21 @@ void AdvancedTechnologyAttachment::Read28(common::uint32_t sectorNum, int count)
printf("Reading ATA Drive: ");

for(int i = 0; i < count; i += 2)
{
uint16_t wdata = dataPort.Read();

char *text = " \0";
text[0] = wdata & 0xFF;

if(i+1 < count)
text[1] = (wdata >> 8) & 0xFF;
else
text[1] = '\0';

printf(text);
}
{
uint16_t wdata = dataPort.Read();

/*
char *text = " \0";
if(i+1 < count)
text[1] = (wdata >> 8) & 0x00FF;
text[0] = wdata & 0x00FF;
printf(text);
*/

data[i] = wdata & 0x00FF;
data[i+1] = (wdata >> 8) & 0x00FF;
}


for(int i = count + (count%2); i < 512; i += 2)
dataPort.Read();
Expand Down Expand Up @@ -172,4 +175,4 @@ void AdvancedTechnologyAttachment::Flush()
return;
}
}


108 changes: 108 additions & 0 deletions src/filesystem/fat.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@

#include <filesystem/fat.h>
using namespace myos;
using namespace myos::common;
using namespace myos::filesystem;
using namespace myos::drivers;


void printf(char*);
void printfHex(uint8_t);

void myos::filesystem::ReadBiosParameterBlock(AdvancedTechnologyAttachment *hd, uint32_t partitionOffset)
{
/*
* Read Bios Parameter block i.e. first sector of partition also known as VolumeId
* Use bpb to find fatStart, fatSize, dataStart, rootStart
* read first rootCluster to find location of files/directory on filesystem
* iterate over directory entries and find location of files using firstClusterLow, firstClusterHi
* then Read all sector/cluster belonging to file:-
i) Get next cluster belonging to file from FAT table
ii) Get next sector belonging to file from current file cluster
*/

BiosParameterBlock32 bpb;
hd->Read28(partitionOffset, (uint8_t*)&bpb, sizeof(BiosParameterBlock32));

// Raw printing of VolumeID sector
/*
for(int i=0x00; i<sizeof(BiosParameterBlock32); i++)
{
printfHex(((uint8_t*)&bpb)[i]);
printf(" ");
}
printf("\n");
*/

printf("sector per cluster: ");
printfHex(bpb.sectorPerCluster);
printf("\n");

uint32_t fatStart = partitionOffset + bpb.reservedSectors;
uint32_t fatSize = bpb.tableSize;

uint32_t dataStart = fatStart + fatSize * bpb.fatCopies;
uint32_t rootStart = dataStart + bpb.sectorPerCluster*(bpb.rootCluster -2);

DirectoryEntryFat32 dirent[16];
hd->Read28(rootStart, (uint8_t*)&dirent[0], 16*sizeof(DirectoryEntryFat32));

for(int i = 0; i<16; i++)
{
if(dirent[i].name[0] == 0x00) // unused directory entry
break;

if((dirent[i].attributes & 0x0F) == 0x0F) // long name directory entry
continue;

char *foo = " \n";
for(int j = 0; j<8; j++)
foo[j] = dirent[i].name[j];
printf(foo);

if((dirent[i].attributes & 0x10) == 0x10) // directory
continue;



/* Read all sector/cluster belonging to file */
uint32_t firstFileCluster = ((uint32_t)dirent[i].firstClusterHi) << 16
| ((uint32_t)dirent[i].firstClusterLow);

int32_t SIZE = dirent[i].size;
int32_t nextFileCluster = firstFileCluster;
uint8_t buffer[513];
uint8_t fatBuffer[513];

while(SIZE > 0)
{
uint32_t fileSector = dataStart + bpb.sectorPerCluster * (nextFileCluster - 2) ;
int sectorOffset = 0;

for(; SIZE > 0; SIZE -= 512)
{
/* Get next sector belonging to file from current file cluster
1) read sector by sector data of file until SIZE < 0 or
all sectors in currentCluster are read
*/
hd->Read28(fileSector + sectorOffset, buffer, 512);
buffer[SIZE > 512 ? 512 : SIZE] = '\0';
printf((char*)buffer);

if(++sectorOffset > bpb.sectorPerCluster)
break;
}

/* Get next cluster belonging to file from FAT table
1) get sector in FAT table holding current file cluster
2) fig out current file cluster entry num in FAT sector out of 128 directory entries
3) update next cluster with most significant 28 bits
*/
uint32_t fatSectorForCurrentCluster = nextFileCluster / (512/sizeof(uint32_t));
hd->Read28(fatStart + fatSectorForCurrentCluster, fatBuffer, 512);

uint32_t fatOffsetInFatSector_ForCurrentCluster = nextFileCluster % (512/sizeof(uint32_t));
nextFileCluster = ((uint32_t*)&fatBuffer)[fatOffsetInFatSector_ForCurrentCluster] & 0x0FFFFFFF;
}
}
}
57 changes: 57 additions & 0 deletions src/filesystem/msdospart.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@

#include <filesystem/fat.h>
#include <filesystem/msdospart.h>
using namespace myos;
using namespace myos::common;
using namespace myos::drivers;
using namespace myos::filesystem;

void printf(char*);
void printfHex(uint8_t);

void MSDOSPartitionTable::ReadPartitions(AdvancedTechnologyAttachment *hd)
{
MasterBootRecord mbr;

printf("MBB: ");
hd->Read28(0, (uint8_t*)&mbr, sizeof(MasterBootRecord));

// RAW printing of MBR
/*
for(int i = 0x1BE; i <= 0x01FF; i++)
{
printfHex(((uint8_t*)&mbr)[i]);
printf(" ");
}
printf("\n");
*/

if(mbr.magicnumber != 0xAA55)
{
printf("illegal MBR");
return;
}

// Pretty print of MBR
for(int i = 0; i < 4; i++)
{
if(mbr.primaryPartition[i].partition_id == 0x00)
continue;

printf(" Partition ");
printfHex(i & 0xFF);

if(mbr.primaryPartition[i].bootable == 0x80)
{
printf(" bootable. Type ");
}
else
{
printf(" not bootable. Type ");
}

printfHex(mbr.primaryPartition[i].partition_id);

ReadBiosParameterBlock(hd, mbr.primaryPartition[i].start_lba);
}
}
1 change: 1 addition & 0 deletions src/kernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <drivers/mouse.h>
#include <drivers/vga.h>
#include <drivers/ata.h>
#include <filesystem/msdospart.h>
#include <gui/desktop.h>
#include <gui/window.h>
#include <multitasking.h>
Expand Down