Click here to Skip to main content
Click here to Skip to main content

Access Physical Memory, Port and PCI Configuration Space

By , 13 Apr 2009
 

Introduction

I recently developed a lot of interest in ACPI programming. By Googling, I found Intel’s ACPICA open source library. Of course, to make it work (such as read ACPI tables, evaluate ACPI methods), I must implement some functions to access physical memory, port and PCI configuration space, even install ISR.

It’s quite easy to implement these functions in kernel mode. But I don't want to put the whole ACPICA library in a “.sys” which will make it very hard to debug. Debugging is important for me because I always want to find out what really happens. So the only solution is to access these resources in user mode.

At first I used WinIO and it works. Yet after reading the source code, I found it used too many “undocumented” and “obsolete” functions. I decided to make a more elegant solution, and add the function of accessing PCI configuration space.

Background

1. The Architecture

I borrow the software architecture from WinIO: a kernel mode driver “phymem.sys” and a user mode DLL “pmdll.dll”. Applications can easily access physical memory using the functions exported by pmdll.dll, which will talk to the phymem.sys by standard “DeviceIoControl”.

To access PCI configuration space in a DDK recommended method, I wrote a PCI bus upper filter driver “PCIFlt.sys”. With this filter driver, we can find the unnamed PCI bus driver which lies under our named filter driver. Then we use “Driver Interface” to directly read and write PCI configuration space.

2. Access Physical Port

IA based PC uses separated port and memory address spaces. In kernel mode, we can read and write port with functions named like WRITE_PORT_UCHAR, READ_PORT_UCHAR.

3. Access Physical Memory

To access physical memory in user mode, we must map this memory region to the user process’ address space. One implementation is through the \Device\PhysicalMemory section object. This is first introduced in the old NT DDK samples. It uses obsolete functions which are not recommended; also the code is really hard to understand.

A better implementation can be found in MSDN. Only three steps are required:

  1. Use MmMapIoSpace to map physical address to kernel mode virtual address, driver can access this virtual address, but it’s not accessible in user mode.
  2. Use IoAllocateMdl and MmBuildMdlForNonPagedPool to build an MDL for the mapped physical address.
  3. Use MmMapLockedPages to map the physical pages described by MDL to user mode virtual address. Since our driver will always be the topmost driver, and run in the context of the current process, this user mode virtual address is valid to the caller.

4. Access PCI Configuration Space

Windows XP bus drivers must implement “Driver Interface” which can be acquired by sending it an IRP with major code IRP_MN_QUERY_INTERFACE. After acquiring “Driver Interface”, we can access the bus address space by calling the interface provided ReadConfig and WriteConfig routines.

The trouble is that the PCI bus driver has no name, that is, we can't find its device object. Without the PCI bus driver’s device object, we have no way to query its “Driver Interface”. The solution is providing a PCI bus upper filter driver, which will be layered above the actual function bus driver.

Using the Code

All source code is built under Visual C++ 6.0, XP DDK 2600, and Windows XP SP3. To build driver (.sys) in Visual C++ IDE, follow the next two steps:

  1. Set environment variable $DDKROOT to DDK installation directory, such as "D:\WINDDK\2600”.
  2. In VC++ IDE, Tools->Options->Directories->Show directories for, choose “Executable files”, add DDK bin directory and move to the first line, such as “D:\WINDDK\2600\BIN\X86”.

The driver source code uses PHDDebugPrint for debugging purposes. Reference the book “Writing Windows WDM Device Drivers” by Chris Cant.

Manual

  1. Copy pmdll.h, pmdll.lib to your source code directory, include and link with.
  2. Copy pmdll.dll, phymem.sys to your application directory to run with.
  3. Function Reference:
    BOOL LoadPhyMemDriver()

    Dynamically load phymem.sys into memory; Return TRUE if succeeded, otherwise FALSE.

    VOID UnloadPhyMemDriver()

    Unload phymem.sys from memory.

    PVOID MapPhyMem(DWORD phyAddr, DWORD memSize)

    Map physical memory to user virtual space

    • phyAddr = physical memory address
    • memSize = memory size in bytes
    VOID UnmapPhyMem(PVOID pVirAddr, DWORD memSize)

    Unmap mapped user virtual address

    • pVirAddr = mapped user virtual address (return value of MapPhyMem)
    • memSize = memory size in bytes
    BYTE ReadPortByte(WORD portAddr) 
    WORD ReadPortWord(WORD portAddr)
    DWORD ReadPortLong(WORD portAddr)

    Read one byte, two bytes and four bytes from Port address portAddr.

    VOID WritePortByte(WORD portAddr, BYTE portValue)
    VOID WritePortWord(WORD portAddr, WORD portValue)
    VOID WritePortLong(WORD portAddr, DWORD portValue) 

    Write one byte, two bytes and four bytes to Port address portAddr.

    BOOL ReadPCI(DWORD busNum, DWORD devNum, DWORD funcNum,
                                 DWORD regOff, DWORD bytes, PVOID pValue)

    Read PCI configuration space

    • busNum: Bus number (0-255)
    • devNum: Device number (0-31)
    • funcNum: Function number (0-7)
    • regOff: Register offset (0-255)
    • bytes: Bytes to read
    • pValue: Buffer to receive returned value (must be allocated by the function caller)
    BOOL WritePCI(DWORD busNum, DWORD devNum, DWORD funcNum, 
                                  DWORD regOff, DWORD bytes, PVOID pValue)

    Write PCI configuration space

    • busNum: Bus number (0-255)
    • devNum: Device number (0-31)
    • funcNum: Function number (0-7)
    • regOff: Register offset (0-255)
    • bytes: Bytes to read
    • pValue: New values to write

