diff --git a/include/drivers/ata.h b/include/drivers/ata.h index 60c15d4..ea7b049 100644 --- a/include/drivers/ata.h +++ b/include/drivers/ata.h @@ -15,6 +15,7 @@ namespace myos { protected: bool master; + common::uint16_t bytesPerSector; hardwarecommunication::Port16Bit dataPort; hardwarecommunication::Port8Bit errorPort; hardwarecommunication::Port8Bit sectorCountPort; @@ -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(); diff --git a/include/filesystem/fat.h b/include/filesystem/fat.h new file mode 100644 index 0000000..bb3de6d --- /dev/null +++ b/include/filesystem/fat.h @@ -0,0 +1,69 @@ +#ifndef __MYOS__FILESYSTEM__FAT_h +#define __MYOS__FILESYSTEM__FAT_h + +#include +#include + +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 diff --git a/include/filesystem/msdospart.h b/include/filesystem/msdospart.h new file mode 100644 index 0000000..bdcddaf --- /dev/null +++ b/include/filesystem/msdospart.h @@ -0,0 +1,49 @@ + +#ifndef __MYOS__FILESYSTEM__MSDOSPART_H +#define __MYOS__FILESYSTEM__MSDOSPART_H + +#include +#include + +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 diff --git a/makefile b/makefile index 8523e04..4152679 100644 --- a/makefile +++ b/makefile @@ -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 \ diff --git a/src/drivers/ata.cpp b/src/drivers/ata.cpp index 48f07e4..3697ee2 100644 --- a/src/drivers/ata.cpp +++ b/src/drivers/ata.cpp @@ -20,6 +20,7 @@ AdvancedTechnologyAttachment::AdvancedTechnologyAttachment(bool master, common:: controlPort(portBase + 0x206) { this->master = master; + bytesPerSector = 512; } AdvancedTechnologyAttachment::~AdvancedTechnologyAttachment() @@ -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; @@ -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(); @@ -172,4 +175,4 @@ void AdvancedTechnologyAttachment::Flush() return; } } - \ No newline at end of file + diff --git a/src/filesystem/fat.cpp b/src/filesystem/fat.cpp new file mode 100644 index 0000000..a646fc2 --- /dev/null +++ b/src/filesystem/fat.cpp @@ -0,0 +1,108 @@ + +#include +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; iRead28(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; + } + } +} diff --git a/src/filesystem/msdospart.cpp b/src/filesystem/msdospart.cpp new file mode 100644 index 0000000..62bd6ba --- /dev/null +++ b/src/filesystem/msdospart.cpp @@ -0,0 +1,57 @@ + +#include +#include +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); + } +} diff --git a/src/kernel.cpp b/src/kernel.cpp index b0709dd..921a9ec 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include