FrankRay78 / PatienceOS

A baremetal C# kernel.
https://frankray.net/blog/category/software-development/os-development/patienceos/
MIT License
21 stars 4 forks source link

Read and write to IO Ports #14

Open FrankRay78 opened 3 months ago

FrankRay78 commented 3 months ago

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:

  1. Utilising the ASM plug architecture of COSMOS (see this and this)
  2. Linking to a machine-specific DLL/library (nb. not great because a cross-compiler setup will be needed for each)

Background reading

  1. Read/Write to Debug Port (0x80h) using C#
  2. QEMU_Monitor (OS Dev)
  3. QEMU Monitor Manual

This command demonstrates the ability for QEMU Monitor to dump physical memory addresses:

i/fmt addr [.index]
Read I/O port.

fmt is a format which tells the command how to format the data. Its syntax is: /{count}{format}{size}

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.

FrankRay78 commented 3 months ago

COSMOS Plug example

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;

FlingOS Plug example

        /// <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

Microsoft specific, C compiler directive

(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

AnErrupTion commented 2 months ago

@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.

FrankRay78 commented 2 months ago

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.

AnErrupTion commented 2 months ago

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?

FrankRay78 commented 2 months ago

Thanks, I hadn't seen this before: https://github.com/nifanfa/MOOS/blob/master/NativeLib/io.cpp Yes, I was thinking exactly like this.

FrankRay78 commented 2 months ago

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.

FrankRay78 commented 1 month ago

Calling x86-64 Assembly code from C#.NET Program How do I make a DLL file with NASM? Minimal example for C# direct P/Invoke calls with static linking

FrankRay78 commented 1 month ago

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.

FrankRay78 commented 1 month ago

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

FrankRay78 commented 2 weeks ago

@AnErrupTion FYI. I'm continuing my OS development here for the time being: https://github.com/FrankRay78/InstructionOS