using System; using System.Collections.Generic; using System.Text; namespace Cosmos.Kernel.FileSystem { public partial class Ext2Old: FileSystem { private static unsafe GroupDescriptor[] ReadGroupDescriptorsOfBlock(byte aController, byte aDrive, uint aBlockGroup, SuperBlock aSuperBlock, ushort* aBuffer) { uint xGroupDescriptorCount = aSuperBlock.INodesCount / aSuperBlock.INodesPerGroup; GroupDescriptor[] xResult = new GroupDescriptor[xGroupDescriptorCount]; GroupDescriptor* xDescriptorPtr = (GroupDescriptor*)aBuffer; for (int i = 0; i < xGroupDescriptorCount; i++) { int xATABlock = (int)((8)); xATABlock += (i / 16); if ((i % 16) == 0) { if (!Hardware.Storage.ATAOld.ReadDataNew(aController, aDrive, xATABlock, aBuffer)) { Console.WriteLine("[Ext2|GroupDescriptors] Error while reading GroupDescriptor data"); return null; } } xResult[i] = xDescriptorPtr[i % 16]; } return xResult; } public static unsafe void PrintAllFilesAndDirectories(byte aController, byte aDrive) { //ushort* xBuffer = (ushort*)Heap.MemAlloc(512); ushort* xBuffer = null; if (!Hardware.Storage.ATAOld.ReadDataNew(aController, aDrive, 2, xBuffer)) { Console.WriteLine("[Ext2|SuperBlock] Error while reading SuperBlock data"); return; } SuperBlock xSuperBlock = *(SuperBlock*)xBuffer; int xBlockSize = (int)(1024 << (byte)(xSuperBlock.LogBlockSize)); uint xGroupsCount = xSuperBlock.INodesCount / xSuperBlock.INodesPerGroup; uint xGroupDescriptorsPerBlock = (uint)(xBlockSize / sizeof(GroupDescriptor)); GroupDescriptor[] xGroupDescriptors = ReadGroupDescriptorsOfBlock(aController, aDrive, xSuperBlock.FirstDataBlock + 1, xSuperBlock, xBuffer); if (xGroupDescriptors == null) { return; } bool[] xUsedINodes = new bool[32]; uint xCount = 0; INode* xINodeTable = (INode*)xBuffer; for (uint g = 0; g < xGroupDescriptors.Length; g++) { GroupDescriptor xGroupDescriptor = xGroupDescriptors[g]; if (!Hardware.Storage.ATAOld.ReadDataNew(aController, aDrive, (int)((xGroupDescriptor.INodeBitmap) * 8), xBuffer)) { return; } if (!ConvertBitmapToBoolArray((uint*)xBuffer, xUsedINodes)) { return; } for (int i = 0; i < 32; i++) { if ((i % 4) == 0) { uint index = (uint)((i % xSuperBlock.INodesPerGroup) * sizeof(INode)); uint offset = index / 512; if (!Hardware.Storage.ATAOld.ReadDataNew(aController, aDrive, (int)((xGroupDescriptor.INodeTable * 8) + offset), xBuffer)) { Console.WriteLine("[Ext2] Error reading INode table entries"); return; } } uint xINodeIdentifier = (uint)((g * xSuperBlock.INodesPerGroup) + i + 1); if (xINodeIdentifier == 0xB) { continue; } if (xUsedINodes[i]) { INode xINode = xINodeTable[i % 4]; //DebugUtil.SendExt2_INode((uint)((g * xSuperBlock.INodesPerGroup) + i), g, &xINodeTable[i % 4]); if ((xINode.Mode & INodeModeEnum.Directory) != 0) { //DebugUtil.SendNumber("Ext2", "Directory found", (uint)((g * xSuperBlock.INodesPerGroup) + i + 1), 32); if (!Hardware.Storage.ATAOld.ReadDataNew(aController, aDrive, (int)(xINode.Block1 * 8), xBuffer)) { Console.WriteLine("[Ext2] Error reading INode entries"); return; } DirectoryEntry* xEntryPtr = (DirectoryEntry*)xBuffer; uint xTotalSize = xINode.Size; while (xTotalSize != 0/* && xEntryPtr->@INode != 0*/) { //DebugUtil.SendExt2_DirectoryEntry(xEntryPtr); uint xPtrAddress = (uint)xEntryPtr; //if (xEntryPtr->@INode == 0xC) { char[] xName = new char[xEntryPtr->NameLength]; byte* xNamePtr = &xEntryPtr->FirstNameChar; for (int c = 0; c < xName.Length; c++) { xName[c] = (char)xNamePtr[c]; } string s = new String(xName); // DebugUtil.SendMessage("Ext2, DirectoryEntryName", s); //} xPtrAddress += xEntryPtr->RecordLength; xTotalSize -= xEntryPtr->RecordLength; xEntryPtr = (DirectoryEntry*)xPtrAddress; } } xCount++; } } } // DebugUtil.SendNumber("Ext2", "Used INode count", xCount, 32); } public static unsafe byte[] ReadFile(byte aController, byte aDrive, string[] xPath) { //ushort* xBuffer = (ushort*)Heap.MemAlloc(512); ushort* xBuffer = null; if (!Hardware.Storage.ATAOld.ReadDataNew(aController, aDrive, 2, xBuffer)) { Console.WriteLine("[Ext2|SuperBlock] Error while reading SuperBlock data"); return null; } SuperBlock xSuperBlock = *(SuperBlock*)xBuffer; //DebugUtil.SendExt2_SuperBlock("ReadFileContents", &xSuperBlock); int xBlockSize = (int)(1024 << (byte)(xSuperBlock.LogBlockSize)); uint xGroupsCount = xSuperBlock.INodesCount / xSuperBlock.INodesPerGroup; uint xGroupDescriptorsPerBlock = (uint)(xBlockSize / sizeof(GroupDescriptor)); GroupDescriptor[] xGroupDescriptors = ReadGroupDescriptorsOfBlock(aController, aDrive, xSuperBlock.FirstDataBlock + 1, xSuperBlock, xBuffer); if (xGroupDescriptors == null) { return null; } bool[] xUsedINodes = new bool[32]; uint xCount = 0; INode* xINodeTable = (INode*)xBuffer; uint xPathPointer = 0; uint xCurrentINode = 2; Console.WriteLine("Looking up directories"); Console.Write(" xPath.Length = "); Hardware.Storage.ATAOld.WriteNumber((uint)xPath.Length, 16); Console.WriteLine(""); int xIterations = 0; while (xPathPointer != (xPath.Length + 1)) { if (xIterations == 5) { Console.WriteLine("DEBUG: Stopping iteration"); break; } Console.WriteLine("Searching items"); Console.Write(" xPathPointer = "); Hardware.Storage.ATAOld.WriteNumber(xPathPointer, 16); Console.WriteLine(""); Console.Write(" xCurrentINode = "); Hardware.Storage.ATAOld.WriteNumber(xCurrentINode, 32); Console.WriteLine(""); // DebugUtil.SendNumber("Ext2", "Current INode", xCurrentINode, 32); for (uint g = 0; g < xGroupDescriptors.Length; g++) { GroupDescriptor xGroupDescriptor = xGroupDescriptors[g]; if (!Hardware.Storage.ATAOld.ReadDataNew(aController, aDrive, (int)((xGroupDescriptor.INodeBitmap) * 8), xBuffer)) { return null; } if (!ConvertBitmapToBoolArray((uint*)xBuffer, xUsedINodes)) { return null; } for (int i = 0; i < 32; i++) { if ((i % 4) == 0) { uint index = (uint)((i % xSuperBlock.INodesPerGroup) * sizeof(INode)); uint offset = index / 512; if (!Hardware.Storage.ATAOld.ReadDataNew(aController, aDrive, (int)((xGroupDescriptor.INodeTable * 8) + offset), xBuffer)) { Console.WriteLine("[Ext2] Error reading INode table entries"); return null; } } uint xINodeIdentifier = (uint)((g * xSuperBlock.INodesPerGroup) + i + 1); //DebugUtil.SendNumber("Ext2", "Checking INode", xINodeIdentifier, 32); if (xINodeIdentifier != xCurrentINode) { continue; } if (xUsedINodes[i]) { INode xINode = xINodeTable[i % 4]; //DebugUtil.SendExt2_INode((uint)((g * xSuperBlock.INodesPerGroup) + i), g, &xINodeTable[i % 4]); if (xPathPointer == xPath.Length) { #region temporary checks if (xINode.Block2 != 0) { Console.WriteLine("Multiblock files not supported yet!"); return null; } if (xINode.Block3 != 0) { Console.WriteLine("Multiblock files not supported yet!"); return null; } if (xINode.Block4 != 0) { Console.WriteLine("Multiblock files not supported yet!"); return null; } if (xINode.Block5 != 0) { Console.WriteLine("Multiblock files not supported yet!"); return null; } if (xINode.Block6 != 0) { Console.WriteLine("Multiblock files not supported yet!"); return null; } if (xINode.Block7 != 0) { Console.WriteLine("Multiblock files not supported yet!"); return null; } if (xINode.Block8 != 0) { Console.WriteLine("Multiblock files not supported yet!"); return null; } if (xINode.Block9 != 0) { Console.WriteLine("Multiblock files not supported yet!"); return null; } if (xINode.Block10 != 0) { Console.WriteLine("Multiblock files not supported yet!"); return null; } if (xINode.Block11 != 0) { Console.WriteLine("Multiblock files not supported yet!"); return null; } if (xINode.Block12 != 0) { Console.WriteLine("Multiblock files not supported yet!"); return null; } if (xINode.Block13 != 0) { Console.WriteLine("Multiblock files not supported yet!"); return null; } if (xINode.Block14 != 0) { Console.WriteLine("Multiblock files not supported yet!"); return null; } if (xINode.Block15 != 0) { Console.WriteLine("Multiblock files not supported yet!"); return null; } #endregion Console.WriteLine("Get file contents now"); if (!Hardware.Storage.ATAOld.ReadDataNew(aController, aDrive, (int)(xINode.Block1 * 8), xBuffer)) { Console.WriteLine("[Ext2] Error reading INode entries"); return null; } byte[] xResult = new byte[512]; byte* xByteBuff = (byte*)xBuffer; for (int b = 0; b < 512; b++) { xResult[b] = xByteBuff[b]; } return xResult; } else { if ((xINode.Mode & INodeModeEnum.Directory) != 0) { //DebugUtil.SendNumber("Ext2", "Directory found", (uint)((g * xSuperBlock.INodesPerGroup) + i + 1), 32); //DebugUtil.SendExt2_INode(xINodeIdentifier, g, &xINodeTable[i % 4]); //DebugUtil.SendExt2_INodeMode(xINodeIdentifier, (ushort)xINode.Mode); if (!Hardware.Storage.ATAOld.ReadDataNew(aController, aDrive, (int)(xINode.Block1 * 8), xBuffer)) { Console.WriteLine("[Ext2] Error reading INode entries"); return null; } DirectoryEntry* xEntryPtr = (DirectoryEntry*)xBuffer; uint xTotalSize = xINode.Size; while (xTotalSize != 0/* && xEntryPtr->@INode != 0*/) { //DebugUtil.SendExt2_DirectoryEntry(xEntryPtr); uint xPtrAddress = (uint)xEntryPtr; char[] xName = new char[xEntryPtr->NameLength]; byte* xNamePtr = &xEntryPtr->FirstNameChar; for (int c = 0; c < xName.Length; c++) { xName[c] = (char)xNamePtr[c]; } if (EqualsName(xPath[xPathPointer], xName)) { xPathPointer++; xCurrentINode = xEntryPtr->@INode; continue; } xPtrAddress += xEntryPtr->RecordLength; xTotalSize -= xEntryPtr->RecordLength; xEntryPtr = (DirectoryEntry*)xPtrAddress; } } } xCount++; } } } } //DebugUtil.SendMessage("Ext2", "Lookup file now"); //DebugUtil.SendExt2_SuperBlock("Looking up file", &xSuperBlock); //Console.WriteLine("Lookup file now:"); //DebugUtil.SendNumber("Ext2", "CurrentINode", xCurrentINode, 32); //uint xGroup = xCurrentINode / xSuperBlock.INodesPerGroup; //uint xGroupINodeBase = xGroup * xSuperBlock.INodesPerGroup; //for (int i = 0; i < 32; i++) { // if ((i % 4) == 0) { // uint index = (uint)((i % xSuperBlock.INodesPerGroup) * sizeof(INode)); // uint offset = index / 512; // if (!Hardware.Storage.ATA.ReadDataNew(aController, aDrive, (int)((xGroupDescriptors[xGroup].INodeTable * 8) + offset), xBuffer)) { // Console.WriteLine("[Ext2] Error reading INode entries"); // return null; // } // } // INode xItem = xINodeTable[i % 4]; // if (((xGroupINodeBase + i) == xCurrentINode) && ((xItem.Mode & INodeModeEnum.RegularFile) != 0)) { // DebugUtil.SendExt2_INode(xCurrentINode, xGroup, &xItem); // Console.WriteLine("File found :-)"); // //return null; // } //} //Console.WriteLine("Directory found"); //DebugUtil.SendNumber("Ext2", "Used INode count", xCount, 32); Console.WriteLine("TODO: Lookup File now"); return null; } private static unsafe bool ConvertBitmapToBoolArray(uint* aBitmap, bool[] aArray) { if (aArray == null || aArray.Length != 32) { Console.WriteLine("[ConvertBitmapToBoolArray] Incorrect Array"); return false; } uint xValue = *aBitmap; for (byte b = 0; b < 32; b++) { uint xCheckBit = (uint)(1 << b); aArray[b] = (xValue & xCheckBit) != 0; } return true; } private static bool EqualsName(string a1, char[] a2) { if (a1 == null || a2 == null) { return false; } if (a1.Length != a2.Length) { return false; } for (int i = 0; i < a1.Length; i++) { if (a1[i] != a2[i]) { return false; } } return true; } } }