How to Install PCI Filter Driver

If you want to access PCI configuration space, the PCI filter driver “PCIFlt.sys” must be installed. In “Device Manager”, find “PCI Bus” and choose “Update Driver”, select the PCIFilter.inf. Don't automatically search the INF file, choose selecting driver by yourself.

The PCI filter driver may totally crash your computer, use it at your own risk.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

cyb70289
China China
Member
From Shanghai, China

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionHow to use with multiple processes?membertseries80019 Feb '13 - 7:31 
AnswerRe: How to use with multiple processes?membercyb7028919 Feb '13 - 14:06 
GeneralRe: How to use with multiple processes?membertseries80020 Feb '13 - 6:33 
GeneralRe: How to use with multiple processes?membertseries80020 Feb '13 - 9:21 
QuestionWhat should I do with upgraded OS Window8 for memory access through PCI? It used to work on WindowXPmemberMember 98081123 Feb '13 - 13:47 
Questioni am not able to use this code any one can help memembervikaspot16 Jan '13 - 18:38 
QuestionInstallation fails on Windows XPmemberRedScreen12 Aug '11 - 4:49 
Questionscanning from the application fails on win 7 x64memberMember 766391824 Feb '11 - 19:36 
QuestionHow to make PhyMem work for XP PAEmemberKeunlee9920 Dec '10 - 11:04 
GeneralIt works for win 7 x64memberkaoea7 Nov '10 - 16:17 
GeneralLoadPhyMemDriver() returns failedmemberLeonid.ravich31 Oct '10 - 5:22 
GeneralRe: LoadPhyMemDriver() returns failedmembervaggosbboy@gmail.com10 Dec '12 - 9:05 
GeneralIs not working on Windows 7 64bits (need driver compatible)memberkornx225 Oct '10 - 21:40 
GeneralMy vote of 5memberBoatBum2 Aug '10 - 4:35 
GeneralCannot apply in Win7memberPdaus21 Apr '10 - 16:28 
GeneralRe: Cannot apply in Win7memberbharatkv27 Apr '10 - 20:30 
GeneralRe: Cannot apply in Win7memberPdaus27 Apr '10 - 21:51 
GeneralIntercept I/O Port and re-route data to Bit-Bang drivermemberGobsek20 Apr '10 - 12:07 
QuestionHint for accessing IO port to change SATA transfer mode?memberConfiger27 Mar '10 - 10:06 
QuestionHow to install the filter driver?memberhustsolo4 Mar '10 - 16:10 
AnswerRe: How to install the filter driver?memberhustsolo4 Mar '10 - 19:47 
GeneralHi,cyb70289, Could I have your e-mail? [modified]memberhustsolo4 Mar '10 - 3:40 
GeneralWrite to Physical (Flash-) MemorymemberMichael Moese4 Mar '10 - 2:56 
QuestionAnyone used this to get thermalzone information from the mobo sensors?memberDaveKolb15 Feb '10 - 17:10 
QuestionCan I use this code for windows 7 64bit OS?memberHa JungChul7 Jan '10 - 2:52 
GeneralThanks for writing this article and sharing it!membermarkyoung14314 Dec '09 - 9:48 
QuestionCan I use this code for windows 7?membermansour_ahmadian21 Nov '09 - 7:33 
GeneralYour Article is really good!!memberleochen11 Sep '09 - 6:47 
QuestionCan anyone use this code to volunteer a simple text interface to modify pci-e bar before enumeration?membernando4411 Sep '09 - 1:54 
QuestionGetting PCI BAR address without parsing pci resources or using PCI filter drivermembereylonp10 Sep '09 - 3:34 
GeneralFailed install/start PHYMEM driver with Vista 32-bitmemberMember 246833712 Jun '09 - 8:21 
GeneralexcellentmemberJone_liuVC17 May '09 - 3:56 
GeneralTried to access PCI memory card that is at 0xDC04000 but could not.memberabhagat635 May '09 - 6:51 
GeneralRe: Tried to access PCI memory card that is at 0xDC04000 but could not.memberMember 4516868 May '09 - 3:29 
GeneralRe: Tried to access PCI memory card that is at 0xDC04000 but could not.membercyb7028912 May '09 - 20:56 
GeneralRe: Tried to access PCI memory card that is at 0xDC04000 but could not.memberrsholmqvist24 Jul '09 - 13:38 
GeneralRe: Tried to access PCI memory card that is at 0xDC04000 but could not.memberJMonteiro_126 Nov '09 - 4:38 
GeneralRe: Tried to access PCI memory card that is at 0xDC04000 but could not.memberJMonteiro_130 Nov '09 - 5:19 
GeneralRe: Tried to access PCI memory card that is at 0xDC04000 but could not.memberdusme4 Dec '09 - 7:29 
GeneralRe: Tried to access PCI memory card that is at 0xDC04000 but could not.memberJMonteiro_19 Dec '09 - 8:00 
GeneralRe: Tried to access PCI memory card that is at 0xDC04000 but could not.memberhimbostar14 Nov '10 - 22:23 
GeneralRe: Tried to access PCI memory card that is at 0xDC04000 but could not.memberwindstroller22 Jan '10 - 19:26 
GeneralRe: Tried to access PCI memory card that is at 0xDC04000 but could not.memberwindstroller22 Jan '10 - 23:13 
Generalgood jobmemberdong zhiyong13 Apr '09 - 4:40 
GeneralRe: good jobmvpDavidCrow21 Apr '09 - 3:34 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130516.1 | Last Updated 14 Apr 2009
Article Copyright 2009 by cyb70289
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid