From d64f99adf3fbd2a1a37fb4f81eaeb9f208a14b0a Mon Sep 17 00:00:00 2001 From: BlueSkeye_cp <7a9a8e0be1356805ba39aaefd2f72a2ce9bd2015XwR8pJkz> Date: Thu, 20 Sep 2012 09:41:02 +0000 Subject: [PATCH] Add Bochs debugging support to Visual Studio Cosmos project (UI). A new pane and associated launch type is added in the Cosmos project properties pane. --- .../Cosmos.Build.Common/BuildProperties.cs | 9 +- .../Build/Cosmos.Build.Common/CosmosPaths.cs | 27 ++++- .../Build/Cosmos.Build.MSBuild/IL2CPUTask.cs | 19 ++- .../Debug/Cosmos.Debug.Common/BochsSupport.cs | 89 ++++++++++++++ .../Cosmos.Debug.Common.csproj | 1 + .../AD7.Impl/AD7Process.cs | 13 ++- .../Cosmos.Debug.VSDebugEngine.csproj | 4 - .../Cosmos.Debug.VSDebugEngine/Host/Bochs.cs | 109 +++++++----------- .../ResourceStrings.Designer.cs | 11 +- .../ResourceStrings.resx | 7 +- .../Cosmos.VS.Package/CosmosPage.Designer.cs | 35 +++++- source2/VSIP/Cosmos.VS.Package/CosmosPage.cs | 44 ++++++- .../VSIP/Cosmos.VS.Package/ProfilePresets.cs | 3 + .../Projects/Cosmos/Cosmos.vstemplate | 1 + .../Proj/CosmosProj.vstemplate | 4 +- .../Cosmos.VS.Wizards.csproj | 1 + source2/VSIP/Cosmos.VS.Wizards/Cosmos.bxrc | 44 +++++++ .../GenerateCosmosProjectWizard.cs | 30 ++++- 18 files changed, 355 insertions(+), 96 deletions(-) create mode 100644 source2/Debug/Cosmos.Debug.Common/BochsSupport.cs create mode 100644 source2/VSIP/Cosmos.VS.Wizards/Cosmos.bxrc diff --git a/source2/Build/Cosmos.Build.Common/BuildProperties.cs b/source2/Build/Cosmos.Build.Common/BuildProperties.cs index e94083e80..216d9a020 100644 --- a/source2/Build/Cosmos.Build.Common/BuildProperties.cs +++ b/source2/Build/Cosmos.Build.Common/BuildProperties.cs @@ -64,7 +64,7 @@ namespace Cosmos.Build.Common { Launch = LaunchType.None; } else if (aName == "Bochs") { - Description = "Use Bochs emulatior to deploy and debug."; + Description = "Use Bochs emulator to deploy and debug."; Deployment = DeploymentType.ISO; Launch = LaunchType.Bochs; } @@ -202,5 +202,12 @@ namespace Cosmos.Build.Common { get { return GetProperty(StartCosmosGDBString, false); } set { SetProperty(StartCosmosGDBString, value); } } + + public const string EnableBochsDebugString = "EnableBochsDebug"; + public Boolean EnableBochsDebug + { + get { return GetProperty(EnableBochsDebugString, false); } + set { SetProperty(EnableBochsDebugString, value); } + } } } \ No newline at end of file diff --git a/source2/Build/Cosmos.Build.Common/CosmosPaths.cs b/source2/Build/Cosmos.Build.Common/CosmosPaths.cs index 6e4d5a30c..1a1562c21 100644 --- a/source2/Build/Cosmos.Build.Common/CosmosPaths.cs +++ b/source2/Build/Cosmos.Build.Common/CosmosPaths.cs @@ -25,11 +25,17 @@ namespace Cosmos.Build.Common { } static CosmosPaths() { - using (var xReg = Registry.LocalMachine.OpenSubKey(@"Software\Cosmos", false)) { - if (xReg == null) { - throw new Exception(@"HKEY_LOCAL_MACHINE\SOFTWARE\Cosmos was not found."); + using (RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32)) + { + using (var xReg = baseKey.OpenSubKey(@"Software\Cosmos", false)) { + if (xReg == null) { + throw new Exception(@"HKEY_LOCAL_MACHINE\SOFTWARE\Cosmos was not found."); + } + UserKit = (string)xReg.GetValue("UserKit"); + if (null == UserKit) { + throw new Exception(@"HKEY_LOCAL_MACHINE\SOFTWARE\Cosmos\@UserKit was not found."); + } } - UserKit = (string)xReg.GetValue("UserKit"); } Build = CheckPath(UserKit, @"Build"); Vsip = CheckPath(UserKit, @"Build\VSIP"); @@ -41,9 +47,20 @@ namespace Cosmos.Build.Common { using (var xReg = Registry.CurrentUser.OpenSubKey(@"Software\Cosmos", false)) { if (xReg != null) { DevKit = (string)xReg.GetValue("DevKit"); - DebugStubSrc = CheckPath(DevKit, @"source2\Compiler\Cosmos.Compiler.DebugStub"); + if (null == DevKit) { + throw new Exception(@"HKEY_LOCAL_MACHINE\SOFTWARE\Cosmos\@DevKit was not found."); + } + try { DebugStubSrc = CheckPath(DevKit, @"source2\Compiler\Cosmos.Compiler.DebugStub"); } + // Not finding this one is not an issue. We will fallback to already retrieved stun from UserKit + catch { } } } } + + /// This method is intentionally empty. It's sole purpose is to be able to trigger + /// class initialization in a controlled manner so as to intercept initializer thrown + /// exceptions. + public static void Initialize() { + } } } \ No newline at end of file diff --git a/source2/Build/Cosmos.Build.MSBuild/IL2CPUTask.cs b/source2/Build/Cosmos.Build.MSBuild/IL2CPUTask.cs index 0f0fc38ce..f9162a473 100644 --- a/source2/Build/Cosmos.Build.MSBuild/IL2CPUTask.cs +++ b/source2/Build/Cosmos.Build.MSBuild/IL2CPUTask.cs @@ -85,10 +85,28 @@ namespace Cosmos.Build.MSBuild { } return null; } + + private bool EnsureCosmosPathsInitialization() { + try { + CosmosPaths.Initialize(); + return true; + } catch (Exception e) + { + StringBuilder builder = new StringBuilder(); + builder.Append("Error while initializing Cosmos paths"); + for (Exception scannedException = e; null != scannedException; scannedException = scannedException.InnerException) + { + builder.Append(" | " + scannedException.Message); + } + LogError(builder.ToString()); + return false; + } + } protected bool Initialize() { // Add UserKit dirs for asms to load from. mSearchDirs.Add(Path.GetDirectoryName(typeof(IL2CPU).Assembly.Location)); + if (!EnsureCosmosPathsInitialization()) { return false; } mSearchDirs.Add(CosmosPaths.UserKit); mSearchDirs.Add(CosmosPaths.Kernel); AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); @@ -135,7 +153,6 @@ namespace Cosmos.Build.MSBuild { } public bool Execute() { - //System.Diagnostics.Debugger.Launch(); try { LogMessage("Executing IL2CPU on assembly"); if (!Initialize()) { diff --git a/source2/Debug/Cosmos.Debug.Common/BochsSupport.cs b/source2/Debug/Cosmos.Debug.Common/BochsSupport.cs new file mode 100644 index 000000000..b478f69aa --- /dev/null +++ b/source2/Debug/Cosmos.Debug.Common/BochsSupport.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +using Microsoft.Win32; + +namespace Cosmos.Debug.Common +{ + /// An helper class that is used from both Cosmos.VS.Package and Cosmos.VS.DebugEngine for + /// Bochs emulator support. + public static class BochsSupport + { + static BochsSupport() + { + FindBochsExe(); + } + + /// Get a flag that tell whether Bochs is enabled on this system. + public static bool BochsEnabled + { + get { return (null != BochsExe); } + } + + /// Get a descriptor for the Bochs emulator with debugger support program. The return value + /// is a null reference if Bochs is not installed. + public static FileInfo BochsDebugExe + { + get; + private set; + } + + /// Get a descriptor for the Bochs emulator program. The return value is a null reference if + /// Bochs is not installed. + public static FileInfo BochsExe + { + get; + private set; + } + + /// Retrieve installation path for Bochs and initialize the property. + /// Search is performed using the registry and rely on the shell command defined for the + /// BochsConfigFile. + private static void FindBochsExe() + { + try + { + using (var runCommandRegistryKey = Registry.ClassesRoot.OpenSubKey(@"BochsConfigFile\shell\Run\command", false)) + { + if (null == runCommandRegistryKey) { return; } + string commandLine = (string)runCommandRegistryKey.GetValue(null, null); + if (null != commandLine) { commandLine = commandLine.Trim(); } + if (string.IsNullOrEmpty(commandLine)) { return; } + // Now perform some parsing on command line to discover full exe path. + string candidateFilePath; + int commandLineLength = commandLine.Length; + if ('"' == commandLine[0]) + { + // Seek for a non escaped double quote. + int lastDoubleQuoteIndex = 1; + for (; lastDoubleQuoteIndex < commandLineLength; lastDoubleQuoteIndex++) + { + if ('"' != commandLine[lastDoubleQuoteIndex]) { continue; } + if ('\\' != commandLine[lastDoubleQuoteIndex - 1]) { break; } + } + if (lastDoubleQuoteIndex >= commandLineLength) { return; } + candidateFilePath = commandLine.Substring(1, lastDoubleQuoteIndex - 1); + } + else + { + // Seek for first separator character. + int firstSeparatorIndex = 0; + for (; firstSeparatorIndex < commandLineLength; firstSeparatorIndex++) + { + if (char.IsSeparator(commandLine[firstSeparatorIndex])) { break; } + } + if (firstSeparatorIndex >= commandLineLength) { return; } + candidateFilePath = commandLine.Substring(0, firstSeparatorIndex); + } + if (!File.Exists(candidateFilePath)) { return; } + BochsExe = new FileInfo(candidateFilePath); + BochsDebugExe = new FileInfo(Path.Combine(BochsExe.Directory.FullName, "bochsdbg.exe")); + return; + } + } + catch { return; } + } + } +} diff --git a/source2/Debug/Cosmos.Debug.Common/Cosmos.Debug.Common.csproj b/source2/Debug/Cosmos.Debug.Common/Cosmos.Debug.Common.csproj index eee5b7e58..ef59a5729 100644 --- a/source2/Debug/Cosmos.Debug.Common/Cosmos.Debug.Common.csproj +++ b/source2/Debug/Cosmos.Debug.Common/Cosmos.Debug.Common.csproj @@ -96,6 +96,7 @@ + diff --git a/source2/Debug/Cosmos.Debug.VSDebugEngine/AD7.Impl/AD7Process.cs b/source2/Debug/Cosmos.Debug.VSDebugEngine/AD7.Impl/AD7Process.cs index 61307f284..23b772b43 100644 --- a/source2/Debug/Cosmos.Debug.VSDebugEngine/AD7.Impl/AD7Process.cs +++ b/source2/Debug/Cosmos.Debug.VSDebugEngine/AD7.Impl/AD7Process.cs @@ -104,7 +104,12 @@ namespace Cosmos.Debug.VSDebugEngine { mDbgConnector = null; string xPort = mDebugInfo[BuildProperties.VisualStudioDebugPortString]; - var xParts = xPort.Split(' '); + var xParts = (null == xPort) ? null : xPort.Split(' '); + if ((null == xParts) || (2 > xParts.Length)) { + throw new Exception(string.Format( + "The '{0}' Cosmos project file property is either ill-formed or missing.", + BuildProperties.VisualStudioDebugPortString)); + } string xPortType = xParts[0].ToLower(); string xPortParam = xParts[1].ToLower(); @@ -168,6 +173,9 @@ namespace Cosmos.Debug.VSDebugEngine { mHost = new Host.Slave(mDebugInfo, xUseGDB); break; case LaunchType.Bochs: + // The project has been created on another machine or Bochs has been uninstalled since the project has + // been created. + if (!BochsSupport.BochsEnabled) { throw new Exception(ResourceStrings.BochsIsNotInstalled); } string bochsConfigurationFileName = mDebugInfo[BuildProperties.BochsEmulatorConfigurationFileString]; if (string.IsNullOrEmpty(bochsConfigurationFileName)) { bochsConfigurationFileName = BuildProperties.BochsDefaultConfigurationFileName; @@ -181,6 +189,9 @@ namespace Cosmos.Debug.VSDebugEngine { // TODO : What if the configuration file doesn't exist ? This will throw a FileNotFoundException in // the Bochs class constructor. Is this appropriate behavior ? mHost = new Host.Bochs(mDebugInfo, xUseGDB, bochsConfigurationFile); + ((Host.Bochs)mHost).FixBochsConfiguration(new KeyValuePair[] + { new KeyValuePair("IsoFileName", mISO) } + ); break; default: throw new Exception("Invalid Launch value: '" + mLaunch + "'."); diff --git a/source2/Debug/Cosmos.Debug.VSDebugEngine/Cosmos.Debug.VSDebugEngine.csproj b/source2/Debug/Cosmos.Debug.VSDebugEngine/Cosmos.Debug.VSDebugEngine.csproj index d355efd91..2f3e323f8 100644 --- a/source2/Debug/Cosmos.Debug.VSDebugEngine/Cosmos.Debug.VSDebugEngine.csproj +++ b/source2/Debug/Cosmos.Debug.VSDebugEngine/Cosmos.Debug.VSDebugEngine.csproj @@ -181,8 +181,4 @@ --> - - - - \ No newline at end of file diff --git a/source2/Debug/Cosmos.Debug.VSDebugEngine/Host/Bochs.cs b/source2/Debug/Cosmos.Debug.VSDebugEngine/Host/Bochs.cs index 6baa159cb..7dd745984 100644 --- a/source2/Debug/Cosmos.Debug.VSDebugEngine/Host/Bochs.cs +++ b/source2/Debug/Cosmos.Debug.VSDebugEngine/Host/Bochs.cs @@ -1,9 +1,4 @@ -// DO NOT remove this line. Consider commenting it out. When the symbol is enabled the Bochs debug -// enbabled version will be launched instead of the regular one. The debug enabled version breaks -// in Bochs internal debugger as soon as the emulator starts. You must use the 'c' (continue) command -// in the Bochs console for the emulation to proceed. -// #define USE_BOCHSDBG -using System; +using System; using System.Collections.Specialized; using System.Collections.Generic; using System.Diagnostics; @@ -13,26 +8,19 @@ using System.Text; using Microsoft.Win32; +using Cosmos.Build.Common; +using Cosmos.Debug.Common; + namespace Cosmos.Debug.VSDebugEngine.Host { /// This class handles interactions with the Bochs emulation environment. public class Bochs : Base { - /// The Bochs runtime. - private static FileInfo _bochsExe; -#if USE_BOCHSDBG - /// The Bochs runtime with internal debugger enabled. - private static FileInfo _bochsDebugExe; -#endif /// The emulator process once started. private static Process _bochsProcess; /// The configuration file to be used when launching the Bochs virtual machine. private FileInfo _bochsConfigurationFile; - - static Bochs() - { - FindBochsExe(); - } + private bool _useDebugVersion; /// Instanciation occurs when debugging engine is invoked to launch the process in suspended /// mode. Bochs process will eventually be launched later when debugging engine is instructed to @@ -43,53 +31,32 @@ namespace Cosmos.Debug.VSDebugEngine.Host if (null == configurationFile) { throw new ArgumentNullException("configurationFile"); } if (!configurationFile.Exists) { throw new FileNotFoundException("Configuration file doesn't exist."); } _bochsConfigurationFile = configurationFile; + bool parseSucceeded = bool.TryParse(aParams[BuildProperties.EnableBochsDebugString], out _useDebugVersion); + return; } - /// Get a flag that tell whether Bochs is enabled on this system. - public bool BochsEnabled + /// Fix the content of the configuration file, replacing each of the symbolic variable occurence + /// with its associated value. + /// A set of key/value pairs where the key is the name of a variable. The value is + /// used for variable replacement. Variables are case sensistive. + internal void FixBochsConfiguration(KeyValuePair[] symbols) { - get { return (null != _bochsExe); } - } + if ((null == symbols) || (0 == symbols.Length)) { return; } + string content; + using (StreamReader reader = new StreamReader(File.Open(_bochsConfigurationFile.FullName, FileMode.Open, FileAccess.Read))) + { + content = reader.ReadToEnd(); + } + foreach (KeyValuePair pair in symbols) + { + string variableName = string.Format("$({0})", pair.Key); - /// Retrieve installation path for Bochs and initialize the field. - /// Search is performed using the registry and rely on the shell command defined for the - /// BochsConfigFile. - private static void FindBochsExe() - { - using (var runCommandRegistryKey = Registry.ClassesRoot.OpenSubKey(@"BochsConfigFile\shell\Run\command", false)) { - if (null == runCommandRegistryKey) { return; } - string commandLine = (string)runCommandRegistryKey.GetValue(null, null); - if (null != commandLine) { commandLine = commandLine.Trim(); } - if (string.IsNullOrEmpty(commandLine)) { return; } - // Now perform some parsing on command line to discover full exe path. - string candidateFilePath; - int commandLineLength = commandLine.Length; - if ('"' == commandLine[0]) { - // Seek for a non escaped double quote. - int lastDoubleQuoteIndex = 1; - for (; lastDoubleQuoteIndex < commandLineLength; lastDoubleQuoteIndex++) { - if ('"' != commandLine[lastDoubleQuoteIndex]) { continue; } - if ('\\' != commandLine[lastDoubleQuoteIndex - 1]) { break; } - } - if (lastDoubleQuoteIndex >= commandLineLength) { return; } - candidateFilePath = commandLine.Substring(1, lastDoubleQuoteIndex - 1); + content.Replace(variableName, pair.Value); } - else { - // Seek for first separator character. - int firstSeparatorIndex = 0; - for(; firstSeparatorIndex < commandLineLength; firstSeparatorIndex++) { - if (char.IsSeparator(commandLine[firstSeparatorIndex])) { break; } - } - if (firstSeparatorIndex >= commandLineLength) { return; } - candidateFilePath = commandLine.Substring(0, firstSeparatorIndex); + using (StreamWriter writer = new StreamWriter(File.Open(_bochsConfigurationFile.FullName, FileMode.Create, FileAccess.Write))) + { + writer.Write(content); } - if (!File.Exists(candidateFilePath)) { return; } - _bochsExe = new FileInfo(candidateFilePath); -#if USE_BOCHSDBG - _bochsDebugExe = new FileInfo(Path.Combine(_bochsExe.Directory.FullName, "bochsdbg.exe")); -#endif - return; - } } /// Initialize and start the Bochs process. @@ -97,37 +64,39 @@ namespace Cosmos.Debug.VSDebugEngine.Host { _bochsProcess = new Process(); ProcessStartInfo _bochsStartInfo = _bochsProcess.StartInfo; -#if USE_BOCHSDBG - _bochsStartInfo.FileName = _bochsDebugExe.FullName; -#else - _bochsStartInfo.FileName = _bochsExe.FullName; -#endif + _bochsStartInfo.FileName = (_useDebugVersion && BochsSupport.BochsDebugExe.Exists) + ? BochsSupport.BochsDebugExe.FullName + : BochsSupport.BochsExe.FullName; // Start Bochs without displaying the configuration interface (-q) and using the specified // configuration file (-f). The user is intended to edit the configuration file coming with // the Cosmos project whenever she wants to modify the environment. _bochsStartInfo.Arguments = string.Format("-q -f \"{0}\"", _bochsConfigurationFile.FullName); _bochsStartInfo.WorkingDirectory = _bochsConfigurationFile.Directory.FullName; + _bochsStartInfo.UseShellExecute = false; // 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 += delegate(object sender, EventArgs e) - { - if (null != OnShutDown) { OnShutDown(sender, e); } - }; + _bochsProcess.Exited += ExitCallback; _bochsProcess.Start(); return; } + private void ExitCallback(object sender, EventArgs e) + { + if (null != OnShutDown) { try { OnShutDown(sender, e); } catch { } } + } + public override void Stop() { - // TODO BlueSkeye : How are we supposed to stop the bochs process ? - CleanUp(); + if (null != _bochsProcess) { try { _bochsProcess.Kill(); } catch { } } + CleanUp(); } private void CleanUp() { - // TODO BlueSkeye : What kind of garbage may Bochs have left for us to clean ? + _bochsProcess.Exited -= ExitCallback; + // TODO BlueSkeye : What kind of garbage may Bochs have left for us to clean ? } } } diff --git a/source2/Debug/Cosmos.Debug.VSDebugEngine/ResourceStrings.Designer.cs b/source2/Debug/Cosmos.Debug.VSDebugEngine/ResourceStrings.Designer.cs index b41565ee2..1c8842a1f 100644 --- a/source2/Debug/Cosmos.Debug.VSDebugEngine/ResourceStrings.Designer.cs +++ b/source2/Debug/Cosmos.Debug.VSDebugEngine/ResourceStrings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.1 +// Runtime Version:4.0.30319.276 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -60,6 +60,15 @@ namespace Cosmos.Debug.VSDebugEngine { } } + /// + /// Looks up a localized string similar to The Bochs emulator doesn't seem to be installed on this machine.. + /// + internal static string BochsIsNotInstalled { + get { + return ResourceManager.GetString("BochsIsNotInstalled", resourceCulture); + } + } + /// /// Looks up a localized string similar to Cosmos Debug Engine. /// diff --git a/source2/Debug/Cosmos.Debug.VSDebugEngine/ResourceStrings.resx b/source2/Debug/Cosmos.Debug.VSDebugEngine/ResourceStrings.resx index 2be69097e..bdc3272ef 100644 --- a/source2/Debug/Cosmos.Debug.VSDebugEngine/ResourceStrings.resx +++ b/source2/Debug/Cosmos.Debug.VSDebugEngine/ResourceStrings.resx @@ -112,11 +112,14 @@ 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + The Bochs emulator doesn't seem to be installed on this machine. + Cosmos Debug Engine diff --git a/source2/VSIP/Cosmos.VS.Package/CosmosPage.Designer.cs b/source2/VSIP/Cosmos.VS.Package/CosmosPage.Designer.cs index 6111591ec..23ab5d67f 100644 --- a/source2/VSIP/Cosmos.VS.Package/CosmosPage.Designer.cs +++ b/source2/VSIP/Cosmos.VS.Package/CosmosPage.Designer.cs @@ -68,6 +68,8 @@ this.lboxDeployment = new System.Windows.Forms.ListBox(); this.tabLaunch = new System.Windows.Forms.TabPage(); this.lboxLaunch = new System.Windows.Forms.ListBox(); + this.tabBochs = new System.Windows.Forms.TabPage(); + this.checkEnableBochsDebug = new System.Windows.Forms.CheckBox(); this.tabVMware = new System.Windows.Forms.TabPage(); this.checkEnableGDB = new System.Windows.Forms.CheckBox(); this.checkStartCosmosGDB = new System.Windows.Forms.CheckBox(); @@ -99,6 +101,7 @@ this.tabUSB.SuspendLayout(); this.tabISO.SuspendLayout(); this.tabSlave.SuspendLayout(); + this.tabBochs.SuspendLayout(); this.SuspendLayout(); // // panel1 @@ -138,6 +141,7 @@ this.TabControl1.Controls.Add(this.tabDeployment); this.TabControl1.Controls.Add(this.tabLaunch); this.TabControl1.Controls.Add(this.tabVMware); + this.TabControl1.Controls.Add(this.tabBochs); this.TabControl1.Controls.Add(this.tabPXE); this.TabControl1.Controls.Add(this.tabUSB); this.TabControl1.Controls.Add(this.tabISO); @@ -546,6 +550,27 @@ this.lboxLaunch.Sorted = true; this.lboxLaunch.TabIndex = 3; // + // tabBochs + // + this.tabBochs.Controls.Add(this.checkEnableBochsDebug); + this.tabBochs.Location = new System.Drawing.Point(4, 22); + this.tabBochs.Name = "tabBochs"; + this.tabBochs.Padding = new System.Windows.Forms.Padding(3); + this.tabBochs.Size = new System.Drawing.Size(627, 387); + this.tabBochs.TabIndex = 5; + this.tabBochs.Text = "Bochs"; + this.tabBochs.UseVisualStyleBackColor = true; + // + // checkEnableBochsDebug + // + this.checkEnableBochsDebug.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.checkEnableBochsDebug.Location = new System.Drawing.Point(9, 12); + this.checkEnableBochsDebug.Name = "checkEnableBochsDebug"; + this.checkEnableBochsDebug.Size = new System.Drawing.Size(218, 20); + this.checkEnableBochsDebug.TabIndex = 25; + this.checkEnableBochsDebug.Text = "Enable Bochs Debugger"; + this.checkEnableBochsDebug.UseVisualStyleBackColor = true; + // // tabVMware // this.tabVMware.Controls.Add(this.checkEnableGDB); @@ -609,7 +634,7 @@ this.tabPXE.Name = "tabPXE"; this.tabPXE.Padding = new System.Windows.Forms.Padding(3); this.tabPXE.Size = new System.Drawing.Size(627, 387); - this.tabPXE.TabIndex = 5; + this.tabPXE.TabIndex = 6; this.tabPXE.Text = "PXE"; this.tabPXE.UseVisualStyleBackColor = true; // @@ -636,7 +661,7 @@ this.tabUSB.Name = "tabUSB"; this.tabUSB.Padding = new System.Windows.Forms.Padding(3); this.tabUSB.Size = new System.Drawing.Size(627, 387); - this.tabUSB.TabIndex = 6; + this.tabUSB.TabIndex = 7; this.tabUSB.Text = "USB"; this.tabUSB.UseVisualStyleBackColor = true; // @@ -656,7 +681,7 @@ this.tabISO.Name = "tabISO"; this.tabISO.Padding = new System.Windows.Forms.Padding(3); this.tabISO.Size = new System.Drawing.Size(627, 387); - this.tabISO.TabIndex = 7; + this.tabISO.TabIndex = 8; this.tabISO.Text = "ISO"; this.tabISO.UseVisualStyleBackColor = true; // @@ -733,6 +758,8 @@ this.panlDebugSettings.PerformLayout(); this.tabDeployment.ResumeLayout(false); this.tabLaunch.ResumeLayout(false); + this.tabBochs.ResumeLayout(false); + this.tabBochs.PerformLayout(); this.tabVMware.ResumeLayout(false); this.tabVMware.PerformLayout(); this.tabPXE.ResumeLayout(false); @@ -779,6 +806,8 @@ private System.Windows.Forms.Label label5; private System.Windows.Forms.Label label9; private System.Windows.Forms.CheckBox checkIgnoreDebugStubAttribute; + private System.Windows.Forms.TabPage tabBochs; + private System.Windows.Forms.CheckBox checkEnableBochsDebug; private System.Windows.Forms.TabPage tabVMware; private System.Windows.Forms.CheckBox checkEnableGDB; private System.Windows.Forms.CheckBox checkStartCosmosGDB; diff --git a/source2/VSIP/Cosmos.VS.Package/CosmosPage.cs b/source2/VSIP/Cosmos.VS.Package/CosmosPage.cs index 339dcfeb3..b8cbace92 100644 --- a/source2/VSIP/Cosmos.VS.Package/CosmosPage.cs +++ b/source2/VSIP/Cosmos.VS.Package/CosmosPage.cs @@ -45,8 +45,11 @@ namespace Cosmos.VS.Package { } protected ProfilePresets mPresets = new ProfilePresets(); - protected int mVMwareDebugPipe; + /// The index in the combo for the pipe name used by both + /// Bochs and VMware environment to communicate with Vsiual Studio debugger. + protected int mVMwareAndBochsDebugPipe; + protected bool mShowTabBochs; protected bool mShowTabDebug; protected bool mShowTabDeployment; protected bool mShowTabLaunch; @@ -81,6 +84,7 @@ namespace Cosmos.VS.Package { RemoveTab(tabUSB); RemoveTab(tabISO); RemoveTab(tabSlave); + RemoveTab(tabBochs); if (mShowTabDebug) { TabControl1.TabPages.Add(tabDebug); @@ -108,6 +112,9 @@ namespace Cosmos.VS.Package { if (mShowTabSlave) { TabControl1.TabPages.Add(tabSlave); } + if (mShowTabBochs) { + TabControl1.TabPages.Add(tabBochs); + } if (TabControl1.TabPages.Contains(xTab)) { TabControl1.SelectedTab = xTab; @@ -133,11 +140,18 @@ namespace Cosmos.VS.Package { chckEnableDebugStub.Checked = true; cmboCosmosDebugPort.Enabled = false; cmboVisualStudioDebugPort.Enabled = false; - cmboVisualStudioDebugPort.SelectedIndex = mVMwareDebugPipe; + cmboVisualStudioDebugPort.SelectedIndex = mVMwareAndBochsDebugPipe; } else if (mProps.Profile == "PXE") { chckEnableDebugStub.Checked = false; + } else if (mProps.Profile == "Bochs") { + mShowTabBochs = true; + chckEnableDebugStub.Checked = true; + cmboCosmosDebugPort.Enabled = false; + cmboVisualStudioDebugPort.Enabled = false; + cmboVisualStudioDebugPort.SelectedIndex = mVMwareAndBochsDebugPipe; + } } @@ -173,6 +187,7 @@ namespace Cosmos.VS.Package { checkUseInternalAssembler.Checked = mProps.UseInternalAssembler; checkEnableGDB.Checked = mProps.EnableGDB; checkStartCosmosGDB.Checked = mProps.StartCosmosGDB; + checkEnableBochsDebug.Checked = mProps.EnableBochsDebug; // Locked to COM1 for now. cmboCosmosDebugPort.SelectedIndex = 0; @@ -199,6 +214,7 @@ namespace Cosmos.VS.Package { // mShowTabVMware = mProps.Launch == LaunchType.VMware; mShowTabSlave = mProps.Launch == LaunchType.Slave; + mShowTabBochs = (LaunchType.Bochs == mProps.Launch); // UpdateTabs(); } @@ -274,6 +290,18 @@ namespace Cosmos.VS.Package { if (xValue != mProps.Launch) { mProps.Launch = xValue; IsDirty = true; + // Bochs requires an ISO. Force Deployment property. + if (LaunchType.Bochs == xValue) { + if (DeploymentType.ISO != mProps.Deployment) { + foreach (EnumValue scannedValue in lboxDeployment.Items) + { + if (DeploymentType.ISO == (DeploymentType)scannedValue.Value) { + lboxDeployment.SelectedItem = scannedValue; + break; + } + } + } + } } }; #endregion @@ -400,6 +428,16 @@ namespace Cosmos.VS.Package { IsDirty = true; } }; + + checkEnableBochsDebug.CheckedChanged += delegate(Object sender, EventArgs e) + { + bool x = checkEnableBochsDebug.Checked; + if (x != mProps.EnableBochsDebug) + { + mProps.EnableBochsDebug = x; + IsDirty = true; + } + }; } void butnProfileRename_Click(object sender, EventArgs e) { @@ -532,7 +570,7 @@ namespace Cosmos.VS.Package { cmboVisualStudioDebugPort.Items.Clear(); FillComPorts(cmboVisualStudioDebugPort.Items); - mVMwareDebugPipe = cmboVisualStudioDebugPort.Items.Add(@"Pipe: Cosmos\Serial"); + mVMwareAndBochsDebugPipe = cmboVisualStudioDebugPort.Items.Add(@"Pipe: Cosmos\Serial"); comboDebugMode.Items.AddRange(EnumValue.GetEnumValues(typeof(Cosmos.Build.Common.DebugMode), false)); comboTraceMode.Items.AddRange(EnumValue.GetEnumValues(typeof(TraceAssemblies), false)); diff --git a/source2/VSIP/Cosmos.VS.Package/ProfilePresets.cs b/source2/VSIP/Cosmos.VS.Package/ProfilePresets.cs index ee3382f1d..a79b51bf3 100644 --- a/source2/VSIP/Cosmos.VS.Package/ProfilePresets.cs +++ b/source2/VSIP/Cosmos.VS.Package/ProfilePresets.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using Cosmos.Debug.Common; + namespace Cosmos.VS.Package { public class ProfilePresets : Dictionary { public ProfilePresets() { @@ -10,6 +12,7 @@ namespace Cosmos.VS.Package { Add("USB", "USB Bootable Drive"); Add("PXE", "PXE Network Boot"); Add("VMware", "VMware"); + if (BochsSupport.BochsEnabled) { Add("Bochs", "Bochs"); } } } } diff --git a/source2/VSIP/Cosmos.VS.Package/Templates/Projects/Cosmos/Cosmos.vstemplate b/source2/VSIP/Cosmos.VS.Package/Templates/Projects/Cosmos/Cosmos.vstemplate index 8a6543416..dc8cade7d 100644 --- a/source2/VSIP/Cosmos.VS.Package/Templates/Projects/Cosmos/Cosmos.vstemplate +++ b/source2/VSIP/Cosmos.VS.Package/Templates/Projects/Cosmos/Cosmos.vstemplate @@ -10,6 +10,7 @@ + Cosmos.bxrc \ No newline at end of file diff --git a/source2/VSIP/Cosmos.VS.Package/Templates/Projects/CosmosProject (C#)/Proj/CosmosProj.vstemplate b/source2/VSIP/Cosmos.VS.Package/Templates/Projects/CosmosProject (C#)/Proj/CosmosProj.vstemplate index 8d3b8f2f5..812256e3d 100644 --- a/source2/VSIP/Cosmos.VS.Package/Templates/Projects/CosmosProject (C#)/Proj/CosmosProj.vstemplate +++ b/source2/VSIP/Cosmos.VS.Package/Templates/Projects/CosmosProject (C#)/Proj/CosmosProj.vstemplate @@ -12,7 +12,9 @@ true--> - + + Cosmos.bxrc + Cosmos.VS.Package, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f4d94ac959d59ec3 diff --git a/source2/VSIP/Cosmos.VS.Wizards/Cosmos.VS.Wizards.csproj b/source2/VSIP/Cosmos.VS.Wizards/Cosmos.VS.Wizards.csproj index 100ae18ee..16ff23aa1 100644 --- a/source2/VSIP/Cosmos.VS.Wizards/Cosmos.VS.Wizards.csproj +++ b/source2/VSIP/Cosmos.VS.Wizards/Cosmos.VS.Wizards.csproj @@ -64,6 +64,7 @@ + diff --git a/source2/VSIP/Cosmos.VS.Wizards/Cosmos.bxrc b/source2/VSIP/Cosmos.VS.Wizards/Cosmos.bxrc new file mode 100644 index 000000000..fcdecc6b4 --- /dev/null +++ b/source2/VSIP/Cosmos.VS.Wizards/Cosmos.bxrc @@ -0,0 +1,44 @@ +# configuration file generated by Bochs +plugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, parallel=1, serial=1, gameport=1 +config_interface: win32config +display_library: win32 +memory: host=256, guest=256 +romimage: file="C:\Program Files (x86)\Bochs-2.6/BIOS-bochs-latest" +vgaromimage: file="C:\Program Files (x86)\Bochs-2.6/VGABIOS-lgpl-latest" +boot: cdrom +floppy_bootsig_check: disabled=0 +# no floppya +# no floppyb +ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 +ata0-master: type=cdrom, path=".\$CosmosProjectName$.iso", status=inserted, biosdetect=auto, model="Generic 1234" +ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 +ata2: enabled=0 +ata3: enabled=0 +pci: enabled=1, chipset=i440fx +vga: extension=vbe, update_freq=5 +cpu: count=1, ips=4000000, model=bx_generic, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 +cpuid: family=6, model=0x03, stepping=3, mmx=1, apic=xapic, sse=sse2, sse4a=0, sep=1, aes=0, xsave=0, xsaveopt=0, movbe=0, adx=0, smep=0, x86_64=1, 1g_pages=0, pcid=0, fsgsbase=0, mwait=1 +cpuid: vendor_string="GenuineIntel" +cpuid: brand_string=" Intel(R) Pentium(R) 4 CPU " + +print_timestamps: enabled=0 +port_e9_hack: enabled=0 +private_colormap: enabled=0 +clock: sync=none, time0=local, rtc_sync=0 +# no cmosimage +# no loader +log: - +logprefix: %t%e%d +panic: action=ask +error: action=report +info: action=report +debug: action=ignore +keyboard: type=mf, serial_delay=250, paste_delay=100000, keymap= +user_shortcut: keys=none +mouse: enabled=0, type=ps2, toggle=ctrl+mbutton +parport1: enabled=1, file="" +parport2: enabled=0 +com1: enabled=1, mode=pipe-client, dev=\\.\pipe\Cosmos\Serial +com2: enabled=0 +com3: enabled=0 +com4: enabled=0 diff --git a/source2/VSIP/Cosmos.VS.Wizards/GenerateCosmosProjectWizard.cs b/source2/VSIP/Cosmos.VS.Wizards/GenerateCosmosProjectWizard.cs index e5b1e3827..01663afcb 100644 --- a/source2/VSIP/Cosmos.VS.Wizards/GenerateCosmosProjectWizard.cs +++ b/source2/VSIP/Cosmos.VS.Wizards/GenerateCosmosProjectWizard.cs @@ -8,14 +8,18 @@ using EnvDTE; namespace Cosmos.VS.Package.Templates { public class GenerateCosmosProjectWizard : IWizard { + private const string BochsConfigurationFileName = "Cosmos.bxrc"; + public void BeforeOpeningFile(EnvDTE.ProjectItem projectItem) { } - private static string GetTemplateString() { + private static string GetTemplate(string templateName) + { var xAsm = typeof(GenerateCosmosProjectWizard).Assembly; - using (var xStream = xAsm.GetManifestResourceStream(typeof(Cosmos.VS.Wizards.ResHelper), "CosmosProject.Cosmos")) { + using (var xStream = xAsm.GetManifestResourceStream(typeof(Cosmos.VS.Wizards.ResHelper), templateName)) + { if (xStream == null) { - MessageBox.Show("Could not find template manifest stream!"); + MessageBox.Show("Could not find template manifest stream : " + templateName); return null; } using (var xReader = new StreamReader(xStream)) { @@ -24,10 +28,18 @@ namespace Cosmos.VS.Package.Templates { } } + private static string GetBochsConfigurationFileTemplate() { + return GetTemplate(BochsConfigurationFileName); + } + + private static string GetProjectFileTemplate() { + return GetTemplate("CosmosProject.Cosmos"); + } + public void ProjectFinishedGenerating(EnvDTE.Project project) { // add Cosmos template to solution // read embedded template file - var xInputString = GetTemplateString(); + var xInputString = GetProjectFileTemplate(); if (xInputString == null) { return; } @@ -60,6 +72,16 @@ namespace Cosmos.VS.Package.Templates { } } + // Copy Bochs configuration file. + xInputString = GetBochsConfigurationFileTemplate(); + if (xInputString == null) { + return; + } + xInputString = xInputString.Replace("$CosmosProjectName$", project.Name + "Boot"); + xFilename = Path.GetDirectoryName(project.FullName); + xFilename = Path.Combine(xFilename, BochsConfigurationFileName); + File.WriteAllText(xFilename, xInputString); + // set Cosmos Boot as startup project project.DTE.Windows.Item(EnvDTE.Constants.vsWindowKindSolutionExplorer).Activate(); EnvDTE.UIHierarchy hierarchy = project.DTE.ActiveWindow.Object as EnvDTE.UIHierarchy;