Conflicts:
	Demos/Guess/GuessOS.cs
This commit is contained in:
Matthijs ter Woord 2015-07-08 16:02:11 +02:00
commit 21ed8e53bc
30 changed files with 657 additions and 258 deletions

14
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,14 @@
CosmosOS is a volunteer effort. We encourage you to pitch in. Join the team!
- Before you begin work, make sure to clear it with the project owners. It will save a lot of time down the road.
- Fork the project over to your account, do not request repostory access.
- Please don't "bump" your issue(s). If you've filed it, we have seen it.
Want to get started contributing to Cosmos? Check out the open issues page:
- [High priority](https://github.com/CosmosOS/Cosmos/issues?q=is%3Aopen+is%3Aissue+label%3Apriority_high)
- [Medium priority](https://github.com/CosmosOS/Cosmos/labels/priority_medium)
Thanks!
Cosmos Team

View file

@ -20,12 +20,12 @@
<OutputPath>bin\Debug\</OutputPath>
<Framework>MicrosoftNET</Framework>
<UseInternalAssembler>False</UseInternalAssembler>
<EnableGDB>False</EnableGDB>
<DebugMode>IL</DebugMode>
<EnableGDB>True</EnableGDB>
<DebugMode>Source</DebugMode>
<TraceMode>User</TraceMode>
<BuildTarget>PXE</BuildTarget>
<VMWareFlavor>Player</VMWareFlavor>
<StartCosmosGDB>False</StartCosmosGDB>
<StartCosmosGDB>True</StartCosmosGDB>
<VMwareEdition>Workstation</VMwareEdition>
<VMwareDeploy>ISO</VMwareDeploy>
<IgnoreDebugStubAttribute>False</IgnoreDebugStubAttribute>
@ -60,15 +60,15 @@
<VMware_Deployment>ISO</VMware_Deployment>
<VMware_Launch>VMware</VMware_Launch>
<VMware_DebugEnabled>True</VMware_DebugEnabled>
<VMware_DebugMode>IL</VMware_DebugMode>
<VMware_DebugMode>Source</VMware_DebugMode>
<VMware_IgnoreDebugStubAttribute>False</VMware_IgnoreDebugStubAttribute>
<VMware_VMwareEdition>Workstation</VMware_VMwareEdition>
<VMware_OutputPath>bin\Debug\</VMware_OutputPath>
<VMware_Framework>MicrosoftNET</VMware_Framework>
<VMware_UseInternalAssembler>False</VMware_UseInternalAssembler>
<VMware_TraceAssemblies>All</VMware_TraceAssemblies>
<VMware_EnableGDB>False</VMware_EnableGDB>
<VMware_StartCosmosGDB>False</VMware_StartCosmosGDB>
<VMware_EnableGDB>True</VMware_EnableGDB>
<VMware_StartCosmosGDB>True</VMware_StartCosmosGDB>
<ISO_Deployment>ISO</ISO_Deployment>
<ISO_Launch>None</ISO_Launch>
<ISO_DebugEnabled>False</ISO_DebugEnabled>
@ -138,7 +138,7 @@
<Bochs_ShowLaunchConsole>False</Bochs_ShowLaunchConsole>
<Bochs_DebugEnabled>True</Bochs_DebugEnabled>
<Bochs_StackCorruptionDetectionEnabled>True</Bochs_StackCorruptionDetectionEnabled>
<Bochs_DebugMode>Source</Bochs_DebugMode>
<Bochs_DebugMode>IL</Bochs_DebugMode>
<Bochs_IgnoreDebugStubAttribute>False</Bochs_IgnoreDebugStubAttribute>
<Bochs_VisualStudioDebugPort>Pipe: Cosmos\Serial</Bochs_VisualStudioDebugPort>
<Bochs_PxeInterface>192.168.43.1</Bochs_PxeInterface>
@ -186,12 +186,12 @@
<OutputPath>bin\Debug\</OutputPath>
<Framework>MicrosoftNET</Framework>
<UseInternalAssembler>False</UseInternalAssembler>
<EnableGDB>False</EnableGDB>
<DebugMode>IL</DebugMode>
<EnableGDB>True</EnableGDB>
<DebugMode>Source</DebugMode>
<TraceMode>User</TraceMode>
<BuildTarget>PXE</BuildTarget>
<VMWareFlavor>Player</VMWareFlavor>
<StartCosmosGDB>False</StartCosmosGDB>
<StartCosmosGDB>True</StartCosmosGDB>
<VMwareEdition>Workstation</VMwareEdition>
<VMwareDeploy>ISO</VMwareDeploy>
<IgnoreDebugStubAttribute>False</IgnoreDebugStubAttribute>
@ -226,15 +226,15 @@
<VMware_Deployment>ISO</VMware_Deployment>
<VMware_Launch>VMware</VMware_Launch>
<VMware_DebugEnabled>True</VMware_DebugEnabled>
<VMware_DebugMode>IL</VMware_DebugMode>
<VMware_DebugMode>Source</VMware_DebugMode>
<VMware_IgnoreDebugStubAttribute>False</VMware_IgnoreDebugStubAttribute>
<VMware_VMwareEdition>Workstation</VMware_VMwareEdition>
<VMware_OutputPath>bin\Debug\</VMware_OutputPath>
<VMware_Framework>MicrosoftNET</VMware_Framework>
<VMware_UseInternalAssembler>False</VMware_UseInternalAssembler>
<VMware_TraceAssemblies>All</VMware_TraceAssemblies>
<VMware_EnableGDB>False</VMware_EnableGDB>
<VMware_StartCosmosGDB>False</VMware_StartCosmosGDB>
<VMware_EnableGDB>True</VMware_EnableGDB>
<VMware_StartCosmosGDB>True</VMware_StartCosmosGDB>
<ISO_Deployment>ISO</ISO_Deployment>
<ISO_Launch>None</ISO_Launch>
<ISO_DebugEnabled>False</ISO_DebugEnabled>
@ -310,7 +310,7 @@
<Bochs_ShowLaunchConsole>False</Bochs_ShowLaunchConsole>
<Bochs_DebugEnabled>True</Bochs_DebugEnabled>
<Bochs_StackCorruptionDetectionEnabled>True</Bochs_StackCorruptionDetectionEnabled>
<Bochs_DebugMode>Source</Bochs_DebugMode>
<Bochs_DebugMode>IL</Bochs_DebugMode>
<Bochs_IgnoreDebugStubAttribute>False</Bochs_IgnoreDebugStubAttribute>
<Bochs_VisualStudioDebugPort>Pipe: Cosmos\Serial</Bochs_VisualStudioDebugPort>
<Bochs_PxeInterface>192.168.43.1</Bochs_PxeInterface>

View file

@ -29,10 +29,22 @@ namespace GuessKernel
private Debugger mDebugger = new Debugger("User", "Guess");
private class KVPClass
{
public int Key;
public int Value;
}
private struct KVPStruct
{
public int Key;
public int Value;
}
protected override void Run()
{
mCount++;
mDebugger.SendMessage("Kernel", "New iteration");
Console.WriteLine();
Console.WriteLine("Guess #" + mCount);

View file

@ -52,6 +52,7 @@
<Compile Include="Engine.Run.cs">
<DependentUpon>Engine.cs</DependentUpon>
</Compile>
<Compile Include="MultiplexingOutputHandler.cs" />
<Compile Include="OutputHandlerBase.cs" />
<Compile Include="OutputHandlerConsole.cs" />
<Compile Include="OutputHandlerText.cs" />

View file

@ -70,6 +70,9 @@ namespace Cosmos.TestRunner.Core
xBochs.OnShutDown = (a, b) =>
{
};
xBochs.RedirectOutput = true;
xBochs.LogError = s => OutputHandler.LogDebugMessage(s);
xBochs.LogOutput = s => OutputHandler.LogDebugMessage(s);
mBochsRunning = true;
xBochs.Start();
@ -79,7 +82,6 @@ namespace Cosmos.TestRunner.Core
mKernelResultSet = false;
Interlocked.Exchange(ref mSucceededAssertions, 0);
Console.WriteLine("Bochs started");
while (mBochsRunning)
{
Thread.Sleep(50);
@ -96,7 +98,6 @@ namespace Cosmos.TestRunner.Core
OutputHandler.SetKernelTestResult(true, null);
}
OutputHandler.SetKernelSucceededAssertionsCount(mSucceededAssertions);
Console.WriteLine("Stopping bochs now");
}
finally
{

View file

@ -0,0 +1,92 @@
using System;
namespace Cosmos.TestRunner.Core
{
public class MultiplexingOutputHandler: OutputHandlerBase
{
private readonly OutputHandlerBase[] mTargets;
public MultiplexingOutputHandler(params OutputHandlerBase[] targets)
{
mTargets = targets;
}
private void RunOnTargets(Action<OutputHandlerBase> action)
{
foreach (var xTarget in mTargets)
{
action(xTarget);
}
}
public override void ExecuteKernelStart(string assemblyName)
{
RunOnTargets(t => t.ExecuteKernelStart(assemblyName));
}
public override void ExecuteKernelEnd(string assemblyName)
{
RunOnTargets(t => t.ExecuteKernelEnd(assemblyName));
}
public override void LogDebugMessage(string message)
{
RunOnTargets(t => t.LogDebugMessage(message));
}
public override void LogMessage(string message)
{
RunOnTargets(t => t.LogMessage(message));
}
public override void LogError(string message)
{
RunOnTargets(t => t.LogError(message));
}
public override void ExecutionStart()
{
RunOnTargets(t => t.ExecutionStart());
}
public override void ExecutionEnd()
{
RunOnTargets(t => t.ExecutionEnd());
}
public override void UnhandledException(Exception exception)
{
RunOnTargets(t => t.UnhandledException(exception));
}
public override void TaskStart(string taskName)
{
RunOnTargets(t => t.TaskStart(taskName));
}
public override void TaskEnd(string taskName)
{
RunOnTargets(t => t.TaskEnd(taskName));
}
public override void SetKernelTestResult(bool succeeded, string message)
{
RunOnTargets(t => t.SetKernelTestResult(succeeded, message));
}
public override void RunConfigurationStart(RunConfiguration configuration)
{
RunOnTargets(t => t.RunConfigurationStart(configuration));
}
public override void RunConfigurationEnd(RunConfiguration configuration)
{
RunOnTargets(t => t.RunConfigurationEnd(configuration));
}
public override void SetKernelSucceededAssertionsCount(int succeededAssertions)
{
RunOnTargets(t => t.SetKernelSucceededAssertionsCount(succeededAssertions));
}
}
}

View file

@ -8,6 +8,7 @@ namespace Cosmos.TestRunner.Core
{
public abstract void ExecuteKernelStart(string assemblyName);
public abstract void ExecuteKernelEnd(string assemblyName);
public abstract void LogDebugMessage(string message);
public abstract void LogMessage(string message);
public abstract void LogError(string message);
public abstract void ExecutionStart();

View file

@ -15,13 +15,13 @@ namespace Cosmos.TestRunner.Core
Log("Running task '" + taskName + "'");
mCurrentTaskStopwatch.Reset();
mCurrentTaskStopwatch.Start();
mLogLevel = 3;
mLogLevel ++;
}
public override void TaskEnd(string taskName)
{
mCurrentTaskStopwatch.Stop();
mLogLevel = 2;
mLogLevel --;
Log("Done running task '" + taskName + "'. Took " + mCurrentTaskStopwatch.Elapsed);
}
@ -35,6 +35,9 @@ namespace Cosmos.TestRunner.Core
mLogLevel = 0;
Log("Done executing");
Log("Took " + mExecutionStopwatch.Elapsed);
Log(String.Format("{0} kernels succeeded their tests", mNumberOfSuccesses));
Log(String.Format("{0} kernels failed their tests", mNumberOfFailures));
}
public override void ExecutionStart()
@ -46,12 +49,20 @@ namespace Cosmos.TestRunner.Core
mLogLevel = 1;
}
public override void LogDebugMessage(string message)
{
}
public override void RunConfigurationStart(RunConfiguration configuration)
{
Log(string.Format("Start configuration. IsELF = {0}", configuration.IsELF));
mLogLevel++;
}
public override void RunConfigurationEnd(RunConfiguration configuration)
{
mLogLevel --;
}
public override void LogError(string message)
@ -61,13 +72,13 @@ namespace Cosmos.TestRunner.Core
public override void LogMessage(string message)
{
Log(message);
}
public override void ExecuteKernelEnd(string assemblyName)
{
mCurrentKernelStopwatch.Stop();
Log("Done running kernel. Took " + mCurrentKernelStopwatch.Elapsed);
mLogLevel--;
}
public override void ExecuteKernelStart(string assemblyName)
@ -75,6 +86,7 @@ namespace Cosmos.TestRunner.Core
Log("Starting kernel '" + assemblyName + "'");
mCurrentKernelStopwatch.Reset();
mCurrentKernelStopwatch.Start();
mLogLevel++;
}
private int mLogLevel;
@ -88,8 +100,19 @@ namespace Cosmos.TestRunner.Core
public override void SetKernelTestResult(bool succeeded, string message)
{
Log(string.Format("Success = {0}, Message = '{1}'", succeeded, message));
if (succeeded)
{
mNumberOfSuccesses++;
}
else
{
mNumberOfFailures++;
}
}
private int mNumberOfSuccesses = 0;
private int mNumberOfFailures = 0;
public override void SetKernelSucceededAssertionsCount(int succeededAssertions)
{
}

