Search code examples
assemblyiogpiokernel-mode

Accessing IO ports on embedded machine running Windows


I am having trouble entering the extended function mode of the Nuvoton NCT6793D. The datasheet says to write 87h twice to to the regsiter 2Eh but on trying to do so I get an exception thrown by Visual Studio that the 3rd line is a 'privileged instruction'.

On looking it up online it is my understanding that this instruction can only be carried out in the kernel mode, but I cannot find any way to run my assembly code in kernel mode.

  .386
  .stack 4096
.
.
.
  main PROC
        mov DX,2EH
        mov AL,87H
        out DX,AL    <----
        out DX,AL
.
.
.

Is my only option writing a kernel mode driver?

Thank you in advance for your kind responses.


Solution

  • Yes, out is a privileged instruction. It must be executed at Ring 0 (kernel mode).
    The only way around this is making a driver, Windows has the Windows Driver Kit for developing drivers (it has all the tools and many examples).

    There is an instruction to jump into privileged mode (more than one, actually) but of course you jump to an entry point in the kernel.
    All these instructions are fundamentally a call to a specific routine, you cannot elevate your code or the OS would be totally broken.

    I assume Windows is involved somehow, since you are using Visual Studio and x86 code, despite the title refers to an embedded machine.

    Windows doesn't exposes a function to read/write the IO ports to user mode applications (for very good reasons).

    Untested (or maybe tested but I don't remember)

    I've found an old driver I wrote for reading IO ports, it exposes the "file" \Device\iomem_io which can be open, read and written as usual (CreateFile, ReadFile, WriteFile).
    Reads and writes at offset X (see SetFilePointer) will read/write from/to port X, the size of the operation must be either 1, 2 or 4 bytes.

    RWEverything comes with a driver that allows to read/write ports (and much more). It's commonly used by malwares that requires HW access, it is not documented and it is controller with IOCTLs (DeviceIoControl) codes that must be gathered from reverse engineering.

    Note If you switch to Linux, you can use iopl to allow a user mode program to access the IO ports. That's great for debugging.