diff --git a/Build/Tools/cygwin/cygwin1.dll b/Build/Tools/cygwin/cygwin1.dll index 00d8a72aad..1bb2e05c6d 100644 Binary files a/Build/Tools/cygwin/cygwin1.dll and b/Build/Tools/cygwin/cygwin1.dll differ diff --git a/Build/Tools/cygwin/ld.exe b/Build/Tools/cygwin/ld.exe index 52fc663fea..53b6be4d88 100644 Binary files a/Build/Tools/cygwin/ld.exe and b/Build/Tools/cygwin/ld.exe differ diff --git a/Build/Tools/cygwin/objdump.exe b/Build/Tools/cygwin/objdump.exe index fbd59f7f51..6b69943664 100644 Binary files a/Build/Tools/cygwin/objdump.exe and b/Build/Tools/cygwin/objdump.exe differ diff --git a/source/Cosmos.Build.Tasks/CreateLimineConfig.cs b/source/Cosmos.Build.Tasks/CreateLimineConfig.cs index e9ea15a8f8..d963c01f0b 100644 --- a/source/Cosmos.Build.Tasks/CreateLimineConfig.cs +++ b/source/Cosmos.Build.Tasks/CreateLimineConfig.cs @@ -12,8 +12,10 @@ public class CreateLimineConfig : Task public string TargetDirectory { get; set; } [Required] - public string BinName { get; set; } - + public string BinName { get; set; } + + [Required] + public string TargetArchitecture { get; set; } public string[] Modules { get; set; } private string Indentation = " "; @@ -43,8 +45,15 @@ public override bool Execute() xWriter.WriteLineAsync($":{xLabelName}"); WriteIndentedLine(xWriter, $"COMMENT=Boot {xLabelName} using multiboot2."); - xWriter.WriteLineAsync(); - WriteIndentedLine(xWriter, "PROTOCOL=multiboot2"); + xWriter.WriteLineAsync(); + if(TargetArchitecture == "amd64") + { + WriteIndentedLine(xWriter, "PROTOCOL=limine"); + } + else + { + WriteIndentedLine(xWriter, "PROTOCOL=multiboot2"); + } WriteIndentedLine(xWriter, xBinName.EndsWith(".gz") ? $"KERNEL_PATH=$boot:///boot/{xBinName}" diff --git a/source/Cosmos.Build.Tasks/IL2CPU.cs b/source/Cosmos.Build.Tasks/IL2CPU.cs index b28712de9f..043780de54 100644 --- a/source/Cosmos.Build.Tasks/IL2CPU.cs +++ b/source/Cosmos.Build.Tasks/IL2CPU.cs @@ -58,7 +58,9 @@ public class IL2CPU : ToolTask public bool AllowComments { get; set; } - public string VBEResolution { get; set; } + public string VBEResolution { get; set; } + + public string TargetArchitecture { get; set; } #endregion @@ -85,8 +87,14 @@ protected override string GenerateFullPathToTool() } protected override string GenerateResponseFileCommands() - { - var args = new Dictionary + { + // default to AMD64 + if (string.IsNullOrEmpty(TargetArchitecture)) + { + TargetArchitecture = "amd64"; + } + + List> args = new Dictionary { ["KernelPkg"] = KernelPkg, ["EnableDebug"] = DebugEnabled.ToString(), @@ -103,7 +111,8 @@ protected override string GenerateResponseFileCommands() ["CompileVBEMultiboot"] = CompileVBEMultiboot.ToString(), ["VBEResolution"] = VBEResolution.ToString(), ["RemoveBootDebugOutput"] = RemoveBootDebugOutput.ToString(), - ["AllowComments"] = AllowComments.ToString() + ["AllowComments"] = AllowComments.ToString(), + ["TargetArchitecture"] = TargetArchitecture.ToString(), }.ToList(); foreach (var reference in References) diff --git a/source/Cosmos.Build.Tasks/Ld.cs b/source/Cosmos.Build.Tasks/Ld.cs index 885e1e4d9c..75b413dc10 100644 --- a/source/Cosmos.Build.Tasks/Ld.cs +++ b/source/Cosmos.Build.Tasks/Ld.cs @@ -25,7 +25,10 @@ public class Ld : ToolTask public string DataAddress { get; set; } - public string BssAddress { get; set; } + public string BssAddress { get; set; } + + [Required] + public string TargetArchitecture { get; set; } #endregion @@ -36,13 +39,13 @@ public class Ld : ToolTask private static bool IsValidAddress(string aAddress) { - if (UInt64.TryParse(aAddress, out var xAddress)) + if (ulong.TryParse(aAddress, out var xAddress)) { return true; } if (aAddress.StartsWith("0x") - && UInt64.TryParse(aAddress.Remove(0, 2), NumberStyles.AllowHexSpecifier, null, out xAddress)) + && ulong.TryParse(aAddress.Remove(0, 2), NumberStyles.AllowHexSpecifier, null, out xAddress)) { return true; } @@ -62,9 +65,9 @@ protected override bool ValidateParameters() { var xFullPath = xFile.GetMetadata("FullPath"); - if (String.IsNullOrWhiteSpace(xFullPath)) + if (string.IsNullOrWhiteSpace(xFullPath)) { - Log.LogError($"Input file is an empty string! Input files: '{String.Join(";", InputFiles.Select(f => f.GetMetadata("Identity")))}'"); + Log.LogError($"Input file is an empty string! Input files: '{string.Join(";", InputFiles.Select(f => f.GetMetadata("Identity")))}'"); } else if (!File.Exists(xFullPath)) { @@ -72,17 +75,17 @@ protected override bool ValidateParameters() } } - if (String.IsNullOrEmpty(OutputFile)) + if (string.IsNullOrEmpty(OutputFile)) { Log.LogError("No output file specified!"); } - if (String.IsNullOrWhiteSpace(Entry)) + if (string.IsNullOrWhiteSpace(Entry)) { Entry = null; } - if (String.IsNullOrWhiteSpace(TextAddress)) + if (string.IsNullOrWhiteSpace(TextAddress)) { TextAddress = null; } @@ -91,7 +94,7 @@ protected override bool ValidateParameters() Log.LogError(nameof(TextAddress) + " isn't a valid 64-bit number!"); } - if (String.IsNullOrWhiteSpace(DataAddress)) + if (string.IsNullOrWhiteSpace(DataAddress)) { DataAddress = null; } @@ -100,7 +103,7 @@ protected override bool ValidateParameters() Log.LogError(nameof(DataAddress) + " isn't a valid 64-bit number!"); } - if (String.IsNullOrWhiteSpace(BssAddress)) + if (string.IsNullOrWhiteSpace(BssAddress)) { BssAddress = null; } @@ -114,12 +117,12 @@ protected override bool ValidateParameters() protected override string GenerateFullPathToTool() { - if (String.IsNullOrWhiteSpace(ToolExe)) + if (string.IsNullOrWhiteSpace(ToolExe)) { return null; } - if (String.IsNullOrWhiteSpace(ToolPath)) + if (string.IsNullOrWhiteSpace(ToolPath)) { return Path.Combine(Directory.GetCurrentDirectory(), ToolExe); } @@ -129,25 +132,104 @@ protected override string GenerateFullPathToTool() protected override string GenerateCommandLineCommands() { - var xBuilder = new CommandLineBuilder(); + CommandLineBuilder xBuilder = new(); - xBuilder.AppendSwitchIfNotNull("-Ttext ", TextAddress); - xBuilder.AppendSwitchIfNotNull("-Tdata ", DataAddress); - xBuilder.AppendSwitchIfNotNull("-Tbss ", BssAddress); - xBuilder.AppendSwitchIfNotNull("-e ", Entry); xBuilder.AppendSwitchIfNotNull("-o ", OutputFile); - xBuilder.AppendFileNamesIfNotNull(InputFiles, " "); - xBuilder.AppendSwitch("-m elf_i386"); - - Log.LogMessage(MessageImportance.High, xBuilder.ToString()); - + xBuilder.AppendFileNamesIfNotNull(InputFiles, " "); + + if (TargetArchitecture == "amd64") + { + var dir = Path.GetDirectoryName(OutputFile); + var path = dir + "/linker.ld"; + xBuilder.AppendSwitch("-m elf_x86_64"); + xBuilder.AppendSwitch("-z text"); + xBuilder.AppendSwitchIfNotNull("-T ", path); + + + + File.WriteAllText(path, @"/* Tell the linker that we want an x86_64 ELF64 output file */ +OUTPUT_FORMAT(elf64-x86-64) +OUTPUT_ARCH(i386:x86-64) + +/* We want the symbol _start to be our entry point */ +ENTRY(" + Entry + @") + +/* Define the program headers we want so the bootloader gives us the right */ +/* MMU permissions */ +PHDRS +{ + text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */ + rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */ + data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */ + dynamic PT_DYNAMIC FLAGS((1 << 1) | (1 << 2)) ; /* Dynamic PHDR for relocations */ +} + +SECTIONS +{ + /* We wanna be placed in the topmost 2GiB of the address space, for optimisations */ + /* and because that is what the Limine spec mandates. */ + /* Any address in this region will do, but often 0xffffffff80000000 is chosen as */ + /* that is the beginning of the region. */ + . = 0xffffffff80000000; + + .text : { + *(.text .text.*) + } :text + + /* Move to the next memory page for .rodata */ + . += CONSTANT(MAXPAGESIZE); + + .rodata : { + *(.rodata .rodata.*) + } :rodata + + /* Move to the next memory page for .data */ + . += CONSTANT(MAXPAGESIZE); + + .data : { + *(.data .data.*) + } :data + + /* Dynamic section for relocations, both in its own PHDR and inside data PHDR */ + .dynamic : { + *(.dynamic) + } :data :dynamic + + /* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */ + /* unnecessary zeros will be written to the binary. */ + /* If you need, for example, .init_array and .fini_array, those should be placed */ + /* above this. */ + .bss : { + *(.bss .bss.*) + *(COMMON) + } :data + + /* Discard .note.* and .eh_frame since they may cause issues on some hosts. */ + /DISCARD/ : { + *(.eh_frame) + *(.note .note.*) + } +}"); + } + else + { + xBuilder.AppendSwitch("-m elf_i386"); + + xBuilder.AppendSwitchIfNotNull("-Ttext ", TextAddress); + xBuilder.AppendSwitchIfNotNull("-Tdata ", DataAddress); + xBuilder.AppendSwitchIfNotNull("-Tbss ", BssAddress); + xBuilder.AppendSwitchIfNotNull("-e ", Entry); + } + + Log.LogMessage(MessageImportance.High, xBuilder.ToString()); + return xBuilder.ToString(); } public override bool Execute() { - var xSW = Stopwatch.StartNew(); + Stopwatch xSW = Stopwatch.StartNew(); try { return base.Execute(); diff --git a/source/Cosmos.Build.Tasks/LimineDeploy.cs b/source/Cosmos.Build.Tasks/LimineDeploy.cs index e4c53bdb93..f2468a6b42 100644 --- a/source/Cosmos.Build.Tasks/LimineDeploy.cs +++ b/source/Cosmos.Build.Tasks/LimineDeploy.cs @@ -1,32 +1,32 @@ -using System; -using System.IO; -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; -using static Cosmos.Build.Tasks.OperatingSystem; - -namespace Cosmos.Build.Tasks; - -public class LimineDeploy : ToolTask -{ - [Required] - public string IsoFile { get; set; } - - [Required] - public string LimineIsoFile { get; set; } - - protected override string ToolName => IsWindows() ? "limine.exe" : "limine"; - - protected override string GenerateFullPathToTool() - { - return string.IsNullOrWhiteSpace(ToolExe) ? null : Path.Combine(string.IsNullOrWhiteSpace(ToolPath) ? Directory.GetCurrentDirectory() : Path.GetFullPath(ToolPath), ToolExe); - } - - protected override string GenerateCommandLineCommands() - { - CommandLineBuilder xBuilder = new(); - xBuilder.AppendSwitch($"bios-install"); - xBuilder.AppendFileNameIfNotNull($"{IsoFile}"); - - return xBuilder.ToString(); - } +using System; +using System.IO; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using static Cosmos.Build.Tasks.OperatingSystem; + +namespace Cosmos.Build.Tasks; + +public class LimineDeploy : ToolTask +{ + [Required] + public string IsoFile { get; set; } + + [Required] + public string LimineIsoFile { get; set; } + + protected override string ToolName => IsWindows() ? "limine.exe" : "limine"; + + protected override string GenerateFullPathToTool() + { + return string.IsNullOrWhiteSpace(ToolExe) ? null : Path.Combine(string.IsNullOrWhiteSpace(ToolPath) ? Directory.GetCurrentDirectory() : Path.GetFullPath(ToolPath), ToolExe); + } + + protected override string GenerateCommandLineCommands() + { + CommandLineBuilder xBuilder = new(); + xBuilder.AppendSwitch($"bios-install"); + xBuilder.AppendFileNameIfNotNull($"{IsoFile}"); + + return xBuilder.ToString(); + } } \ No newline at end of file diff --git a/source/Cosmos.Build.Tasks/Nasm.cs b/source/Cosmos.Build.Tasks/Nasm.cs index 8b18d3e376..56b4147911 100644 --- a/source/Cosmos.Build.Tasks/Nasm.cs +++ b/source/Cosmos.Build.Tasks/Nasm.cs @@ -13,10 +13,10 @@ enum OutputFormatEnum { Bin, ELF - } - + } + #region Task Parameters - + [Required] public string InputFile { get; set; } @@ -30,7 +30,10 @@ public string OutputFormat set => mOutputFormat = (OutputFormatEnum)Enum.Parse(typeof(OutputFormatEnum), value, true); } - public string OptimizationLevel { get; set; } + public string OptimizationLevel { get; set; } + + [Required] + public string TargetArchitecture { get; set; } #endregion @@ -98,11 +101,16 @@ protected override string GenerateCommandLineCommands() else { xBuilder.AppendSwitch("-dBIN_COMPILATION"); - } - - /* Apply the optimization level that the user chose */ - if(!String.IsNullOrWhiteSpace(OptimizationLevel) && !String.IsNullOrWhiteSpace(OptimizationLevel)) - xBuilder.AppendSwitch($"-O{OptimizationLevel}"); + } + + if (TargetArchitecture == "amd64") + { + xBuilder.AppendSwitch("-m amd64"); + } + + /* Apply the optimization level that the user chose */ + if (!String.IsNullOrWhiteSpace(OptimizationLevel) && !String.IsNullOrWhiteSpace(OptimizationLevel)) + xBuilder.AppendSwitch($"-O{OptimizationLevel}"); xBuilder.AppendFileNameIfNotNull(InputFile); diff --git a/source/Cosmos.Build.Tasks/build/Cosmos.Build.targets b/source/Cosmos.Build.Tasks/build/Cosmos.Build.targets index 3e3be754ab..619b3c4b33 100644 --- a/source/Cosmos.Build.Tasks/build/Cosmos.Build.targets +++ b/source/Cosmos.Build.Tasks/build/Cosmos.Build.targets @@ -202,7 +202,8 @@ ToolExe="$(Il2cpuToolExe)" CompileVBEMultiboot="$(CompileVBEMultiboot)" AllowComments="$(AllowComments)" - VBEResolution="$(VBEResolution)"/> + VBEResolution="$(VBEResolution)" + TargetArchitecture="$(TargetArchitecture)"/> @@ -227,7 +228,8 @@ OutputFormat="$(BinFormat)" ToolPath="$(NasmToolPath)" ToolExe="$(NasmToolExe)" - OptimizationLevel="$(OptimizationLevel)"/> + OptimizationLevel="$(OptimizationLevel)" + TargetArchitecture="$(TargetArchitecture)"/> @@ -254,7 +256,8 @@ DataAddress="0x1000000" Entry="Kernel_Start" ToolPath="$(LdToolPath)" - ToolExe="$(LdToolExe)" /> + ToolExe="$(LdToolExe)" + TargetArchitecture="$(TargetArchitecture)"/> @@ -367,12 +370,10 @@ - - + BinName="$([System.IO.Path]::GetFileName('$(BinGzFile)'))" + Timeout="$(Timeout)" + Condition="'$(CompressionType)' == 'Gzip'" + TargetArchitecture="$(TargetArchitecture)"/> + BinName="$([System.IO.Path]::GetFileName('$(BinFile)'))" + Timeout="$(Timeout)" + Condition="'$(CompressionType)' == 'None'" + TargetArchitecture="$(TargetArchitecture)"/>