View file

@ -10,15 +10,13 @@ namespace Cosmos.TestRunner.Core
{
public partial class OutputHandlerXml: OutputHandlerBase
{
private readonly string mFilename;
private XmlDocument mDocument;
private bool mConfigurationSucceeded = false;
private bool mExecutionSucceeded = false;
public OutputHandlerXml(string filename)
public OutputHandlerXml()
{
mFilename = filename;
}
public override void ExecuteKernelStart(string assemblyName)
@ -42,11 +40,25 @@ namespace Cosmos.TestRunner.Core
xItem.Attributes.Append(NewXmlAttribute("Duration", mKernelStopwatch.Elapsed.ToString("c")));
}
public override void LogDebugMessage(string message)
{
var xParent = mCurrentNode.Peek();
var xNode = xParent.SelectSingleNode("./DebugMessages");
if (xNode == null)
{
xNode = mDocument.CreateElement("DebugMessages");
xParent.PrependChild(xNode);
}
var xItem = mDocument.CreateElement("Message");
xItem.InnerText = message;
xNode.AppendChild(xItem);
}
public override void LogMessage(string message)
{
var xParent = mCurrentNode.Peek();
var xItem = mDocument.CreateElement("Message");
xItem.AppendChild(mDocument.CreateCDataSection(message));
xItem.InnerText = message;
xParent.AppendChild(xItem);
}
@ -75,10 +87,14 @@ namespace Cosmos.TestRunner.Core
mExecutionStopwatch.Stop();
mDocument.DocumentElement.Attributes.Append(NewXmlAttribute("Duration", mExecutionStopwatch.Elapsed.ToString("c")));
mDocument.DocumentElement.Attributes.Append(NewXmlAttribute("Succeeded", mExecutionSucceeded.ToString()));
mDocument.Save(mFilename);
mCurrentNode.Pop();
}
public void SaveToFile(string filename)
{
mDocument.Save(filename);
}
private Stack<XmlElement> mCurrentNode = new Stack<XmlElement>();
private Stopwatch mTaskStopwatch;
private Stopwatch mConfigurationStopwatch;

