1

I'm trying to write a simple C# program on Windows to display a character or digit on the Debug Port (address at: 0x80h, also known as the POST code display) of any supported motherboard (as shown here and here). This has already been done before in Linux, C, Assembly, and via a freeware called "TempLCD":

C (__outword command example): What does the 0x80 port address connect to?

Assembly: Is there a way to manually change BIOS POST codes on motherboard LCD?

Linux: Writing LCD Temperatures in Linux to Debug Port

In this screenshot, you can see the debug port at 80 (Device Manager > View > Resource by type): Device Manager with Port 80

How can I target this port for read/writes using any high-level programming language, such as C#? The SerialPort class fails, since it expects COM1, COM2, etc.

Moshe
  • 113
  • 4
  • 1
    You can't do this directly from a user mode program - you'll need a kernel mode driver. There's probably a generic one available that you could use but I am not aware of one that would work off the top of my head. – 500 - Internal Server Error Dec 29 '20 at 10:25
  • Normally your development board is connected to another PC using a USB to USB cable. You write to com port (Com1 or Com2) on the development board and then read on PC on a Com port. You do not use the I/O address. There is a driver on both the development board and PC which maps the I/O address to the name of the port (Com1, Com2, ...). – jdweng Dec 29 '20 at 10:27
  • TempLCD uses both a DLL file and driver.sys file named: WinRing0x64. Could this possibly be the jump from ring 3 to ring 0 that's needed? – Moshe Dec 29 '20 at 10:32

1 Answers1

4

You can only write to this I/O port in kernel mode. Read/writes to these I/O ports are not supported in a normal user-mode application.

You can see even in the solutions to the linked question that these all require a kernel-mode driver. In particular, the Windows solution __outword is just a MSVC-specific intrinsic that causes the x86 OUT instruction to be emitted, and, as the Intel x86 documentation says, OUT is a privileged instruction that is not allowed to be executed in Ring 3 (which is where user-mode applications are run).

Since it can't be executed from user mode, it cannot be executed at all from a .NET application. You cannot use .NET to write a Windows driver that runs in Ring 0. You will need to use a different programming language that can generate native (i.e., unmanaged) code. C and C++ are the typical choices.

If you wrote the driver in an unmanaged language like C or C++, you could then call it from a C# application using the P/Invoke (DllImport) mechanism. See: Accessing Device Drivers from C# and similar resources.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • 1
    Technically it is up to the OS design to allow or allow/disallow access to ports in usermode (ring 3). You can set IOPL to 3 for usermode and the IN/OUT instructions will execute without raising an exception. Alternatively you can use an IO Bitmap in the TSS to grant/deny individual port access with IOPL=0 to give access to specific ports. Linux for example use to have the `iopl` function and still has `ioperm` – Michael Petch Dec 29 '20 at 21:42