From aff3c38ac28f6b9ea45ebee435898433336ab60c Mon Sep 17 00:00:00 2001 From: Sourabh Sagar Date: Mon, 24 Apr 2023 17:12:03 +0530 Subject: [PATCH 1/3] [MBR] In series of writing os in cpp:- Appendix B01) Disecting MBR(master boot record) alongwith partition table written by fdisk from TinyCoreOS ++ create 2 parition via fdisk in virtual hardisk using TinyCoreOS then in wyoos using ata driver gather info about MBR and Parition Table --- include/drivers/ata.h | 3 +- include/filesystem/msdospart.h | 49 +++++++++++++++++++++++++++++++++ makefile | 1 + src/drivers/ata.cpp | 32 ++++++++++++---------- src/filesystem/msdospart.cpp | 50 ++++++++++++++++++++++++++++++++++ src/kernel.cpp | 1 + 6 files changed, 120 insertions(+), 16 deletions(-) create mode 100644 include/filesystem/msdospart.h create mode 100644 src/filesystem/msdospart.cpp 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/msdospart.h b/include/filesystem/msdospart.h new file mode 100644 index 0000000..6f3c7ac --- /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 primaryPartitions[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..db904cd 100644 --- a/makefile +++ b/makefile @@ -21,6 +21,7 @@ objects = obj/loader.o \ obj/drivers/mouse.o \ obj/drivers/vga.o \ obj/drivers/ata.o \ + obj/filesystem/msdospart.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..f8bcb9a 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,20 @@ 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 +174,4 @@ void AdvancedTechnologyAttachment::Flush() return; } } - \ No newline at end of file + diff --git a/src/filesystem/msdospart.cpp b/src/filesystem/msdospart.cpp new file mode 100644 index 0000000..5a147bb --- /dev/null +++ b/src/filesystem/msdospart.cpp @@ -0,0 +1,50 @@ + +#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++) + { + printf(" Partition "); + printfHex(i & 0xFF); + + if(mbr.primaryPartitions[i].bootable == 0x80) + { + printf(" bootable. Type "); + } + else + { + printf(" not bootable. Type "); + } + + printfHex(mbr.primaryPartitions[i].partition_id); + } +} 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 From bec5bbd13d14a2fe60ad2b24bf29db91a3569e28 Mon Sep 17 00:00:00 2001 From: Sourabh Sagar Date: Mon, 24 Apr 2023 17:35:48 +0530 Subject: [PATCH 2/3] [FAT32 fs] In series of writing os in cpp:- Appendix B02) Implemented Fat32 filesystem ++ Using partitionOffset accessed 1st sector of partition which is known as BiosParameterBlock / VolumeID. bpb helps find location of FAT table, data, root directory cluster, etc From rootCluster we get access to DirectoryEntries which holds location of file data if dirent[i].attributes & 0x10 != 0x10 --- include/filesystem/fat.h | 69 +++++++++++++++++++++++++++++++++ include/filesystem/msdospart.h | 2 +- makefile | 1 + src/drivers/ata.cpp | 3 +- src/filesystem/fat.cpp | 71 ++++++++++++++++++++++++++++++++++ src/filesystem/msdospart.cpp | 13 +++++-- 6 files changed, 154 insertions(+), 5 deletions(-) create mode 100644 include/filesystem/fat.h create mode 100644 src/filesystem/fat.cpp 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 index 6f3c7ac..bdcddaf 100644 --- a/include/filesystem/msdospart.h +++ b/include/filesystem/msdospart.h @@ -33,7 +33,7 @@ namespace myos common::uint32_t signature; common::uint16_t unused; - PartitionTableEntry primaryPartitions[4]; + PartitionTableEntry primaryPartition[4]; common::uint16_t magicnumber; } __attribute__((packed)); diff --git a/makefile b/makefile index db904cd..4152679 100644 --- a/makefile +++ b/makefile @@ -22,6 +22,7 @@ objects = obj/loader.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 f8bcb9a..3697ee2 100644 --- a/src/drivers/ata.cpp +++ b/src/drivers/ata.cpp @@ -102,12 +102,13 @@ void AdvancedTechnologyAttachment::Read28(common::uint32_t sectorNum, common::ui { 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; diff --git a/src/filesystem/fat.cpp b/src/filesystem/fat.cpp new file mode 100644 index 0000000..a52fd3a --- /dev/null +++ b/src/filesystem/fat.cpp @@ -0,0 +1,71 @@ + +#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 finally access 1st sector of data and print it + */ + + 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) + break; + + if((dirent[i].attributes & 0x0F) == 0x0F) + 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; + + uint32_t fileCluster = ((uint32_t)dirent[i].firstClusterHi) << 16 + | ((uint32_t)dirent[i].firstClusterLow); + + uint32_t fileSector = dataStart + bpb.sectorPerCluster * (fileCluster - 2) ; + + uint8_t buffer[512]; + + hd->Read28(fileSector, buffer, 512); + buffer[dirent[i].size] = '\0'; + printf((char*)buffer); + } +} diff --git a/src/filesystem/msdospart.cpp b/src/filesystem/msdospart.cpp index 5a147bb..62bd6ba 100644 --- a/src/filesystem/msdospart.cpp +++ b/src/filesystem/msdospart.cpp @@ -1,4 +1,5 @@ +#include #include using namespace myos; using namespace myos::common; @@ -16,13 +17,14 @@ void MSDOSPartitionTable::ReadPartitions(AdvancedTechnologyAttachment *hd) 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) { @@ -33,10 +35,13 @@ void MSDOSPartitionTable::ReadPartitions(AdvancedTechnologyAttachment *hd) // 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.primaryPartitions[i].bootable == 0x80) + if(mbr.primaryPartition[i].bootable == 0x80) { printf(" bootable. Type "); } @@ -45,6 +50,8 @@ void MSDOSPartitionTable::ReadPartitions(AdvancedTechnologyAttachment *hd) printf(" not bootable. Type "); } - printfHex(mbr.primaryPartitions[i].partition_id); + printfHex(mbr.primaryPartition[i].partition_id); + + ReadBiosParameterBlock(hd, mbr.primaryPartition[i].start_lba); } } From a35756d3e857951b6f0cd8498e3be0d3963eac4e Mon Sep 17 00:00:00 2001 From: Sourabh Sagar Date: Mon, 24 Apr 2023 17:45:02 +0530 Subject: [PATCH 3/3] [FAT32 extended] In series of writing os in cpp:- Appendix B03) Added functionality to Read all sector/cluster belonging to file:- ++ using tinyCoreOs create 8kb bile that span over multiple sector and cluster ++ Using 1st rootCluster we are able to reach 1st cluster of file data then i) Get next cluster belonging to file from FAT table ii) Get next sector belonging to file from current file cluster --- src/filesystem/fat.cpp | 59 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 11 deletions(-) diff --git a/src/filesystem/fat.cpp b/src/filesystem/fat.cpp index a52fd3a..a646fc2 100644 --- a/src/filesystem/fat.cpp +++ b/src/filesystem/fat.cpp @@ -16,7 +16,9 @@ void myos::filesystem::ReadBiosParameterBlock(AdvancedTechnologyAttachment *hd, * 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 finally access 1st sector of data and print it + * 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; @@ -32,6 +34,10 @@ void myos::filesystem::ReadBiosParameterBlock(AdvancedTechnologyAttachment *hd, printf("\n"); */ + printf("sector per cluster: "); + printfHex(bpb.sectorPerCluster); + printf("\n"); + uint32_t fatStart = partitionOffset + bpb.reservedSectors; uint32_t fatSize = bpb.tableSize; @@ -43,10 +49,10 @@ void myos::filesystem::ReadBiosParameterBlock(AdvancedTechnologyAttachment *hd, for(int i = 0; i<16; i++) { - if(dirent[i].name[0] == 0x00) + if(dirent[i].name[0] == 0x00) // unused directory entry break; - if((dirent[i].attributes & 0x0F) == 0x0F) + if((dirent[i].attributes & 0x0F) == 0x0F) // long name directory entry continue; char *foo = " \n"; @@ -57,15 +63,46 @@ void myos::filesystem::ReadBiosParameterBlock(AdvancedTechnologyAttachment *hd, if((dirent[i].attributes & 0x10) == 0x10) // directory continue; - uint32_t fileCluster = ((uint32_t)dirent[i].firstClusterHi) << 16 - | ((uint32_t)dirent[i].firstClusterLow); - - uint32_t fileSector = dataStart + bpb.sectorPerCluster * (fileCluster - 2) ; - uint8_t buffer[512]; - hd->Read28(fileSector, buffer, 512); - buffer[dirent[i].size] = '\0'; - printf((char*)buffer); + /* 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; + } } }