View file

@ -34,6 +34,7 @@
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />

View file

@ -3,21 +3,42 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Cosmos.TestRunner.Core;
using Microsoft.Win32;
namespace Cosmos.TestRunner.Console
{
class Program
{
[STAThread]
static void Main(string[] args)
{
var xEngine = new Engine();
DefaultEngineConfiguration.Apply(xEngine);
xEngine.OutputHandler = new OutputHandlerXml(@"c:\data\CosmosTests.xml");
//xEngine.OutputHandler = new OutputHandlerConsole();
var xOutputXml = new OutputHandlerXml();
xEngine.OutputHandler = new MultiplexingOutputHandler(
xOutputXml,
new OutputHandlerConsole());
xEngine.Execute();
global::System.Console.WriteLine("Do you want to save test run details?");
global::System.Console.Write("Type yes, or nothing to just exit: ");
var xResult = global::System.Console.ReadLine();
if (xResult != null && xResult.Equals("yes", StringComparison.OrdinalIgnoreCase))
{
var xSaveDialog = new SaveFileDialog();
xSaveDialog.Filter = "XML documents|*.xml";
if (xSaveDialog.ShowDialog() != DialogResult.OK)
{
return;
}
xOutputXml.SaveToFile(xSaveDialog.FileName);
}
}
}
}

View file

@ -108,8 +108,6 @@ namespace SimpleStructsAndArraysTest
Assert.IsTrue(xItem2.E == 5, "xItem2.E == 5");
Console.Write("E: ");
Console.WriteLine(xItem2.E);
TestController.Completed();
}
private class KVPClass
@ -199,7 +197,7 @@ namespace SimpleStructsAndArraysTest
{
get
{
Assert.IsTrue(index == ExpectedIndex, "index = " + ExpectedIndex);
Assert.IsTrue(index == ExpectedIndex, "index == " + ExpectedIndex);
if (index >= this._size)
{
throw new Exception("Out of range!");
@ -212,7 +210,7 @@ namespace SimpleStructsAndArraysTest
}
protected static void TestSimpleItemsInArray()
protected static void TestOurList()
{
Assert.IsTrue(true, "Start of test");
var xListClasses = new OurList<KVPClass>();
@ -243,11 +241,40 @@ namespace SimpleStructsAndArraysTest
Assert.AreEqual(5, xStructItem.Value, "xListStructs[1].Value == 5");
}
protected static void TestStandardList()
{
Assert.IsTrue(true, "Start of test");
var xListClasses = new List<KVPClass>();
var xListStructs = new List<KVPStruct>();
xListClasses.Add(new KVPClass { Key = 1, Value = 2 });
xListClasses.Add(new KVPClass { Key = 2, Value = 5 });
var xListItem = xListClasses[0];
Assert.AreEqual(1, xListItem.Key, "xListClasses[0].Key == 1");
Assert.AreEqual(2, xListItem.Value, "xListClasses[0].Value == 2");
xListItem = xListClasses[1];
Assert.AreEqual(2, xListItem.Key, "xListClasses[1].Key == 2");
Assert.AreEqual(5, xListItem.Value, "xListClasses[1].Value == 5");
xListStructs.Add(new KVPStruct { Key = 1, Value = 2 });
xListStructs.Add(new KVPStruct { Key = 2, Value = 5 });
var xStructItem = xListStructs[0];
Assert.AreEqual(1, xStructItem.Key, "xListStructs[0].Key == 1");
Assert.AreEqual(2, xStructItem.Value, "xListStructs[0].Value == 2");
xStructItem = xListStructs[1];
Assert.AreEqual(2, xStructItem.Key, "xListStructs[1].Key == 2");
Assert.AreEqual(5, xStructItem.Value, "xListStructs[1].Value == 5");
}
protected override void Run()
{
TestStep1();
TestSimpleItemsInArray();
Assert.IsTrue(true, "After TestSimpleItemsInArray");
TestOurList();
Assert.IsTrue(true, "After TestOurList");
TestStandardList();
Assert.IsTrue(true, "After TestStandardList");
TestController.Completed();
}
}

View file

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Text;
using System.IO;
using SentinelKernel.System.FileSystem.VFS;
using Cosmos.Common.Extensions;
using Sys = Cosmos.System;
namespace SentinelKernel
@ -26,32 +27,55 @@ namespace SentinelKernel
var xRoot = Path.GetPathRoot(@"0:\test");
bool xTest = Directory.Exists("0:\\test");
Console.WriteLine("After test");
if (xTest)
{
Console.WriteLine("Folder exists!");
xTest = Directory.Exists("0:\\test\\DirInTest");
if (xTest)
{
Console.WriteLine("Subfolder exists as well!");
}
else
{
Console.WriteLine("Subfolder doesn't exist!");
}
}
else
if (!xTest)
{
Console.WriteLine("Folder does not exist!");
return;
}
Console.WriteLine("Folder exists!");
xTest = Directory.Exists("0:\\test\\DirInTest");
if (!xTest)
{
Console.WriteLine("Subfolder doesn't exist!");
return;
}
Console.WriteLine("Subfolder exists as well!");
xTest = File.Exists(@"0:\KudzU.txt");
if (!xTest)
{
Console.WriteLine(@"\Kudzu.txt not found!");
return;
}
Console.WriteLine("Kudzu.txt found!");
xTest = File.Exists(@"0:\Test\DirInTest\Readme.txt");
if (!xTest)
{
Console.WriteLine(@"\Test\DirInTest\Readme.txt not found!");
return;
}
Console.WriteLine(@"Test\DirInTest\Readme.txt found!");
Console.Write("File contents of Kudzu.txt: ");
Console.WriteLine(File.ReadAllText(@"0:\Kudzu.txt"));
Console.WriteLine(@"File contents of Test\DirInTest\Readme.txt: ");
Console.WriteLine(File.ReadAllText(@"0:\Test\DirInTest\Readme.txt"));
}
catch (Exception e)
{
Console.WriteLine("Exception occurred:");
Console.WriteLine(e.Message);
}
Stop();
finally
{
while (true)
;
}
}
}
}

View file

