Open FrankRay78 opened 3 months ago
namespace Cosmos.Core
{
/// <summary>
/// IOPort static class.
/// </summary>
public static class IOPort
{
/// <summary>
/// Write byte to port.
/// Plugged.
/// </summary>
/// <param name="aPort">A port to write to.</param>
/// <param name="aData">A data.</param>
[PlugMethod(PlugRequired = true)]
public static void Write8(int aPort, byte aData) => throw null;
and also
namespace Cosmos.Core_Asm
{
[Plug(Target = typeof(IOPort))]
public class IOPortImpl
{
private class Write8Assembler : AssemblerMethod
{
public override void AssembleNew(Assembler aAssembler, object aMethodInfo)
{
//TODO: This is a lot of work to write to a single port.
// We need to have some kind of inline ASM option that can
// emit a single out instruction
XS.Set(XSRegisters.EDX, XSRegisters.EBP, sourceDisplacement: 0x0C);
XS.Set(XSRegisters.EAX, XSRegisters.EBP, sourceDisplacement: 0x08);
XS.WriteToPortDX(XSRegisters.AL);
}
}
[PlugMethod(Assembler = typeof(Write8Assembler))]
public static void Write8(ushort aPort, byte aData) => throw null;
/// <summary>
/// Writes a byte to the specified port.
/// </summary>
/// <param name="port">The port to write to.</param>
/// <param name="aVal">The value to write.</param>
[PluggedMethod(ASMFilePath = @"ASM\IO\IOPort\Write")]
public static void doWrite_Byte(ushort port, byte aVal)
{
}
and also
method_System_Void_RETEND_Kernel_IO_IOPort_DECLEND_doWrite_Byte_NAMEEND__System_UInt16_System_Byte_:
push dword ebp
mov dword ebp, esp
mov dword edx, [ebp+12]
mov dword eax, [ebp+8]
out dx, al
pop dword ebp
ret
(could be compiled into a native object, and then linked into the native kernel, I guess).
void __outbyte(
unsigned short Port,
unsigned char Data
);
https://learn.microsoft.com/en-us/cpp/intrinsics/outbyte?view=msvc-160
@FrankRay78 How would you plan on adding a custom plug architecture to NativeAOT? That requires hijacking the compiler, and I'm not sure if it's possible.
How would you plan on adding a custom plug architecture to NativeAOT?
@AnErrupTion I've been thinking about this a lot, and at the moment, I'm favouring an architecture-specific library written in C/C++ with the required methods and inline assembly that I can compile and then somehow link the kernel with.
I'm favouring an architecture-specific library written in C/C++ with the required methods and inline assembly that I can compile and then somehow link the kernel with.
So essentially the way MOOS did it with its NativeLib?
Thanks, I hadn't seen this before: https://github.com/nifanfa/MOOS/blob/master/NativeLib/io.cpp Yes, I was thinking exactly like this.
I'm having difficulty writing to an IO port from assembly, as being discussed here: io port 0x80 - usage for debugging during OS development. I need to resolve this first, before attempting to call similar from within the C# kernel.
I'm not sure if I'm going to use the nativelib approach MOOS takes, as it seems that C# .Net does not support direct linking of an an AOT compiled object file to another native object file. Instead, .Net uses the DllImport
attribute as a primary way to call into unmanaged code, for example:
using System;
using System.Runtime.InteropServices;
// Declare the method signature
[DllImport("addThree.dll")]
static extern int addThree(int number);
Console.WriteLine($"addThree(5) = { addThree(5) }");
If I take this approach, then I need to explicitly implement the DllImport
attribute the compiler requires eg: https://github.com/nifanfa/MOOS/blob/master/Corlib/System/Runtime/InteropServices/DllImportAttribute.cs
And also implement a host of accompanying InteropHelpers eg: https://github.com/nifanfa/MOOS/blob/master/Corlib/Internal/Runtime/CompilerHelpers/InteropHelpers.cs https://github.com/nifanfa/MOOS/blob/master/Corlib/System/EETypePtr.cs
However, without this, I'm not sure there is any other way except for the plug (see above) approach COSMOS/FlingOS took.
I wonder if a modified fork of the ILCompiler might be the way to go? https://github.com/dotnet/runtime/tree/main/src/coreclr/tools/aot
@AnErrupTion FYI. I'm continuing my OS development here for the time being: https://github.com/FrankRay78/InstructionOS
The ability to read and write to IO ports is needed (nb. this is something different to memory mapped IO).
Switch between VGA text modes is a good example that requires writing to an IO Port.
Various ways exist to do this, namely:
Background reading
This command demonstrates the ability for QEMU Monitor to dump physical memory addresses:
I intend to use
i 0x80
to validate a successful write to the debug port (0x80h).Please upvote :+1: this issue if you are interested in it.