일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 멀티테넌시
- 클라우드 자원 관리자
- 클라우드 보안 취약성
- 이 컴퓨터는 도메인의 구성원이 아닙니다.
- dhcp
- DHCP 설치
- Virtual Private Cloud
- Community Cloud
- Error 1720
- 수직적 확장
- 클라우드 소비자
- 자원 풀링
- 제한된 이식성
- VMware
- 정수형 데이터타입
- 도메인 사용자 또는 그룹을 확인할 수 없습니다.
- VMWare View Connection Serve
- 온 프레미스
- View Connection
- 수평적 확장
- 클라우드 제공자
- 가상 프라이빗 클라우드
- 고정 IP주소를 가진 네트워크 어댑터를 검색할 수 없습니다.
- DHCP 설정
- VMWare vSphere
- 클라우드 서비스 소유자
- 온디맨드식
- 운영관리제어의 축소
- 커뮤니티 클라우드
- IT 자원
- Today
- Total
한 걸음씩..
PC의 모든 PCI 장치가 사용중인 리소스 정보를 가져오는 방법 본문
프로젝트 도중 PCI장치의 Base Address를 임의로 할당 해 줘야 하는 일이 발생하여 다른 PCI장치들이 사용하지 않는 영역을 구하고 물리 메모리를 필요한만큼 할당하기 위해 Application에 기능 구현
1. PCI장치가 사용하는 물리 메모리 영역은 E00000000 ~ FFFFFFFF 까지 이다.
2. 모든 PCI장치들의 리소스 정보는 레지스트리에서 확인할 수 있다.
HKEY_LOCAL_MACHINE\HARDWARE\RESOURCEMAP\PnP Manager\PnpManager |
- 예를 들어 PCI Lan Card 의 정보[ 속성->자세히->실제 장치 개체 이름 ]을 확인하면 [ \Device\NTPNP_PCI0014 ] 라는 값을 확인할 수 있다.
- 이를 위 레지스트리에서 확인하게 되면 [ \Device\NTPNP_PCI0014.Translated ] 라는 이름으로 존재하고 있음을 확인할 수 있다.
- 위 레지스트리 정보 중 Raw와 Translated 라는 이름으로 하나의 장치에 두개씩의 이름이 있는것을 확인 할 수 있다.
두가지 정보의 차이점을 msdn에서 찾아보면 아래와 같이 나온다.
|
- 따라서 우리가 사용할 정보는 Translated 이다.
3. 구현
- Application에 이 기능을 구현하기 위해서 WinDDK 에 정의되어 있는 구조체 정보 중에 CM_RESOURCE_LIST 구조체를 복사하였다. 아래 define과 구조체를 복사하여 사용하여도 좋고 wdm.h 파일을 include 하여 사용해도 무관하다.
- Header
/* Taken from ntddk.h(shorten) */
#define CmResourceTypeNull 0 // ResType_All or ResType_None (0x0000)
#define CmResourceTypePort 1 // ResType_IO (0x0002)
#define CmResourceTypeInterrupt 2 // ResType_IRQ (0x0004)
#define CmResourceTypeMemory 3 // ResType_Mem (0x0001)
#define CmResourceTypeDma 4 // ResType_DMA (0x0003)
#define CmResourceTypeDeviceSpecific 5 // ResType_ClassSpecific (0xFFFF)
#define CmResourceTypeBusNumber 6 // ResType_BusNumber (0x0006)
#define CmResourceTypeMaximum 7
#define CmResourceTypeAssignedResource 8 // BUGBUG--remove
#define CmResourceTypeSubAllocateFrom 9 // BUGBUG--remove
#define CmResourceTypeNonArbitrated 128 // Not arbitrated if 0x80 bit set
#define CmResourceTypeConfigData 128 // ResType_Reserved (0x8000)
#define CmResourceTypeDevicePrivate 129 // ResType_DevicePrivate (0x8001)
#define CmResourceTypePcCardConfig 130 // ResType_PcCardConfig (0x8002)
#define CmResourceTypeMfCardConfig 131 // ResType_MfCardConfig (0x8003)
typedef enum _INTERFACE_TYPE {
InterfaceTypeUndefined = -1,
Internal,
Isa,
Eisa,
MicroChannel,
TurboChannel,
PCIBus,
VMEBus,
NuBus,
PCMCIABus,
CBus,
MPIBus,
MPSABus,
ProcessorInternal,
InternalPowerBus,
PNPISABus,
PNPBus,
MaximumInterfaceType
}INTERFACE_TYPE, *PINTERFACE_TYPE;
//////////////////////////////////////////////////////////////////////////////
typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS;
#pragma pack(4)
typedef struct _CM_PARTIAL_RESOURCE_DESCRIPTOR {
UCHAR Type;
UCHAR ShareDisposition;
USHORT Flags;
union {
struct {
PHYSICAL_ADDRESS Start;
ULONG Length;
} Generic;
struct {
PHYSICAL_ADDRESS Start;
ULONG Length;
} Port;
struct {
ULONG Level;
ULONG Vector;
ULONG Affinity;
} Interrupt;
struct {
PHYSICAL_ADDRESS Start; // 64 bit physical addresses.
ULONG Length;
} Memory;
struct {
ULONG Channel;
ULONG Port;
ULONG Reserved1;
} Dma;
struct {
ULONG Data[3];
} DevicePrivate;
struct {
ULONG Start;
ULONG Length;
ULONG Reserved;
} BusNumber;
struct {
ULONG DataSize;
ULONG Reserved1;
ULONG Reserved2;
} DeviceSpecificData;
} u;
} CM_PARTIAL_RESOURCE_DESCRIPTOR, *PCM_PARTIAL_RESOURCE_DESCRIPTOR;
#pragma pack()
typedef struct _CM_PARTIAL_RESOURCE_LIST {
USHORT Version;
USHORT Revision;
ULONG Count;
CM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptors[1];
} CM_PARTIAL_RESOURCE_LIST, *PCM_PARTIAL_RESOURCE_LIST;
typedef struct _CM_FULL_RESOURCE_DESCRIPTOR {
INTERFACE_TYPE InterfaceType;
ULONG BusNumber;
CM_PARTIAL_RESOURCE_LIST PartialResourceList;
} CM_FULL_RESOURCE_DESCRIPTOR, *PCM_FULL_RESOURCE_DESCRIPTOR;
typedef struct _CM_RESOURCE_LIST {
ULONG Count;
CM_FULL_RESOURCE_DESCRIPTOR List[1];
} CM_RESOURCE_LIST, *PCM_RESOURCE_LIST;
////////////////////////////////////////////////////////////////////////////
/* 사용중인 메모리 영역을 저장하고 필요한 메모리 영역을 구하기 위해 만든 구조체 */
typedef struct _Memory_Range
{
PHYSICAL_ADDRESS Start;
DWORD Len;
}Memory_Range, *PMemory_Range;
- Sources
물리 메모리 영역 E00000000 ~ FFFFFFFF 중 F00000000 ~ FFFFFFFF 사이에 비어있는 영역을 구하고 있음
변수명이 기니까 전체화면으로 보는걸 추천합니다.
#define BufSize 512
HKEY h_Key;
LONG Reg_Result;
DWORD DeviceValueSize;
DWORD dwType;
DWORD dwSize;
TCHAR DeviceValue[MAX_PATH];
PCM_RESOURCE_LIST pPCIDeviceResource; /* 가져온 데이터를 구조체에 저장 */
char szbuf[BufSize];
DWORD TypeMemoryCount = 0;
DWORD SkipMemory;
BOOL Address_Result;
/* 읽어온 메모리 영역을 저장하기 위해 */
PMemory_Range AddressRange = (PMemory_Range)malloc( BufSize );
DeviceValueSize = sizeof(DeviceValue);
dwSize = sizeof(szbuf);
Reg_Result = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
_T("HARDWARE\\RESOURCEMAP\\PnP Manager\\PnpManager"), /*Sub key*/
0,
KEY_READ | KEY_QUERY_VALUE,
&h_Key);
if(Reg_Result == ERROR_SUCCESS){
for(int i = 0; i < Reg_Result == ERROR_SUCCESS; i++){
/* 지정된 레지스트리 키가 가지는 값을 열거 */
Reg_Result = RegEnumValue(
h_Key,
i,
DeviceValue,
&DeviceValueSize,
NULL, NULL, NULL, NULL);
/* 내가 필요한 정보는 PCI장치의 Translated이므로 */
if( _tcsstr(DeviceValue, _T("\\Device\\NTPNP_PCI") ) != NULL && _tcsstr( DeviceValue, _T("Translated") ) != NULL ){
if(Reg_Result == ERROR_SUCCESS){
/*****************************************************/
//dwSize = BufSize; 꼭 초기화 해주자......
//이 부분이 없어서 0x000000ea Error [ERROR_MORE_DATA] 발생
//If the lpData buffer is too small to receive the data, the function returns
// ERROR_MORE_DATA
/*****************************************************/
dwSize = BufSize;
/* 명시된 항목이름의 데이터 형식이나 내용을 얻는데 사용 */
Reg_Result = RegQueryValueEx(
h_Key,
DeviceValue,
0,
&dwType,
(LPBYTE)&szbuf,
&dwSize);
if (Reg_Result == ERROR_SUCCESS){
/* 읽어 온 szbuf 를 PCM_RESOURCE_LIST에 적용 */
pPCIDeviceResource = (PCM_RESOURCE_LIST)szbuf;
for ( DWORD ii = 0; ii < pPCIDeviceResource->Count; ii++){
if( pPCIDeviceResource->List[ii].InterfaceType == PCIBus){
for ( DWORD iii = 0; iii < pPCIDeviceResource->List[ii].PartialResourceList.Count; iii++ ){
switch( pPCIDeviceResource->List[ii].PartialResourceList.PartialDescriptors[iii].Type )
{
case CmResourceTypeMemory:
{
if( pPCIDeviceResource->List[ii].PartialResourceList.PartialDescriptors[iii].u.Memory.Start.QuadPart >= 0xF0000000 ){
AddressRange[TypeMemoryCount].Start = pPCIDeviceResource->List[ii].PartialResourceList.PartialDescriptors[iii].u.Memory.Start;
AddressRange[TypeMemoryCount].Len = pPCIDeviceResource-> List[ii].PartialResourceList.PartialDescriptors[iii].u.Memory.Length;
TypeMemoryCount++;
}
}
break;
}
}
}
}
}
else
{
//Error Code
}
}
}
DeviceValueSize = MAX_PATH;
}
}
RegCloseKey(h_Key);
/* 0xF0000000 ~ 0xFFFFFFFF 까지 영역중에 사용하지 않고
16MB ( 0x1000000 ) 의 연속된 공간이 있는 영역 찾기*/
for(DWORD i = 0xF0000000; i < 0xFFFFFFFF; i++)
{
SkipMemory = i;
Address_Result = TRUE;
for(DWORD j = 0; j < TypeMemoryCount; j++)
{
if( SkipMemory > AddressRange[j].Start.LowPart && SkipMemory <= AddressRange[j].Start.LowPart + AddressRange[j].Len )
Address_Result = FALSE;
}
if ( Address_Result )
{
SkipMemory += 0x1000000;
for(DWORD j = 0; j < TypeMemoryCount; j++)
{
if( SkipMemory > AddressRange[j].Start.LowPart && SkipMemory <= AddressRange[j].Start.LowPart + AddressRange[j].Len )
Address_Result = FALSE;
}
if( Address_Result )
{
CString Print;
Print.Format(_T("0x%08x"),i);
AfxMessageBox( Print );
SkipMemory = i;
break;
}
}
}
free(AddressRange);
// IOCTL을 통하여 위에서 구한 SkipMemory Address를 전송. Base Address 등록
'프로그래밍' 카테고리의 다른 글
[MFC] 4대 Class간 참조 (0) | 2013.07.15 |
---|---|
어셈블리어 디버깅 / 윈도우 코드 에러분석, 수정 (0) | 2013.07.15 |
[PCI] 0x0CF8, 0x0CFC 레지스터 사용 (0) | 2013.07.15 |
[MFC]SendInput 사용시 주의 점 (0) | 2013.07.15 |
드라이버 설치할 때 INF 에서 OS 버전 구분하기 (0) | 2013.07.15 |