@ -1,11 +1,14 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Cosmos.Common.Extensions;
using Cosmos.HAL.BlockDevice;
using SentinelKernel.System.FileSystem.FAT.Listing;
using SentinelKernel.System.FileSystem.Listing;
using Directory = SentinelKernel.System.FileSystem.Listing.Directory;
using File = SentinelKernel.System.FileSystem.Listing.File;
namespace SentinelKernel.System.FileSystem.FAT
{
@ -241,17 +244,20 @@ namespace SentinelKernel.System.FileSystem.FAT
{
var xResult = new List<Base>();
//TODO: Change xLongName to StringBuilder
string xLongName = "";
string xName = "";
for (UInt32 i = 0; i < xData.Length; i = i + 32)
{
FatHelpers.Debug("-------------------------------------------------");
string xLongName = "";
byte xAttrib = xData[i + 11];
FatHelpers.Debug("Attrib = " + xAttrib.ToString());
byte xStatus = xData[i];
FatHelpers.Debug("Attrib = " + xAttrib.ToString() + ", Status = " + xStatus);
if (xAttrib == DirectoryEntryAttributeConsts.LongName)
{
byte xType = xData[i + 12];
byte xOrd = xData[i];
FatHelpers.Debug("Reading LFN with Seqnr " + xOrd.ToString());
FatHelpers.Debug("Reading LFN with Seqnr " + xOrd.ToString() + ", Type = " + xType);
if (xOrd == 0xE5)
{
FatHelpers.Debug("Skipping deleted entry");
@ -280,65 +286,74 @@ namespace SentinelKernel.System.FileSystem.FAT
}
}
xLongName = xLongPart + xLongName;
xLongPart = null;
//TODO: LDIR_Chksum
}
}
string xName = xLongName;
byte xStatus = xData[i];
if (xStatus == 0x00)
else
{
// Empty slot, and no more entries after this
break;
}
else if (xStatus == 0x05)
{
// Japanese characters - We dont handle these
}
else if (xStatus == 0xE5)
{
// Empty slot, skip it
}
else if (xStatus >= 0x20)
{
if (xLongName.Length > 0)
xName = xLongName;
if (xStatus == 0x00)
{
// Leading and trailing spaces are to be ignored according to spec.
// Many programs (including Windows) pad trailing spaces although it
// it is not required for long names.
// As per spec, ignore trailing periods
xName = xLongName.Trim();
//If there are trailing periods
int nameIndex = xName.Length - 1;
if (xName[nameIndex] == '.')
{
//Search backwards till we find the first non-period character
for (; nameIndex > 0; nameIndex--)
{
if (xName[nameIndex] != '.')
{
break;
}
}
//Substring to remove the periods
xName = xName.Substring(0, nameIndex + 1);
}
// Empty slot, and no more entries after this
break;
}
else
else if (xStatus == 0x05)
{
string xEntry = xData.GetAsciiString(i, 11);
xName = xEntry.Substring(0, 8).TrimEnd();
string xExt = xEntry.Substring(8, 3).TrimEnd();
if (xExt.Length > 0)
// Japanese characters - We dont handle these
}
else if (xStatus == 0xE5)
{
// Empty slot, skip it
}
else if (xStatus >= 0x20)
{
if (xLongName.Length > 0)
{
xName = xName + "." + xExt;
// Leading and trailing spaces are to be ignored according to spec.
// Many programs (including Windows) pad trailing spaces although it
// it is not required for long names.
// As per spec, ignore trailing periods
xName = xLongName.Trim();
//If there are trailing periods
int nameIndex = xName.Length - 1;
if (xName[nameIndex] == '.')
{
//Search backwards till we find the first non-period character
for (; nameIndex > 0; nameIndex--)
{
if (xName[nameIndex] != '.')
{
break;
}
}
//Substring to remove the periods
xName = xName.Substring(0, nameIndex + 1);
}
xLongName = "";
}
else
{
string xEntry = xData.GetAsciiString(i, 11);
xName = xEntry.Substring(0, 8).TrimEnd();
string xExt = xEntry.Substring(8, 3).TrimEnd();
if (xExt.Length > 0)
{
xName = xName + "." + xExt;
}
}
}
}
UInt32 xFirstCluster = (UInt32)(xData.ToUInt16(i + 20) << 16 | xData.ToUInt16(i + 26));
var xTest = xAttrib & (DirectoryEntryAttributeConsts.Directory | DirectoryEntryAttributeConsts.VolumeID);
if (xTest == 0)
if (xAttrib == DirectoryEntryAttributeConsts.LongName)
{
// skip adding, as it's a LongFileName entry, meaning the next normal entry is the item with the name.
FatHelpers.Debug("Entry was an Long FileName entry. Current LongName = '" + xLongName + "'");
}
else if (xTest == 0)
{
UInt32 xSize = xData.ToUInt32(i + 28);
if (xSize == 0 && xName.Length == 0)
@ -348,11 +363,11 @@ namespace SentinelKernel.System.FileSystem.FAT
xResult.Add(new FatFile(this, xName, xSize, xFirstCluster));
FatHelpers.Debug("Returning file '" + xName + "'");
}
else if (xTest == DirectoryEntryAttributeConsts.Directory || xAttrib == DirectoryEntryAttributeConsts.LongName)
else if (xTest == DirectoryEntryAttributeConsts.Directory)
{
UInt32 xSize = xData.ToUInt32(i + 28);
var xFatDirectory = new FatDirectory(this, xName, xFirstCluster);
FatHelpers.Debug("Returning directory '" + xFatDirectory.Name + "'");
FatHelpers.Debug("Returning directory '" + xFatDirectory.Name + "', FirstCluster = " + xFirstCluster);
xResult.Add(xFatDirectory);
}
else if (xTest == DirectoryEntryAttributeConsts.VolumeID)
@ -364,7 +379,6 @@ namespace SentinelKernel.System.FileSystem.FAT
{
FatHelpers.Debug("Not sure what to do!");
}
xLongName = "";
}
return xResult;
@ -394,5 +408,15 @@ namespace SentinelKernel.System.FileSystem.FAT
return GetDirectoryContents((FatDirectory)baseDirectory);
}
}
public override Directory GetRootDirectory(string name)
{
return new FatDirectory(this, name, RootCluster);
}
public override Stream GetFileStream(File fileInfo)
{
return new FatStream((FatFile)fileInfo);
}
}
}

View file

@ -8,7 +8,7 @@ namespace SentinelKernel.System.FileSystem
private static Debugger mDebugger = new Debugger("FAT", "Debug");
public static void Debug(string message)
{
mDebugger.Send("FAT Debug: " + message);
//mDebugger.Send("FAT Debug: " + message);
}
}
}

View file

@ -1,9 +1,11 @@
using Cosmos.HAL.BlockDevice;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using SentinelKernel.System.FileSystem.Listing;
using Directory = SentinelKernel.System.FileSystem.Listing.Directory;
using File = SentinelKernel.System.FileSystem.Listing.File;
namespace SentinelKernel.System.FileSystem
{
@ -41,5 +43,8 @@ namespace SentinelKernel.System.FileSystem
}
public abstract List<Listing.Base> GetDirectoryListing(Directory baseDirectory);
public abstract Directory GetRootDirectory(string name);
public abstract Stream GetFileStream(File fileInfo);
}
}

View file

@ -134,36 +134,40 @@ namespace SentinelKernel.System.FileSystem.VFS
#endregion
public static Listing.File GetFile(string aPath)
public static Listing.File TryGetFile(string aPath)
{
if (string.IsNullOrEmpty(aPath))
{
throw new ArgumentNullException("aPath");
}
return null;
/*
string xFileName = Path.GetFileName(aPath);
string xDirectory = Path.GetDirectoryName(aPath) + Path.DirectorySeparatorChar;
foreach (var xEntry in GetDirectoryListing(xDirectory))
string xDirectory = Path.GetDirectoryName(aPath);
var xLastChar = xDirectory[xDirectory.Length - 1];
if (xLastChar != Path.DirectorySeparatorChar)
{
if ((xEntry is FileSystem.Listing.File) && (xEntry.Name == xFileName))
xDirectory = xDirectory + Path.DirectorySeparatorChar;
}
var xList = GetDirectoryListing(xDirectory);
for (int i = 0; i < xList.Count; i++)
{
var xEntry = xList[i];
var xFile = xEntry as Listing.File;
if (xFile != null && String.Equals(xEntry.Name, xFileName, StringComparison.OrdinalIgnoreCase))
{
return (xEntry as FileSystem.Listing.File);
return xFile;
}
}
return null;
*/
}
public static List<Listing.File> GetFiles(string aPath)
{
if (string.IsNullOrEmpty(aPath))
{
throw new ArgumentNullException("sPath");
throw new ArgumentNullException("aPath");
}
return null;
@ -272,10 +276,12 @@ namespace SentinelKernel.System.FileSystem.VFS
{
try
{
return (VFSManager.GetFile(aPath) != null);
return (VFSManager.TryGetFile(aPath) != null);
}
catch (Exception)
catch (Exception E)
{
Console.Write("Exception occurred: ");
Console.WriteLine(E.Message);
return false;
}
}
@ -297,5 +303,16 @@ namespace SentinelKernel.System.FileSystem.VFS
}
}
public static Stream GetFileStream(string aPathname)
{
var xFileInfo = TryGetFile(aPathname);
if (xFileInfo == null)
{
throw new Exception("File not found: " + aPathname);
}
return xFileInfo.FileSystem.GetFileStream(xFileInfo);
}
}
}

View file

@ -8,6 +8,7 @@ using System.IO;
using SentinelKernel.System.FileSystem.FAT;
using SentinelKernel.System.FileSystem.Listing;
using Console = global::System.Console;
using Directory = SentinelKernel.System.FileSystem.Listing.Directory;
namespace SentinelKernel.System.FileSystem.VFS
{
@ -199,12 +200,12 @@ namespace SentinelKernel.System.FileSystem.VFS
for (int i = 0; i < mFileSystems.Count; i++)
{
string xTest = mFileSystems[i].Key;
if (xTest == xPath)
if (String.Equals(xTest, xPath))
{
return mFileSystems[i].Value;
}
}
return null;
throw new Exception("Unable to determine filesystem for path: " + aPath);
}
public override void Initialize()
@ -221,55 +222,63 @@ namespace SentinelKernel.System.FileSystem.VFS
public override Listing.Directory GetDirectory(string aPath)
{
string[] xPathParts = VFSManager.SplitPath(aPath);
var xFS = GetFileSystemFromPath(aPath);
if (xFS != null)
return DoGetDirectory(aPath, xFS);
}
private Directory DoGetDirectory(string aPath, FileSystem aFS)
{
if (aFS == null)
{
if (xPathParts.Length == 1)
throw new ArgumentNullException("aFS");
}
string[] xPathParts = VFSManager.SplitPath(aPath);
if (xPathParts.Length == 1)
{
return GetVolume(aFS, aPath);
}
Listing.Directory xBaseDirectory = null;
// start at index 1, because 0 is the volume
for (int i = 1; i < xPathParts.Length; i++)
{
var xPathPart = xPathParts[i];
var xPartFound = false;
var xListing = aFS.GetDirectoryListing(xBaseDirectory);
for (int j = 0; j < xListing.Count; j++)
{
return GetVolume(xPathParts[0]);
}
Listing.Directory xBaseDirectory = null;
// start at index 1, because 0 is the volume
for (int i = 1; i < xPathParts.Length; i++)
{
var xPathPart = xPathParts[i];
var xPartFound = false;
var xListing = xFS.GetDirectoryListing(xBaseDirectory);
for (int j = 0; j < xListing.Count; j++)
var xListingItem = xListing[j];
if (String.Equals(xListingItem.Name, xPathPart, StringComparison.OrdinalIgnoreCase))
{
var xListingItem = xListing[j];
if (String.Equals(xListingItem.Name, xPathPart, StringComparison.OrdinalIgnoreCase))
if (xListingItem is Listing.Directory)
{
if (xListingItem is Listing.Directory)
{
xBaseDirectory = (Listing.Directory)xListingItem;
xPartFound = true;
}
else
{
throw new Exception("Path part '" + xPathPart + "' found, but not a directory!");
}
xBaseDirectory = (Listing.Directory)xListingItem;
xPartFound = true;
}
else
{
throw new Exception("Path part '" + xPathPart + "' found, but not a directory!");
}
}
if (!xPartFound)
{
throw new Exception("Path part '" + xPathPart + "' not found!");
}
}
return xBaseDirectory;
if (!xPartFound)
{
throw new Exception("Path part '" + xPathPart + "' not found!");
}
}
return null;
return xBaseDirectory;
}
public override List<Listing.Base> GetDirectoryListing(string aPath)
{
throw new NotImplementedException();
var xFS = GetFileSystemFromPath(aPath);
var xDirectory = DoGetDirectory(aPath, xFS);
return xFS.GetDirectoryListing(xDirectory);
}
public override List<Listing.Base> GetDirectoryListing(Listing.Directory aParentDirectory)
@ -287,6 +296,11 @@ namespace SentinelKernel.System.FileSystem.VFS
throw new NotImplementedException();
}
public Listing.Directory GetVolume(FileSystem filesystem, string name)
{
return filesystem.GetRootDirectory(name);
}
/*
public override SentinelKernel.System.FileSystem.Listing.Directory GetVolume(string aVolume)
{

View file

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Cosmos.Common.Extensions;
using Cosmos.IL2CPU.Plugs;
using SentinelKernel.System.FileSystem.VFS;
@ -16,9 +17,23 @@ namespace SentinelKernel.System.Plugs.System.IO
return FileSystem.VFS.VFSManager.FileExists(aFile);
}
//public static string ReadAllText(string aFile)
//{
// //Find file
public static string ReadAllText(string aFile)
{
using (var xFS = new FileStream(aFile, FileMode.Open))
{
var xBuff = new byte[(int)xFS.Length];
var xResult = xFS.Read(xBuff, 0, xBuff.Length);
if (xResult != xBuff.Length)
{
throw new Exception("Couldn't read complete file!");
}
return xBuff.GetUtf8String(0, (uint)xBuff.Length);
}
}
// if (!File.Exists(aFile))
// return "Could not find file " + aFile;
// //throw new FileNotFoundException("Could not find file " + aFile);
@ -26,4 +41,4 @@ namespace SentinelKernel.System.Plugs.System.IO
// return VFSManager.ReadFileAsString(aFile);
//}
}
}
}

View file

@ -8,38 +8,50 @@ using SentinelKernel.System.FileSystem.VFS;
namespace SentinelKernel.System.Plugs.System.IO
{
[Plug(Target = typeof(IO::FileStream))]
public class FileStreamImpl {
[Plug(Target = typeof(IO::FileStream))]
[PlugField(FieldId = "$$InnerStream$$", FieldType = typeof(IO::Stream))]
public class FileStreamImpl
{
// This plug basically forwards all calls to the $$InnerStream$$ stream, which is supplied by the file system.
// public static unsafe void Ctor(String aThis, [FieldAccess(Name = "$$Storage$$")]ref Char[] aStorage, Char[] aChars, int aStartIndex, int aLength,
public static void Ctor(IO::FileStream aThis, string aPathname, IO::FileMode aMode, [FieldAccess(Name = "$$InnerStream$$")] ref IO::Stream innerStream)
{
innerStream = VFSManager.GetFileStream(aPathname);
}
public static void CCtor()
{
// plug cctor as it (indirectly) uses Thread.MemoryBarrier()
}
public static int Read(IO::FileStream aThis, byte[] aBuffer, int aOffset, int aCount, [FieldAccess(Name = "$$InnerStream$$")] ref IO::Stream innerStream)
{
return innerStream.Read(aBuffer, aOffset, aCount);
}
public static long get_Length(IO::FileStream aThis, [FieldAccess(Name = "$$InnerStream$$")] ref IO::Stream innerStream)
{
return innerStream.Length;
}
public static void SetLength(IO::FileStream aThis, long value)
{
throw new NotImplementedException();
}
public static void Dispose(IO::FileStream aThis, bool disposing)
{
throw new NotImplementedException();
}
//static void Init(IO::FileStream aThis, string path, IO::FileMode mode, IO::FileAccess access, int rights, bool useRights, IO::FileShare share, int bufferSize
// , IO::FileOptions options, Microsoft.Win32.Win32Native.SECURITY_ATTRIBUTES secAttrs, string msgPath, bool bFromProxy) { }
//[PlugField(FieldId = "$$Storage$$", FieldType = typeof(char[]))]
//[PlugField(FieldId = "System.Char System.String.m_firstChar", IsExternalValue = true)]
//public static class StringImpl {
// //[PlugMethod(Signature = "System_Void__System_String__ctor_System_Char____System_Int32__System_Int32_")]
// public static unsafe void Ctor(String aThis, [FieldAccess(Name = "$$Storage$$")]ref Char[] aStorage, Char[] aChars, int aStartIndex, int aLength,
// [FieldAccess(Name = "System.Int32 System.String.m_stringLength")] ref int aStringLength,
// [FieldAccess(Name = "System.Char System.String.m_firstChar")] ref char* aFirstChar) {
// Char[] newChars = new Char[aLength];
// Array.Copy(aChars, aStartIndex, newChars, 0, aLength);
// aStorage = newChars;
// aStringLength = newChars.Length;
// fixed (char* xFirstChar = &aStorage[0]) {
// aFirstChar = xFirstChar;
// }
// }
static public void Ctor(IO::FileStream aThis, string aPathname, IO::FileMode aMode) {
}
static public void CCtor() {
// plug cctor as it (indirectly) uses Thread.MemoryBarrier()
}
static public int Read(IO::FileStream aThis, byte[] aBuffer, int aOffset, int aCount) {
return 0;
}
//static void Init(IO::FileStream aThis, string path, IO::FileMode mode, IO::FileAccess access, int rights, bool useRights, IO::FileShare share, int bufferSize
// , IO::FileOptions options, Microsoft.Win32.Win32Native.SECURITY_ATTRIBUTES secAttrs, string msgPath, bool bFromProxy) { }
}
}

View file

@ -245,7 +245,12 @@ namespace SentinelKernel.System.Plugs.System.IO
return null;
}
aPath = NormalizePath(aPath, false);
return aPath.Substring(0, GetRootLength(aPath));
var xResult = aPath.Substring(0, GetRootLength(aPath));
if (xResult[xResult.Length - 1] != Path.DirectorySeparatorChar)
{
xResult = xResult + Path.DirectorySeparatorChar;
}
return xResult;
}
public static string GetRandomFileName()

View file

@ -35,6 +35,21 @@ namespace Cosmos.Common.Extensions {
return new string(xChars);
}
static public string GetUtf8String(this byte[] n, UInt32 aStart, UInt32 aCharCount)
{
// TODO: This method handles ASCII only currently, no unicode.
var xChars = new char[aCharCount];
for (int i = 0; i < aCharCount; i++)
{
xChars[i] = (char)n[(aStart) + i];
if (xChars[i] == 0)
{
return new string(xChars, 0, i);
}
}
return new string(xChars);
}
static public string GetUtf16String(this byte[] n, UInt32 aStart, UInt32 aCharCount) {
//TODO: This routine only handles ASCII. It does not handle unicode yet.
var xChars = new char[aCharCount];

View file

@ -4,3 +4,6 @@ indent_style=space
[Host/*.cs]
indent_size=2
[AD7.Impl/AD7StackFrame.cs]
indent_size=2

View file

@ -13,7 +13,7 @@ using SQLinq;
using SQLinq.Dapper;
namespace Cosmos.Debug.VSDebugEngine {
// Represents a logical stack frame on the thread stack.
// Represents a logical stack frame on the thread stack.
// Also implements the IDebugExpressionContext interface, which allows expression evaluation and watch windows.
public class AD7StackFrame : IDebugStackFrame2, IDebugExpressionContext2 {
readonly AD7Engine mEngine;
@ -24,7 +24,7 @@ namespace Cosmos.Debug.VSDebugEngine {
private string mFunctionName;
private uint mLineNum;
private bool mHasSource;
// Must have empty holders, some code looks at length and can run
// before we set them.
internal LOCAL_ARGUMENT_INFO[] mLocalInfos = new LOCAL_ARGUMENT_INFO[] {};
@ -36,7 +36,7 @@ namespace Cosmos.Debug.VSDebugEngine {
// An array of this frame's locals
private DebugLocalInfo[] mLocals;
private AD7Process mProcess;
public AD7StackFrame(AD7Engine aEngine, AD7Thread aThread, AD7Process aProcess)
{
mEngine = aEngine;
@ -49,7 +49,7 @@ namespace Cosmos.Debug.VSDebugEngine {
var xSourceInfos = xProcess.mDebugInfoDb.GetSourceInfos(xAddress);
if (!xSourceInfos.ContainsKey(xAddress))
{
//Attempt to find the ASM address of the first ASM line of the C# line that contains
//Attempt to find the ASM address of the first ASM line of the C# line that contains
//the current ASM address line
// Because of Asm breakpoints the address we have might be in the middle of a C# line.
@ -83,7 +83,7 @@ namespace Cosmos.Debug.VSDebugEngine {
xSymbolInfo = aProcess.mDebugInfoDb.Connection.Query<MethodIlOp>(new SQLinq<MethodIlOp>().Where(q => q.LabelName == xLabel)).FirstOrDefault();
if (xSymbolInfo != null)
{
var xMethod = mProcess.mDebugInfoDb.Connection.Get<Method>(xSymbolInfo.MethodID);
var xMethod = mProcess.mDebugInfoDb.Connection.Get<Method>(xSymbolInfo.MethodID);
var xAllInfos = aProcess.mDebugInfoDb.Connection.Query<LOCAL_ARGUMENT_INFO>(new SQLinq<LOCAL_ARGUMENT_INFO>().Where(q => q.METHODLABELNAME == xMethod.LabelCall));
mLocalInfos = xAllInfos.Where(q => !q.IsArgument).ToArray();
mArgumentInfos = xAllInfos.Where(q => q.IsArgument).ToArray();
@ -99,6 +99,7 @@ namespace Cosmos.Debug.VSDebugEngine {
IsLocal = false
};
}
mParams = mParams.OrderBy(i => i.Name, StringComparer.OrdinalIgnoreCase).ToArray();
}
if (mLocalInfos.Length > 0)
@ -113,6 +114,7 @@ namespace Cosmos.Debug.VSDebugEngine {
IsLocal = true
};
}
mLocals = mLocals.OrderBy(i => i.Name, StringComparer.OrdinalIgnoreCase).ToArray();
}
}
}
@ -278,6 +280,7 @@ namespace Cosmos.Debug.VSDebugEngine {
}
}
propInfo = propInfo.OrderBy(i => i.bstrName).ToArray();
enumObject = new AD7PropertyInfoEnum(propInfo);
}
@ -291,6 +294,7 @@ namespace Cosmos.Debug.VSDebugEngine {
propInfo[i] = property.ConstructDebugPropertyInfo(enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_STANDARD);
}
propInfo = propInfo.OrderBy(i => i.bstrName).ToArray();
enumObject = new AD7PropertyInfoEnum(propInfo);
}
@ -304,6 +308,7 @@ namespace Cosmos.Debug.VSDebugEngine {
propInfo[i] = property.ConstructDebugPropertyInfo(enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_STANDARD);
}
propInfo = propInfo.OrderBy(i => i.bstrName).ToArray();
enumObject = new AD7PropertyInfoEnum(propInfo);
}
@ -364,7 +369,7 @@ namespace Cosmos.Debug.VSDebugEngine {
}
// Gets a description of the properties of a stack frame.
// Calling the IDebugProperty2::EnumChildren method with appropriate filters can retrieve the local variables, method parameters, registers, and "this"
// Calling the IDebugProperty2::EnumChildren method with appropriate filters can retrieve the local variables, method parameters, registers, and "this"
// pointer associated with the stack frame. The debugger calls EnumProperties to obtain these values in the sample.
int IDebugStackFrame2.GetDebugProperty(out IDebugProperty2 property) {
throw new NotImplementedException();
@ -400,8 +405,8 @@ namespace Cosmos.Debug.VSDebugEngine {
}
// Gets an evaluation context for expression evaluation within the current context of a stack frame and thread.
// Generally, an expression evaluation context can be thought of as a scope for performing expression evaluation.
// Call the IDebugExpressionContext2::ParseText method to parse an expression and then call the resulting IDebugExpression2::EvaluateSync
// Generally, an expression evaluation context can be thought of as a scope for performing expression evaluation.
// Call the IDebugExpressionContext2::ParseText method to parse an expression and then call the resulting IDebugExpression2::EvaluateSync
// or IDebugExpression2::EvaluateAsync methods to evaluate the parsed expression.
int IDebugStackFrame2.GetExpressionContext(out IDebugExpressionContext2 ppExprCxt) {
ppExprCxt = (IDebugExpressionContext2)this;
@ -424,7 +429,7 @@ namespace Cosmos.Debug.VSDebugEngine {
}
}
// Gets the language associated with this stack frame.
// Gets the language associated with this stack frame.
// In this sample, all the supported stack frames are C++
int IDebugStackFrame2.GetLanguageInfo(ref string pbstrLanguage, ref Guid pguidLanguage) {
pbstrLanguage = "CSharp";
@ -466,9 +471,9 @@ namespace Cosmos.Debug.VSDebugEngine {
#endregion
// Retrieves the name of the evaluation context.
// The name is the description of this evaluation context. It is typically something that can be parsed by an expression evaluator
// that refers to this exact evaluation context. For example, in C++ the name is as follows:
// Retrieves the name of the evaluation context.
// The name is the description of this evaluation context. It is typically something that can be parsed by an expression evaluator
// that refers to this exact evaluation context. For example, in C++ the name is as follows:
// "{ function-name, source-file-name, module-file-name }"
int IDebugExpressionContext2.GetName(out string pbstrName) {
throw new NotImplementedException();

View file

@ -32,11 +32,11 @@ namespace Cosmos.Debug.VSDebugEngine.Host
"floppy_bootsig_check: disabled=0\n" +
"# no floppya\n" +
"# no floppyb\n" +
"ata0-master: type=cdrom, path=\"%CDROMBOOTPATH%\", status=inserted, model=\"Generic 1234\", biosdetect=auto\n" +
"ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14\n" +
"ata0-master: type=disk, path=\"%HARDDISKPATH%\", mode=vmware4, cylinders=0, heads=0, spt=0, model=\"Generic 1234\", biosdetect=auto, translation=auto\n" +
"ata0-slave: type=none\n" +
"ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15\n" +
"ata1-master: type=cdrom, path=\"%CDROMBOOTPATH%\", status=inserted, model=\"Generic 1234\", biosdetect=auto\n" +
"ata1-master: type=disk, path=\"%HARDDISKPATH%\", mode=vmware4, cylinders=0, heads=0, spt=0, model=\"Generic 1234\", biosdetect=auto, translation=auto\n" +
"ata2: enabled=0\n" +
"ata3: enabled=0\n" +
"pci: enabled=1, chipset=i440fx\n" +
@ -85,11 +85,8 @@ namespace Cosmos.Debug.VSDebugEngine.Host
defaultConfigs.Set("com1", defaultConfigs.Get("com1").Replace("%PIPESERVERNAME%", xParts[1].ToLower()));
var xHarddiskFile = Path.Combine(CosmosPaths.Build, @"VMWare\Workstation\Filesystem.vmdk");
defaultConfigs.Set("ata0-master", defaultConfigs.Get("ata0-master").Replace("%HARDDISKPATH%", xHarddiskFile));
defaultConfigs.Set("ata1-master", defaultConfigs.Get("ata1-master").Replace("%CDROMBOOTPATH%", mParams["ISOFile"]));
defaultConfigs.Set("ata0-master", defaultConfigs.Get("ata0-master").Replace("%CDROMBOOTPATH%", mParams["ISOFile"]));
defaultConfigs.Set("ata1-master", defaultConfigs.Get("ata1-master").Replace("%HARDDISKPATH%", xHarddiskFile));
}
private void GenerateConfiguration(string filePath)

View file

@ -72,6 +72,11 @@ namespace Cosmos.Debug.VSDebugEngine.Host
}
}
public bool RedirectOutput = false;
public Action<string> LogOutput;
public Action<string> LogError;
/// <summary>Initialize and start the Bochs process.</summary>
public override void Start()
{
@ -86,12 +91,31 @@ namespace Cosmos.Debug.VSDebugEngine.Host
_bochsStartInfo.Arguments = string.Format("-q -f \"{0}\"", _bochsConfigurationFile.FullName);
_bochsStartInfo.WorkingDirectory = _bochsConfigurationFile.Directory.FullName;
_bochsStartInfo.UseShellExecute = false;
if (RedirectOutput)
{
if (LogOutput == null)
{
throw new Exception("No LogOutput handler specified!");
}
if (LogError == null)
{
throw new Exception("No LogError handler specified!");
}
_bochsStartInfo.RedirectStandardOutput = true;
_bochsStartInfo.RedirectStandardError = true;
_bochsProcess.OutputDataReceived += (sender, args) => LogOutput(args.Data);
_bochsProcess.ErrorDataReceived += (sender, args) => LogError(args.Data);
}
// Register for process completion event so that we can funnel it to any code that
// subscribed to this event in our base class.
_bochsProcess.EnableRaisingEvents = true;
_bochsProcess.Exited += ExitCallback;
_bochsProcess.Start();
if (RedirectOutput)
{
_bochsProcess.BeginErrorReadLine();
_bochsProcess.BeginOutputReadLine();
}
return;
}

View file

@ -1,2 +1,8 @@
[*.cs]
indent_size=4
[Global.cs]
indent_size = 2
[BlockDevice/Ata.cs]
indent_size = 2

View file

@ -2,15 +2,19 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Cosmos.Debug.Kernel;
namespace Cosmos.HAL.BlockDevice {
public abstract class Ata : BlockDevice {
public abstract class Ata : BlockDevice
{
internal static Debugger AtaDebugger = new Debugger("HAL", "Ata");
protected Ata() {
mBlockSize = 512;
}
// In future may need to add a None for PCI ATA controllers.
// In future may need to add a None for PCI ATA controllers.
// Or maybe they all have Primary and Secondary on them as well.
public enum ControllerIdEnum { Primary, Secondary }
protected ControllerIdEnum mControllerID;

View file

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Text;
using System.Threading;
using Cosmos.Common;
using Cosmos.Debug.Kernel;
namespace Cosmos.HAL.BlockDevice
{
@ -80,7 +81,7 @@ namespace Cosmos.HAL.BlockDevice
//* Bit 6: LBA (0: CHS, 1: LBA).
LBA = 0x40,
//* Bit 5: Obsolete and isn't used, but should be set.
//* Bit 7: Obsolete and isn't used, but should be set.
//* Bit 7: Obsolete and isn't used, but should be set.
Default = 0xA0
};
@ -127,6 +128,13 @@ namespace Cosmos.HAL.BlockDevice
}
#endregion
internal static Debugger mDebugger = new Debugger("HAL", "AtaPio");
private static void Debug(string message)
{
mDebugger.Send("AtaPio debug: " + message);
}
public AtaPio(Core.IOGroup.ATA aIO, Ata.ControllerIdEnum aControllerId, Ata.BusPositionEnum aBusPosition)
{
IO = aIO;
@ -180,10 +188,10 @@ namespace Cosmos.HAL.BlockDevice
}
// ATA requires a wait of 400 nanoseconds.
// Read the Status register FIVE TIMES, and only pay attention to the value
// returned by the last one -- after selecting a new master or slave device. The point being that
// you can assume an IO port read takes approximately 100ns, so doing the first four creates a 400ns
// delay -- which allows the drive time to push the correct voltages onto the bus.
// Read the Status register FIVE TIMES, and only pay attention to the value
// returned by the last one -- after selecting a new master or slave device. The point being that
// you can assume an IO port read takes approximately 100ns, so doing the first four creates a 400ns
// delay -- which allows the drive time to push the correct voltages onto the bus.
// Since we read status again later, we wait by reading it 4 times.
protected void Wait()
{
@ -206,7 +214,6 @@ namespace Cosmos.HAL.BlockDevice
return SendCmd(aCmd, true);
}
public Status SendCmd(Cmd aCmd, bool aThrowOnError)
{
IO.Command.Byte = (byte)aCmd;
@ -221,6 +228,7 @@ namespace Cosmos.HAL.BlockDevice
if (aThrowOnError && (xStatus & Status.Error) != 0)
{
// TODO: Read error port
Debug("ATA Error in SendCmd. Cmd = " + (byte)aCmd + ", Status = " + (byte)xStatus);
throw new Exception("ATA Error");
}
return xStatus;
@ -228,7 +236,7 @@ namespace Cosmos.HAL.BlockDevice
protected string GetString(UInt16[] aBuffer, int aIndexStart, int aStringLength)
{
// Would be nice to convert to byte[] and use
// Would be nice to convert to byte[] and use
// new string(ASCIIEncoding.ASCII.GetChars(xBytes));
// But it requires some code Cosmos doesnt support yet
var xChars = new char[aStringLength];
@ -256,13 +264,13 @@ namespace Cosmos.HAL.BlockDevice
// Not sure if all this is needed, its different than documented elsewhere but might not be bad
// to add code to do all listed here:
//
//To use the IDENTIFY command, select a target drive by sending 0xA0 for the master drive, or 0xB0 for the slave, to the "drive select" IO port. On the Primary bus, this would be port 0x1F6.
// Then set the Sectorcount, LBAlo, LBAmid, and LBAhi IO ports to 0 (port 0x1F2 to 0x1F5).
// Then send the IDENTIFY command (0xEC) to the Command IO port (0x1F7).
// Then read the Status port (0x1F7) again. If the value read is 0, the drive does not exist. For any other value: poll the Status port (0x1F7) until bit 7 (BSY, value = 0x80) clears.
// Because of some ATAPI drives that do not follow spec, at this point you need to check the LBAmid and LBAhi ports (0x1F4 and 0x1F5) to see if they are non-zero.
//To use the IDENTIFY command, select a target drive by sending 0xA0 for the master drive, or 0xB0 for the slave, to the "drive select" IO port. On the Primary bus, this would be port 0x1F6.
// Then set the Sectorcount, LBAlo, LBAmid, and LBAhi IO ports to 0 (port 0x1F2 to 0x1F5).
// Then send the IDENTIFY command (0xEC) to the Command IO port (0x1F7).
// Then read the Status port (0x1F7) again. If the value read is 0, the drive does not exist. For any other value: poll the Status port (0x1F7) until bit 7 (BSY, value = 0x80) clears.
// Because of some ATAPI drives that do not follow spec, at this point you need to check the LBAmid and LBAhi ports (0x1F4 and 0x1F5) to see if they are non-zero.
// If so, the drive is not ATA, and you should stop polling. Otherwise, continue polling one of the Status ports until bit 3 (DRQ, value = 8) sets, or until bit 0 (ERR, value = 1) sets.
// At that point, if ERR is clear, the data is ready to read from the Data port (0x1F0). Read 256 words, and store them.
// At that point, if ERR is clear, the data is ready to read from the Data port (0x1F0). Read 256 words, and store them.
// Read Identification Space of the Device
var xBuff = new UInt16[256];
@ -310,7 +318,7 @@ namespace Cosmos.HAL.BlockDevice
IO.SectorCount.Byte = (byte)aSectorCount;
IO.LBA0.Byte = (byte)(aSectorNo);
IO.LBA1.Byte = (byte)(aSectorNo >> 8);
IO.LBA2.Byte = (byte)(aSectorNo >> 16);
IO.LBA2.Byte = (byte)(aSectorNo >> 16);
//IO.LBA0.Byte = (byte)(aSectorNo & 0xFF);
//IO.LBA1.Byte = (byte)((aSectorNo & 0xFF00) >> 8);
//IO.LBA2.Byte = (byte)((aSectorNo & 0xFF0000) >> 16);
@ -347,4 +355,4 @@ namespace Cosmos.HAL.BlockDevice
}
}
}
}

View file

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Cosmos.HAL.BlockDevice;
namespace Cosmos.HAL {
static public class Global {
@ -14,46 +15,57 @@ namespace Cosmos.HAL {
public static PCI Pci;
static void InitAta(BlockDevice.Ata.ControllerIdEnum aControllerID, BlockDevice.Ata.BusPositionEnum aBusPosition) {
private static void InitAta(BlockDevice.Ata.ControllerIdEnum aControllerID, BlockDevice.Ata.BusPositionEnum aBusPosition)
{
var xIO = aControllerID == BlockDevice.Ata.ControllerIdEnum.Primary ? Cosmos.Core.Global.BaseIOGroups.ATA1 : Cosmos.Core.Global.BaseIOGroups.ATA2;
var xATA = new BlockDevice.AtaPio(xIO, aControllerID, aBusPosition);
if (xATA.DriveType != BlockDevice.AtaPio.SpecLevel.Null) {
if (xATA.DriveType == BlockDevice.AtaPio.SpecLevel.Null)
{
return;
}
if (xATA.DriveType == BlockDevice.AtaPio.SpecLevel.ATA)
{
BlockDevice.BlockDevice.Devices.Add(xATA);
var xMbrData = new byte[512];
xATA.ReadBlock(0UL, 1U, xMbrData);
var xMBR = new BlockDevice.MBR(xMbrData);
}
else
{
Ata.AtaDebugger.Send("ATA device with spec level " + (int)xATA.DriveType + " found, which is not supported!");
return;
}
var xMbrData = new byte[512];
xATA.ReadBlock(0UL, 1U, xMbrData);
var xMBR = new BlockDevice.MBR(xMbrData);
if (xMBR.EBRLocation != 0)
{
//EBR Detected
var xEbrData = new byte[512];
xATA.ReadBlock(xMBR.EBRLocation, 1U, xEbrData);
var xEBR = new BlockDevice.EBR(xEbrData);
if (xMBR.EBRLocation != 0)
{
//EBR Detected
var xEbrData = new byte[512];
xATA.ReadBlock(xMBR.EBRLocation, 1U, xEbrData);
var xEBR = new BlockDevice.EBR(xEbrData);
for (int i = 0; i < xEBR.Partitions.Count; i++)
{
//var xPart = xEBR.Partitions[i];
//var xPartDevice = new BlockDevice.Partition(xATA, xPart.StartSector, xPart.SectorCount);
//BlockDevice.BlockDevice.Devices.Add(xPartDevice);
}
}
for (int i = 0; i < xEBR.Partitions.Count; i++)
{
//var xPart = xEBR.Partitions[i];
//var xPartDevice = new BlockDevice.Partition(xATA, xPart.StartSector, xPart.SectorCount);
//BlockDevice.BlockDevice.Devices.Add(xPartDevice);
}
}
// TODO Change this to foreach when foreach is supported
Console.WriteLine("Number of MBR partitions found: " + xMBR.Partitions.Count);
for (int i = 0; i < xMBR.Partitions.Count; i++)
{
var xPart = xMBR.Partitions[i];
if (xPart == null)
{
Console.WriteLine("Null partition found at idx " + i);
}
else
{
var xPartDevice = new BlockDevice.Partition(xATA, xPart.StartSector, xPart.SectorCount);
BlockDevice.BlockDevice.Devices.Add(xPartDevice);
Console.WriteLine("Found partition at idx " + i);
}
}
// TODO Change this to foreach when foreach is supported
Console.WriteLine("Number of MBR partitions found: " + xMBR.Partitions.Count);
for (int i = 0; i < xMBR.Partitions.Count; i++)
{
var xPart = xMBR.Partitions[i];
if (xPart == null)
{
Console.WriteLine("Null partition found at idx " + i);
}
else
{
var xPartDevice = new BlockDevice.Partition(xATA, xPart.StartSector, xPart.SectorCount);
BlockDevice.BlockDevice.Devices.Add(xPartDevice);
Console.WriteLine("Found partition at idx " + i);
}
}
}